@intentius/chant-lexicon-sql 0.124.49 → 0.124.51
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/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/postgres/live/catalog-kinds.d.ts.map +1 -1
- package/dist/postgres/live/catalog-kinds.js +8 -6
- package/dist/postgres/live/catalog.d.ts.map +1 -1
- package/dist/postgres/live/catalog.js +2 -2
- package/dist/postgres/live/undeclarable.js +1 -1
- package/package.json +2 -2
- package/src/postgres/live/catalog-kinds.ts +7 -6
- package/src/postgres/live/catalog.ts +2 -2
- package/src/postgres/live/helper-aliases.test.ts +34 -0
- package/src/postgres/live/undeclarable.ts +1 -1
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "9928e70ad17be8df0440de2a6f27dc97f90ab1a66126192e4a0ecd798c4a2fcd",
|
|
5
5
|
"meta.json": "2a75a38ea0fb186f27a59d6b8401d7af0809db5e471769f0259f7c1a4292b858",
|
|
6
6
|
"types/index.d.ts": "0286ebb367773e84c76818b0f69cb14cff8328fd2f8c65ed87563c8d5815458c",
|
|
7
7
|
"rules/postgres-templates.ts": "cbbe8b3c3531300ef5f17d596bf9403343d9fde019961436b6af0cdc66e4064a",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"rules/sqlpg125.ts": "cc7411c57c525613dc720ba00e986bbc4e5a84b8b0bcfa7a6ce0d058f039f025",
|
|
81
81
|
"rules/sqlpg126.ts": "d57b82a5842273876510131d67bf4418cbd61eff821e245edebc644dafd502bb"
|
|
82
82
|
},
|
|
83
|
-
"composite": "
|
|
83
|
+
"composite": "12c4938cc7cd5e1a38236a460468faa2954a24072c71fe16040ea81aa418301c"
|
|
84
84
|
}
|
package/dist/manifest.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-kinds.d.ts","sourceRoot":"","sources":["../../../src/postgres/live/catalog-kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAA+B,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog-kinds.d.ts","sourceRoot":"","sources":["../../../src/postgres/live/catalog-kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAA+B,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AA4C7F,4GAA4G;AAC5G,wBAAsB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA0EvG;AAED,kFAAkF;AAClF,wBAAsB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAuCxG;AAID,gFAAgF;AAChF,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA8H1G;AAMD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAwCvG;AAkBD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA2E3G;AA0KD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAcpG"}
|
|
@@ -33,13 +33,15 @@ function commentOn(what, comment) {
|
|
|
33
33
|
const own = stripMarker(c);
|
|
34
34
|
return own === "" ? [] : [`COMMENT ON ${what} IS ${literal(own)}`];
|
|
35
35
|
}
|
|
36
|
-
const notInternal = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
36
|
+
const notInternal = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'i')`;
|
|
37
37
|
/** What depends on an object of catalog `catalog` (a normal dependency), as the server describes each. */
|
|
38
|
-
const dependentsOf = (catalog, oid) =>
|
|
39
|
-
|
|
38
|
+
const dependentsOf = (catalog, oid) =>
|
|
39
|
+
// `dep_`, not `d`: a caller's own alias (the text search dictionary query's `d`) would otherwise shadow it.
|
|
40
|
+
`ARRAY(SELECT pg_catalog.pg_describe_object(dep_.classid, dep_.objid, dep_.objsubid) FROM pg_catalog.pg_depend dep_
|
|
41
|
+
WHERE dep_.refclassid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.refobjid = ${oid} AND dep_.deptype = 'n' ORDER BY 1)`;
|
|
40
42
|
/** A collation's name as a clause: a `pg_catalog` one bare. */
|
|
41
|
-
const collationName = (oid) => `(SELECT CASE WHEN
|
|
42
|
-
`FROM pg_catalog.pg_collation
|
|
43
|
+
const collationName = (oid) => `(SELECT CASE WHEN colln_.nspname = 'pg_catalog' THEN pg_catalog.quote_ident(coll_.collname) ELSE pg_catalog.quote_ident(colln_.nspname) || '.' || pg_catalog.quote_ident(coll_.collname) END ` +
|
|
44
|
+
`FROM pg_catalog.pg_collation coll_ JOIN pg_catalog.pg_namespace colln_ ON colln_.oid = coll_.collnamespace WHERE coll_.oid = ${oid})`;
|
|
43
45
|
/** A function named by a `regproc` column, or nothing for 0 (which `regproc` prints as `-`). */
|
|
44
46
|
const proc = (column) => `NULLIF(${column}::text, '-')`;
|
|
45
47
|
const dependents = (r) => {
|
|
@@ -301,7 +303,7 @@ export async function readRoutineKinds(client, scope) {
|
|
|
301
303
|
return out;
|
|
302
304
|
}
|
|
303
305
|
/** An operator named by another's COMMUTATOR or NEGATOR, as `OPERATOR(schema.symbol)`. */
|
|
304
|
-
const operatorRef = (column) => `(SELECT 'OPERATOR(' || pg_catalog.quote_ident(
|
|
306
|
+
const operatorRef = (column) => `(SELECT 'OPERATOR(' || pg_catalog.quote_ident(oprn_.nspname) || '.' || opr_.oprname || ')' FROM pg_catalog.pg_operator opr_ JOIN pg_catalog.pg_namespace oprn_ ON oprn_.oid = opr_.oprnamespace WHERE opr_.oid = ${column})`;
|
|
305
307
|
/**
|
|
306
308
|
* Operators: the ones a schema defines, not the server's own (oids below the
|
|
307
309
|
* first normal object id) or an extension's. Identified by name and operand
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/postgres/live/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAKjF,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,iEAAiE;AACjE,eAAO,MAAM,cAAc,UAAmD,CAAC;AAE/E,gHAAgH;AAChH,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,kBAAkB,CAAC;IACzB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uIAAuI;IACvI,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iIAAiI;IACjI,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oHAAoH;IACpH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,gHAAgH;IAChH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2GAA2G;IAC3G,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAqBD,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAM/F;AAED,yGAAyG;AACzG,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,EAAE,KAAK,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/postgres/live/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAKjF,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,iEAAiE;AACjE,eAAO,MAAM,cAAc,UAAmD,CAAC;AAE/E,gHAAgH;AAChH,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,kBAAkB,CAAC;IACzB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uIAAuI;IACvI,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iIAAiI;IACjI,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oHAAoH;IACpH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,gHAAgH;IAChH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2GAA2G;IAC3G,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAqBD,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAE,CAM/F;AAED,yGAAyG;AACzG,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,EAAE,KAAK,MAAM,KAAG,MACwG,CAAC;AAa1K,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAQD,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,CAKtH;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CAa9E;AAcD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,GAAE,WAAgB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAkgB7G;AAED,+HAA+H;AAC/H,eAAO,MAAM,OAAO,GAAI,MAAM,MAAM,EAAE,QAAQ,MAAM,GAAG,SAAS,EAAE,MAAM,MAAM,EAAE,YAAY,MAAM,KAAG,MAA6D,CAAC;AAEnK;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,QAAQ,EAAE,gBAAgB,GAAG,SAAS,GAAG,YAAY,EAAE,CAW1H"}
|
|
@@ -80,9 +80,9 @@ export function scopeSql(column, scope) {
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
/** `NOT <object is owned by an extension>`, for an object of catalog `catalog` with oid column `oid`. */
|
|
83
|
-
export const notExtensionOwned = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
83
|
+
export const notExtensionOwned = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'e')`;
|
|
84
84
|
/** `NOT <object is part of another>` (`pg_depend.deptype = 'i'`): a range type's constructor functions, its multirange cast. */
|
|
85
|
-
const notInternal = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
85
|
+
const notInternal = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'i')`;
|
|
86
86
|
/** A collation name as a clause, `pg_catalog` names unqualified. */
|
|
87
87
|
const COLLATION_NAME = (oid) => `(SELECT CASE WHEN cn.nspname = 'pg_catalog' THEN pg_catalog.quote_ident(co.collname) ELSE pg_catalog.quote_ident(cn.nspname) || '.' || pg_catalog.quote_ident(co.collname) END ` +
|
|
88
88
|
`FROM pg_catalog.pg_collation co JOIN pg_catalog.pg_namespace cn ON cn.oid = co.collnamespace WHERE co.oid = ${oid})`;
|
|
@@ -23,7 +23,7 @@ import { KIND_COVERAGE } from "../../coverage.js";
|
|
|
23
23
|
const FIRST_USER_OID = 16384;
|
|
24
24
|
const C = 'COLLATE "C"';
|
|
25
25
|
/** Not part of another object (`pg_depend.deptype = 'i'`): the multirange cast a range type makes for itself is the range type's. */
|
|
26
|
-
const notInternal = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
26
|
+
const notInternal = (catalog, oid) => `NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'i')`;
|
|
27
27
|
const ns = (alias, column) => `JOIN pg_catalog.pg_namespace ${alias} ON ${alias}.oid = ${column}`;
|
|
28
28
|
const args = (oid) => `'(' || pg_catalog.replace(pg_catalog.oidvectortypes(${oid}), ', ', ',') || ')'`;
|
|
29
29
|
/** A probe for objects of a catalog in a schema, the catalog aliased `x`; `name` is the name expression. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-sql",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.51",
|
|
4
4
|
"description": "SQL lexicon for chant — database schema as typed declarations, one dialect at a time; ClickHouse first, with types read from a pinned server's catalog",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -72,6 +72,6 @@
|
|
|
72
72
|
"typescript": "^5.9.3"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"@intentius/chant": "^0.124.
|
|
75
|
+
"@intentius/chant": "^0.124.51"
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -40,17 +40,18 @@ function commentOn(what: string, comment: unknown): string[] {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const notInternal = (catalog: string, oid: string): string =>
|
|
43
|
-
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
43
|
+
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'i')`;
|
|
44
44
|
|
|
45
45
|
/** What depends on an object of catalog `catalog` (a normal dependency), as the server describes each. */
|
|
46
46
|
const dependentsOf = (catalog: string, oid: string): string =>
|
|
47
|
-
`
|
|
48
|
-
|
|
47
|
+
// `dep_`, not `d`: a caller's own alias (the text search dictionary query's `d`) would otherwise shadow it.
|
|
48
|
+
`ARRAY(SELECT pg_catalog.pg_describe_object(dep_.classid, dep_.objid, dep_.objsubid) FROM pg_catalog.pg_depend dep_
|
|
49
|
+
WHERE dep_.refclassid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.refobjid = ${oid} AND dep_.deptype = 'n' ORDER BY 1)`;
|
|
49
50
|
|
|
50
51
|
/** A collation's name as a clause: a `pg_catalog` one bare. */
|
|
51
52
|
const collationName = (oid: string): string =>
|
|
52
|
-
`(SELECT CASE WHEN
|
|
53
|
-
`FROM pg_catalog.pg_collation
|
|
53
|
+
`(SELECT CASE WHEN colln_.nspname = 'pg_catalog' THEN pg_catalog.quote_ident(coll_.collname) ELSE pg_catalog.quote_ident(colln_.nspname) || '.' || pg_catalog.quote_ident(coll_.collname) END ` +
|
|
54
|
+
`FROM pg_catalog.pg_collation coll_ JOIN pg_catalog.pg_namespace colln_ ON colln_.oid = coll_.collnamespace WHERE coll_.oid = ${oid})`;
|
|
54
55
|
|
|
55
56
|
/** A function named by a `regproc` column, or nothing for 0 (which `regproc` prints as `-`). */
|
|
56
57
|
const proc = (column: string): string => `NULLIF(${column}::text, '-')`;
|
|
@@ -314,7 +315,7 @@ export async function readRoutineKinds(client: PostgresClient, scope: SchemaScop
|
|
|
314
315
|
|
|
315
316
|
/** An operator named by another's COMMUTATOR or NEGATOR, as `OPERATOR(schema.symbol)`. */
|
|
316
317
|
const operatorRef = (column: string): string =>
|
|
317
|
-
`(SELECT 'OPERATOR(' || pg_catalog.quote_ident(
|
|
318
|
+
`(SELECT 'OPERATOR(' || pg_catalog.quote_ident(oprn_.nspname) || '.' || opr_.oprname || ')' FROM pg_catalog.pg_operator opr_ JOIN pg_catalog.pg_namespace oprn_ ON oprn_.oid = opr_.oprnamespace WHERE opr_.oid = ${column})`;
|
|
318
319
|
|
|
319
320
|
/**
|
|
320
321
|
* Operators: the ones a schema defines, not the server's own (oids below the
|
|
@@ -132,11 +132,11 @@ export function scopeSql(column: string, scope: SchemaScope): { sql: string; par
|
|
|
132
132
|
|
|
133
133
|
/** `NOT <object is owned by an extension>`, for an object of catalog `catalog` with oid column `oid`. */
|
|
134
134
|
export const notExtensionOwned = (catalog: string, oid: string): string =>
|
|
135
|
-
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
135
|
+
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'e')`;
|
|
136
136
|
|
|
137
137
|
/** `NOT <object is part of another>` (`pg_depend.deptype = 'i'`): a range type's constructor functions, its multirange cast. */
|
|
138
138
|
const notInternal = (catalog: string, oid: string): string =>
|
|
139
|
-
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
139
|
+
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'i')`;
|
|
140
140
|
|
|
141
141
|
/** A collation name as a clause, `pg_catalog` names unqualified. */
|
|
142
142
|
const COLLATION_NAME = (oid: string) =>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The catalog read's SQL helpers embed subqueries in their callers' queries,
|
|
3
|
+
* so an alias a helper declares shadows the caller's alias of the same name.
|
|
4
|
+
* A text search dictionary query aliased `pg_ts_dict` as `d` while
|
|
5
|
+
* `notExtensionOwned` and `dependentsOf` aliased `pg_depend` as `d`, and the
|
|
6
|
+
* whole live read failed on every server with "column d.oid does not exist"
|
|
7
|
+
* (chant 0.124.49 and 0.124.50). Unit tests run no server, so this reads the
|
|
8
|
+
* helpers' source instead: a helper's aliases end in `_`, which no caller's
|
|
9
|
+
* one- to three-letter alias does.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { describe, expect, test } from "vitest";
|
|
15
|
+
|
|
16
|
+
const DIR = import.meta.dirname;
|
|
17
|
+
const HELPER = /^(?:export )?const ([A-Za-z]+) = \(/;
|
|
18
|
+
const SHORT_ALIAS = /(?:FROM|JOIN) pg_catalog\.pg_[a-z_]+ ([a-z]{1,3})\b/g;
|
|
19
|
+
|
|
20
|
+
describe("the catalog read's SQL helpers", () => {
|
|
21
|
+
test("declare no alias a caller could shadow", () => {
|
|
22
|
+
const found: string[] = [];
|
|
23
|
+
for (const file of readdirSync(DIR).filter((f) => f.endsWith(".ts") && !f.endsWith(".test.ts"))) {
|
|
24
|
+
const lines = readFileSync(join(DIR, file), "utf-8").split("\n");
|
|
25
|
+
lines.forEach((line, i) => {
|
|
26
|
+
const helper = HELPER.exec(line);
|
|
27
|
+
if (!helper) return;
|
|
28
|
+
const body = lines.slice(i, i + 5).join("\n");
|
|
29
|
+
for (const m of body.matchAll(SHORT_ALIAS)) found.push(`${file}:${String(i + 1)} ${helper[1]} declares ${m[1]}`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
expect(found).toEqual([]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -39,7 +39,7 @@ const C = 'COLLATE "C"';
|
|
|
39
39
|
|
|
40
40
|
/** Not part of another object (`pg_depend.deptype = 'i'`): the multirange cast a range type makes for itself is the range type's. */
|
|
41
41
|
const notInternal = (catalog: string, oid: string) =>
|
|
42
|
-
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend
|
|
42
|
+
`NOT EXISTS (SELECT 1 FROM pg_catalog.pg_depend dep_ WHERE dep_.classid = 'pg_catalog.${catalog}'::pg_catalog.regclass AND dep_.objid = ${oid} AND dep_.deptype = 'i')`;
|
|
43
43
|
const ns = (alias: string, column: string) => `JOIN pg_catalog.pg_namespace ${alias} ON ${alias}.oid = ${column}`;
|
|
44
44
|
const args = (oid: string) => `'(' || pg_catalog.replace(pg_catalog.oidvectortypes(${oid}), ', ', ',') || ')'`;
|
|
45
45
|
|