WriteUsersSchemasInPostgreSQL will create a schema for each user in each database that user has access to
(ctx context.Context, exec Executor, users []v1beta1.PostgresUserSpec)
| 182 | |
| 183 | // WriteUsersSchemasInPostgreSQL will create a schema for each user in each database that user has access to |
| 184 | func WriteUsersSchemasInPostgreSQL(ctx context.Context, exec Executor, |
| 185 | users []v1beta1.PostgresUserSpec) error { |
| 186 | |
| 187 | log := logging.FromContext(ctx) |
| 188 | |
| 189 | var err error |
| 190 | var stdout string |
| 191 | var stderr string |
| 192 | |
| 193 | for i := range users { |
| 194 | spec := users[i] |
| 195 | |
| 196 | // We skip if the user has the name of a reserved schema |
| 197 | if RESERVED_SCHEMA_NAMES[spec.Name] { |
| 198 | log.V(1).Info("Skipping schema creation for user with reserved name", |
| 199 | "name", spec.Name) |
| 200 | continue |
| 201 | } |
| 202 | |
| 203 | // We skip if the user has no databases |
| 204 | if len(spec.Databases) == 0 { |
| 205 | continue |
| 206 | } |
| 207 | |
| 208 | var sql bytes.Buffer |
| 209 | |
| 210 | // Prevent unexpected dereferences by emptying "search_path". The "pg_catalog" |
| 211 | // schema is still searched, and only temporary objects can be created. |
| 212 | // - https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-SEARCH-PATH |
| 213 | _, _ = sql.WriteString(`SET search_path TO '';`) |
| 214 | |
| 215 | _, _ = sql.WriteString(`SELECT * FROM json_array_elements_text(:'databases');`) |
| 216 | |
| 217 | databases, _ := json.Marshal(spec.Databases) |
| 218 | |
| 219 | stdout, stderr, err = exec.ExecInDatabasesFromQuery(ctx, |
| 220 | sql.String(), |
| 221 | strings.Join([]string{ |
| 222 | // Quiet NOTICE messages from IF EXISTS statements. |
| 223 | // - https://www.postgresql.org/docs/current/runtime-config-client.html |
| 224 | `SET client_min_messages = WARNING;`, |
| 225 | |
| 226 | // Do not wait for changes to be replicated. [Since PostgreSQL v9.1] |
| 227 | // - https://www.postgresql.org/docs/current/runtime-config-wal.html |
| 228 | `SET synchronous_commit = LOCAL;`, |
| 229 | |
| 230 | // Creates a schema named after and owned by the user |
| 231 | // - https://www.postgresql.org/docs/current/ddl-schemas.html |
| 232 | // - https://www.postgresql.org/docs/current/sql-createschema.html |
| 233 | |
| 234 | // We create a schema named after the user because |
| 235 | // the PG search_path does not need to be updated, |
| 236 | // since search_path defaults to "$user", public. |
| 237 | // - https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH |
| 238 | `CREATE SCHEMA IF NOT EXISTS :"username" AUTHORIZATION :"username";`, |
| 239 | }, "\n"), |
| 240 | map[string]string{ |
| 241 | "databases": string(databases), |