neon 8.4.5 → 8.6.0
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 +18 -9
- package/dist/_chunks/{env-4WGRW2nw.js → env-BNm69Qh8.js} +2 -5
- package/dist/commands/config.js +11 -28
- package/dist/commands/dev.js +93 -27
- package/dist/commands/env.js +2 -3
- package/dist/commands/init.js +1 -2
- package/dist/commands/link.js +1 -1
- package/dist/commands/manifest.js +1 -3
- package/dist/commands/subscribe.js +16 -16
- package/dist/credential_io.js +1 -2
- package/dist/dev/env.js +1 -2
- package/dist/dev/runtime.js +8 -0
- package/dist/env_file.js +9 -1
- package/dist/index.js +1 -1
- package/dist/init/auth.js +1 -4
- package/dist/init/choices.js +21 -7
- package/dist/init/copy.js +21 -7
- package/dist/init/run.js +25 -16
- package/dist/plugins/run.js +2 -1
- package/dist/psql/command/cmd_io.js +1 -2
- package/dist/psql/command/cmd_pipeline.js +1 -2
- package/dist/psql/core/common.js +1 -2
- package/dist/psql/core/startup.js +1 -2
- package/dist/psql/index.js +1 -2
- package/dist/psql/types/index.js +1 -2
- package/dist/skills/catalog.js +5 -0
- package/dist/utils/hooks.js +0 -2
- package/dist/utils/staging.js +1 -14
- package/{LICENSE → dist/vendor/postgres-meta/LICENSE} +0 -1
- package/dist/vendor/postgres-meta/constants.js +14 -0
- package/dist/vendor/postgres-meta/lib/PostgresMeta.js +49 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaColumnPrivileges.js +85 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaColumns.js +235 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaConfig.js +16 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaExtensions.js +79 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaForeignTables.js +81 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaFunctions.js +173 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaIndexes.js +42 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaMaterializedViews.js +84 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaPolicies.js +120 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaPublications.js +193 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaRelationships.js +87 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaRoles.js +203 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaSchemas.js +105 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTablePrivileges.js +91 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTables.js +183 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTriggers.js +156 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaTypes.js +22 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaVersion.js +20 -0
- package/dist/vendor/postgres-meta/lib/PostgresMetaViews.js +83 -0
- package/dist/vendor/postgres-meta/lib/constants.js +8 -0
- package/dist/vendor/postgres-meta/lib/db.js +147 -0
- package/dist/vendor/postgres-meta/lib/generators.js +106 -0
- package/dist/vendor/postgres-meta/lib/helpers.js +26 -0
- package/dist/vendor/postgres-meta/lib/index.js +1 -0
- package/dist/vendor/postgres-meta/lib/sql/column_privileges.sql.js +154 -0
- package/dist/vendor/postgres-meta/lib/sql/columns.sql.js +123 -0
- package/dist/vendor/postgres-meta/lib/sql/common.js +1 -0
- package/dist/vendor/postgres-meta/lib/sql/config.sql.js +32 -0
- package/dist/vendor/postgres-meta/lib/sql/extensions.sql.js +20 -0
- package/dist/vendor/postgres-meta/lib/sql/foreign_tables.sql.js +20 -0
- package/dist/vendor/postgres-meta/lib/sql/functions.sql.js +141 -0
- package/dist/vendor/postgres-meta/lib/sql/indexes.sql.js +51 -0
- package/dist/vendor/postgres-meta/lib/sql/materialized_views.sql.js +21 -0
- package/dist/vendor/postgres-meta/lib/sql/policies.sql.js +53 -0
- package/dist/vendor/postgres-meta/lib/sql/publications.sql.js +46 -0
- package/dist/vendor/postgres-meta/lib/sql/roles.sql.js +40 -0
- package/dist/vendor/postgres-meta/lib/sql/schemas.sql.js +26 -0
- package/dist/vendor/postgres-meta/lib/sql/table.sql.js +109 -0
- package/dist/vendor/postgres-meta/lib/sql/table_privileges.sql.js +85 -0
- package/dist/vendor/postgres-meta/lib/sql/table_relationships.sql.js +52 -0
- package/dist/vendor/postgres-meta/lib/sql/triggers.sql.js +64 -0
- package/dist/vendor/postgres-meta/lib/sql/types.sql.js +65 -0
- package/dist/vendor/postgres-meta/lib/sql/version.sql.js +15 -0
- package/dist/vendor/postgres-meta/lib/sql/views.sql.js +22 -0
- package/dist/vendor/postgres-meta/lib/sql/views_key_dependencies.sql.js +198 -0
- package/dist/vendor/postgres-meta/lib/types.js +1 -0
- package/dist/vendor/postgres-meta/templates/typescript.js +608 -0
- package/package.json +12 -5
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import pg from "pg";
|
|
2
|
+
import { parse } from "postgres-array";
|
|
3
|
+
//#region src/vendor/postgres-meta/lib/db.ts
|
|
4
|
+
pg.types.setTypeParser(pg.types.builtins.INT8, (x) => {
|
|
5
|
+
const asNumber = Number(x);
|
|
6
|
+
if (Number.isSafeInteger(asNumber)) return asNumber;
|
|
7
|
+
else return x;
|
|
8
|
+
});
|
|
9
|
+
pg.types.setTypeParser(pg.types.builtins.DATE, (x) => x);
|
|
10
|
+
pg.types.setTypeParser(pg.types.builtins.INTERVAL, (x) => x);
|
|
11
|
+
pg.types.setTypeParser(pg.types.builtins.TIMESTAMP, (x) => x);
|
|
12
|
+
pg.types.setTypeParser(pg.types.builtins.TIMESTAMPTZ, (x) => x);
|
|
13
|
+
pg.types.setTypeParser(1115, parse);
|
|
14
|
+
pg.types.setTypeParser(1182, parse);
|
|
15
|
+
pg.types.setTypeParser(1185, parse);
|
|
16
|
+
pg.types.setTypeParser(600, (x) => x);
|
|
17
|
+
pg.types.setTypeParser(1017, (x) => x);
|
|
18
|
+
const poolerQueryHandleError = (pgpool, sql, parameters) => {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
let rejected = false;
|
|
21
|
+
const connectionErrorHandler = (err) => {
|
|
22
|
+
if (!rejected) setTimeout(() => {
|
|
23
|
+
rejected = true;
|
|
24
|
+
return reject(err);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
pgpool.once("error", connectionErrorHandler);
|
|
28
|
+
pgpool.query(sql, parameters).then((results) => {
|
|
29
|
+
if (!rejected) return resolve(results);
|
|
30
|
+
}).catch((err) => {
|
|
31
|
+
if (!rejected) {
|
|
32
|
+
rejected = true;
|
|
33
|
+
return reject(err);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const init = (config) => {
|
|
39
|
+
if (config.connectionString) {
|
|
40
|
+
const u = new URL(config.connectionString);
|
|
41
|
+
const sslmode = u.searchParams.get("sslmode");
|
|
42
|
+
u.searchParams.delete("sslmode");
|
|
43
|
+
u.searchParams.delete("sslca");
|
|
44
|
+
u.searchParams.delete("sslkey");
|
|
45
|
+
u.searchParams.delete("sslcert");
|
|
46
|
+
u.searchParams.delete("sslrootcert");
|
|
47
|
+
config.connectionString = u.toString();
|
|
48
|
+
if (sslmode === null) {} else if (sslmode === "disable") config.ssl = false;
|
|
49
|
+
else {
|
|
50
|
+
if (typeof config.ssl !== "object") config.ssl = {};
|
|
51
|
+
config.ssl.rejectUnauthorized = sslmode === "verify-full";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let pool = new pg.Pool(config);
|
|
55
|
+
return {
|
|
56
|
+
async query(sql, { statementQueryTimeout, parameters } = {}) {
|
|
57
|
+
const statementTimeoutQueryPrefix = statementQueryTimeout ? `SET statement_timeout='${statementQueryTimeout}s'; SET idle_session_timeout='${statementQueryTimeout}s';` : "";
|
|
58
|
+
const sqlWithStatementTimeout = `${statementTimeoutQueryPrefix}${sql}`;
|
|
59
|
+
try {
|
|
60
|
+
if (!pool) {
|
|
61
|
+
const transientPool = new pg.Pool(config);
|
|
62
|
+
let res = await poolerQueryHandleError(transientPool, sqlWithStatementTimeout, parameters);
|
|
63
|
+
if (Array.isArray(res)) res = res.reverse().find((x) => x.rows.length !== 0) ?? { rows: [] };
|
|
64
|
+
await transientPool.end();
|
|
65
|
+
return {
|
|
66
|
+
data: res.rows,
|
|
67
|
+
error: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
let res = await poolerQueryHandleError(pool, sqlWithStatementTimeout, parameters);
|
|
71
|
+
if (Array.isArray(res)) res = res.reverse().find((x) => x.rows.length !== 0) ?? { rows: [] };
|
|
72
|
+
return {
|
|
73
|
+
data: res.rows,
|
|
74
|
+
error: null
|
|
75
|
+
};
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error.constructor.name === "DatabaseError") {
|
|
78
|
+
let formattedError = "";
|
|
79
|
+
if (error.severity) formattedError += `${error.severity}: `;
|
|
80
|
+
if (error.code) formattedError += `${error.code}: `;
|
|
81
|
+
if (error.message) formattedError += error.message;
|
|
82
|
+
formattedError += "\n";
|
|
83
|
+
if (error.position) {
|
|
84
|
+
const position = Number(error.position) - 1 - statementTimeoutQueryPrefix.length;
|
|
85
|
+
error.position = `${position + 1}`;
|
|
86
|
+
let line = "";
|
|
87
|
+
let lineNumber = 0;
|
|
88
|
+
let lineOffset = 0;
|
|
89
|
+
const lines = sql.split("\n");
|
|
90
|
+
let currentOffset = 0;
|
|
91
|
+
for (let i = 0; i < lines.length; i++) {
|
|
92
|
+
if (currentOffset + lines[i].length > position) {
|
|
93
|
+
line = lines[i];
|
|
94
|
+
lineNumber = i + 1;
|
|
95
|
+
lineOffset = position - currentOffset;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
currentOffset += lines[i].length + 1;
|
|
99
|
+
}
|
|
100
|
+
formattedError += `LINE ${lineNumber}: ${line}\n${" ".repeat(5 + lineNumber.toString().length + 2 + lineOffset)}^\n`;
|
|
101
|
+
}
|
|
102
|
+
if (error.detail) formattedError += `DETAIL: ${error.detail}\n`;
|
|
103
|
+
if (error.hint) formattedError += `HINT: ${error.hint}\n`;
|
|
104
|
+
if (error.internalQuery) formattedError += `QUERY: ${error.internalQuery}\n`;
|
|
105
|
+
if (error.where) formattedError += `CONTEXT: ${error.where}\n`;
|
|
106
|
+
return {
|
|
107
|
+
data: null,
|
|
108
|
+
error: {
|
|
109
|
+
...error,
|
|
110
|
+
message: error.message,
|
|
111
|
+
formattedError
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
return {
|
|
117
|
+
data: null,
|
|
118
|
+
error: {
|
|
119
|
+
code: error.code,
|
|
120
|
+
message: error.message
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
} finally {
|
|
124
|
+
try {
|
|
125
|
+
await this.end.bind(this);
|
|
126
|
+
} catch (_endError) {
|
|
127
|
+
console.error("Failed to end the connection on error: ", {
|
|
128
|
+
this: this,
|
|
129
|
+
end: this.end
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
async end() {
|
|
136
|
+
try {
|
|
137
|
+
const _pool = pool;
|
|
138
|
+
pool = null;
|
|
139
|
+
if (_pool) await _pool.end();
|
|
140
|
+
} catch (endError) {
|
|
141
|
+
console.error("Failed ending connection pool", endError);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
147
|
+
export { init };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/generators.ts
|
|
2
|
+
async function getGeneratorMetadata(pgMeta, filters = {
|
|
3
|
+
includedSchemas: [],
|
|
4
|
+
excludedSchemas: []
|
|
5
|
+
}) {
|
|
6
|
+
const includedSchemas = filters.includedSchemas ?? [];
|
|
7
|
+
const excludedSchemas = filters.excludedSchemas ?? [];
|
|
8
|
+
const { data: schemas, error: schemasError } = await pgMeta.schemas.list({
|
|
9
|
+
includeSystemSchemas: false,
|
|
10
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
11
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0
|
|
12
|
+
});
|
|
13
|
+
if (schemasError) return {
|
|
14
|
+
data: null,
|
|
15
|
+
error: schemasError
|
|
16
|
+
};
|
|
17
|
+
const { data: tables, error: tablesError } = await pgMeta.tables.list({
|
|
18
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
19
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
20
|
+
includeColumns: false
|
|
21
|
+
});
|
|
22
|
+
if (tablesError) return {
|
|
23
|
+
data: null,
|
|
24
|
+
error: tablesError
|
|
25
|
+
};
|
|
26
|
+
const { data: foreignTables, error: foreignTablesError } = await pgMeta.foreignTables.list({
|
|
27
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
28
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
29
|
+
includeColumns: false
|
|
30
|
+
});
|
|
31
|
+
if (foreignTablesError) return {
|
|
32
|
+
data: null,
|
|
33
|
+
error: foreignTablesError
|
|
34
|
+
};
|
|
35
|
+
const { data: views, error: viewsError } = await pgMeta.views.list({
|
|
36
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
37
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
38
|
+
includeColumns: false
|
|
39
|
+
});
|
|
40
|
+
if (viewsError) return {
|
|
41
|
+
data: null,
|
|
42
|
+
error: viewsError
|
|
43
|
+
};
|
|
44
|
+
const { data: materializedViews, error: materializedViewsError } = await pgMeta.materializedViews.list({
|
|
45
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
46
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
47
|
+
includeColumns: false
|
|
48
|
+
});
|
|
49
|
+
if (materializedViewsError) return {
|
|
50
|
+
data: null,
|
|
51
|
+
error: materializedViewsError
|
|
52
|
+
};
|
|
53
|
+
const { data: columns, error: columnsError } = await pgMeta.columns.list({
|
|
54
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
55
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
56
|
+
includeSystemSchemas: false
|
|
57
|
+
});
|
|
58
|
+
if (columnsError) return {
|
|
59
|
+
data: null,
|
|
60
|
+
error: columnsError
|
|
61
|
+
};
|
|
62
|
+
const { data: relationships, error: relationshipsError } = await pgMeta.relationships.list({
|
|
63
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
64
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
65
|
+
includeSystemSchemas: false
|
|
66
|
+
});
|
|
67
|
+
if (relationshipsError) return {
|
|
68
|
+
data: null,
|
|
69
|
+
error: relationshipsError
|
|
70
|
+
};
|
|
71
|
+
const { data: functions, error: functionsError } = await pgMeta.functions.list({
|
|
72
|
+
includedSchemas: includedSchemas.length > 0 ? includedSchemas : void 0,
|
|
73
|
+
excludedSchemas: excludedSchemas.length > 0 ? excludedSchemas : void 0,
|
|
74
|
+
includeSystemSchemas: false
|
|
75
|
+
});
|
|
76
|
+
if (functionsError) return {
|
|
77
|
+
data: null,
|
|
78
|
+
error: functionsError
|
|
79
|
+
};
|
|
80
|
+
const { data: types, error: typesError } = await pgMeta.types.list({
|
|
81
|
+
includeTableTypes: true,
|
|
82
|
+
includeArrayTypes: true,
|
|
83
|
+
includeSystemSchemas: true
|
|
84
|
+
});
|
|
85
|
+
if (typesError) return {
|
|
86
|
+
data: null,
|
|
87
|
+
error: typesError
|
|
88
|
+
};
|
|
89
|
+
await pgMeta.end();
|
|
90
|
+
return {
|
|
91
|
+
data: {
|
|
92
|
+
schemas: schemas.filter(({ name }) => !excludedSchemas.includes(name) && (includedSchemas.length === 0 || includedSchemas.includes(name))),
|
|
93
|
+
tables,
|
|
94
|
+
foreignTables,
|
|
95
|
+
views,
|
|
96
|
+
materializedViews,
|
|
97
|
+
columns,
|
|
98
|
+
relationships,
|
|
99
|
+
functions: functions.filter(({ return_type }) => !["trigger", "event_trigger"].includes(return_type)),
|
|
100
|
+
types
|
|
101
|
+
},
|
|
102
|
+
error: null
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { getGeneratorMetadata };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { literal } from "pg-format";
|
|
2
|
+
//#region src/vendor/postgres-meta/lib/helpers.ts
|
|
3
|
+
const coalesceRowsToArray = (source, filter) => {
|
|
4
|
+
return `
|
|
5
|
+
COALESCE(
|
|
6
|
+
(
|
|
7
|
+
SELECT
|
|
8
|
+
array_agg(row_to_json(${source})) FILTER (WHERE ${filter})
|
|
9
|
+
FROM
|
|
10
|
+
${source}
|
|
11
|
+
),
|
|
12
|
+
'{}'
|
|
13
|
+
) AS ${source}`;
|
|
14
|
+
};
|
|
15
|
+
const filterByList = (include, exclude, defaultExclude) => {
|
|
16
|
+
if (defaultExclude) exclude = defaultExclude.concat(exclude ?? []);
|
|
17
|
+
if (include?.length) return `IN (${include.map(literal).join(",")})`;
|
|
18
|
+
else if (exclude?.length) return `NOT IN (${exclude.map(literal).join(",")})`;
|
|
19
|
+
return "";
|
|
20
|
+
};
|
|
21
|
+
const filterByValue = (ids) => {
|
|
22
|
+
if (ids?.length) return `IN (${ids.map(literal).join(",")})`;
|
|
23
|
+
return "";
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { coalesceRowsToArray, filterByList, filterByValue };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PostgresMeta } from "./PostgresMeta.js";
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/column_privileges.sql.ts
|
|
2
|
+
const COLUMN_PRIVILEGES_SQL = (props) => `
|
|
3
|
+
-- Lists each column's privileges in the form of:
|
|
4
|
+
--
|
|
5
|
+
-- [
|
|
6
|
+
-- {
|
|
7
|
+
-- "column_id": "12345.1",
|
|
8
|
+
-- "relation_schema": "public",
|
|
9
|
+
-- "relation_name": "mytable",
|
|
10
|
+
-- "column_name": "mycolumn",
|
|
11
|
+
-- "privileges": [
|
|
12
|
+
-- {
|
|
13
|
+
-- "grantor": "postgres",
|
|
14
|
+
-- "grantee": "myrole",
|
|
15
|
+
-- "privilege_type": "SELECT",
|
|
16
|
+
-- "is_grantable": false
|
|
17
|
+
-- },
|
|
18
|
+
-- ...
|
|
19
|
+
-- ]
|
|
20
|
+
-- },
|
|
21
|
+
-- ...
|
|
22
|
+
-- ]
|
|
23
|
+
--
|
|
24
|
+
-- Modified from information_schema.column_privileges. We try to be as close as
|
|
25
|
+
-- possible to the view definition, obtained from:
|
|
26
|
+
--
|
|
27
|
+
-- select pg_get_viewdef('information_schema.column_privileges');
|
|
28
|
+
--
|
|
29
|
+
-- The main differences are:
|
|
30
|
+
-- - we include column privileges for materialized views
|
|
31
|
+
-- (reason for exclusion in information_schema.column_privileges:
|
|
32
|
+
-- https://www.postgresql.org/message-id/9136.1502740844%40sss.pgh.pa.us)
|
|
33
|
+
-- - we query a.attrelid and a.attnum to generate \`column_id\`
|
|
34
|
+
-- - \`table_catalog\` is omitted
|
|
35
|
+
-- - table_schema -> relation_schema, table_name -> relation_name
|
|
36
|
+
--
|
|
37
|
+
-- Column privileges are intertwined with table privileges in that table
|
|
38
|
+
-- privileges override column privileges. E.g. if we do:
|
|
39
|
+
--
|
|
40
|
+
-- grant all on mytable to myrole;
|
|
41
|
+
--
|
|
42
|
+
-- Then \`myrole\` is granted privileges for ALL columns. Likewise, if we do:
|
|
43
|
+
--
|
|
44
|
+
-- grant all (id) on mytable to myrole;
|
|
45
|
+
-- revoke all on mytable from myrole;
|
|
46
|
+
--
|
|
47
|
+
-- Then the grant on the \`id\` column is revoked.
|
|
48
|
+
--
|
|
49
|
+
-- This is unlike how grants for schemas and tables interact, where you need
|
|
50
|
+
-- privileges for BOTH the schema the table is in AND the table itself in order
|
|
51
|
+
-- to access the table.
|
|
52
|
+
|
|
53
|
+
select (x.attrelid || '.' || x.attnum) as column_id,
|
|
54
|
+
nc.nspname as relation_schema,
|
|
55
|
+
x.relname as relation_name,
|
|
56
|
+
x.attname as column_name,
|
|
57
|
+
coalesce(
|
|
58
|
+
jsonb_agg(
|
|
59
|
+
jsonb_build_object(
|
|
60
|
+
'grantor', u_grantor.rolname,
|
|
61
|
+
'grantee', grantee.rolname,
|
|
62
|
+
'privilege_type', x.prtype,
|
|
63
|
+
'is_grantable', x.grantable
|
|
64
|
+
)
|
|
65
|
+
),
|
|
66
|
+
'[]'
|
|
67
|
+
) as privileges
|
|
68
|
+
from
|
|
69
|
+
(select pr_c.grantor,
|
|
70
|
+
pr_c.grantee,
|
|
71
|
+
a.attrelid,
|
|
72
|
+
a.attnum,
|
|
73
|
+
a.attname,
|
|
74
|
+
pr_c.relname,
|
|
75
|
+
pr_c.relnamespace,
|
|
76
|
+
pr_c.prtype,
|
|
77
|
+
pr_c.grantable,
|
|
78
|
+
pr_c.relowner
|
|
79
|
+
from
|
|
80
|
+
(select pg_class.oid,
|
|
81
|
+
pg_class.relname,
|
|
82
|
+
pg_class.relnamespace,
|
|
83
|
+
pg_class.relowner,
|
|
84
|
+
(aclexplode(coalesce(pg_class.relacl, acldefault('r', pg_class.relowner)))).grantor as grantor,
|
|
85
|
+
(aclexplode(coalesce(pg_class.relacl, acldefault('r', pg_class.relowner)))).grantee as grantee,
|
|
86
|
+
(aclexplode(coalesce(pg_class.relacl, acldefault('r', pg_class.relowner)))).privilege_type as privilege_type,
|
|
87
|
+
(aclexplode(coalesce(pg_class.relacl, acldefault('r', pg_class.relowner)))).is_grantable as is_grantable
|
|
88
|
+
from pg_class
|
|
89
|
+
where (pg_class.relkind = any (array['r',
|
|
90
|
+
'v',
|
|
91
|
+
'm',
|
|
92
|
+
'f',
|
|
93
|
+
'p'])) ) pr_c(oid, relname, relnamespace, relowner, grantor, grantee, prtype, grantable),
|
|
94
|
+
pg_attribute a
|
|
95
|
+
where ((a.attrelid = pr_c.oid)
|
|
96
|
+
and (a.attnum > 0)
|
|
97
|
+
and (not a.attisdropped))
|
|
98
|
+
union select pr_a.grantor,
|
|
99
|
+
pr_a.grantee,
|
|
100
|
+
pr_a.attrelid,
|
|
101
|
+
pr_a.attnum,
|
|
102
|
+
pr_a.attname,
|
|
103
|
+
c.relname,
|
|
104
|
+
c.relnamespace,
|
|
105
|
+
pr_a.prtype,
|
|
106
|
+
pr_a.grantable,
|
|
107
|
+
c.relowner
|
|
108
|
+
from
|
|
109
|
+
(select a.attrelid,
|
|
110
|
+
a.attnum,
|
|
111
|
+
a.attname,
|
|
112
|
+
(aclexplode(coalesce(a.attacl, acldefault('c', cc.relowner)))).grantor as grantor,
|
|
113
|
+
(aclexplode(coalesce(a.attacl, acldefault('c', cc.relowner)))).grantee as grantee,
|
|
114
|
+
(aclexplode(coalesce(a.attacl, acldefault('c', cc.relowner)))).privilege_type as privilege_type,
|
|
115
|
+
(aclexplode(coalesce(a.attacl, acldefault('c', cc.relowner)))).is_grantable as is_grantable
|
|
116
|
+
from (pg_attribute a
|
|
117
|
+
join pg_class cc on ((a.attrelid = cc.oid)))
|
|
118
|
+
where ((a.attnum > 0)
|
|
119
|
+
and (not a.attisdropped))) pr_a(attrelid, attnum, attname, grantor, grantee, prtype, grantable),
|
|
120
|
+
pg_class c
|
|
121
|
+
where ((pr_a.attrelid = c.oid)
|
|
122
|
+
and (c.relkind = any (ARRAY['r',
|
|
123
|
+
'v',
|
|
124
|
+
'm',
|
|
125
|
+
'f',
|
|
126
|
+
'p'])))) x,
|
|
127
|
+
pg_namespace nc,
|
|
128
|
+
pg_authid u_grantor,
|
|
129
|
+
(select pg_authid.oid,
|
|
130
|
+
pg_authid.rolname
|
|
131
|
+
from pg_authid
|
|
132
|
+
union all select (0)::oid as oid,
|
|
133
|
+
'PUBLIC') grantee(oid, rolname)
|
|
134
|
+
where ((x.relnamespace = nc.oid)
|
|
135
|
+
${props.schemaFilter ? `and nc.nspname ${props.schemaFilter}` : ""}
|
|
136
|
+
${props.columnIdsFilter ? `and (x.attrelid || '.' || x.attnum) ${props.columnIdsFilter}` : ""}
|
|
137
|
+
and (x.grantee = grantee.oid)
|
|
138
|
+
and (x.grantor = u_grantor.oid)
|
|
139
|
+
and (x.prtype = any (ARRAY['INSERT',
|
|
140
|
+
'SELECT',
|
|
141
|
+
'UPDATE',
|
|
142
|
+
'REFERENCES']))
|
|
143
|
+
and (pg_has_role(u_grantor.oid, 'USAGE')
|
|
144
|
+
or pg_has_role(grantee.oid, 'USAGE')
|
|
145
|
+
or (grantee.rolname = 'PUBLIC')))
|
|
146
|
+
group by column_id,
|
|
147
|
+
nc.nspname,
|
|
148
|
+
x.relname,
|
|
149
|
+
x.attname
|
|
150
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
151
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
152
|
+
`;
|
|
153
|
+
//#endregion
|
|
154
|
+
export { COLUMN_PRIVILEGES_SQL };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/columns.sql.ts
|
|
2
|
+
const COLUMNS_SQL = (props) => `
|
|
3
|
+
-- Adapted from information_schema.columns
|
|
4
|
+
|
|
5
|
+
SELECT
|
|
6
|
+
c.oid :: int8 AS table_id,
|
|
7
|
+
nc.nspname AS schema,
|
|
8
|
+
c.relname AS table,
|
|
9
|
+
(c.oid || '.' || a.attnum) AS id,
|
|
10
|
+
a.attnum AS ordinal_position,
|
|
11
|
+
a.attname AS name,
|
|
12
|
+
CASE
|
|
13
|
+
WHEN a.atthasdef THEN pg_get_expr(ad.adbin, ad.adrelid)
|
|
14
|
+
ELSE NULL
|
|
15
|
+
END AS default_value,
|
|
16
|
+
CASE
|
|
17
|
+
WHEN t.typtype = 'd' THEN CASE
|
|
18
|
+
WHEN bt.typelem <> 0 :: oid
|
|
19
|
+
AND bt.typlen = -1 THEN 'ARRAY'
|
|
20
|
+
WHEN nbt.nspname = 'pg_catalog' THEN format_type(t.typbasetype, NULL)
|
|
21
|
+
ELSE 'USER-DEFINED'
|
|
22
|
+
END
|
|
23
|
+
ELSE CASE
|
|
24
|
+
WHEN t.typelem <> 0 :: oid
|
|
25
|
+
AND t.typlen = -1 THEN 'ARRAY'
|
|
26
|
+
WHEN nt.nspname = 'pg_catalog' THEN format_type(a.atttypid, NULL)
|
|
27
|
+
ELSE 'USER-DEFINED'
|
|
28
|
+
END
|
|
29
|
+
END AS data_type,
|
|
30
|
+
COALESCE(bt.typname, t.typname) AS format,
|
|
31
|
+
a.attidentity IN ('a', 'd') AS is_identity,
|
|
32
|
+
CASE
|
|
33
|
+
a.attidentity
|
|
34
|
+
WHEN 'a' THEN 'ALWAYS'
|
|
35
|
+
WHEN 'd' THEN 'BY DEFAULT'
|
|
36
|
+
ELSE NULL
|
|
37
|
+
END AS identity_generation,
|
|
38
|
+
a.attgenerated IN ('s') AS is_generated,
|
|
39
|
+
NOT (
|
|
40
|
+
a.attnotnull
|
|
41
|
+
OR t.typtype = 'd' AND t.typnotnull
|
|
42
|
+
) AS is_nullable,
|
|
43
|
+
(
|
|
44
|
+
c.relkind IN ('r', 'p')
|
|
45
|
+
OR c.relkind IN ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, FALSE)
|
|
46
|
+
) AS is_updatable,
|
|
47
|
+
uniques.table_id IS NOT NULL AS is_unique,
|
|
48
|
+
check_constraints.definition AS "check",
|
|
49
|
+
array_to_json(
|
|
50
|
+
array(
|
|
51
|
+
SELECT
|
|
52
|
+
enumlabel
|
|
53
|
+
FROM
|
|
54
|
+
pg_catalog.pg_enum enums
|
|
55
|
+
WHERE
|
|
56
|
+
enums.enumtypid = coalesce(bt.oid, t.oid)
|
|
57
|
+
OR enums.enumtypid = coalesce(bt.typelem, t.typelem)
|
|
58
|
+
ORDER BY
|
|
59
|
+
enums.enumsortorder
|
|
60
|
+
)
|
|
61
|
+
) AS enums,
|
|
62
|
+
col_description(c.oid, a.attnum) AS comment
|
|
63
|
+
FROM
|
|
64
|
+
pg_attribute a
|
|
65
|
+
LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid
|
|
66
|
+
AND a.attnum = ad.adnum
|
|
67
|
+
JOIN (
|
|
68
|
+
pg_class c
|
|
69
|
+
JOIN pg_namespace nc ON c.relnamespace = nc.oid
|
|
70
|
+
) ON a.attrelid = c.oid
|
|
71
|
+
JOIN (
|
|
72
|
+
pg_type t
|
|
73
|
+
JOIN pg_namespace nt ON t.typnamespace = nt.oid
|
|
74
|
+
) ON a.atttypid = t.oid
|
|
75
|
+
LEFT JOIN (
|
|
76
|
+
pg_type bt
|
|
77
|
+
JOIN pg_namespace nbt ON bt.typnamespace = nbt.oid
|
|
78
|
+
) ON t.typtype = 'd'
|
|
79
|
+
AND t.typbasetype = bt.oid
|
|
80
|
+
LEFT JOIN (
|
|
81
|
+
SELECT DISTINCT ON (table_id, ordinal_position)
|
|
82
|
+
conrelid AS table_id,
|
|
83
|
+
conkey[1] AS ordinal_position
|
|
84
|
+
FROM pg_catalog.pg_constraint
|
|
85
|
+
WHERE contype = 'u' AND cardinality(conkey) = 1
|
|
86
|
+
) AS uniques ON uniques.table_id = c.oid AND uniques.ordinal_position = a.attnum
|
|
87
|
+
LEFT JOIN (
|
|
88
|
+
-- We only select the first column check
|
|
89
|
+
SELECT DISTINCT ON (table_id, ordinal_position)
|
|
90
|
+
conrelid AS table_id,
|
|
91
|
+
conkey[1] AS ordinal_position,
|
|
92
|
+
substring(
|
|
93
|
+
pg_get_constraintdef(pg_constraint.oid, true),
|
|
94
|
+
8,
|
|
95
|
+
length(pg_get_constraintdef(pg_constraint.oid, true)) - 8
|
|
96
|
+
) AS "definition"
|
|
97
|
+
FROM pg_constraint
|
|
98
|
+
WHERE contype = 'c' AND cardinality(conkey) = 1
|
|
99
|
+
ORDER BY table_id, ordinal_position, oid asc
|
|
100
|
+
) AS check_constraints ON check_constraints.table_id = c.oid AND check_constraints.ordinal_position = a.attnum
|
|
101
|
+
WHERE
|
|
102
|
+
${props.schemaFilter ? `nc.nspname ${props.schemaFilter} AND` : ""}
|
|
103
|
+
${props.idsFilter ? `(c.oid || '.' || a.attnum) ${props.idsFilter} AND` : ""}
|
|
104
|
+
${props.columnNameFilter ? `(c.relname || '.' || a.attname) ${props.columnNameFilter} AND` : ""}
|
|
105
|
+
${props.tableIdFilter ? `c.oid ${props.tableIdFilter} AND` : ""}
|
|
106
|
+
${props.tableIdentifierFilter ? `nc.nspname || '.' || c.relname ${props.tableIdentifierFilter} AND` : ""}
|
|
107
|
+
NOT pg_is_other_temp_schema(nc.oid)
|
|
108
|
+
AND a.attnum > 0
|
|
109
|
+
AND NOT a.attisdropped
|
|
110
|
+
AND (c.relkind IN ('r', 'v', 'm', 'f', 'p'))
|
|
111
|
+
AND (
|
|
112
|
+
pg_has_role(c.relowner, 'USAGE')
|
|
113
|
+
OR has_column_privilege(
|
|
114
|
+
c.oid,
|
|
115
|
+
a.attnum,
|
|
116
|
+
'SELECT, INSERT, UPDATE, REFERENCES'
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
120
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
121
|
+
`;
|
|
122
|
+
//#endregion
|
|
123
|
+
export { COLUMNS_SQL };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/config.sql.ts
|
|
2
|
+
const CONFIG_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
name,
|
|
5
|
+
setting,
|
|
6
|
+
category,
|
|
7
|
+
TRIM(split_part(category, '/', 1)) AS group,
|
|
8
|
+
TRIM(split_part(category, '/', 2)) AS subgroup,
|
|
9
|
+
unit,
|
|
10
|
+
short_desc,
|
|
11
|
+
extra_desc,
|
|
12
|
+
context,
|
|
13
|
+
vartype,
|
|
14
|
+
source,
|
|
15
|
+
min_val,
|
|
16
|
+
max_val,
|
|
17
|
+
enumvals,
|
|
18
|
+
boot_val,
|
|
19
|
+
reset_val,
|
|
20
|
+
sourcefile,
|
|
21
|
+
sourceline,
|
|
22
|
+
pending_restart
|
|
23
|
+
FROM
|
|
24
|
+
pg_settings
|
|
25
|
+
ORDER BY
|
|
26
|
+
category,
|
|
27
|
+
name
|
|
28
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
29
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
30
|
+
`;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { CONFIG_SQL };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/extensions.sql.ts
|
|
2
|
+
const EXTENSIONS_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
e.name,
|
|
5
|
+
n.nspname AS schema,
|
|
6
|
+
e.default_version,
|
|
7
|
+
x.extversion AS installed_version,
|
|
8
|
+
e.comment
|
|
9
|
+
FROM
|
|
10
|
+
pg_available_extensions() e(name, default_version, comment)
|
|
11
|
+
LEFT JOIN pg_extension x ON e.name = x.extname
|
|
12
|
+
LEFT JOIN pg_namespace n ON x.extnamespace = n.oid
|
|
13
|
+
WHERE
|
|
14
|
+
true
|
|
15
|
+
${props.nameFilter ? `AND e.name ${props.nameFilter}` : ""}
|
|
16
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
17
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
18
|
+
`;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { EXTENSIONS_SQL };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/vendor/postgres-meta/lib/sql/foreign_tables.sql.ts
|
|
2
|
+
const FOREIGN_TABLES_SQL = (props) => `
|
|
3
|
+
SELECT
|
|
4
|
+
c.oid :: int8 AS id,
|
|
5
|
+
n.nspname AS schema,
|
|
6
|
+
c.relname AS name,
|
|
7
|
+
obj_description(c.oid) AS comment
|
|
8
|
+
FROM
|
|
9
|
+
pg_class c
|
|
10
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
11
|
+
WHERE
|
|
12
|
+
${props.schemaFilter ? `n.nspname ${props.schemaFilter} AND` : ""}
|
|
13
|
+
${props.idsFilter ? `c.oid ${props.idsFilter} AND` : ""}
|
|
14
|
+
${props.tableIdentifierFilter ? `(n.nspname || '.' || c.relname) ${props.tableIdentifierFilter} AND` : ""}
|
|
15
|
+
c.relkind = 'f'
|
|
16
|
+
${props.limit ? `limit ${props.limit}` : ""}
|
|
17
|
+
${props.offset ? `offset ${props.offset}` : ""}
|
|
18
|
+
`;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { FOREIGN_TABLES_SQL };
|