prostgles-server 3.0.129 → 3.0.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/TableConfig/TableConfig.d.ts +2 -2
  2. package/dist/TableConfig/TableConfig.d.ts.map +1 -1
  3. package/dist/TableConfig/TableConfig.js +65 -34
  4. package/dist/TableConfig/TableConfig.js.map +1 -1
  5. package/dist/TableConfig/getColumnDefinitionQuery.d.ts +22 -2
  6. package/dist/TableConfig/getColumnDefinitionQuery.d.ts.map +1 -1
  7. package/dist/TableConfig/getColumnDefinitionQuery.js +29 -13
  8. package/dist/TableConfig/getColumnDefinitionQuery.js.map +1 -1
  9. package/dist/TableConfig/getConstraintDefinitionQueries.d.ts +8 -0
  10. package/dist/TableConfig/getConstraintDefinitionQueries.d.ts.map +1 -0
  11. package/dist/TableConfig/getConstraintDefinitionQueries.js +32 -0
  12. package/dist/TableConfig/getConstraintDefinitionQueries.js.map +1 -0
  13. package/lib/TableConfig/TableConfig.d.ts +2 -2
  14. package/lib/TableConfig/TableConfig.d.ts.map +1 -1
  15. package/lib/TableConfig/TableConfig.js +65 -34
  16. package/lib/TableConfig/TableConfig.ts +97 -63
  17. package/lib/TableConfig/getColumnDefinitionQuery.d.ts +22 -2
  18. package/lib/TableConfig/getColumnDefinitionQuery.d.ts.map +1 -1
  19. package/lib/TableConfig/getColumnDefinitionQuery.js +29 -13
  20. package/lib/TableConfig/getColumnDefinitionQuery.ts +43 -14
  21. package/lib/TableConfig/getConstraintDefinitionQueries.d.ts +8 -0
  22. package/lib/TableConfig/getConstraintDefinitionQueries.d.ts.map +1 -0
  23. package/lib/TableConfig/getConstraintDefinitionQueries.js +31 -0
  24. package/lib/TableConfig/getConstraintDefinitionQueries.ts +37 -0
  25. package/package.json +1 -1
  26. package/tests/client/PID.txt +1 -1
  27. package/tests/server/package-lock.json +1 -1
@@ -6,6 +6,7 @@ const DboBuilder_1 = require("../DboBuilder");
6
6
  const PubSubManager_1 = require("../PubSubManager/PubSubManager");
7
7
  const validate_jsonb_schema_sql_1 = require("../JSONBValidation/validate_jsonb_schema_sql");
8
8
  const getColumnDefinitionQuery_1 = require("./getColumnDefinitionQuery");
9
+ const getConstraintDefinitionQueries_1 = require("./getConstraintDefinitionQueries");
9
10
  const parseI18N = (params) => {
10
11
  const { config, lang, defaultLang, defaultValue } = params;
11
12
  if (config) {
@@ -150,7 +151,7 @@ class TableConfigurator {
150
151
  catch (e) {
151
152
  }
152
153
  if (!existingVersion || existingVersion < version) {
153
- await onMigrate({ db: this.db, oldVersion: existingVersion, getConstraints: (table, col, types) => (0, getColumnDefinitionQuery_1.getColConstraints)(this.db, table, col, types) });
154
+ await onMigrate({ db: this.db, oldVersion: existingVersion, getConstraints: (table, col, types) => (0, getColumnDefinitionQuery_1.getColConstraints)({ db: this.db, table, column: col, types }) });
154
155
  }
155
156
  }
156
157
  /* Create lookup tables */
@@ -170,9 +171,9 @@ class TableConfigurator {
170
171
  if (isDropped || !this.dbo?.[tableNameRaw]) {
171
172
  const columnNames = Object.keys(rows[0]).filter(k => k !== "id");
172
173
  queries.push(`CREATE TABLE IF NOT EXISTS ${tableName} (
173
- id TEXT PRIMARY KEY
174
- ${columnNames.length ? (", " + columnNames.map(k => asName(k) + " TEXT ").join(", ")) : ""}
175
- );`);
174
+ id TEXT PRIMARY KEY
175
+ ${columnNames.length ? (", " + columnNames.map(k => asName(k) + " TEXT ").join(", ")) : ""}
176
+ );`);
176
177
  rows.map(row => {
177
178
  const values = this.prostgles.pgp.helpers.values(row);
178
179
  queries.push(this.prostgles.pgp.as.format(`INSERT INTO ${tableName} (${["id", ...columnNames].map(t => asName(t)).join(", ")}) ` + " VALUES ${values:raw} ;", { values }));
@@ -190,9 +191,10 @@ class TableConfigurator {
190
191
  await this.prostgles.refreshDBO();
191
192
  }
192
193
  queries = [];
193
- /* Create columns */
194
+ /* Create/Alter columns */
194
195
  for await (const tableName of (0, prostgles_types_1.getKeys)(this.config)) {
195
196
  const tableConf = this.config[tableName];
197
+ const constraintQueries = (0, getConstraintDefinitionQueries_1.getConstraintDefinitionQueries)({ tableName, tableConf: tableConf });
196
198
  if ("columns" in tableConf) {
197
199
  const colCreateLines = [];
198
200
  const tableHandler = this.dbo[tableName];
@@ -204,12 +206,7 @@ class TableConfigurator {
204
206
  /** Must install validation function */
205
207
  if (hasJSONBValidation) {
206
208
  try {
207
- const fileContent = `
208
- /* prevent duplicate key value violates unique constraint "pg_namespace_nspname_index" Key (nspname)=(prostgles) already exists.*/
209
- LOCK TABLE pg_catalog.pg_namespace IN SHARE ROW EXCLUSIVE MODE;
210
- CREATE SCHEMA IF NOT EXISTS prostgles;\n
211
- ${validate_jsonb_schema_sql_1.validate_jsonb_schema_sql}`;
212
- await this.db.any(fileContent);
209
+ await this.db.any(validate_jsonb_schema_sql_1.validate_jsonb_schema_sql);
213
210
  }
214
211
  catch (err) {
215
212
  console.error("Could not install the jsonb validation function due to error: ", err);
@@ -218,23 +215,30 @@ class TableConfigurator {
218
215
  }
219
216
  const columns = (0, prostgles_types_1.getKeys)(tableConf.columns).filter(c => {
220
217
  const colDef = tableConf.columns[c];
218
+ /** Exclude NamedJoinColumn */
221
219
  return typeof colDef === "string" || !("joinDef" in colDef);
222
220
  });
221
+ const columnDefs = [];
223
222
  for await (const colName of columns) {
224
223
  const colConf = tableConf.columns[colName];
225
- /* Add columns to create statement */
226
- if (!tableHandler) {
227
- const colDef = await (0, getColumnDefinitionQuery_1.getColumnDefinitionQuery)({ colConf, column: colName, db: this.db, table: tableName });
224
+ /* Add column to create statement */
225
+ const colDef = await (0, getColumnDefinitionQuery_1.getColumnDefinitionQuery)({ colConf, column: colName, db: this.db, table: tableName });
226
+ if (!colDef) {
227
+ // Column has only labels
228
+ }
229
+ else if (!tableHandler) {
230
+ columnDefs.push(colDef);
228
231
  colCreateLines.push(colDef);
232
+ /** Alter existing column */
229
233
  }
230
234
  else if (tableHandler && !tableHandler.columns?.find(c => colName === c.name)) {
231
- const colDef = await (0, getColumnDefinitionQuery_1.getColumnDefinitionQuery)({ colConf, column: colName, db: this.db, table: tableName });
235
+ columnDefs.push(colDef);
232
236
  queries.push(`
233
237
  ALTER TABLE ${asName(tableName)}
234
238
  ADD COLUMN ${colDef};
235
239
  `);
236
240
  if ((0, prostgles_types_1.isObject)(colConf) && "references" in colConf && colConf.references) {
237
- const { tableName: lookupTable, } = colConf.references;
241
+ const { tableName: lookupTable } = colConf.references;
238
242
  this.log(`TableConfigurator: ${tableName}(${colName})` + " referenced lookup table " + lookupTable);
239
243
  }
240
244
  else {
@@ -242,6 +246,50 @@ class TableConfigurator {
242
246
  }
243
247
  }
244
248
  }
249
+ /** Remove droped/altered constraints */
250
+ if (tableHandler && columnDefs.length) {
251
+ let newConstraints = [];
252
+ let newCols = [];
253
+ try {
254
+ await this.db.tx(async (t) => {
255
+ const { v } = await t.one("SELECT md5(random()::text) as v");
256
+ const randomTableName = `prostgles_constr_${v}`;
257
+ const columnDefsWithoutReferences = columnDefs.map(cdef => {
258
+ return cdef.slice(0, cdef.toLowerCase().indexOf(" references "));
259
+ });
260
+ await t.any(`CREATE TABLE ${randomTableName} ( \n${columnDefsWithoutReferences.join(",\n")}\n );\n` +
261
+ (constraintQueries ?? []).join("\n"));
262
+ newConstraints = await (0, getColumnDefinitionQuery_1.getColConstraints)({ db: t, table: randomTableName });
263
+ newCols = await (0, getColumnDefinitionQuery_1.getTableColumns)({ db: this.db, tableName });
264
+ return Promise.reject("Done");
265
+ });
266
+ }
267
+ catch (e) {
268
+ }
269
+ const ALTER_TABLE_Q = `ALTER TABLE ${asName(tableName)}`;
270
+ const currConstraints = await (0, getColumnDefinitionQuery_1.getColConstraints)({ db: this.db, table: tableName });
271
+ currConstraints.forEach(c => {
272
+ if (!newConstraints.some(nc => nc.type === c.type && nc.definition === c.definition && nc.cols.sort().join() === c.cols.sort().join())) {
273
+ queries.unshift(`${ALTER_TABLE_Q} DROP CONSTRAINT ${asName(c.name)} CASCADE;`);
274
+ }
275
+ });
276
+ const currCols = await (0, getColumnDefinitionQuery_1.getTableColumns)({ db: this.db, tableName });
277
+ currCols.forEach(c => {
278
+ const newCol = newCols.find(nc => nc.column_name === c.column_name);
279
+ if (!newCol) {
280
+ queries.push(`${ALTER_TABLE_Q} DROP COLUMN ${asName(c.column_name)} CASCADE;`);
281
+ }
282
+ else if (newCol.nullable !== c.nullable) {
283
+ queries.push(`${ALTER_TABLE_Q} ALTER COLUMN ${asName(c.column_name)} ${newCol.nullable ? "SET" : "DROP"} NOT NULL;`);
284
+ }
285
+ else if (newCol.udt_name !== c.udt_name) {
286
+ queries.push(`${ALTER_TABLE_Q} ALTER COLUMN ${asName(c.column_name)} TYPE ${newCol.udt_name};`);
287
+ }
288
+ else if (newCol.column_default !== c.column_default) {
289
+ queries.push(`${ALTER_TABLE_Q} ALTER COLUMN ${asName(c.column_name)} ${newCol.column_default === null ? "DROP DEFAULT" : `SET DEFAULT ${newCol.column_default}`};`);
290
+ }
291
+ });
292
+ }
245
293
  }
246
294
  if (colCreateLines.length) {
247
295
  queries.push([
@@ -252,24 +300,7 @@ class TableConfigurator {
252
300
  this.log("TableConfigurator: Created table: \n" + queries.at(-1));
253
301
  }
254
302
  }
255
- if ("constraints" in tableConf && tableConf.constraints) {
256
- const constraints = await getTableConstraings(this.db, tableName);
257
- const constraintNames = (0, prostgles_types_1.getKeys)(tableConf.constraints);
258
- constraintNames.map(constraintName => {
259
- const _cnstr = tableConf.constraints[constraintName];
260
- const constraintDef = typeof _cnstr === "string" ? _cnstr : `${_cnstr.type} (${_cnstr.content})`;
261
- const canDrop = (0, prostgles_types_1.isObject)(_cnstr) && _cnstr.dropIfExists;
262
- /** Drop constraints with the same name */
263
- const existingConstraint = constraints.some(c => c.conname === constraintName);
264
- if (existingConstraint) {
265
- if (canDrop)
266
- queries.push(`ALTER TABLE ${asName(tableName)} DROP CONSTRAINT ${asName(constraintName)};`);
267
- }
268
- if (!existingConstraint || canDrop) {
269
- queries.push(`ALTER TABLE ${asName(tableName)} ADD CONSTRAINT ${asName(constraintName)} ${constraintDef} ;`);
270
- }
271
- });
272
- }
303
+ queries.push(...constraintQueries ?? []);
273
304
  if ("indexes" in tableConf && tableConf.indexes) {
274
305
  /*
275
306
  CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
@@ -3,8 +3,8 @@ import { isPlainObject, JoinInfo } from "../DboBuilder";
3
3
  import { DB, DBHandlerServer, Prostgles } from "../Prostgles";
4
4
  import { asValue } from "../PubSubManager/PubSubManager";
5
5
  import { validate_jsonb_schema_sql } from "../JSONBValidation/validate_jsonb_schema_sql";
6
- import { getColConstraints, getColumnDefinitionQuery } from "./getColumnDefinitionQuery";
7
- import { stringify } from "querystring";
6
+ import { ColConstraint, ColumnMinimalInfo, getColConstraints, getColumnDefinitionQuery, getTableColumns } from "./getColumnDefinitionQuery";
7
+ import { getConstraintDefinitionQueries } from "./getConstraintDefinitionQueries";
8
8
 
9
9
  type ColExtraInfo = {
10
10
  min?: string | number;
@@ -208,33 +208,35 @@ type StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<Uni
208
208
  export type StrictUnion<T> = StrictUnionHelper<T, T>
209
209
 
210
210
  export const CONSTRAINT_TYPES = ["PRIMARY KEY", "UNIQUE", "CHECK"] as const; // "FOREIGN KEY",
211
- type TableDefinition<LANG_IDS> = {
211
+ export type TableDefinition<LANG_IDS> = {
212
212
  columns?: {
213
213
  [column_name: string]: ColumnConfig<LANG_IDS>
214
214
  },
215
- constraints?: {
216
- [constraint_name: string]:
217
- | string
218
- | {
219
- type: typeof CONSTRAINT_TYPES[number];
220
- dropIfExists?: boolean;
221
- /**
222
- * E.g.:
223
- * colname
224
- * col1, col2
225
- * col1 > col3
226
- */
227
- content: string;
228
- }
229
- // & ({
230
- // }
231
- // | {
232
- // type: "FOREIGN KEY",
233
- // columns: string[];
234
- // ftable: string;
235
- // fcols: string[];
236
- // }
237
- // )
215
+ constraints?:
216
+ | string[]
217
+ | {
218
+ [constraint_name: string]:
219
+ | string
220
+ | {
221
+ type: typeof CONSTRAINT_TYPES[number];
222
+ dropIfExists?: boolean;
223
+ /**
224
+ * E.g.:
225
+ * colname
226
+ * col1, col2
227
+ * col1 > col3
228
+ */
229
+ content: string;
230
+ }
231
+ // & ({
232
+ // }
233
+ // | {
234
+ // type: "FOREIGN KEY",
235
+ // columns: string[];
236
+ // ftable: string;
237
+ // fcols: string[];
238
+ // }
239
+ // )
238
240
  },
239
241
 
240
242
  /**
@@ -442,7 +444,7 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
442
444
  }
443
445
 
444
446
  if(!existingVersion || existingVersion < version){
445
- await onMigrate({ db: this.db, oldVersion: existingVersion, getConstraints: (table, col, types) => getColConstraints(this.db, table, col, types) })
447
+ await onMigrate({ db: this.db, oldVersion: existingVersion, getConstraints: (table, col, types) => getColConstraints({ db: this.db, table, column: col, types }) })
446
448
  }
447
449
  }
448
450
 
@@ -463,10 +465,12 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
463
465
  const rows = Object.keys(tableConf.isLookupTable?.values).map(id => ({ id, ...(tableConf.isLookupTable?.values[id]) }));
464
466
  if (isDropped || !this.dbo?.[tableNameRaw]) {
465
467
  const columnNames = Object.keys(rows[0]).filter(k => k !== "id");
466
- queries.push(`CREATE TABLE IF NOT EXISTS ${tableName} (
467
- id TEXT PRIMARY KEY
468
- ${columnNames.length? (", " + columnNames.map(k => asName(k) + " TEXT ").join(", ")) : ""}
469
- );`);
468
+ queries.push(
469
+ `CREATE TABLE IF NOT EXISTS ${tableName} (
470
+ id TEXT PRIMARY KEY
471
+ ${columnNames.length? (", " + columnNames.map(k => asName(k) + " TEXT ").join(", ")) : ""}
472
+ );`
473
+ );
470
474
 
471
475
  rows.map(row => {
472
476
  const values = this.prostgles.pgp!.helpers.values(row)
@@ -487,9 +491,10 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
487
491
  }
488
492
  queries = [];
489
493
 
490
- /* Create columns */
494
+ /* Create/Alter columns */
491
495
  for await (const tableName of getKeys(this.config)){
492
496
  const tableConf = this.config![tableName];
497
+ const constraintQueries = getConstraintDefinitionQueries({ tableName, tableConf: tableConf as any });
493
498
  if ("columns" in tableConf) {
494
499
  const colCreateLines: string[] = [];
495
500
  const tableHandler = this.dbo[tableName];
@@ -502,13 +507,7 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
502
507
  /** Must install validation function */
503
508
  if(hasJSONBValidation){
504
509
  try {
505
-
506
- const fileContent = `
507
- /* prevent duplicate key value violates unique constraint "pg_namespace_nspname_index" Key (nspname)=(prostgles) already exists.*/
508
- LOCK TABLE pg_catalog.pg_namespace IN SHARE ROW EXCLUSIVE MODE;
509
- CREATE SCHEMA IF NOT EXISTS prostgles;\n
510
- ${validate_jsonb_schema_sql}`;
511
- await this.db.any(fileContent);
510
+ await this.db.any(validate_jsonb_schema_sql);
512
511
  } catch(err: any){
513
512
  console.error("Could not install the jsonb validation function due to error: ", err);
514
513
  throw err;
@@ -517,34 +516,85 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
517
516
 
518
517
  const columns = getKeys(tableConf.columns).filter(c => {
519
518
  const colDef = tableConf.columns![c];
519
+ /** Exclude NamedJoinColumn */
520
520
  return typeof colDef === "string" || !("joinDef" in colDef)
521
521
  });
522
522
 
523
+ const columnDefs: string[] = [];
523
524
  for await(const colName of columns) {
524
525
  const colConf = tableConf.columns![colName];
525
526
 
526
-
527
- /* Add columns to create statement */
528
- if (!tableHandler) {
529
- const colDef = await getColumnDefinitionQuery({ colConf, column: colName, db: this.db, table: tableName })
527
+ /* Add column to create statement */
528
+ const colDef = await getColumnDefinitionQuery({ colConf, column: colName, db: this.db, table: tableName });
529
+ if(!colDef){
530
+ // Column has only labels
531
+ } else if (!tableHandler) {
532
+ columnDefs.push(colDef);
530
533
  colCreateLines.push(colDef);
531
534
 
535
+ /** Alter existing column */
532
536
  } else if (tableHandler && !tableHandler.columns?.find(c => colName === c.name)) {
533
- const colDef = await getColumnDefinitionQuery({ colConf, column: colName, db: this.db, table: tableName })
537
+ columnDefs.push(colDef);
534
538
 
535
539
  queries.push(`
536
540
  ALTER TABLE ${asName(tableName)}
537
541
  ADD COLUMN ${colDef};
538
542
  `);
539
- if (isObject(colConf) && "references" in colConf && colConf.references) {
543
+ if(isObject(colConf) && "references" in colConf && colConf.references){
540
544
 
541
- const { tableName: lookupTable, } = colConf.references;
545
+ const { tableName: lookupTable } = colConf.references;
542
546
  this.log(`TableConfigurator: ${tableName}(${colName})` + " referenced lookup table " + lookupTable);
543
547
  } else {
544
548
  this.log(`TableConfigurator: created/added column ${tableName}(${colName}) `)
545
549
  }
546
550
  }
547
551
  }
552
+
553
+ /** Remove droped/altered constraints */
554
+ if(tableHandler && columnDefs.length){
555
+ let newConstraints: ColConstraint[] = [];
556
+ let newCols: ColumnMinimalInfo[] = [];
557
+ try {
558
+ await this.db.tx(async t => {
559
+ const { v } = await t.one("SELECT md5(random()::text) as v");
560
+ const randomTableName = `prostgles_constr_${v}`;
561
+ const columnDefsWithoutReferences = columnDefs.map(cdef => {
562
+ return cdef.slice(0, cdef.toLowerCase().indexOf(" references "));
563
+ });
564
+ await t.any(
565
+ `CREATE TABLE ${randomTableName} ( \n${columnDefsWithoutReferences.join(",\n")}\n );\n` +
566
+ (constraintQueries ?? []).join("\n")
567
+ );
568
+ newConstraints = await getColConstraints({ db: t, table: randomTableName });
569
+ newCols = await getTableColumns({ db: this.db, tableName });
570
+ return Promise.reject("Done");
571
+ });
572
+
573
+ } catch(e){
574
+
575
+ }
576
+ const ALTER_TABLE_Q = `ALTER TABLE ${asName(tableName)}`;
577
+ const currConstraints = await getColConstraints({ db: this.db, table: tableName });
578
+ currConstraints.forEach(c => {
579
+ if(!newConstraints.some(nc => nc.type === c.type && nc.definition === c.definition && nc.cols.sort().join() === c.cols.sort().join())){
580
+ queries.unshift(`${ALTER_TABLE_Q} DROP CONSTRAINT ${asName(c.name)} CASCADE;`);
581
+ }
582
+ });
583
+
584
+ const currCols = await getTableColumns({ db: this.db, tableName });
585
+ currCols.forEach(c => {
586
+ const newCol = newCols.find(nc => nc.column_name === c.column_name);
587
+ if(!newCol){
588
+ queries.push(`${ALTER_TABLE_Q} DROP COLUMN ${asName(c.column_name)} CASCADE;`)
589
+ } else if(newCol.nullable !== c.nullable){
590
+ queries.push(`${ALTER_TABLE_Q} ALTER COLUMN ${asName(c.column_name)} ${newCol.nullable? "SET" : "DROP"} NOT NULL;`)
591
+ } else if(newCol.udt_name !== c.udt_name){
592
+ queries.push(`${ALTER_TABLE_Q} ALTER COLUMN ${asName(c.column_name)} TYPE ${newCol.udt_name};`)
593
+ } else if(newCol.column_default !== c.column_default){
594
+ queries.push(`${ALTER_TABLE_Q} ALTER COLUMN ${asName(c.column_name)} ${newCol.column_default === null? "DROP DEFAULT" : `SET DEFAULT ${newCol.column_default}`};`)
595
+ }
596
+ })
597
+ }
548
598
  }
549
599
 
550
600
  if (colCreateLines.length) {
@@ -556,23 +606,7 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
556
606
  this.log("TableConfigurator: Created table: \n" + queries.at(-1))
557
607
  }
558
608
  }
559
- if ("constraints" in tableConf && tableConf.constraints) {
560
- const constraints = await getTableConstraings(this.db, tableName);
561
- const constraintNames = getKeys(tableConf.constraints);
562
- constraintNames.map(constraintName => {
563
- const _cnstr = tableConf.constraints![constraintName];
564
- const constraintDef = typeof _cnstr === "string"? _cnstr : `${_cnstr.type} (${_cnstr.content})`;
565
- const canDrop = isObject(_cnstr) && _cnstr.dropIfExists;
566
- /** Drop constraints with the same name */
567
- const existingConstraint = constraints.some(c => c.conname === constraintName);
568
- if(existingConstraint){
569
- if(canDrop) queries.push(`ALTER TABLE ${asName(tableName)} DROP CONSTRAINT ${asName(constraintName)};`);
570
- }
571
- if(!existingConstraint || canDrop){
572
- queries.push(`ALTER TABLE ${asName(tableName)} ADD CONSTRAINT ${asName(constraintName)} ${constraintDef} ;`);
573
- }
574
- });
575
- }
609
+ queries.push(...constraintQueries ?? []);
576
610
  if ("indexes" in tableConf && tableConf.indexes) {
577
611
  /*
578
612
  CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
@@ -1,5 +1,6 @@
1
1
  import { DB } from "../Prostgles";
2
2
  import { ColumnConfig } from "./TableConfig";
3
+ import pgPromise from "pg-promise";
3
4
  type Args = {
4
5
  column: string;
5
6
  colConf: ColumnConfig;
@@ -9,7 +10,7 @@ type Args = {
9
10
  /**
10
11
  * Column create statement for a given config
11
12
  */
12
- export declare const getColumnDefinitionQuery: ({ colConf, column, db, table }: Args) => Promise<string>;
13
+ export declare const getColumnDefinitionQuery: ({ colConf: colConfRaw, column, db, table }: Args) => Promise<string | undefined>;
13
14
  export type ColConstraint = {
14
15
  name: string;
15
16
  table: string;
@@ -18,6 +19,25 @@ export type ColConstraint = {
18
19
  definition: string;
19
20
  schema: string;
20
21
  };
21
- export declare const getColConstraints: (db: DB, table?: string, column?: string, types?: ColConstraint["type"][]) => Promise<ColConstraint[]>;
22
+ type ColConstraintsArgs = {
23
+ db: DB | pgPromise.ITask<{}>;
24
+ table?: string;
25
+ column?: string;
26
+ types?: ColConstraint["type"][];
27
+ };
28
+ export declare const getColConstraintsQuery: ({ column, table, types }: Omit<ColConstraintsArgs, "db">) => string;
29
+ export declare const getColConstraints: ({ db, column, table, types }: ColConstraintsArgs) => Promise<ColConstraint[]>;
30
+ export type ColumnMinimalInfo = {
31
+ table_name: string;
32
+ table_schema: string;
33
+ column_name: string;
34
+ column_default: string | null;
35
+ udt_name: string;
36
+ nullable: boolean;
37
+ };
38
+ export declare const getTableColumns: ({ db, tableName }: {
39
+ db: DB;
40
+ tableName: string;
41
+ }) => Promise<ColumnMinimalInfo[]>;
22
42
  export {};
23
43
  //# sourceMappingURL=getColumnDefinitionQuery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getColumnDefinitionQuery.d.ts","sourceRoot":"","sources":["getColumnDefinitionQuery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAGlC,OAAO,EAAmB,YAAY,EAAE,MAAM,eAAe,CAAC;AAE9D,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,mCAA0C,IAAI,KAAG,QAAQ,MAAM,CAiFnG,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAA;AACD,eAAO,MAAM,iBAAiB,mBAAoB,MAAM,WAAW,MAAM,UAAU,aAAa,CAAC,MAAM,CAAC,EAAE,KAAG,QAAQ,aAAa,EAAE,CAyBnI,CAAA"}
1
+ {"version":3,"file":"getColumnDefinitionQuery.d.ts","sourceRoot":"","sources":["getColumnDefinitionQuery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAGlC,OAAO,EAAmB,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,YAAY,CAAC;IACtB,EAAE,EAAE,EAAE,CAAC;IACP,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,+CAAsD,IAAI,KAAG,QAAQ,MAAM,GAAG,SAAS,CAiF3H,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC5B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAA;AACD,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;CACjC,CAAA;AACD,eAAO,MAAM,sBAAsB,6BAA8B,KAAK,kBAAkB,EAAE,IAAI,CAAC,WAyB9F,CAAA;AACD,eAAO,MAAM,iBAAiB,iCAAkC,kBAAkB,KAAI,QAAQ,aAAa,EAAE,CAG5G,CAAA;AACD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,eAAO,MAAM,eAAe;;eAA4C,MAAM;MAAK,QAAQ,iBAAiB,EAAE,CAS7G,CAAA"}
@@ -1,30 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getColConstraints = exports.getColumnDefinitionQuery = void 0;
3
+ exports.getTableColumns = exports.getColConstraints = exports.getColConstraintsQuery = exports.getColumnDefinitionQuery = void 0;
4
4
  const prostgles_types_1 = require("prostgles-types");
5
5
  const PubSubManager_1 = require("../PubSubManager/PubSubManager");
6
6
  const validate_jsonb_schema_sql_1 = require("../JSONBValidation/validate_jsonb_schema_sql");
7
7
  /**
8
8
  * Column create statement for a given config
9
9
  */
10
- const getColumnDefinitionQuery = async ({ colConf, column, db, table }) => {
10
+ const getColumnDefinitionQuery = async ({ colConf: colConfRaw, column, db, table }) => {
11
+ const colConf = typeof colConfRaw === "string" ? { sqlDefinition: colConfRaw } : colConfRaw;
11
12
  const colNameEsc = (0, prostgles_types_1.asName)(column);
12
13
  const getColTypeDef = (colConf, pgType) => {
13
14
  const { nullable, defaultValue } = colConf;
14
15
  return `${pgType} ${!nullable ? " NOT NULL " : ""} ${defaultValue ? ` DEFAULT ${(0, PubSubManager_1.asValue)(defaultValue)} ` : ""}`;
15
16
  };
16
- const jsonbSchema = (0, prostgles_types_1.isObject)(colConf) ? (("jsonbSchema" in colConf && colConf.jsonbSchema) ? { jsonbSchema: colConf.jsonbSchema, jsonbSchemaType: undefined } :
17
+ const jsonbSchema = ("jsonbSchema" in colConf && colConf.jsonbSchema) ? { jsonbSchema: colConf.jsonbSchema, jsonbSchemaType: undefined } :
17
18
  ("jsonbSchemaType" in colConf && colConf.jsonbSchemaType) ? { jsonbSchema: undefined, jsonbSchemaType: colConf.jsonbSchemaType } :
18
- undefined) :
19
- undefined;
20
- if ((0, prostgles_types_1.isObject)(colConf) && "references" in colConf && colConf.references) {
19
+ undefined;
20
+ if ("references" in colConf && colConf.references) {
21
21
  const { tableName: lookupTable, columnName: lookupCol = "id" } = colConf.references;
22
22
  return ` ${colNameEsc} ${getColTypeDef(colConf.references, "TEXT")} REFERENCES ${lookupTable} (${lookupCol}) `;
23
23
  }
24
- else if (typeof colConf === "string" || "sqlDefinition" in colConf && colConf.sqlDefinition) {
25
- return ` ${colNameEsc} ${typeof colConf === "string" ? colConf : colConf.sqlDefinition} `;
24
+ else if ("sqlDefinition" in colConf && colConf.sqlDefinition) {
25
+ return ` ${colNameEsc} ${colConf.sqlDefinition} `;
26
26
  }
27
- else if ((0, prostgles_types_1.isObject)(colConf) && "isText" in colConf && colConf.isText) {
27
+ else if ("isText" in colConf && colConf.isText) {
28
28
  let checks = "";
29
29
  const colChecks = [];
30
30
  if (colConf.lowerCased) {
@@ -62,7 +62,7 @@ const getColumnDefinitionQuery = async ({ colConf, column, db, table }) => {
62
62
  const namePreffix = 'prostgles_jsonb_';
63
63
  const { val: nameEnding } = await db.one("SELECT MD5( ${table} || ${column} || ${schema}) as val", { table: table, column, schema: jsonbSchemaStr });
64
64
  const constraintName = namePreffix + nameEnding;
65
- const colConstraints = await (0, exports.getColConstraints)(db, table, column);
65
+ const colConstraints = await (0, exports.getColConstraints)({ db, table, column });
66
66
  const existingNonMatchingConstraints = colConstraints.filter(c => c.name.startsWith(namePreffix) && c.name !== constraintName);
67
67
  for await (const oldCons of existingNonMatchingConstraints) {
68
68
  await db.any(`ALTER TABLE ${(0, prostgles_types_1.asName)(table)} DROP CONSTRAINT ${(0, prostgles_types_1.asName)(oldCons.name)};`);
@@ -77,11 +77,12 @@ const getColumnDefinitionQuery = async ({ colConf, column, db, table }) => {
77
77
  return ` ${colNameEsc} ${type} ${colConf.nullable ? "" : "NOT NULL"} ${"defaultValue" in colConf ? ` DEFAULT ${(0, PubSubManager_1.asValue)(colConf.defaultValue)}` : ""} CHECK(${checks})`;
78
78
  }
79
79
  else {
80
- throw "Unknown column config: " + JSON.stringify(colConf);
80
+ return undefined;
81
+ // throw "Unknown column config: " + JSON.stringify(colConf);
81
82
  }
82
83
  };
83
84
  exports.getColumnDefinitionQuery = getColumnDefinitionQuery;
84
- const getColConstraints = (db, table, column, types) => {
85
+ const getColConstraintsQuery = ({ column, table, types }) => {
85
86
  let query = `
86
87
  SELECT *
87
88
  FROM (
@@ -108,6 +109,21 @@ const getColConstraints = (db, table, column, types) => {
108
109
  query += `\nAND cols @> ARRAY[${(0, PubSubManager_1.asValue)(column)}]`;
109
110
  if (types?.length)
110
111
  query += `\nAND type IN (${types.map(v => (0, PubSubManager_1.asValue)(v)).join(", ")})`;
111
- return db.manyOrNone(query);
112
+ return query;
113
+ };
114
+ exports.getColConstraintsQuery = getColConstraintsQuery;
115
+ const getColConstraints = ({ db, column, table, types }) => {
116
+ return db.manyOrNone((0, exports.getColConstraintsQuery)({ column, table, types }));
112
117
  };
113
118
  exports.getColConstraints = getColConstraints;
119
+ const getTableColumns = ({ db, tableName }) => {
120
+ return db.manyOrNone(`
121
+ SELECT table_name,
122
+ table_schema, column_name,
123
+ column_default, udt_name,
124
+ is_nullable = 'YES' as nullable
125
+ FROM information_schema.columns
126
+ WHERE table_name = $1
127
+ `, [tableName]);
128
+ };
129
+ exports.getTableColumns = getTableColumns;