graphile-build-pg 4.9.1 → 4.11.2
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.
- package/README.md +1 -0
- package/node8plus/plugins/PageInfoStartEndCursor.js +2 -2
- package/node8plus/plugins/PageInfoStartEndCursor.js.flow +6 -2
- package/node8plus/plugins/PageInfoStartEndCursor.js.map +1 -1
- package/node8plus/plugins/PgAllRows.js +1 -1
- package/node8plus/plugins/PgAllRows.js.flow +6 -3
- package/node8plus/plugins/PgAllRows.js.map +1 -1
- package/node8plus/plugins/PgBackwardRelationPlugin.js +2 -2
- package/node8plus/plugins/PgBackwardRelationPlugin.js.flow +8 -2
- package/node8plus/plugins/PgBackwardRelationPlugin.js.map +1 -1
- package/node8plus/plugins/PgBasicsPlugin.js +1 -1
- package/node8plus/plugins/PgBasicsPlugin.js.flow +1 -1
- package/node8plus/plugins/PgBasicsPlugin.js.map +1 -1
- package/node8plus/plugins/PgConditionComputedColumnPlugin.js +1 -1
- package/node8plus/plugins/PgConditionComputedColumnPlugin.js.flow +4 -1
- package/node8plus/plugins/PgConditionComputedColumnPlugin.js.map +1 -1
- package/node8plus/plugins/PgConnectionArgCondition.js +3 -3
- package/node8plus/plugins/PgConnectionArgCondition.js.flow +11 -3
- package/node8plus/plugins/PgConnectionArgCondition.js.map +1 -1
- package/node8plus/plugins/PgConnectionArgFirstLastBeforeAfter.js +5 -5
- package/node8plus/plugins/PgConnectionArgFirstLastBeforeAfter.js.flow +20 -7
- package/node8plus/plugins/PgConnectionArgFirstLastBeforeAfter.js.map +1 -1
- package/node8plus/plugins/PgConnectionArgOrderBy.js +2 -2
- package/node8plus/plugins/PgConnectionArgOrderBy.js.flow +8 -2
- package/node8plus/plugins/PgConnectionArgOrderBy.js.map +1 -1
- package/node8plus/plugins/PgConnectionTotalCount.js +1 -1
- package/node8plus/plugins/PgConnectionTotalCount.js.flow +4 -1
- package/node8plus/plugins/PgConnectionTotalCount.js.map +1 -1
- package/node8plus/plugins/PgForwardRelationPlugin.js +1 -1
- package/node8plus/plugins/PgForwardRelationPlugin.js.flow +4 -1
- package/node8plus/plugins/PgForwardRelationPlugin.js.map +1 -1
- package/node8plus/plugins/PgIntrospectionPlugin.d.ts +1 -0
- package/node8plus/plugins/PgIntrospectionPlugin.js +182 -159
- package/node8plus/plugins/PgIntrospectionPlugin.js.flow +218 -198
- package/node8plus/plugins/PgIntrospectionPlugin.js.map +1 -1
- package/node8plus/plugins/PgJWTPlugin.js +1 -1
- package/node8plus/plugins/PgJWTPlugin.js.flow +3 -1
- package/node8plus/plugins/PgJWTPlugin.js.map +1 -1
- package/node8plus/plugins/PgMutationCreatePlugin.js +7 -7
- package/node8plus/plugins/PgMutationCreatePlugin.js.flow +26 -7
- package/node8plus/plugins/PgMutationCreatePlugin.js.map +1 -1
- package/node8plus/plugins/PgMutationPayloadEdgePlugin.js +2 -2
- package/node8plus/plugins/PgMutationPayloadEdgePlugin.js.flow +8 -2
- package/node8plus/plugins/PgMutationPayloadEdgePlugin.js.map +1 -1
- package/node8plus/plugins/PgMutationUpdateDeletePlugin.js +11 -11
- package/node8plus/plugins/PgMutationUpdateDeletePlugin.js.flow +40 -11
- package/node8plus/plugins/PgMutationUpdateDeletePlugin.js.map +1 -1
- package/node8plus/plugins/PgRecordFunctionConnectionPlugin.js +6 -6
- package/node8plus/plugins/PgRecordFunctionConnectionPlugin.js.flow +24 -6
- package/node8plus/plugins/PgRecordFunctionConnectionPlugin.js.map +1 -1
- package/node8plus/plugins/PgRecordReturnTypesPlugin.js +1 -1
- package/node8plus/plugins/PgRecordReturnTypesPlugin.js.flow +6 -3
- package/node8plus/plugins/PgRecordReturnTypesPlugin.js.map +1 -1
- package/node8plus/plugins/PgRowNode.js +2 -2
- package/node8plus/plugins/PgRowNode.js.flow +8 -2
- package/node8plus/plugins/PgRowNode.js.map +1 -1
- package/node8plus/plugins/PgScalarFunctionConnectionPlugin.js +6 -6
- package/node8plus/plugins/PgScalarFunctionConnectionPlugin.js.flow +24 -6
- package/node8plus/plugins/PgScalarFunctionConnectionPlugin.js.map +1 -1
- package/node8plus/plugins/PgTablesPlugin.js +13 -13
- package/node8plus/plugins/PgTablesPlugin.js.flow +56 -20
- package/node8plus/plugins/PgTablesPlugin.js.map +1 -1
- package/node8plus/plugins/PgTypesPlugin.js +62 -78
- package/node8plus/plugins/PgTypesPlugin.js.flow +193 -76
- package/node8plus/plugins/PgTypesPlugin.js.map +1 -1
- package/node8plus/plugins/makeProcField.js +3 -3
- package/node8plus/plugins/makeProcField.js.flow +16 -7
- package/node8plus/plugins/makeProcField.js.map +1 -1
- package/node8plus/plugins/viaTemporaryTable.js +1 -1
- package/node8plus/plugins/viaTemporaryTable.js.flow +8 -4
- package/node8plus/plugins/viaTemporaryTable.js.map +1 -1
- package/node8plus/postgresInterval.js +12 -33
- package/node8plus/postgresInterval.js.flow +22 -51
- package/node8plus/postgresInterval.js.map +1 -1
- package/package.json +9 -9
- package/res/watch-fixtures.sql +1 -1
|
@@ -171,7 +171,7 @@ function smartCommentConstraints(introspectionResults) {
|
|
|
171
171
|
|
|
172
172
|
if (klass.tags.unique) {
|
|
173
173
|
if (Array.isArray(klass.tags.unique)) {
|
|
174
|
-
klass.tags.unique.forEach(key => addKey(key
|
|
174
|
+
klass.tags.unique.forEach(key => addKey(key));
|
|
175
175
|
} else {
|
|
176
176
|
addKey(klass.tags.unique);
|
|
177
177
|
}
|
|
@@ -256,6 +256,142 @@ function smartCommentConstraints(introspectionResults) {
|
|
|
256
256
|
}
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
|
+
|
|
260
|
+
function isEnumConstraint(klass, con, isEnumTable) {
|
|
261
|
+
if (con.classId === klass.id) {
|
|
262
|
+
const isPrimaryKey = con.type === "p";
|
|
263
|
+
const isUniqueConstraint = con.type === "u";
|
|
264
|
+
|
|
265
|
+
if (isPrimaryKey || isUniqueConstraint) {
|
|
266
|
+
const isExplicitEnumConstraint = con.tags.enum === true || typeof con.tags.enum === "string";
|
|
267
|
+
const isPrimaryKeyOfEnumTableConstraint = con.type === "p" && isEnumTable;
|
|
268
|
+
|
|
269
|
+
if (isExplicitEnumConstraint || isPrimaryKeyOfEnumTableConstraint) {
|
|
270
|
+
const hasExactlyOneColumn = con.keyAttributeNums.length === 1;
|
|
271
|
+
|
|
272
|
+
if (!hasExactlyOneColumn) {
|
|
273
|
+
throw new Error(`Enum table "${klass.namespaceName}"."${klass.name}" enum constraint '${con.name}' is composite; it should have exactly one column (found: ${con.keyAttributeNums.length})`);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function enumTables(introspectionResults) {
|
|
285
|
+
introspectionResults.class.map(async klass => {
|
|
286
|
+
const isEnumTable = klass.tags.enum === true || typeof klass.tags.enum === "string";
|
|
287
|
+
|
|
288
|
+
if (isEnumTable) {
|
|
289
|
+
// Prevent the table being recognised as a table
|
|
290
|
+
// eslint-disable-next-line require-atomic-updates
|
|
291
|
+
klass.tags.omit = true; // eslint-disable-next-line require-atomic-updates
|
|
292
|
+
|
|
293
|
+
klass.isSelectable = false; // eslint-disable-next-line require-atomic-updates
|
|
294
|
+
|
|
295
|
+
klass.isInsertable = false; // eslint-disable-next-line require-atomic-updates
|
|
296
|
+
|
|
297
|
+
klass.isUpdatable = false; // eslint-disable-next-line require-atomic-updates
|
|
298
|
+
|
|
299
|
+
klass.isDeletable = false;
|
|
300
|
+
} // By this point, even views should have "fake" constraints we can use
|
|
301
|
+
// (e.g. `@primaryKey`)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
const enumConstraints = introspectionResults.constraint.filter(con => isEnumConstraint(klass, con, isEnumTable)); // Get all the columns
|
|
305
|
+
|
|
306
|
+
const enumTableColumns = introspectionResults.attribute.filter(attr => attr.classId === klass.id); // Get description column
|
|
307
|
+
|
|
308
|
+
const descriptionColumn = enumTableColumns.find(attr => attr.name === "description" || attr.tags.enumDescription);
|
|
309
|
+
const allData = klass._internalEnumData || [];
|
|
310
|
+
enumConstraints.forEach(constraint => {
|
|
311
|
+
const col = enumTableColumns.find(col => col.num === constraint.keyAttributeNums[0]);
|
|
312
|
+
|
|
313
|
+
if (!col) {
|
|
314
|
+
// Should never happen
|
|
315
|
+
throw new Error("Graphile Engine error - could not find column for enum constraint");
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const data = allData.filter(row => row[col.name] != null);
|
|
319
|
+
|
|
320
|
+
if (data.length < 1) {
|
|
321
|
+
throw new Error(`Enum table "${klass.namespaceName}"."${klass.name}" contains no entries for enum constraint '${constraint.name}'.`);
|
|
322
|
+
} // Create fake enum type
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
const constraintIdent = constraint.type === "p" ? "" : `_${constraint.name}`;
|
|
326
|
+
const enumTypeArray = {
|
|
327
|
+
kind: "type",
|
|
328
|
+
isFake: true,
|
|
329
|
+
id: `FAKE_ENUM_${klass.namespaceName}_${klass.name}${constraintIdent}_list`,
|
|
330
|
+
name: `_${klass.name}${constraintIdent}`,
|
|
331
|
+
description: null,
|
|
332
|
+
tags: {},
|
|
333
|
+
namespaceId: klass.namespaceId,
|
|
334
|
+
namespaceName: klass.namespaceName,
|
|
335
|
+
type: "b",
|
|
336
|
+
category: "A",
|
|
337
|
+
domainIsNotNull: null,
|
|
338
|
+
arrayItemTypeId: null,
|
|
339
|
+
typeLength: -1,
|
|
340
|
+
isPgArray: true,
|
|
341
|
+
classId: null,
|
|
342
|
+
domainBaseTypeId: null,
|
|
343
|
+
domainTypeModifier: null,
|
|
344
|
+
domainHasDefault: false,
|
|
345
|
+
enumVariants: null,
|
|
346
|
+
enumDescriptions: null,
|
|
347
|
+
rangeSubTypeId: null
|
|
348
|
+
};
|
|
349
|
+
const enumType = {
|
|
350
|
+
kind: "type",
|
|
351
|
+
isFake: true,
|
|
352
|
+
id: `FAKE_ENUM_${klass.namespaceName}_${klass.name}${constraintIdent}`,
|
|
353
|
+
name: `${klass.name}${constraintIdent}`,
|
|
354
|
+
description: klass.description,
|
|
355
|
+
tags: { ...klass.tags,
|
|
356
|
+
...constraint.tags
|
|
357
|
+
},
|
|
358
|
+
namespaceId: klass.namespaceId,
|
|
359
|
+
namespaceName: klass.namespaceName,
|
|
360
|
+
type: "e",
|
|
361
|
+
category: "E",
|
|
362
|
+
domainIsNotNull: null,
|
|
363
|
+
arrayItemTypeId: enumTypeArray.id,
|
|
364
|
+
typeLength: 4,
|
|
365
|
+
// ???
|
|
366
|
+
isPgArray: false,
|
|
367
|
+
classId: null,
|
|
368
|
+
domainBaseTypeId: null,
|
|
369
|
+
domainTypeModifier: null,
|
|
370
|
+
domainHasDefault: false,
|
|
371
|
+
enumVariants: data.map(r => r[col.name]),
|
|
372
|
+
enumDescriptions: descriptionColumn ? data.map(r => r[descriptionColumn.name]) : null,
|
|
373
|
+
// TODO: enumDescriptions
|
|
374
|
+
rangeSubTypeId: null
|
|
375
|
+
};
|
|
376
|
+
introspectionResults.type.push(enumType, enumTypeArray);
|
|
377
|
+
introspectionResults.typeById[enumType.id] = enumType;
|
|
378
|
+
introspectionResults.typeById[enumTypeArray.id] = enumTypeArray; // Change type of all attributes that reference this table to
|
|
379
|
+
// reference this enum type
|
|
380
|
+
|
|
381
|
+
introspectionResults.constraint.forEach(c => {
|
|
382
|
+
if (c.type === "f" && c.foreignClassId === klass.id && c.foreignKeyAttributeNums.length === 1 && c.foreignKeyAttributeNums[0] === col.num) {
|
|
383
|
+
// Get the attribute
|
|
384
|
+
const fkattr = introspectionResults.attribute.find(attr => attr.classId === c.classId && attr.num === c.keyAttributeNums[0]);
|
|
385
|
+
|
|
386
|
+
if (fkattr) {
|
|
387
|
+
// Override the detected type to pretend to be our enum
|
|
388
|
+
fkattr.typeId = enumType.id;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
}
|
|
259
395
|
/* The argument to this must not contain cyclic references! */
|
|
260
396
|
|
|
261
397
|
|
|
@@ -340,74 +476,29 @@ var PgIntrospectionPlugin = async function PgIntrospectionPlugin(builder, {
|
|
|
340
476
|
const extensionConfigurationClassIds = (0, _flatMap.default)(result.extension, e => e.configurationClassIds);
|
|
341
477
|
result.class.forEach(klass => {
|
|
342
478
|
klass.isExtensionConfigurationTable = extensionConfigurationClassIds.indexOf(klass.id) >= 0;
|
|
343
|
-
});
|
|
344
|
-
await Promise.all(result.class.map(async klass => {
|
|
345
|
-
const isEnumTable = klass.tags.enum === true || typeof klass.tags.enum === "string";
|
|
346
|
-
|
|
347
|
-
if (isEnumTable) {
|
|
348
|
-
// Prevent the table being recognised as a table
|
|
349
|
-
// eslint-disable-next-line require-atomic-updates
|
|
350
|
-
klass.tags.omit = true; // eslint-disable-next-line require-atomic-updates
|
|
351
|
-
|
|
352
|
-
klass.isSelectable = false; // eslint-disable-next-line require-atomic-updates
|
|
353
|
-
|
|
354
|
-
klass.isInsertable = false; // eslint-disable-next-line require-atomic-updates
|
|
355
|
-
|
|
356
|
-
klass.isUpdatable = false; // eslint-disable-next-line require-atomic-updates
|
|
479
|
+
}); // Assert the columns are text
|
|
357
480
|
|
|
358
|
-
|
|
481
|
+
const VARCHAR_ID = "1043";
|
|
482
|
+
const TEXT_ID = "25";
|
|
483
|
+
const CHAR_ID = "18";
|
|
484
|
+
const BPCHAR_ID = "1042";
|
|
485
|
+
const VALID_TYPE_IDS = [VARCHAR_ID, TEXT_ID, CHAR_ID, BPCHAR_ID];
|
|
486
|
+
await Promise.all(result.class.map(async klass => {
|
|
487
|
+
if (!schemas.includes(klass.namespaceName)) {
|
|
488
|
+
// Only support enums in public tables/views
|
|
489
|
+
return;
|
|
359
490
|
}
|
|
360
491
|
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
const isPrimaryKey = con.type === "p";
|
|
364
|
-
const isUniqueConstraint = con.type === "u";
|
|
365
|
-
|
|
366
|
-
if (isPrimaryKey || isUniqueConstraint) {
|
|
367
|
-
const isExplicitEnumConstraint = con.tags.enum === true || typeof con.tags.enum === "string";
|
|
368
|
-
const isPrimaryKeyOfEnumTableConstraint = con.type === "p" && isEnumTable;
|
|
369
|
-
|
|
370
|
-
if (isExplicitEnumConstraint || isPrimaryKeyOfEnumTableConstraint) {
|
|
371
|
-
const hasExactlyOneColumn = con.keyAttributeNums.length === 1;
|
|
372
|
-
|
|
373
|
-
if (!hasExactlyOneColumn) {
|
|
374
|
-
throw new Error(`Enum table "${klass.namespaceName}"."${klass.name}" enum constraint '${con.name}' is composite; it should have exactly one column (found: ${con.keyAttributeNums.length})`);
|
|
375
|
-
}
|
|
492
|
+
const isEnumTable = klass.tags.enum === true || typeof klass.tags.enum === "string"; // NOTE: this only matches on tables (not views, since they don't
|
|
493
|
+
// have constraints), which is why we repeat the isEnumTable check below.
|
|
376
494
|
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
return false;
|
|
383
|
-
});
|
|
495
|
+
const hasEnumConstraints = result.constraint.some(con => isEnumConstraint(klass, con, isEnumTable));
|
|
384
496
|
|
|
385
|
-
if (
|
|
386
|
-
// Get
|
|
387
|
-
const enumTableColumns = result.attribute.filter(attr => attr.classId === klass.id).sort((a, z) => a.num - z.num); //
|
|
497
|
+
if (isEnumTable || hasEnumConstraints) {
|
|
498
|
+
// Get the list of columns enums are defined for
|
|
499
|
+
const enumTableColumns = result.attribute.filter(attr => attr.classId === klass.id && VALID_TYPE_IDS.includes(attr.typeId)).sort((a, z) => a.num - z.num); // Load data from the table/view.
|
|
388
500
|
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
const VARCHAR_ID = "1043";
|
|
392
|
-
const TEXT_ID = "25";
|
|
393
|
-
const CHAR_ID = "18";
|
|
394
|
-
const BPCHAR_ID = "1042"; // Get the list of columns enums are defined for
|
|
395
|
-
|
|
396
|
-
const enumColumns = enumConstraints.map(con => {
|
|
397
|
-
const attr = enumTableColumns.find(attr => attr.num === con.keyAttributeNums[0]);
|
|
398
|
-
|
|
399
|
-
if (!attr) {
|
|
400
|
-
throw new Error(`Enum table "${klass.namespaceName}"."${klass.name}" enum column '${con.keyAttributeNums[0]}' couldn't be found`);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if (attr.typeId !== VARCHAR_ID && attr.typeId !== TEXT_ID && attr.typeId !== CHAR_ID && attr.typeId !== BPCHAR_ID) {
|
|
404
|
-
throw new Error(`Enum table "${klass.namespaceName}"."${klass.name}" enum column '${attr.name}' must be 'text', 'char' or 'varchar' (actual type OID: ${attr.typeId})`);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
return attr;
|
|
408
|
-
}); // Load data from the table.
|
|
409
|
-
|
|
410
|
-
const query = pgSql.compile(pgSql.fragment`select ${pgSql.join(enumColumns.map(col => pgSql.identifier(col.name)), ", ")}${descriptionColumn ? pgSql.fragment`, ${pgSql.identifier(descriptionColumn.name)}` : pgSql.blank} from ${pgSql.identifier(klass.namespaceName, klass.name)};`);
|
|
501
|
+
const query = pgSql.compile(pgSql.fragment`select ${pgSql.join(enumTableColumns.map(col => pgSql.identifier(col.name)), ", ")} from ${pgSql.identifier(klass.namespaceName, klass.name)};`);
|
|
411
502
|
let allData;
|
|
412
503
|
|
|
413
504
|
try {
|
|
@@ -425,7 +516,10 @@ var PgIntrospectionPlugin = async function PgIntrospectionPlugin(builder, {
|
|
|
425
516
|
} = await pgClient.query("select user;");
|
|
426
517
|
role = user;
|
|
427
518
|
} catch (e) {
|
|
428
|
-
/*
|
|
519
|
+
/*
|
|
520
|
+
* Ignore; this is likely a 25P02 (transaction aborted)
|
|
521
|
+
* error caused by the statement above failing.
|
|
522
|
+
*/
|
|
429
523
|
}
|
|
430
524
|
|
|
431
525
|
throw new Error(`Introspection could not read from enum table "${klass.namespaceName}"."${klass.name}", perhaps you need to grant access:
|
|
@@ -435,88 +529,9 @@ var PgIntrospectionPlugin = async function PgIntrospectionPlugin(builder, {
|
|
|
435
529
|
|
|
436
530
|
Original error: ${e.message}
|
|
437
531
|
`);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
enumConstraints.forEach(constraint => {
|
|
442
|
-
const col = enumColumns.find(col => col.num === constraint.keyAttributeNums[0]);
|
|
443
|
-
|
|
444
|
-
if (!col) {
|
|
445
|
-
// Should never happen
|
|
446
|
-
throw new Error("Graphile Engine error - could not find column for enum constraint");
|
|
447
|
-
}
|
|
532
|
+
}
|
|
448
533
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (data.length < 1) {
|
|
452
|
-
throw new Error(`Enum table "${klass.namespaceName}"."${klass.name}" contains no entries for enum constraint '${constraint.name}'.`);
|
|
453
|
-
} // Create fake enum type
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const constraintIdent = constraint.type === "p" ? "" : `_${constraint.name}`;
|
|
457
|
-
const enumTypeArray = {
|
|
458
|
-
kind: "type",
|
|
459
|
-
id: `FAKE_ENUM_${klass.namespaceName}_${klass.name}${constraintIdent}_list`,
|
|
460
|
-
name: `_${klass.name}${constraintIdent}`,
|
|
461
|
-
description: null,
|
|
462
|
-
tags: {},
|
|
463
|
-
namespaceId: klass.namespaceId,
|
|
464
|
-
namespaceName: klass.namespaceName,
|
|
465
|
-
type: "b",
|
|
466
|
-
category: "A",
|
|
467
|
-
domainIsNotNull: null,
|
|
468
|
-
arrayItemTypeId: null,
|
|
469
|
-
typeLength: -1,
|
|
470
|
-
isPgArray: true,
|
|
471
|
-
classId: null,
|
|
472
|
-
domainBaseTypeId: null,
|
|
473
|
-
domainTypeModifier: null,
|
|
474
|
-
domainHasDefault: false,
|
|
475
|
-
enumVariants: null,
|
|
476
|
-
enumDescriptions: null,
|
|
477
|
-
rangeSubTypeId: null
|
|
478
|
-
};
|
|
479
|
-
const enumType = {
|
|
480
|
-
kind: "type",
|
|
481
|
-
id: `FAKE_ENUM_${klass.namespaceName}_${klass.name}${constraintIdent}`,
|
|
482
|
-
name: `${klass.name}${constraintIdent}`,
|
|
483
|
-
description: klass.description,
|
|
484
|
-
tags: { ...klass.tags,
|
|
485
|
-
...constraint.tags
|
|
486
|
-
},
|
|
487
|
-
namespaceId: klass.namespaceId,
|
|
488
|
-
namespaceName: klass.namespaceName,
|
|
489
|
-
type: "e",
|
|
490
|
-
category: "E",
|
|
491
|
-
domainIsNotNull: null,
|
|
492
|
-
arrayItemTypeId: enumTypeArray.id,
|
|
493
|
-
typeLength: 4,
|
|
494
|
-
// ???
|
|
495
|
-
isPgArray: false,
|
|
496
|
-
classId: null,
|
|
497
|
-
domainBaseTypeId: null,
|
|
498
|
-
domainTypeModifier: null,
|
|
499
|
-
domainHasDefault: false,
|
|
500
|
-
enumVariants: data.map(r => r[col.name]),
|
|
501
|
-
enumDescriptions: descriptionColumn ? data.map(r => r[descriptionColumn.name]) : null,
|
|
502
|
-
// TODO: enumDescriptions
|
|
503
|
-
rangeSubTypeId: null
|
|
504
|
-
};
|
|
505
|
-
result.type.push(enumType, enumTypeArray); // Change type of all attributes that reference this table to
|
|
506
|
-
// reference this enum type
|
|
507
|
-
|
|
508
|
-
result.constraint.forEach(c => {
|
|
509
|
-
if (c.type === "f" && c.foreignClassId === klass.id && c.foreignKeyAttributeNums.length === 1 && c.foreignKeyAttributeNums[0] === col.num) {
|
|
510
|
-
// Get the attribute
|
|
511
|
-
const fkattr = result.attribute.find(attr => attr.classId === c.classId && attr.num === c.keyAttributeNums[0]);
|
|
512
|
-
|
|
513
|
-
if (fkattr) {
|
|
514
|
-
// Override the detected type to pretend to be our enum
|
|
515
|
-
fkattr.typeId = enumType.id;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
});
|
|
519
|
-
});
|
|
534
|
+
klass._internalEnumData = allData;
|
|
520
535
|
}
|
|
521
536
|
}));
|
|
522
537
|
["namespace", "class", "attribute", "type", "constraint", "procedure", "extension", "index"].forEach(k => {
|
|
@@ -586,7 +601,7 @@ Original error: ${e.message}
|
|
|
586
601
|
return;
|
|
587
602
|
}
|
|
588
603
|
|
|
589
|
-
throw new Error(`Could not look up '${newAttr}' by '${lookupAttr}' on '${JSON.stringify(entry)}'`);
|
|
604
|
+
throw new Error(`Could not look up '${newAttr}' by '${lookupAttr}' (= '${key}') on '${JSON.stringify(entry)}'`);
|
|
590
605
|
}
|
|
591
606
|
|
|
592
607
|
entry[newAttr] = result;
|
|
@@ -595,7 +610,7 @@ Original error: ${e.message}
|
|
|
595
610
|
};
|
|
596
611
|
|
|
597
612
|
const augment = introspectionResults => {
|
|
598
|
-
[pgAugmentIntrospectionResults, smartCommentConstraints].forEach(fn => fn ? fn(introspectionResults) : null);
|
|
613
|
+
[pgAugmentIntrospectionResults, smartCommentConstraints, enumTables].forEach(fn => fn ? fn(introspectionResults) : null);
|
|
599
614
|
};
|
|
600
615
|
|
|
601
616
|
augment(introspectionResultsByKind);
|
|
@@ -754,9 +769,7 @@ Original error: ${e.message}
|
|
|
754
769
|
}
|
|
755
770
|
|
|
756
771
|
_handleClientError(e) {
|
|
757
|
-
|
|
758
|
-
this.client = null;
|
|
759
|
-
this._reallyReleaseClient = null;
|
|
772
|
+
this._releaseClient(false);
|
|
760
773
|
|
|
761
774
|
this._reconnect(e);
|
|
762
775
|
}
|
|
@@ -816,28 +829,38 @@ Original error: ${e.message}
|
|
|
816
829
|
|
|
817
830
|
async stop() {
|
|
818
831
|
this.stopped = true;
|
|
832
|
+
|
|
833
|
+
this._handleChange.cancel();
|
|
834
|
+
|
|
819
835
|
await this._releaseClient();
|
|
820
836
|
}
|
|
837
|
+
/**
|
|
838
|
+
* Only pass `false` to this function if you know the client is going to be
|
|
839
|
+
* terminated; otherwise we risk leaving listeners running.
|
|
840
|
+
*/
|
|
821
841
|
|
|
822
|
-
async _releaseClient() {
|
|
823
|
-
// $FlowFixMe
|
|
824
|
-
this._handleChange.cancel();
|
|
825
842
|
|
|
843
|
+
async _releaseClient(clientIsStillViable = true) {
|
|
844
|
+
// $FlowFixMe
|
|
826
845
|
const pgClient = this.client;
|
|
827
846
|
const reallyReleaseClient = this._reallyReleaseClient;
|
|
828
847
|
this.client = null;
|
|
829
848
|
this._reallyReleaseClient = null;
|
|
830
849
|
|
|
831
850
|
if (pgClient) {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
851
|
+
// Don't attempt to run a query after a client has errored.
|
|
852
|
+
if (clientIsStillViable) {
|
|
853
|
+
pgClient.query("unlisten postgraphile_watch").catch(e => {
|
|
854
|
+
debug(`Error occurred trying to unlisten watch: ${e}`);
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
|
|
835
858
|
pgClient.removeListener("notification", this._listener);
|
|
836
859
|
pgClient.removeListener("error", this._handleClientError);
|
|
860
|
+
}
|
|
837
861
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
}
|
|
862
|
+
if (reallyReleaseClient) {
|
|
863
|
+
await reallyReleaseClient();
|
|
841
864
|
}
|
|
842
865
|
}
|
|
843
866
|
|