package pgsql import ( "errors" "fmt" "gorm.io/gorm" "zestack.dev/env" ) func PublicSchema() string { return env.String("DB_PUBLIC_SCHEMA", "public") } func TenantBasename() string { return env.String("TENANT_BASENAME", "tenant_") } func TenantSchema(tenant uint) string { if tenant == 0 { return PublicSchema() } return fmt.Sprintf("%s%d", TenantBasename(), tenant) } func SetSearchPath(tx *gorm.DB, schema string) (reset func() error, err error) { // tx = tx.Session(&gorm.Session{}) if schema == "" { err = errors.New("schema name is empty") tx.AddError(err) return } if schema == CurrentSearchPath(tx) { reset = func() error { return nil } return } sqlstr := "SET search_path TO " + tx.Statement.Quote(schema) if execErr := tx.Exec(sqlstr).Error; execErr != nil { err = fmt.Errorf("failed to set search path %q: %w", schema, execErr) tx.AddError(err) return } reset = func() error { publicSchema := PublicSchema() if schema == publicSchema { return nil } return tx.Exec("SET search_path TO " + tx.Statement.Quote(publicSchema)).Error } return } func CurrentSearchPath(tx *gorm.DB) string { // tx = tx.Session(&gorm.Session{}) var searchPath string tx.Raw("SHOW search_path").Scan(&searchPath) if searchPath == `"$user", public` { return "public" } return searchPath }