pgterra 0.2.11 → 0.2.13
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/index.js +411 -493
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17322,19 +17322,19 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
17322
17322
|
ret += " BC";
|
|
17323
17323
|
return ret;
|
|
17324
17324
|
}
|
|
17325
|
-
function normalizeQueryConfig(
|
|
17326
|
-
|
|
17325
|
+
function normalizeQueryConfig(config6, values, callback) {
|
|
17326
|
+
config6 = typeof config6 === "string" ? { text: config6 } : config6;
|
|
17327
17327
|
if (values) {
|
|
17328
17328
|
if (typeof values === "function") {
|
|
17329
|
-
|
|
17329
|
+
config6.callback = values;
|
|
17330
17330
|
} else {
|
|
17331
|
-
|
|
17331
|
+
config6.values = values;
|
|
17332
17332
|
}
|
|
17333
17333
|
}
|
|
17334
17334
|
if (callback) {
|
|
17335
|
-
|
|
17335
|
+
config6.callback = callback;
|
|
17336
17336
|
}
|
|
17337
|
-
return
|
|
17337
|
+
return config6;
|
|
17338
17338
|
}
|
|
17339
17339
|
var escapeIdentifier = function(str) {
|
|
17340
17340
|
return '"' + str.replace(/"/g, '""') + '"';
|
|
@@ -17775,10 +17775,10 @@ var require_type_overrides = __commonJS((exports, module) => {
|
|
|
17775
17775
|
var require_pg_connection_string = __commonJS((exports, module) => {
|
|
17776
17776
|
function parse2(str, options = {}) {
|
|
17777
17777
|
if (str.charAt(0) === "/") {
|
|
17778
|
-
const
|
|
17779
|
-
return { host:
|
|
17778
|
+
const config7 = str.split(" ");
|
|
17779
|
+
return { host: config7[0], database: config7[1] };
|
|
17780
17780
|
}
|
|
17781
|
-
const
|
|
17781
|
+
const config6 = {};
|
|
17782
17782
|
let result;
|
|
17783
17783
|
let dummyHost = false;
|
|
17784
17784
|
if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) {
|
|
@@ -17791,72 +17791,72 @@ var require_pg_connection_string = __commonJS((exports, module) => {
|
|
|
17791
17791
|
dummyHost = true;
|
|
17792
17792
|
}
|
|
17793
17793
|
for (const entry of result.searchParams.entries()) {
|
|
17794
|
-
|
|
17794
|
+
config6[entry[0]] = entry[1];
|
|
17795
17795
|
}
|
|
17796
|
-
|
|
17797
|
-
|
|
17796
|
+
config6.user = config6.user || decodeURIComponent(result.username);
|
|
17797
|
+
config6.password = config6.password || decodeURIComponent(result.password);
|
|
17798
17798
|
if (result.protocol == "socket:") {
|
|
17799
|
-
|
|
17800
|
-
|
|
17801
|
-
|
|
17802
|
-
return
|
|
17799
|
+
config6.host = decodeURI(result.pathname);
|
|
17800
|
+
config6.database = result.searchParams.get("db");
|
|
17801
|
+
config6.client_encoding = result.searchParams.get("encoding");
|
|
17802
|
+
return config6;
|
|
17803
17803
|
}
|
|
17804
17804
|
const hostname = dummyHost ? "" : result.hostname;
|
|
17805
|
-
if (!
|
|
17806
|
-
|
|
17805
|
+
if (!config6.host) {
|
|
17806
|
+
config6.host = decodeURIComponent(hostname);
|
|
17807
17807
|
} else if (hostname && /^%2f/i.test(hostname)) {
|
|
17808
17808
|
result.pathname = hostname + result.pathname;
|
|
17809
17809
|
}
|
|
17810
|
-
if (!
|
|
17811
|
-
|
|
17810
|
+
if (!config6.port) {
|
|
17811
|
+
config6.port = result.port;
|
|
17812
17812
|
}
|
|
17813
17813
|
const pathname = result.pathname.slice(1) || null;
|
|
17814
|
-
|
|
17815
|
-
if (
|
|
17816
|
-
|
|
17814
|
+
config6.database = pathname ? decodeURI(pathname) : null;
|
|
17815
|
+
if (config6.ssl === "true" || config6.ssl === "1") {
|
|
17816
|
+
config6.ssl = true;
|
|
17817
17817
|
}
|
|
17818
|
-
if (
|
|
17819
|
-
|
|
17818
|
+
if (config6.ssl === "0") {
|
|
17819
|
+
config6.ssl = false;
|
|
17820
17820
|
}
|
|
17821
|
-
if (
|
|
17822
|
-
|
|
17821
|
+
if (config6.sslcert || config6.sslkey || config6.sslrootcert || config6.sslmode) {
|
|
17822
|
+
config6.ssl = {};
|
|
17823
17823
|
}
|
|
17824
|
-
const fs =
|
|
17825
|
-
if (
|
|
17826
|
-
|
|
17824
|
+
const fs = config6.sslcert || config6.sslkey || config6.sslrootcert ? __require("fs") : null;
|
|
17825
|
+
if (config6.sslcert) {
|
|
17826
|
+
config6.ssl.cert = fs.readFileSync(config6.sslcert).toString();
|
|
17827
17827
|
}
|
|
17828
|
-
if (
|
|
17829
|
-
|
|
17828
|
+
if (config6.sslkey) {
|
|
17829
|
+
config6.ssl.key = fs.readFileSync(config6.sslkey).toString();
|
|
17830
17830
|
}
|
|
17831
|
-
if (
|
|
17832
|
-
|
|
17831
|
+
if (config6.sslrootcert) {
|
|
17832
|
+
config6.ssl.ca = fs.readFileSync(config6.sslrootcert).toString();
|
|
17833
17833
|
}
|
|
17834
|
-
if (options.useLibpqCompat &&
|
|
17834
|
+
if (options.useLibpqCompat && config6.uselibpqcompat) {
|
|
17835
17835
|
throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
|
|
17836
17836
|
}
|
|
17837
|
-
if (
|
|
17838
|
-
switch (
|
|
17837
|
+
if (config6.uselibpqcompat === "true" || options.useLibpqCompat) {
|
|
17838
|
+
switch (config6.sslmode) {
|
|
17839
17839
|
case "disable": {
|
|
17840
|
-
|
|
17840
|
+
config6.ssl = false;
|
|
17841
17841
|
break;
|
|
17842
17842
|
}
|
|
17843
17843
|
case "prefer": {
|
|
17844
|
-
|
|
17844
|
+
config6.ssl.rejectUnauthorized = false;
|
|
17845
17845
|
break;
|
|
17846
17846
|
}
|
|
17847
17847
|
case "require": {
|
|
17848
|
-
if (
|
|
17849
|
-
|
|
17848
|
+
if (config6.sslrootcert) {
|
|
17849
|
+
config6.ssl.checkServerIdentity = function() {};
|
|
17850
17850
|
} else {
|
|
17851
|
-
|
|
17851
|
+
config6.ssl.rejectUnauthorized = false;
|
|
17852
17852
|
}
|
|
17853
17853
|
break;
|
|
17854
17854
|
}
|
|
17855
17855
|
case "verify-ca": {
|
|
17856
|
-
if (!
|
|
17856
|
+
if (!config6.ssl.ca) {
|
|
17857
17857
|
throw new Error("SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.");
|
|
17858
17858
|
}
|
|
17859
|
-
|
|
17859
|
+
config6.ssl.checkServerIdentity = function() {};
|
|
17860
17860
|
break;
|
|
17861
17861
|
}
|
|
17862
17862
|
case "verify-full": {
|
|
@@ -17864,9 +17864,9 @@ var require_pg_connection_string = __commonJS((exports, module) => {
|
|
|
17864
17864
|
}
|
|
17865
17865
|
}
|
|
17866
17866
|
} else {
|
|
17867
|
-
switch (
|
|
17867
|
+
switch (config6.sslmode) {
|
|
17868
17868
|
case "disable": {
|
|
17869
|
-
|
|
17869
|
+
config6.ssl = false;
|
|
17870
17870
|
break;
|
|
17871
17871
|
}
|
|
17872
17872
|
case "prefer":
|
|
@@ -17876,12 +17876,12 @@ var require_pg_connection_string = __commonJS((exports, module) => {
|
|
|
17876
17876
|
break;
|
|
17877
17877
|
}
|
|
17878
17878
|
case "no-verify": {
|
|
17879
|
-
|
|
17879
|
+
config6.ssl.rejectUnauthorized = false;
|
|
17880
17880
|
break;
|
|
17881
17881
|
}
|
|
17882
17882
|
}
|
|
17883
17883
|
}
|
|
17884
|
-
return
|
|
17884
|
+
return config6;
|
|
17885
17885
|
}
|
|
17886
17886
|
function toConnectionOptions(sslConfig) {
|
|
17887
17887
|
const connectionOptions = Object.entries(sslConfig).reduce((c, [key, value]) => {
|
|
@@ -17892,8 +17892,8 @@ var require_pg_connection_string = __commonJS((exports, module) => {
|
|
|
17892
17892
|
}, {});
|
|
17893
17893
|
return connectionOptions;
|
|
17894
17894
|
}
|
|
17895
|
-
function toClientConfig(
|
|
17896
|
-
const poolConfig = Object.entries(
|
|
17895
|
+
function toClientConfig(config6) {
|
|
17896
|
+
const poolConfig = Object.entries(config6).reduce((c, [key, value]) => {
|
|
17897
17897
|
if (key === "ssl") {
|
|
17898
17898
|
const sslConfig = value;
|
|
17899
17899
|
if (typeof sslConfig === "boolean") {
|
|
@@ -17933,13 +17933,13 @@ var require_connection_parameters = __commonJS((exports, module) => {
|
|
|
17933
17933
|
var dns = __require("dns");
|
|
17934
17934
|
var defaults = require_defaults();
|
|
17935
17935
|
var parse2 = require_pg_connection_string().parse;
|
|
17936
|
-
var val = function(key,
|
|
17936
|
+
var val = function(key, config6, envVar) {
|
|
17937
17937
|
if (envVar === undefined) {
|
|
17938
17938
|
envVar = process.env["PG" + key.toUpperCase()];
|
|
17939
17939
|
} else if (envVar === false) {} else {
|
|
17940
17940
|
envVar = process.env[envVar];
|
|
17941
17941
|
}
|
|
17942
|
-
return
|
|
17942
|
+
return config6[key] || envVar || defaults[key];
|
|
17943
17943
|
};
|
|
17944
17944
|
var readSSLConfigFromEnvironment = function() {
|
|
17945
17945
|
switch (process.env.PGSSLMODE) {
|
|
@@ -17958,35 +17958,35 @@ var require_connection_parameters = __commonJS((exports, module) => {
|
|
|
17958
17958
|
var quoteParamValue = function(value) {
|
|
17959
17959
|
return "'" + ("" + value).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
|
|
17960
17960
|
};
|
|
17961
|
-
var add = function(params,
|
|
17962
|
-
const value =
|
|
17961
|
+
var add = function(params, config6, paramName) {
|
|
17962
|
+
const value = config6[paramName];
|
|
17963
17963
|
if (value !== undefined && value !== null) {
|
|
17964
17964
|
params.push(paramName + "=" + quoteParamValue(value));
|
|
17965
17965
|
}
|
|
17966
17966
|
};
|
|
17967
17967
|
|
|
17968
17968
|
class ConnectionParameters {
|
|
17969
|
-
constructor(
|
|
17970
|
-
|
|
17971
|
-
if (
|
|
17972
|
-
|
|
17969
|
+
constructor(config6) {
|
|
17970
|
+
config6 = typeof config6 === "string" ? parse2(config6) : config6 || {};
|
|
17971
|
+
if (config6.connectionString) {
|
|
17972
|
+
config6 = Object.assign({}, config6, parse2(config6.connectionString));
|
|
17973
17973
|
}
|
|
17974
|
-
this.user = val("user",
|
|
17975
|
-
this.database = val("database",
|
|
17974
|
+
this.user = val("user", config6);
|
|
17975
|
+
this.database = val("database", config6);
|
|
17976
17976
|
if (this.database === undefined) {
|
|
17977
17977
|
this.database = this.user;
|
|
17978
17978
|
}
|
|
17979
|
-
this.port = parseInt(val("port",
|
|
17980
|
-
this.host = val("host",
|
|
17979
|
+
this.port = parseInt(val("port", config6), 10);
|
|
17980
|
+
this.host = val("host", config6);
|
|
17981
17981
|
Object.defineProperty(this, "password", {
|
|
17982
17982
|
configurable: true,
|
|
17983
17983
|
enumerable: false,
|
|
17984
17984
|
writable: true,
|
|
17985
|
-
value: val("password",
|
|
17985
|
+
value: val("password", config6)
|
|
17986
17986
|
});
|
|
17987
|
-
this.binary = val("binary",
|
|
17988
|
-
this.options = val("options",
|
|
17989
|
-
this.ssl = typeof
|
|
17987
|
+
this.binary = val("binary", config6);
|
|
17988
|
+
this.options = val("options", config6);
|
|
17989
|
+
this.ssl = typeof config6.ssl === "undefined" ? readSSLConfigFromEnvironment() : config6.ssl;
|
|
17990
17990
|
if (typeof this.ssl === "string") {
|
|
17991
17991
|
if (this.ssl === "true") {
|
|
17992
17992
|
this.ssl = true;
|
|
@@ -18000,27 +18000,27 @@ var require_connection_parameters = __commonJS((exports, module) => {
|
|
|
18000
18000
|
enumerable: false
|
|
18001
18001
|
});
|
|
18002
18002
|
}
|
|
18003
|
-
this.client_encoding = val("client_encoding",
|
|
18004
|
-
this.replication = val("replication",
|
|
18003
|
+
this.client_encoding = val("client_encoding", config6);
|
|
18004
|
+
this.replication = val("replication", config6);
|
|
18005
18005
|
this.isDomainSocket = !(this.host || "").indexOf("/");
|
|
18006
|
-
this.application_name = val("application_name",
|
|
18007
|
-
this.fallback_application_name = val("fallback_application_name",
|
|
18008
|
-
this.statement_timeout = val("statement_timeout",
|
|
18009
|
-
this.lock_timeout = val("lock_timeout",
|
|
18010
|
-
this.idle_in_transaction_session_timeout = val("idle_in_transaction_session_timeout",
|
|
18011
|
-
this.query_timeout = val("query_timeout",
|
|
18012
|
-
if (
|
|
18006
|
+
this.application_name = val("application_name", config6, "PGAPPNAME");
|
|
18007
|
+
this.fallback_application_name = val("fallback_application_name", config6, false);
|
|
18008
|
+
this.statement_timeout = val("statement_timeout", config6, false);
|
|
18009
|
+
this.lock_timeout = val("lock_timeout", config6, false);
|
|
18010
|
+
this.idle_in_transaction_session_timeout = val("idle_in_transaction_session_timeout", config6, false);
|
|
18011
|
+
this.query_timeout = val("query_timeout", config6, false);
|
|
18012
|
+
if (config6.connectionTimeoutMillis === undefined) {
|
|
18013
18013
|
this.connect_timeout = process.env.PGCONNECT_TIMEOUT || 0;
|
|
18014
18014
|
} else {
|
|
18015
|
-
this.connect_timeout = Math.floor(
|
|
18015
|
+
this.connect_timeout = Math.floor(config6.connectionTimeoutMillis / 1000);
|
|
18016
18016
|
}
|
|
18017
|
-
if (
|
|
18017
|
+
if (config6.keepAlive === false) {
|
|
18018
18018
|
this.keepalives = 0;
|
|
18019
|
-
} else if (
|
|
18019
|
+
} else if (config6.keepAlive === true) {
|
|
18020
18020
|
this.keepalives = 1;
|
|
18021
18021
|
}
|
|
18022
|
-
if (typeof
|
|
18023
|
-
this.keepalives_idle = Math.floor(
|
|
18022
|
+
if (typeof config6.keepAliveInitialDelayMillis === "number") {
|
|
18023
|
+
this.keepalives_idle = Math.floor(config6.keepAliveInitialDelayMillis / 1000);
|
|
18024
18024
|
}
|
|
18025
18025
|
}
|
|
18026
18026
|
getLibpqConnectionString(cb) {
|
|
@@ -18158,21 +18158,21 @@ var require_query = __commonJS((exports, module) => {
|
|
|
18158
18158
|
var utils = require_utils();
|
|
18159
18159
|
|
|
18160
18160
|
class Query extends EventEmitter {
|
|
18161
|
-
constructor(
|
|
18161
|
+
constructor(config6, values, callback) {
|
|
18162
18162
|
super();
|
|
18163
|
-
|
|
18164
|
-
this.text =
|
|
18165
|
-
this.values =
|
|
18166
|
-
this.rows =
|
|
18167
|
-
this.types =
|
|
18168
|
-
this.name =
|
|
18169
|
-
this.queryMode =
|
|
18170
|
-
this.binary =
|
|
18171
|
-
this.portal =
|
|
18172
|
-
this.callback =
|
|
18173
|
-
this._rowMode =
|
|
18174
|
-
if (process.domain &&
|
|
18175
|
-
this.callback = process.domain.bind(
|
|
18163
|
+
config6 = utils.normalizeQueryConfig(config6, values, callback);
|
|
18164
|
+
this.text = config6.text;
|
|
18165
|
+
this.values = config6.values;
|
|
18166
|
+
this.rows = config6.rows;
|
|
18167
|
+
this.types = config6.types;
|
|
18168
|
+
this.name = config6.name;
|
|
18169
|
+
this.queryMode = config6.queryMode;
|
|
18170
|
+
this.binary = config6.binary;
|
|
18171
|
+
this.portal = config6.portal || "";
|
|
18172
|
+
this.callback = config6.callback;
|
|
18173
|
+
this._rowMode = config6.rowMode;
|
|
18174
|
+
if (process.domain && config6.callback) {
|
|
18175
|
+
this.callback = process.domain.bind(config6.callback);
|
|
18176
18176
|
}
|
|
18177
18177
|
this._result = new Result(this._rowMode, this.types);
|
|
18178
18178
|
this._results = this._result;
|
|
@@ -18661,27 +18661,27 @@ var require_serializer = __commonJS((exports) => {
|
|
|
18661
18661
|
}
|
|
18662
18662
|
}
|
|
18663
18663
|
};
|
|
18664
|
-
var bind = (
|
|
18665
|
-
const portal =
|
|
18666
|
-
const statement =
|
|
18667
|
-
const binary =
|
|
18668
|
-
const values =
|
|
18664
|
+
var bind = (config6 = {}) => {
|
|
18665
|
+
const portal = config6.portal || "";
|
|
18666
|
+
const statement = config6.statement || "";
|
|
18667
|
+
const binary = config6.binary || false;
|
|
18668
|
+
const values = config6.values || emptyArray;
|
|
18669
18669
|
const len = values.length;
|
|
18670
18670
|
writer.addCString(portal).addCString(statement);
|
|
18671
18671
|
writer.addInt16(len);
|
|
18672
|
-
writeValues(values,
|
|
18672
|
+
writeValues(values, config6.valueMapper);
|
|
18673
18673
|
writer.addInt16(len);
|
|
18674
18674
|
writer.add(paramWriter.flush());
|
|
18675
18675
|
writer.addInt16(binary ? 1 : 0);
|
|
18676
18676
|
return writer.flush(66);
|
|
18677
18677
|
};
|
|
18678
18678
|
var emptyExecute = Buffer.from([69, 0, 0, 0, 9, 0, 0, 0, 0, 0]);
|
|
18679
|
-
var execute = (
|
|
18680
|
-
if (!
|
|
18679
|
+
var execute = (config6) => {
|
|
18680
|
+
if (!config6 || !config6.portal && !config6.rows) {
|
|
18681
18681
|
return emptyExecute;
|
|
18682
18682
|
}
|
|
18683
|
-
const portal =
|
|
18684
|
-
const rows =
|
|
18683
|
+
const portal = config6.portal || "";
|
|
18684
|
+
const rows = config6.rows || 0;
|
|
18685
18685
|
const portalLength = Buffer.byteLength(portal);
|
|
18686
18686
|
const len = 4 + portalLength + 1 + 4;
|
|
18687
18687
|
const buff = Buffer.allocUnsafe(1 + len);
|
|
@@ -19337,18 +19337,18 @@ var require_connection = __commonJS((exports, module) => {
|
|
|
19337
19337
|
var endBuffer = serialize.end();
|
|
19338
19338
|
|
|
19339
19339
|
class Connection extends EventEmitter {
|
|
19340
|
-
constructor(
|
|
19340
|
+
constructor(config6) {
|
|
19341
19341
|
super();
|
|
19342
|
-
|
|
19343
|
-
this.stream =
|
|
19342
|
+
config6 = config6 || {};
|
|
19343
|
+
this.stream = config6.stream || getStream(config6.ssl);
|
|
19344
19344
|
if (typeof this.stream === "function") {
|
|
19345
|
-
this.stream = this.stream(
|
|
19345
|
+
this.stream = this.stream(config6);
|
|
19346
19346
|
}
|
|
19347
|
-
this._keepAlive =
|
|
19348
|
-
this._keepAliveInitialDelayMillis =
|
|
19347
|
+
this._keepAlive = config6.keepAlive;
|
|
19348
|
+
this._keepAliveInitialDelayMillis = config6.keepAliveInitialDelayMillis;
|
|
19349
19349
|
this.lastBuffer = false;
|
|
19350
19350
|
this.parsedStatements = {};
|
|
19351
|
-
this.ssl =
|
|
19351
|
+
this.ssl = config6.ssl || false;
|
|
19352
19352
|
this._ending = false;
|
|
19353
19353
|
this._emitMessage = false;
|
|
19354
19354
|
const self = this;
|
|
@@ -19429,8 +19429,8 @@ var require_connection = __commonJS((exports, module) => {
|
|
|
19429
19429
|
requestSsl() {
|
|
19430
19430
|
this.stream.write(serialize.requestSsl());
|
|
19431
19431
|
}
|
|
19432
|
-
startup(
|
|
19433
|
-
this.stream.write(serialize.startup(
|
|
19432
|
+
startup(config6) {
|
|
19433
|
+
this.stream.write(serialize.startup(config6));
|
|
19434
19434
|
}
|
|
19435
19435
|
cancel(processID, secretKey) {
|
|
19436
19436
|
this._send(serialize.cancel(processID, secretKey));
|
|
@@ -19456,11 +19456,11 @@ var require_connection = __commonJS((exports, module) => {
|
|
|
19456
19456
|
parse(query) {
|
|
19457
19457
|
this._send(serialize.parse(query));
|
|
19458
19458
|
}
|
|
19459
|
-
bind(
|
|
19460
|
-
this._send(serialize.bind(
|
|
19459
|
+
bind(config6) {
|
|
19460
|
+
this._send(serialize.bind(config6));
|
|
19461
19461
|
}
|
|
19462
|
-
execute(
|
|
19463
|
-
this._send(serialize.execute(
|
|
19462
|
+
execute(config6) {
|
|
19463
|
+
this._send(serialize.execute(config6));
|
|
19464
19464
|
}
|
|
19465
19465
|
flush() {
|
|
19466
19466
|
if (this.stream.writable) {
|
|
@@ -19800,9 +19800,9 @@ var require_client = __commonJS((exports, module) => {
|
|
|
19800
19800
|
var crypto = require_utils2();
|
|
19801
19801
|
|
|
19802
19802
|
class Client extends EventEmitter {
|
|
19803
|
-
constructor(
|
|
19803
|
+
constructor(config6) {
|
|
19804
19804
|
super();
|
|
19805
|
-
this.connectionParameters = new ConnectionParameters(
|
|
19805
|
+
this.connectionParameters = new ConnectionParameters(config6);
|
|
19806
19806
|
this.user = this.connectionParameters.user;
|
|
19807
19807
|
this.database = this.connectionParameters.database;
|
|
19808
19808
|
this.port = this.connectionParameters.port;
|
|
@@ -19814,7 +19814,7 @@ var require_client = __commonJS((exports, module) => {
|
|
|
19814
19814
|
value: this.connectionParameters.password
|
|
19815
19815
|
});
|
|
19816
19816
|
this.replication = this.connectionParameters.replication;
|
|
19817
|
-
const c =
|
|
19817
|
+
const c = config6 || {};
|
|
19818
19818
|
this._Promise = c.Promise || global.Promise;
|
|
19819
19819
|
this._types = new TypeOverrides(c.types);
|
|
19820
19820
|
this._ending = false;
|
|
@@ -20194,23 +20194,23 @@ var require_client = __commonJS((exports, module) => {
|
|
|
20194
20194
|
}
|
|
20195
20195
|
}
|
|
20196
20196
|
}
|
|
20197
|
-
query(
|
|
20197
|
+
query(config6, values, callback) {
|
|
20198
20198
|
let query;
|
|
20199
20199
|
let result;
|
|
20200
20200
|
let readTimeout;
|
|
20201
20201
|
let readTimeoutTimer;
|
|
20202
20202
|
let queryCallback;
|
|
20203
|
-
if (
|
|
20203
|
+
if (config6 === null || config6 === undefined) {
|
|
20204
20204
|
throw new TypeError("Client was passed a null or undefined query");
|
|
20205
|
-
} else if (typeof
|
|
20206
|
-
readTimeout =
|
|
20207
|
-
result = query =
|
|
20205
|
+
} else if (typeof config6.submit === "function") {
|
|
20206
|
+
readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
|
|
20207
|
+
result = query = config6;
|
|
20208
20208
|
if (typeof values === "function") {
|
|
20209
20209
|
query.callback = query.callback || values;
|
|
20210
20210
|
}
|
|
20211
20211
|
} else {
|
|
20212
|
-
readTimeout =
|
|
20213
|
-
query = new Query(
|
|
20212
|
+
readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
|
|
20213
|
+
query = new Query(config6, values, callback);
|
|
20214
20214
|
if (!query.callback) {
|
|
20215
20215
|
result = new this._Promise((resolve, reject) => {
|
|
20216
20216
|
query.callback = (err, res) => err ? reject(err) : resolve(res);
|
|
@@ -20679,16 +20679,16 @@ var require_query2 = __commonJS((exports, module) => {
|
|
|
20679
20679
|
var EventEmitter = __require("events").EventEmitter;
|
|
20680
20680
|
var util = __require("util");
|
|
20681
20681
|
var utils = require_utils();
|
|
20682
|
-
var NativeQuery = module.exports = function(
|
|
20682
|
+
var NativeQuery = module.exports = function(config6, values, callback) {
|
|
20683
20683
|
EventEmitter.call(this);
|
|
20684
|
-
|
|
20685
|
-
this.text =
|
|
20686
|
-
this.values =
|
|
20687
|
-
this.name =
|
|
20688
|
-
this.queryMode =
|
|
20689
|
-
this.callback =
|
|
20684
|
+
config6 = utils.normalizeQueryConfig(config6, values, callback);
|
|
20685
|
+
this.text = config6.text;
|
|
20686
|
+
this.values = config6.values;
|
|
20687
|
+
this.name = config6.name;
|
|
20688
|
+
this.queryMode = config6.queryMode;
|
|
20689
|
+
this.callback = config6.callback;
|
|
20690
20690
|
this.state = "new";
|
|
20691
|
-
this._arrayMode =
|
|
20691
|
+
this._arrayMode = config6.rowMode === "array";
|
|
20692
20692
|
this._emitRowEvents = false;
|
|
20693
20693
|
this.on("newListener", function(event) {
|
|
20694
20694
|
if (event === "row")
|
|
@@ -20823,11 +20823,11 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
20823
20823
|
var util = __require("util");
|
|
20824
20824
|
var ConnectionParameters = require_connection_parameters();
|
|
20825
20825
|
var NativeQuery = require_query2();
|
|
20826
|
-
var Client = module.exports = function(
|
|
20826
|
+
var Client = module.exports = function(config6) {
|
|
20827
20827
|
EventEmitter.call(this);
|
|
20828
|
-
|
|
20829
|
-
this._Promise =
|
|
20830
|
-
this._types = new TypeOverrides(
|
|
20828
|
+
config6 = config6 || {};
|
|
20829
|
+
this._Promise = config6.Promise || global.Promise;
|
|
20830
|
+
this._types = new TypeOverrides(config6.types);
|
|
20831
20831
|
this.native = new Native({
|
|
20832
20832
|
types: this._types
|
|
20833
20833
|
});
|
|
@@ -20836,9 +20836,9 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
20836
20836
|
this._connecting = false;
|
|
20837
20837
|
this._connected = false;
|
|
20838
20838
|
this._queryable = true;
|
|
20839
|
-
const cp = this.connectionParameters = new ConnectionParameters(
|
|
20840
|
-
if (
|
|
20841
|
-
cp.nativeConnectionString =
|
|
20839
|
+
const cp = this.connectionParameters = new ConnectionParameters(config6);
|
|
20840
|
+
if (config6.nativeConnectionString)
|
|
20841
|
+
cp.nativeConnectionString = config6.nativeConnectionString;
|
|
20842
20842
|
this.user = cp.user;
|
|
20843
20843
|
Object.defineProperty(this, "password", {
|
|
20844
20844
|
configurable: true,
|
|
@@ -20917,23 +20917,23 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
20917
20917
|
});
|
|
20918
20918
|
});
|
|
20919
20919
|
};
|
|
20920
|
-
Client.prototype.query = function(
|
|
20920
|
+
Client.prototype.query = function(config6, values, callback) {
|
|
20921
20921
|
let query;
|
|
20922
20922
|
let result;
|
|
20923
20923
|
let readTimeout;
|
|
20924
20924
|
let readTimeoutTimer;
|
|
20925
20925
|
let queryCallback;
|
|
20926
|
-
if (
|
|
20926
|
+
if (config6 === null || config6 === undefined) {
|
|
20927
20927
|
throw new TypeError("Client was passed a null or undefined query");
|
|
20928
|
-
} else if (typeof
|
|
20929
|
-
readTimeout =
|
|
20930
|
-
result = query =
|
|
20928
|
+
} else if (typeof config6.submit === "function") {
|
|
20929
|
+
readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
|
|
20930
|
+
result = query = config6;
|
|
20931
20931
|
if (typeof values === "function") {
|
|
20932
|
-
|
|
20932
|
+
config6.callback = values;
|
|
20933
20933
|
}
|
|
20934
20934
|
} else {
|
|
20935
|
-
readTimeout =
|
|
20936
|
-
query = new NativeQuery(
|
|
20935
|
+
readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
|
|
20936
|
+
query = new NativeQuery(config6, values, callback);
|
|
20937
20937
|
if (!query.callback) {
|
|
20938
20938
|
let resolveOut, rejectOut;
|
|
20939
20939
|
result = new this._Promise((resolve, reject) => {
|
|
@@ -21475,6 +21475,7 @@ function parseCreateIndex(stmt) {
|
|
|
21475
21475
|
const schema = stmt.relation?.schemaname || undefined;
|
|
21476
21476
|
const indexParams = stmt.indexParams || [];
|
|
21477
21477
|
const columns = [];
|
|
21478
|
+
let opclasses;
|
|
21478
21479
|
let expression;
|
|
21479
21480
|
if (indexParams.length === 1 && indexParams[0].IndexElem?.expr) {
|
|
21480
21481
|
expression = import_pgsql_parser3.deparseSync([indexParams[0].IndexElem.expr]).trim();
|
|
@@ -21484,6 +21485,14 @@ function parseCreateIndex(stmt) {
|
|
|
21484
21485
|
const colName = param.IndexElem.name;
|
|
21485
21486
|
if (colName) {
|
|
21486
21487
|
columns.push(colName);
|
|
21488
|
+
if (param.IndexElem.opclass && param.IndexElem.opclass.length > 0) {
|
|
21489
|
+
const opclassName = param.IndexElem.opclass.map((node) => node.String?.sval).filter(Boolean).join(".");
|
|
21490
|
+
if (opclassName) {
|
|
21491
|
+
if (!opclasses)
|
|
21492
|
+
opclasses = {};
|
|
21493
|
+
opclasses[colName] = opclassName;
|
|
21494
|
+
}
|
|
21495
|
+
}
|
|
21487
21496
|
} else if (param.IndexElem.expr) {
|
|
21488
21497
|
expression = import_pgsql_parser3.deparseSync([param.IndexElem.expr]).trim();
|
|
21489
21498
|
break;
|
|
@@ -21553,6 +21562,7 @@ function parseCreateIndex(stmt) {
|
|
|
21553
21562
|
tableName,
|
|
21554
21563
|
schema,
|
|
21555
21564
|
columns,
|
|
21565
|
+
opclasses,
|
|
21556
21566
|
type,
|
|
21557
21567
|
unique,
|
|
21558
21568
|
concurrent,
|
|
@@ -22846,6 +22856,22 @@ class DatabaseInspector {
|
|
|
22846
22856
|
-- Expression index - no simple column names
|
|
22847
22857
|
ARRAY[]::text[]
|
|
22848
22858
|
END as column_names,
|
|
22859
|
+
-- Get operator class names for each column (non-default only)
|
|
22860
|
+
CASE
|
|
22861
|
+
WHEN ix.indexprs IS NULL THEN
|
|
22862
|
+
ARRAY(
|
|
22863
|
+
SELECT
|
|
22864
|
+
CASE
|
|
22865
|
+
WHEN opc.opcdefault THEN NULL
|
|
22866
|
+
ELSE opc.opcname
|
|
22867
|
+
END
|
|
22868
|
+
FROM unnest(ix.indclass) WITH ORDINALITY AS u(opcoid, ord)
|
|
22869
|
+
JOIN pg_opclass opc ON opc.oid = u.opcoid
|
|
22870
|
+
ORDER BY u.ord
|
|
22871
|
+
)
|
|
22872
|
+
ELSE
|
|
22873
|
+
ARRAY[]::text[]
|
|
22874
|
+
END as opclass_names,
|
|
22849
22875
|
CASE
|
|
22850
22876
|
WHEN ix.indpred IS NOT NULL THEN
|
|
22851
22877
|
regexp_replace(
|
|
@@ -22874,19 +22900,32 @@ class DatabaseInspector {
|
|
|
22874
22900
|
)
|
|
22875
22901
|
ORDER BY i.indexname
|
|
22876
22902
|
`, [tableName, tableSchema]);
|
|
22877
|
-
return result.rows.map((row) =>
|
|
22878
|
-
|
|
22879
|
-
|
|
22880
|
-
|
|
22881
|
-
columns
|
|
22882
|
-
|
|
22883
|
-
|
|
22884
|
-
|
|
22885
|
-
|
|
22886
|
-
|
|
22887
|
-
|
|
22888
|
-
|
|
22889
|
-
|
|
22903
|
+
return result.rows.map((row) => {
|
|
22904
|
+
const columns = row.column_names || [];
|
|
22905
|
+
const opclassNames = row.opclass_names || [];
|
|
22906
|
+
let opclasses;
|
|
22907
|
+
for (let i = 0;i < columns.length; i++) {
|
|
22908
|
+
if (opclassNames[i]) {
|
|
22909
|
+
if (!opclasses)
|
|
22910
|
+
opclasses = {};
|
|
22911
|
+
opclasses[columns[i]] = opclassNames[i];
|
|
22912
|
+
}
|
|
22913
|
+
}
|
|
22914
|
+
return {
|
|
22915
|
+
name: row.index_name,
|
|
22916
|
+
tableName: row.table_name,
|
|
22917
|
+
schema: row.table_schema,
|
|
22918
|
+
columns,
|
|
22919
|
+
opclasses,
|
|
22920
|
+
type: this.mapPostgreSQLIndexType(row.access_method),
|
|
22921
|
+
unique: row.is_unique,
|
|
22922
|
+
concurrent: false,
|
|
22923
|
+
where: row.where_clause || undefined,
|
|
22924
|
+
expression: row.has_expressions ? row.expression_def : undefined,
|
|
22925
|
+
storageParameters: this.parseStorageOptions(row.storage_options),
|
|
22926
|
+
tablespace: row.tablespace_name || undefined
|
|
22927
|
+
};
|
|
22928
|
+
});
|
|
22890
22929
|
}
|
|
22891
22930
|
parseStorageOptions(reloptions) {
|
|
22892
22931
|
if (!reloptions || !Array.isArray(reloptions) || reloptions.length === 0) {
|
|
@@ -23688,6 +23727,30 @@ function normalizeDefault(value) {
|
|
|
23688
23727
|
normalized = normalized.replace(/::[a-z_]+(\s+[a-z_]+)*(\([^)]*\))?$/i, "");
|
|
23689
23728
|
return normalized.trim();
|
|
23690
23729
|
}
|
|
23730
|
+
function normalizeExpression(expr) {
|
|
23731
|
+
let normalized = expr.replace(/\s+/g, " ").trim().replace(/::[a-z_]+(\([^)]*\))?/gi, "").replace(/\(([a-z_][a-z0-9_]*)\)/gi, "$1");
|
|
23732
|
+
while (/^\(.*\)$/.test(normalized)) {
|
|
23733
|
+
const inner = normalized.slice(1, -1);
|
|
23734
|
+
let depth = 0;
|
|
23735
|
+
let balanced = true;
|
|
23736
|
+
for (const char of inner) {
|
|
23737
|
+
if (char === "(")
|
|
23738
|
+
depth++;
|
|
23739
|
+
if (char === ")")
|
|
23740
|
+
depth--;
|
|
23741
|
+
if (depth < 0) {
|
|
23742
|
+
balanced = false;
|
|
23743
|
+
break;
|
|
23744
|
+
}
|
|
23745
|
+
}
|
|
23746
|
+
if (balanced && depth === 0) {
|
|
23747
|
+
normalized = inner.trim();
|
|
23748
|
+
} else {
|
|
23749
|
+
break;
|
|
23750
|
+
}
|
|
23751
|
+
}
|
|
23752
|
+
return normalized.replace(/\s+/g, " ").trim();
|
|
23753
|
+
}
|
|
23691
23754
|
function columnsAreDifferent(desired, current) {
|
|
23692
23755
|
const normalizedDesiredType = normalizeType(desired.type);
|
|
23693
23756
|
const normalizedCurrentType = normalizeType(current.type);
|
|
@@ -23718,7 +23781,7 @@ function columnsAreDifferent(desired, current) {
|
|
|
23718
23781
|
if (!desired.generated || !current.generated) {
|
|
23719
23782
|
return true;
|
|
23720
23783
|
}
|
|
23721
|
-
if (desired.generated.always !== current.generated.always || desired.generated.stored !== current.generated.stored || desired.generated.expression !== current.generated.expression) {
|
|
23784
|
+
if (desired.generated.always !== current.generated.always || desired.generated.stored !== current.generated.stored || normalizeExpression(desired.generated.expression) !== normalizeExpression(current.generated.expression)) {
|
|
23722
23785
|
return true;
|
|
23723
23786
|
}
|
|
23724
23787
|
}
|
|
@@ -24073,94 +24136,10 @@ class DependencyResolver {
|
|
|
24073
24136
|
return this.topologicalSort(true);
|
|
24074
24137
|
}
|
|
24075
24138
|
topologicalSortCreation() {
|
|
24076
|
-
|
|
24077
|
-
for (const tableName of this.nodes.keys()) {
|
|
24078
|
-
inDegree.set(tableName, 0);
|
|
24079
|
-
}
|
|
24080
|
-
for (const [tableName, node] of this.nodes) {
|
|
24081
|
-
for (const dependency of node.dependencies) {
|
|
24082
|
-
inDegree.set(tableName, (inDegree.get(tableName) || 0) + 1);
|
|
24083
|
-
}
|
|
24084
|
-
}
|
|
24085
|
-
const result = [];
|
|
24086
|
-
const queue = [];
|
|
24087
|
-
for (const [tableName, degree] of inDegree) {
|
|
24088
|
-
if (degree === 0) {
|
|
24089
|
-
queue.push(tableName);
|
|
24090
|
-
}
|
|
24091
|
-
}
|
|
24092
|
-
while (queue.length > 0) {
|
|
24093
|
-
const current = queue.shift();
|
|
24094
|
-
result.push(current);
|
|
24095
|
-
const currentNode = this.nodes.get(current);
|
|
24096
|
-
if (currentNode) {
|
|
24097
|
-
for (const dependent of currentNode.dependents) {
|
|
24098
|
-
const newDegree = (inDegree.get(dependent) || 0) - 1;
|
|
24099
|
-
inDegree.set(dependent, newDegree);
|
|
24100
|
-
if (newDegree === 0) {
|
|
24101
|
-
queue.push(dependent);
|
|
24102
|
-
}
|
|
24103
|
-
}
|
|
24104
|
-
}
|
|
24105
|
-
}
|
|
24106
|
-
if (result.length !== this.nodes.size) {
|
|
24107
|
-
const cycles = this.getCircularDependencies();
|
|
24108
|
-
if (cycles.length > 0) {
|
|
24109
|
-
const cycleDescriptions = cycles.map((cycle) => cycle.join(" → ")).join(`
|
|
24110
|
-
`);
|
|
24111
|
-
throw new Error(`Circular dependency detected. Cannot resolve table creation order.
|
|
24112
|
-
` + `Detected cycles:
|
|
24113
|
-
${cycleDescriptions}
|
|
24114
|
-
` + `Tables involved in cycles cannot be created because they reference each other.`);
|
|
24115
|
-
}
|
|
24116
|
-
throw new Error(`Cannot resolve table creation order. ` + `Processed ${result.length} out of ${this.nodes.size} tables.`);
|
|
24117
|
-
}
|
|
24118
|
-
return result;
|
|
24139
|
+
return this.topologicalSortCore(this.nodes, false, "creation");
|
|
24119
24140
|
}
|
|
24120
24141
|
topologicalSortDeletion() {
|
|
24121
|
-
|
|
24122
|
-
for (const tableName of this.nodes.keys()) {
|
|
24123
|
-
inDegree.set(tableName, 0);
|
|
24124
|
-
}
|
|
24125
|
-
for (const [tableName, node] of this.nodes) {
|
|
24126
|
-
for (const dependent of node.dependents) {
|
|
24127
|
-
inDegree.set(tableName, (inDegree.get(tableName) || 0) + 1);
|
|
24128
|
-
}
|
|
24129
|
-
}
|
|
24130
|
-
const result = [];
|
|
24131
|
-
const queue = [];
|
|
24132
|
-
for (const [tableName, degree] of inDegree) {
|
|
24133
|
-
if (degree === 0) {
|
|
24134
|
-
queue.push(tableName);
|
|
24135
|
-
}
|
|
24136
|
-
}
|
|
24137
|
-
while (queue.length > 0) {
|
|
24138
|
-
const current = queue.shift();
|
|
24139
|
-
result.push(current);
|
|
24140
|
-
const currentNode = this.nodes.get(current);
|
|
24141
|
-
if (currentNode) {
|
|
24142
|
-
for (const dependency of currentNode.dependencies) {
|
|
24143
|
-
const newDegree = (inDegree.get(dependency) || 0) - 1;
|
|
24144
|
-
inDegree.set(dependency, newDegree);
|
|
24145
|
-
if (newDegree === 0) {
|
|
24146
|
-
queue.push(dependency);
|
|
24147
|
-
}
|
|
24148
|
-
}
|
|
24149
|
-
}
|
|
24150
|
-
}
|
|
24151
|
-
if (result.length !== this.nodes.size) {
|
|
24152
|
-
const cycles = this.getCircularDependencies();
|
|
24153
|
-
if (cycles.length > 0) {
|
|
24154
|
-
const cycleDescriptions = cycles.map((cycle) => cycle.join(" → ")).join(`
|
|
24155
|
-
`);
|
|
24156
|
-
throw new Error(`Circular dependency detected. Cannot resolve table deletion order.
|
|
24157
|
-
` + `Detected cycles:
|
|
24158
|
-
${cycleDescriptions}
|
|
24159
|
-
` + `Tables involved in cycles cannot be deleted in a valid order.`);
|
|
24160
|
-
}
|
|
24161
|
-
throw new Error(`Cannot resolve table deletion order. ` + `Processed ${result.length} out of ${this.nodes.size} tables.`);
|
|
24162
|
-
}
|
|
24163
|
-
return result;
|
|
24142
|
+
return this.topologicalSortCore(this.nodes, true, "deletion");
|
|
24164
24143
|
}
|
|
24165
24144
|
topologicalSort(reverse) {
|
|
24166
24145
|
return reverse ? this.topologicalSortDeletion() : this.topologicalSortCreation();
|
|
@@ -24250,7 +24229,7 @@ class DependencyResolver {
|
|
|
24250
24229
|
}
|
|
24251
24230
|
}
|
|
24252
24231
|
}
|
|
24253
|
-
const order = this.
|
|
24232
|
+
const order = this.topologicalSortCore(modifiedNodes, false);
|
|
24254
24233
|
return {
|
|
24255
24234
|
order,
|
|
24256
24235
|
foreignKeysToDefer
|
|
@@ -24299,13 +24278,13 @@ class DependencyResolver {
|
|
|
24299
24278
|
}
|
|
24300
24279
|
}
|
|
24301
24280
|
}
|
|
24302
|
-
const order = this.
|
|
24281
|
+
const order = this.topologicalSortCore(modifiedNodes, true);
|
|
24303
24282
|
return {
|
|
24304
24283
|
order,
|
|
24305
24284
|
foreignKeysToDefer: foreignKeysToDrop
|
|
24306
24285
|
};
|
|
24307
24286
|
}
|
|
24308
|
-
|
|
24287
|
+
topologicalSortCore(nodes, reverse, mode = "internal") {
|
|
24309
24288
|
const inDegree = new Map;
|
|
24310
24289
|
for (const tableName of nodes.keys()) {
|
|
24311
24290
|
inDegree.set(tableName, 0);
|
|
@@ -24346,7 +24325,21 @@ class DependencyResolver {
|
|
|
24346
24325
|
}
|
|
24347
24326
|
}
|
|
24348
24327
|
if (result.length !== nodes.size) {
|
|
24349
|
-
|
|
24328
|
+
if (mode === "internal") {
|
|
24329
|
+
throw new Error(`Internal error: topological sort failed even after removing cycle-forming edges. ` + `Processed ${result.length} out of ${nodes.size} tables.`);
|
|
24330
|
+
}
|
|
24331
|
+
const cycles = this.getCircularDependencies();
|
|
24332
|
+
if (cycles.length > 0) {
|
|
24333
|
+
const cycleDescriptions = cycles.map((cycle) => cycle.join(" → ")).join(`
|
|
24334
|
+
`);
|
|
24335
|
+
const orderType2 = mode === "creation" ? "creation" : "deletion";
|
|
24336
|
+
throw new Error(`Circular dependency detected. Cannot resolve table ${orderType2} order.
|
|
24337
|
+
` + `Detected cycles:
|
|
24338
|
+
${cycleDescriptions}
|
|
24339
|
+
` + `Tables involved in cycles cannot be ${mode === "creation" ? "created because they reference each other" : "deleted in a valid order"}.`);
|
|
24340
|
+
}
|
|
24341
|
+
const orderType = mode === "creation" ? "creation" : "deletion";
|
|
24342
|
+
throw new Error(`Cannot resolve table ${orderType} order. ` + `Processed ${result.length} out of ${nodes.size} tables.`);
|
|
24350
24343
|
}
|
|
24351
24344
|
return result;
|
|
24352
24345
|
}
|
|
@@ -24489,7 +24482,7 @@ class SchemaDiffer {
|
|
|
24489
24482
|
}
|
|
24490
24483
|
generateColumnModificationStatements(tableName, desiredColumn, currentColumn) {
|
|
24491
24484
|
const statements = [];
|
|
24492
|
-
const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || desiredColumn.generated.expression !== currentColumn.generated.expression || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
|
|
24485
|
+
const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || normalizeExpression(desiredColumn.generated.expression) !== normalizeExpression(currentColumn.generated.expression) || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
|
|
24493
24486
|
if (generatedChanging) {
|
|
24494
24487
|
const dropSql = new SQLBuilder().p("ALTER TABLE").p(tableName).p("DROP COLUMN").ident(desiredColumn.name).p(";").build();
|
|
24495
24488
|
statements.push(dropSql);
|
|
@@ -24694,6 +24687,16 @@ class SchemaDiffer {
|
|
|
24694
24687
|
return false;
|
|
24695
24688
|
if (index1.tablespace !== index2.tablespace)
|
|
24696
24689
|
return false;
|
|
24690
|
+
const opclasses1 = index1.opclasses || {};
|
|
24691
|
+
const opclasses2 = index2.opclasses || {};
|
|
24692
|
+
const opKeys1 = Object.keys(opclasses1);
|
|
24693
|
+
const opKeys2 = Object.keys(opclasses2);
|
|
24694
|
+
if (opKeys1.length !== opKeys2.length)
|
|
24695
|
+
return false;
|
|
24696
|
+
for (const key of opKeys1) {
|
|
24697
|
+
if (opclasses1[key] !== opclasses2[key])
|
|
24698
|
+
return false;
|
|
24699
|
+
}
|
|
24697
24700
|
const params1 = index1.storageParameters || {};
|
|
24698
24701
|
const params2 = index2.storageParameters || {};
|
|
24699
24702
|
const keys1 = Object.keys(params1);
|
|
@@ -24739,7 +24742,11 @@ class SchemaDiffer {
|
|
|
24739
24742
|
if (index.expression) {
|
|
24740
24743
|
builder.p(`(${index.expression})`);
|
|
24741
24744
|
} else {
|
|
24742
|
-
const quotedColumns = index.columns.map((col) =>
|
|
24745
|
+
const quotedColumns = index.columns.map((col) => {
|
|
24746
|
+
const quoted = `"${col.replace(/"/g, '""')}"`;
|
|
24747
|
+
const opclass = index.opclasses?.[col];
|
|
24748
|
+
return opclass ? `${quoted} ${opclass}` : quoted;
|
|
24749
|
+
}).join(", ");
|
|
24743
24750
|
builder.p(`(${quotedColumns})`);
|
|
24744
24751
|
}
|
|
24745
24752
|
if (index.where) {
|
|
@@ -24769,9 +24776,9 @@ class SchemaDiffer {
|
|
|
24769
24776
|
}
|
|
24770
24777
|
generateCheckConstraintStatements(tableName, desiredConstraints, currentConstraints) {
|
|
24771
24778
|
const statements = [];
|
|
24772
|
-
const
|
|
24773
|
-
const currentMap = new Map(currentConstraints.map((c) => [
|
|
24774
|
-
const desiredMap = new Map(desiredConstraints.map((c) => [
|
|
24779
|
+
const normalizeExpression2 = (expr) => expr.replace(/\s+/g, " ").trim();
|
|
24780
|
+
const currentMap = new Map(currentConstraints.map((c) => [normalizeExpression2(c.expression), c]));
|
|
24781
|
+
const desiredMap = new Map(desiredConstraints.map((c) => [normalizeExpression2(c.expression), c]));
|
|
24775
24782
|
for (const [key, constraint] of currentMap) {
|
|
24776
24783
|
if (!desiredMap.has(key)) {
|
|
24777
24784
|
if (constraint.name) {
|
|
@@ -24892,7 +24899,7 @@ class SchemaDiffer {
|
|
|
24892
24899
|
return alterations;
|
|
24893
24900
|
}
|
|
24894
24901
|
collectColumnModificationAlterations(desiredColumn, currentColumn, alterations) {
|
|
24895
|
-
const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || desiredColumn.generated.expression !== currentColumn.generated.expression || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
|
|
24902
|
+
const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || normalizeExpression(desiredColumn.generated.expression) !== normalizeExpression(currentColumn.generated.expression) || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
|
|
24896
24903
|
if (generatedChanging) {
|
|
24897
24904
|
alterations.push({ type: "drop_column", columnName: desiredColumn.name });
|
|
24898
24905
|
alterations.push({ type: "add_column", column: desiredColumn });
|
|
@@ -24950,9 +24957,9 @@ class SchemaDiffer {
|
|
|
24950
24957
|
}
|
|
24951
24958
|
}
|
|
24952
24959
|
collectCheckConstraintAlterations(desiredConstraints, currentConstraints, alterations) {
|
|
24953
|
-
const
|
|
24954
|
-
const currentMap = new Map(currentConstraints.map((c) => [
|
|
24955
|
-
const desiredMap = new Map(desiredConstraints.map((c) => [
|
|
24960
|
+
const normalizeExpression2 = (expr) => expr.replace(/\s+/g, " ").trim();
|
|
24961
|
+
const currentMap = new Map(currentConstraints.map((c) => [normalizeExpression2(c.expression), c]));
|
|
24962
|
+
const desiredMap = new Map(desiredConstraints.map((c) => [normalizeExpression2(c.expression), c]));
|
|
24956
24963
|
for (const [key, constraint] of currentMap) {
|
|
24957
24964
|
if (!desiredMap.has(key) && constraint.name) {
|
|
24958
24965
|
alterations.push({
|
|
@@ -25189,27 +25196,32 @@ class MigrationExecutor {
|
|
|
25189
25196
|
spinner.stopAndPersist({ symbol: "✔", text: `Applied concurrent change (${elapsed}s)` });
|
|
25190
25197
|
} catch (error2) {
|
|
25191
25198
|
spinner.stopAndPersist({ symbol: "✗", text: "Failed to apply concurrent change" });
|
|
25192
|
-
|
|
25199
|
+
if (error2 && typeof error2 === "object" && "code" in error2) {
|
|
25200
|
+
const pgError = error2;
|
|
25201
|
+
throw new MigrationError(pgError.message || "Concurrent statement failed", statement, {
|
|
25202
|
+
code: pgError.code,
|
|
25203
|
+
detail: pgError.detail,
|
|
25204
|
+
hint: pgError.hint,
|
|
25205
|
+
position: pgError.position
|
|
25206
|
+
});
|
|
25207
|
+
}
|
|
25208
|
+
throw new MigrationError(error2 instanceof Error ? error2.message : String(error2), statement);
|
|
25193
25209
|
}
|
|
25194
25210
|
}
|
|
25195
25211
|
}
|
|
25196
25212
|
} catch (error2) {
|
|
25213
|
+
if (error2 instanceof MigrationError) {
|
|
25214
|
+
throw error2;
|
|
25215
|
+
}
|
|
25197
25216
|
if (error2 && typeof error2 === "object" && "code" in error2) {
|
|
25198
25217
|
const pgError = error2;
|
|
25199
|
-
|
|
25200
|
-
if (pgError.message) {
|
|
25201
|
-
failedStatement = undefined;
|
|
25202
|
-
}
|
|
25203
|
-
throw new MigrationError(pgError.message || "Database migration failed", failedStatement, {
|
|
25218
|
+
throw new MigrationError(pgError.message || "Database migration failed", undefined, {
|
|
25204
25219
|
code: pgError.code,
|
|
25205
25220
|
detail: pgError.detail,
|
|
25206
25221
|
hint: pgError.hint,
|
|
25207
25222
|
position: pgError.position
|
|
25208
25223
|
});
|
|
25209
25224
|
}
|
|
25210
|
-
if (error2 instanceof MigrationError) {
|
|
25211
|
-
throw error2;
|
|
25212
|
-
}
|
|
25213
25225
|
throw new MigrationError(error2 instanceof Error ? error2.message : String(error2));
|
|
25214
25226
|
}
|
|
25215
25227
|
}
|
|
@@ -25279,18 +25291,13 @@ class EnumHandler {
|
|
|
25279
25291
|
}
|
|
25280
25292
|
return { transactional, concurrent };
|
|
25281
25293
|
}
|
|
25282
|
-
|
|
25294
|
+
generateRemovalStatements(desiredEnums, currentEnums) {
|
|
25283
25295
|
const statements = [];
|
|
25284
25296
|
const desiredEnumNames = new Set(desiredEnums.map((e) => e.name));
|
|
25285
25297
|
for (const currentEnum of currentEnums) {
|
|
25286
25298
|
if (!desiredEnumNames.has(currentEnum.name)) {
|
|
25287
|
-
|
|
25288
|
-
|
|
25289
|
-
statements.push(generateDropTypeSQL(currentEnum.name, currentEnum.schema));
|
|
25290
|
-
Logger.info(`Dropping unused ENUM type '${currentEnum.name}'`);
|
|
25291
|
-
} else {
|
|
25292
|
-
Logger.warning(`ENUM type '${currentEnum.name}' is not in schema but is still referenced by table columns. ` + `Cannot auto-drop. Remove column references first.`);
|
|
25293
|
-
}
|
|
25299
|
+
statements.push(generateDropTypeSQL(currentEnum.name, currentEnum.schema));
|
|
25300
|
+
Logger.info(`Dropping ENUM type '${currentEnum.name}'`);
|
|
25294
25301
|
}
|
|
25295
25302
|
}
|
|
25296
25303
|
return statements;
|
|
@@ -25328,14 +25335,6 @@ class EnumHandler {
|
|
|
25328
25335
|
}
|
|
25329
25336
|
return statements;
|
|
25330
25337
|
}
|
|
25331
|
-
async isTypeUsed(enumName, client, schemas) {
|
|
25332
|
-
const result = await client.query(`
|
|
25333
|
-
SELECT COUNT(*) as usage_count
|
|
25334
|
-
FROM information_schema.columns
|
|
25335
|
-
WHERE udt_name = $1 AND table_schema = ANY($2::text[])
|
|
25336
|
-
`, [enumName, schemas]);
|
|
25337
|
-
return parseInt(result.rows[0].usage_count) > 0;
|
|
25338
|
-
}
|
|
25339
25338
|
}
|
|
25340
25339
|
// src/core/schema/handlers/extension-handler.ts
|
|
25341
25340
|
class ExtensionHandler {
|
|
@@ -25380,72 +25379,77 @@ class ExtensionHandler {
|
|
|
25380
25379
|
return builder.build() + ";";
|
|
25381
25380
|
}
|
|
25382
25381
|
}
|
|
25383
|
-
// src/core/schema/handlers/
|
|
25384
|
-
|
|
25385
|
-
|
|
25386
|
-
|
|
25387
|
-
|
|
25388
|
-
|
|
25389
|
-
|
|
25390
|
-
|
|
25391
|
-
|
|
25392
|
-
|
|
25393
|
-
}
|
|
25394
|
-
}
|
|
25395
|
-
|
|
25396
|
-
|
|
25397
|
-
|
|
25398
|
-
|
|
25399
|
-
|
|
25382
|
+
// src/core/schema/handlers/base-handler.ts
|
|
25383
|
+
function generateStatements(desired, current, config) {
|
|
25384
|
+
const statements = [];
|
|
25385
|
+
const currentMap = new Map(current.map((obj) => [config.getKey(obj), obj]));
|
|
25386
|
+
const desiredKeys = new Set(desired.map((obj) => config.getKey(obj)));
|
|
25387
|
+
const getLogName = config.getLogName ?? config.getKey;
|
|
25388
|
+
for (const curr of current) {
|
|
25389
|
+
const shouldManage = config.shouldManage?.(curr) ?? true;
|
|
25390
|
+
if (!desiredKeys.has(config.getKey(curr)) && shouldManage) {
|
|
25391
|
+
statements.push(config.generateDrop(curr));
|
|
25392
|
+
Logger.info(`Dropping ${config.name} '${getLogName(curr)}'`);
|
|
25393
|
+
}
|
|
25394
|
+
}
|
|
25395
|
+
for (const des of desired) {
|
|
25396
|
+
const key = config.getKey(des);
|
|
25397
|
+
const curr = currentMap.get(key);
|
|
25398
|
+
const shouldManage = config.shouldManage?.(curr ?? des) ?? true;
|
|
25399
|
+
if (!shouldManage) {
|
|
25400
|
+
Logger.info(`${config.name} '${getLogName(des)}' is owned by a table column, skipping`);
|
|
25401
|
+
continue;
|
|
25402
|
+
}
|
|
25403
|
+
if (!curr) {
|
|
25404
|
+
statements.push(config.generateCreate(des));
|
|
25405
|
+
Logger.info(`Creating ${config.name} '${getLogName(des)}'`);
|
|
25406
|
+
} else if (config.needsUpdate(des, curr)) {
|
|
25407
|
+
if (config.generateUpdate) {
|
|
25408
|
+
statements.push(config.generateUpdate(des));
|
|
25400
25409
|
} else {
|
|
25401
|
-
|
|
25402
|
-
|
|
25403
|
-
statements.push(generateCreateFunctionSQL(desiredFunc));
|
|
25404
|
-
Logger.info(`Updating function '${desiredFunc.name}'`);
|
|
25405
|
-
} else {
|
|
25406
|
-
Logger.info(`Function '${desiredFunc.name}' is up to date, skipping`);
|
|
25407
|
-
}
|
|
25410
|
+
statements.push(config.generateDrop(curr));
|
|
25411
|
+
statements.push(config.generateCreate(des));
|
|
25408
25412
|
}
|
|
25413
|
+
Logger.info(`Updating ${config.name} '${getLogName(des)}'`);
|
|
25414
|
+
} else {
|
|
25415
|
+
Logger.info(`${config.name} '${getLogName(des)}' is up to date, skipping`);
|
|
25409
25416
|
}
|
|
25410
|
-
return statements;
|
|
25411
25417
|
}
|
|
25412
|
-
|
|
25413
|
-
|
|
25414
|
-
|
|
25418
|
+
return statements;
|
|
25419
|
+
}
|
|
25420
|
+
|
|
25421
|
+
// src/core/schema/handlers/function-handler.ts
|
|
25422
|
+
function normalizeBody(body) {
|
|
25423
|
+
return body.replace(/\s+/g, " ").trim();
|
|
25424
|
+
}
|
|
25425
|
+
var config = {
|
|
25426
|
+
name: "function",
|
|
25427
|
+
getKey: (f) => f.name,
|
|
25428
|
+
generateDrop: generateDropFunctionSQL,
|
|
25429
|
+
generateCreate: generateCreateFunctionSQL,
|
|
25430
|
+
needsUpdate: (desired, current) => normalizeBody(desired.body) !== normalizeBody(current.body) || desired.returnType !== current.returnType || desired.language !== current.language || desired.volatility !== current.volatility
|
|
25431
|
+
};
|
|
25432
|
+
|
|
25433
|
+
class FunctionHandler {
|
|
25434
|
+
generateStatements(desiredFunctions, currentFunctions) {
|
|
25435
|
+
return generateStatements(desiredFunctions, currentFunctions, config);
|
|
25415
25436
|
}
|
|
25416
25437
|
}
|
|
25417
25438
|
// src/core/schema/handlers/procedure-handler.ts
|
|
25439
|
+
function normalizeBody2(body) {
|
|
25440
|
+
return body.replace(/\s+/g, " ").trim();
|
|
25441
|
+
}
|
|
25442
|
+
var config2 = {
|
|
25443
|
+
name: "procedure",
|
|
25444
|
+
getKey: (p) => p.name,
|
|
25445
|
+
generateDrop: generateDropProcedureSQL,
|
|
25446
|
+
generateCreate: generateCreateProcedureSQL,
|
|
25447
|
+
needsUpdate: (desired, current) => normalizeBody2(desired.body) !== normalizeBody2(current.body) || desired.language !== current.language
|
|
25448
|
+
};
|
|
25449
|
+
|
|
25418
25450
|
class ProcedureHandler {
|
|
25419
25451
|
generateStatements(desiredProcedures, currentProcedures) {
|
|
25420
|
-
|
|
25421
|
-
const currentProcedureMap = new Map(currentProcedures.map((p) => [p.name, p]));
|
|
25422
|
-
const desiredProcedureNames = new Set(desiredProcedures.map((p) => p.name));
|
|
25423
|
-
for (const currentProc of currentProcedures) {
|
|
25424
|
-
if (!desiredProcedureNames.has(currentProc.name)) {
|
|
25425
|
-
statements.push(generateDropProcedureSQL(currentProc));
|
|
25426
|
-
Logger.info(`Dropping procedure '${currentProc.name}'`);
|
|
25427
|
-
}
|
|
25428
|
-
}
|
|
25429
|
-
for (const desiredProc of desiredProcedures) {
|
|
25430
|
-
const currentProc = currentProcedureMap.get(desiredProc.name);
|
|
25431
|
-
if (!currentProc) {
|
|
25432
|
-
statements.push(generateCreateProcedureSQL(desiredProc));
|
|
25433
|
-
Logger.info(`Creating procedure '${desiredProc.name}'`);
|
|
25434
|
-
} else {
|
|
25435
|
-
if (this.needsUpdate(desiredProc, currentProc)) {
|
|
25436
|
-
statements.push(generateDropProcedureSQL(currentProc));
|
|
25437
|
-
statements.push(generateCreateProcedureSQL(desiredProc));
|
|
25438
|
-
Logger.info(`Updating procedure '${desiredProc.name}'`);
|
|
25439
|
-
} else {
|
|
25440
|
-
Logger.info(`Procedure '${desiredProc.name}' is up to date, skipping`);
|
|
25441
|
-
}
|
|
25442
|
-
}
|
|
25443
|
-
}
|
|
25444
|
-
return statements;
|
|
25445
|
-
}
|
|
25446
|
-
needsUpdate(desired, current) {
|
|
25447
|
-
const normalizeBody = (body) => body.replace(/\s+/g, " ").trim();
|
|
25448
|
-
return normalizeBody(desired.body) !== normalizeBody(current.body) || desired.language !== current.language;
|
|
25452
|
+
return generateStatements(desiredProcedures, currentProcedures, config2);
|
|
25449
25453
|
}
|
|
25450
25454
|
}
|
|
25451
25455
|
// src/core/schema/handlers/schema-handler.ts
|
|
@@ -25473,123 +25477,51 @@ class SchemaHandler {
|
|
|
25473
25477
|
}
|
|
25474
25478
|
}
|
|
25475
25479
|
// src/core/schema/handlers/sequence-handler.ts
|
|
25480
|
+
var config3 = {
|
|
25481
|
+
name: "sequence",
|
|
25482
|
+
getKey: (s) => s.name,
|
|
25483
|
+
generateDrop: (s) => generateDropSequenceSQL(s.name),
|
|
25484
|
+
generateCreate: generateCreateSequenceSQL,
|
|
25485
|
+
shouldManage: (s) => !s.ownedBy,
|
|
25486
|
+
needsUpdate: (desired, current) => desired.increment !== current.increment || desired.minValue !== current.minValue || desired.maxValue !== current.maxValue || desired.start !== current.start || desired.cache !== current.cache || desired.cycle !== current.cycle
|
|
25487
|
+
};
|
|
25488
|
+
|
|
25476
25489
|
class SequenceHandler {
|
|
25477
25490
|
generateStatements(desiredSequences, currentSequences) {
|
|
25478
|
-
|
|
25479
|
-
const currentSequenceMap = new Map(currentSequences.map((s) => [s.name, s]));
|
|
25480
|
-
const desiredSequenceNames = new Set(desiredSequences.map((s) => s.name));
|
|
25481
|
-
for (const currentSeq of currentSequences) {
|
|
25482
|
-
if (!desiredSequenceNames.has(currentSeq.name) && !currentSeq.ownedBy) {
|
|
25483
|
-
statements.push(generateDropSequenceSQL(currentSeq.name));
|
|
25484
|
-
Logger.info(`Dropping sequence '${currentSeq.name}'`);
|
|
25485
|
-
}
|
|
25486
|
-
}
|
|
25487
|
-
for (const desiredSeq of desiredSequences) {
|
|
25488
|
-
const currentSeq = currentSequenceMap.get(desiredSeq.name);
|
|
25489
|
-
if (!currentSeq) {
|
|
25490
|
-
statements.push(generateCreateSequenceSQL(desiredSeq));
|
|
25491
|
-
Logger.info(`Creating sequence '${desiredSeq.name}'`);
|
|
25492
|
-
} else if (!currentSeq.ownedBy) {
|
|
25493
|
-
if (this.needsUpdate(desiredSeq, currentSeq)) {
|
|
25494
|
-
statements.push(generateDropSequenceSQL(currentSeq.name));
|
|
25495
|
-
statements.push(generateCreateSequenceSQL(desiredSeq));
|
|
25496
|
-
Logger.info(`Updating sequence '${desiredSeq.name}'`);
|
|
25497
|
-
} else {
|
|
25498
|
-
Logger.info(`Sequence '${desiredSeq.name}' is up to date, skipping`);
|
|
25499
|
-
}
|
|
25500
|
-
} else {
|
|
25501
|
-
Logger.info(`Sequence '${desiredSeq.name}' is owned by a table column, skipping`);
|
|
25502
|
-
}
|
|
25503
|
-
}
|
|
25504
|
-
return statements;
|
|
25505
|
-
}
|
|
25506
|
-
needsUpdate(desired, current) {
|
|
25507
|
-
return desired.increment !== current.increment || desired.minValue !== current.minValue || desired.maxValue !== current.maxValue || desired.start !== current.start || desired.cache !== current.cache || desired.cycle !== current.cycle;
|
|
25491
|
+
return generateStatements(desiredSequences, currentSequences, config3);
|
|
25508
25492
|
}
|
|
25509
25493
|
}
|
|
25510
25494
|
// src/core/schema/handlers/trigger-handler.ts
|
|
25495
|
+
var config4 = {
|
|
25496
|
+
name: "trigger",
|
|
25497
|
+
getKey: (t) => `${t.tableName}.${t.name}`,
|
|
25498
|
+
getLogName: (t) => `${t.name}' on '${t.tableName}`,
|
|
25499
|
+
generateDrop: generateDropTriggerSQL,
|
|
25500
|
+
generateCreate: generateCreateTriggerSQL,
|
|
25501
|
+
needsUpdate: (desired, current) => desired.timing !== current.timing || desired.forEach !== current.forEach || desired.functionName !== current.functionName || JSON.stringify(desired.events) !== JSON.stringify(current.events)
|
|
25502
|
+
};
|
|
25503
|
+
|
|
25511
25504
|
class TriggerHandler {
|
|
25512
25505
|
generateStatements(desiredTriggers, currentTriggers) {
|
|
25513
|
-
|
|
25514
|
-
const currentTriggerMap = new Map(currentTriggers.map((t) => [`${t.tableName}.${t.name}`, t]));
|
|
25515
|
-
const desiredTriggerKeys = new Set(desiredTriggers.map((t) => `${t.tableName}.${t.name}`));
|
|
25516
|
-
for (const currentTrig of currentTriggers) {
|
|
25517
|
-
const key = `${currentTrig.tableName}.${currentTrig.name}`;
|
|
25518
|
-
if (!desiredTriggerKeys.has(key)) {
|
|
25519
|
-
statements.push(generateDropTriggerSQL(currentTrig));
|
|
25520
|
-
Logger.info(`Dropping trigger '${currentTrig.name}' on '${currentTrig.tableName}'`);
|
|
25521
|
-
}
|
|
25522
|
-
}
|
|
25523
|
-
for (const desiredTrig of desiredTriggers) {
|
|
25524
|
-
const key = `${desiredTrig.tableName}.${desiredTrig.name}`;
|
|
25525
|
-
const currentTrig = currentTriggerMap.get(key);
|
|
25526
|
-
if (!currentTrig) {
|
|
25527
|
-
statements.push(generateCreateTriggerSQL(desiredTrig));
|
|
25528
|
-
Logger.info(`Creating trigger '${desiredTrig.name}' on '${desiredTrig.tableName}'`);
|
|
25529
|
-
} else {
|
|
25530
|
-
if (this.needsUpdate(desiredTrig, currentTrig)) {
|
|
25531
|
-
statements.push(generateDropTriggerSQL(currentTrig));
|
|
25532
|
-
statements.push(generateCreateTriggerSQL(desiredTrig));
|
|
25533
|
-
Logger.info(`Updating trigger '${desiredTrig.name}' on '${desiredTrig.tableName}'`);
|
|
25534
|
-
} else {
|
|
25535
|
-
Logger.info(`Trigger '${desiredTrig.name}' is up to date, skipping`);
|
|
25536
|
-
}
|
|
25537
|
-
}
|
|
25538
|
-
}
|
|
25539
|
-
return statements;
|
|
25540
|
-
}
|
|
25541
|
-
needsUpdate(desired, current) {
|
|
25542
|
-
return desired.timing !== current.timing || desired.forEach !== current.forEach || desired.functionName !== current.functionName || JSON.stringify(desired.events) !== JSON.stringify(current.events);
|
|
25506
|
+
return generateStatements(desiredTriggers, currentTriggers, config4);
|
|
25543
25507
|
}
|
|
25544
25508
|
}
|
|
25545
25509
|
// src/core/schema/handlers/view-handler.ts
|
|
25510
|
+
function normalizeDefinition(def) {
|
|
25511
|
+
return def.replace(/\s+/g, " ").trim();
|
|
25512
|
+
}
|
|
25513
|
+
var config5 = {
|
|
25514
|
+
name: "view",
|
|
25515
|
+
getKey: (v) => v.name,
|
|
25516
|
+
generateDrop: (v) => generateDropViewSQL(v.name, v.materialized),
|
|
25517
|
+
generateCreate: generateCreateViewSQL,
|
|
25518
|
+
generateUpdate: generateCreateOrReplaceViewSQL,
|
|
25519
|
+
needsUpdate: (desired, current) => desired.materialized !== current.materialized || normalizeDefinition(desired.definition) !== normalizeDefinition(current.definition) || desired.checkOption !== current.checkOption || desired.securityBarrier !== current.securityBarrier
|
|
25520
|
+
};
|
|
25521
|
+
|
|
25546
25522
|
class ViewHandler {
|
|
25547
25523
|
generateStatements(desiredViews, currentViews) {
|
|
25548
|
-
|
|
25549
|
-
const currentViewMap = new Map(currentViews.map((v) => [v.name, v]));
|
|
25550
|
-
const desiredViewNames = new Set(desiredViews.map((v) => v.name));
|
|
25551
|
-
for (const currentView of currentViews) {
|
|
25552
|
-
if (!desiredViewNames.has(currentView.name)) {
|
|
25553
|
-
statements.push(generateDropViewSQL(currentView.name, currentView.materialized));
|
|
25554
|
-
Logger.info(`Dropping view '${currentView.name}'`);
|
|
25555
|
-
}
|
|
25556
|
-
}
|
|
25557
|
-
for (const desiredView of desiredViews) {
|
|
25558
|
-
const currentView = currentViewMap.get(desiredView.name);
|
|
25559
|
-
if (!currentView) {
|
|
25560
|
-
statements.push(generateCreateViewSQL(desiredView));
|
|
25561
|
-
Logger.info(`Creating view '${desiredView.name}'`);
|
|
25562
|
-
} else {
|
|
25563
|
-
if (this.needsUpdate(desiredView, currentView)) {
|
|
25564
|
-
statements.push(generateCreateOrReplaceViewSQL(desiredView));
|
|
25565
|
-
Logger.info(`Updating view '${desiredView.name}'`);
|
|
25566
|
-
} else {
|
|
25567
|
-
Logger.info(`View '${desiredView.name}' is up to date, skipping`);
|
|
25568
|
-
}
|
|
25569
|
-
}
|
|
25570
|
-
}
|
|
25571
|
-
return statements;
|
|
25572
|
-
}
|
|
25573
|
-
needsUpdate(desired, current) {
|
|
25574
|
-
if (desired.materialized !== current.materialized) {
|
|
25575
|
-
return true;
|
|
25576
|
-
}
|
|
25577
|
-
const normalizeDefinition = (def) => def.replace(/\s+/g, " ").trim();
|
|
25578
|
-
const normalizedDesired = normalizeDefinition(desired.definition);
|
|
25579
|
-
const normalizedCurrent = normalizeDefinition(current.definition);
|
|
25580
|
-
if (normalizedDesired !== normalizedCurrent) {
|
|
25581
|
-
Logger.info(`View '${desired.name}' needs update:`);
|
|
25582
|
-
Logger.info(` Desired: ${normalizedDesired.substring(0, 100)}...`);
|
|
25583
|
-
Logger.info(` Current: ${normalizedCurrent.substring(0, 100)}...`);
|
|
25584
|
-
return true;
|
|
25585
|
-
}
|
|
25586
|
-
if (desired.checkOption !== current.checkOption) {
|
|
25587
|
-
return true;
|
|
25588
|
-
}
|
|
25589
|
-
if (desired.securityBarrier !== current.securityBarrier) {
|
|
25590
|
-
return true;
|
|
25591
|
-
}
|
|
25592
|
-
return false;
|
|
25524
|
+
return generateStatements(desiredViews, currentViews, config5);
|
|
25593
25525
|
}
|
|
25594
25526
|
}
|
|
25595
25527
|
// src/core/schema/service.ts
|
|
@@ -25741,15 +25673,25 @@ class SchemaService {
|
|
|
25741
25673
|
return;
|
|
25742
25674
|
}
|
|
25743
25675
|
}
|
|
25744
|
-
|
|
25745
|
-
|
|
25746
|
-
|
|
25747
|
-
|
|
25748
|
-
|
|
25749
|
-
|
|
25750
|
-
|
|
25751
|
-
|
|
25752
|
-
|
|
25676
|
+
const enumRemovalStatements = this.enumHandler.generateRemovalStatements(desiredEnums, currentEnums);
|
|
25677
|
+
const combinedPlan = {
|
|
25678
|
+
transactional: [
|
|
25679
|
+
...sequenceStatements,
|
|
25680
|
+
...plan.transactional,
|
|
25681
|
+
...plan.deferred,
|
|
25682
|
+
...enumRemovalStatements,
|
|
25683
|
+
...functionStatements,
|
|
25684
|
+
...procedureStatements,
|
|
25685
|
+
...viewStatements,
|
|
25686
|
+
...triggerStatements,
|
|
25687
|
+
...commentStatements,
|
|
25688
|
+
...extensionDropStatements
|
|
25689
|
+
],
|
|
25690
|
+
concurrent: plan.concurrent,
|
|
25691
|
+
deferred: [],
|
|
25692
|
+
hasChanges: true
|
|
25693
|
+
};
|
|
25694
|
+
await this.executor.executePlan(client, combinedPlan, autoApprove);
|
|
25753
25695
|
} finally {
|
|
25754
25696
|
if (lockOptions && !dryRun) {
|
|
25755
25697
|
await this.databaseService.releaseAdvisoryLock(client, lockOptions.lockName);
|
|
@@ -25782,32 +25724,6 @@ class SchemaService {
|
|
|
25782
25724
|
return await this.parser.parseSchemaFile(input);
|
|
25783
25725
|
}
|
|
25784
25726
|
}
|
|
25785
|
-
async executeStatements(client, statements, autoApprove) {
|
|
25786
|
-
if (statements.length === 0)
|
|
25787
|
-
return;
|
|
25788
|
-
await this.executor.executePlan(client, {
|
|
25789
|
-
transactional: statements,
|
|
25790
|
-
concurrent: [],
|
|
25791
|
-
deferred: [],
|
|
25792
|
-
hasChanges: true
|
|
25793
|
-
}, autoApprove);
|
|
25794
|
-
}
|
|
25795
|
-
async executeEnumRemovals(client, desiredEnums, currentEnums, schemas) {
|
|
25796
|
-
const statements = await this.enumHandler.generateRemovalStatements(desiredEnums, currentEnums, client, schemas);
|
|
25797
|
-
for (const statement of statements) {
|
|
25798
|
-
try {
|
|
25799
|
-
await client.query(statement);
|
|
25800
|
-
} catch (error2) {
|
|
25801
|
-
if (error2.code === "2BP01") {
|
|
25802
|
-
const match = statement.match(/DROP TYPE\s+(?:"?(\w+)"?\.)?"?(\w+)"?/i);
|
|
25803
|
-
const typeName = match ? match[1] ? `${match[1]}.${match[2]}` : match[2] : "unknown";
|
|
25804
|
-
Logger.warning(`Could not drop ENUM '${typeName}': now in use (concurrent change). Will retry next migration.`);
|
|
25805
|
-
} else {
|
|
25806
|
-
throw error2;
|
|
25807
|
-
}
|
|
25808
|
-
}
|
|
25809
|
-
}
|
|
25810
|
-
}
|
|
25811
25727
|
validateSchemaReferences(managedSchemas, tables, enums, views, functions, procedures, triggers, sequences) {
|
|
25812
25728
|
const errors = [];
|
|
25813
25729
|
const checkSchema = (objType, objName, objSchema) => {
|
|
@@ -25852,8 +25768,8 @@ var defaults = import_lib.default.defaults;
|
|
|
25852
25768
|
// src/core/database/client.ts
|
|
25853
25769
|
class DatabaseService {
|
|
25854
25770
|
config;
|
|
25855
|
-
constructor(
|
|
25856
|
-
this.config =
|
|
25771
|
+
constructor(config6) {
|
|
25772
|
+
this.config = config6;
|
|
25857
25773
|
}
|
|
25858
25774
|
async createClient() {
|
|
25859
25775
|
const client = new Client(this.config);
|
|
@@ -25906,6 +25822,7 @@ class DatabaseService {
|
|
|
25906
25822
|
const timeoutMs = options.lockTimeout;
|
|
25907
25823
|
const lockKeyResult = await client.query("SELECT hashtext($1)::bigint as lock_key", [options.lockName]);
|
|
25908
25824
|
const lockKey = lockKeyResult.rows[0].lock_key;
|
|
25825
|
+
let delay = 100;
|
|
25909
25826
|
while (true) {
|
|
25910
25827
|
const result = await client.query("SELECT pg_try_advisory_lock($1) as acquired", [lockKey]);
|
|
25911
25828
|
if (result.rows[0].acquired) {
|
|
@@ -25915,7 +25832,8 @@ class DatabaseService {
|
|
|
25915
25832
|
if (elapsed >= timeoutMs) {
|
|
25916
25833
|
throw new MigrationError(`Failed to acquire advisory lock '${options.lockName}' within ${timeoutMs / 1000}s. Another migration may be in progress. Please wait and try again.`);
|
|
25917
25834
|
}
|
|
25918
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
25835
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
25836
|
+
delay = Math.min(delay * 2, 5000);
|
|
25919
25837
|
}
|
|
25920
25838
|
}
|
|
25921
25839
|
async releaseAdvisoryLock(client, lockName) {
|
|
@@ -25930,8 +25848,8 @@ class DatabaseService {
|
|
|
25930
25848
|
}
|
|
25931
25849
|
|
|
25932
25850
|
// src/cli/commands/apply.ts
|
|
25933
|
-
async function applyCommand(options,
|
|
25934
|
-
const databaseService = new DatabaseService(
|
|
25851
|
+
async function applyCommand(options, config6) {
|
|
25852
|
+
const databaseService = new DatabaseService(config6);
|
|
25935
25853
|
const schemaService = new SchemaService(databaseService);
|
|
25936
25854
|
const lockTimeout = parseInt(options.lockTimeout, 10);
|
|
25937
25855
|
if (isNaN(lockTimeout) || lockTimeout <= 0) {
|
|
@@ -25946,7 +25864,7 @@ async function applyCommand(options, config) {
|
|
|
25946
25864
|
// package.json
|
|
25947
25865
|
var package_default = {
|
|
25948
25866
|
name: "pgterra",
|
|
25949
|
-
version: "0.2.
|
|
25867
|
+
version: "0.2.13",
|
|
25950
25868
|
description: "Declarative schema management for Postgres",
|
|
25951
25869
|
keywords: [
|
|
25952
25870
|
"postgres",
|
|
@@ -26042,8 +25960,8 @@ async function runCLI() {
|
|
|
26042
25960
|
const program2 = new Command;
|
|
26043
25961
|
program2.name("pgterra").description("Declarative schema management for Postgres").version(package_default.version, "-v, --version");
|
|
26044
25962
|
program2.command("apply").description("Apply schema changes to database").requiredOption("-f, --file <file>", "Schema file path").option("-u, --url <url>", "Database connection string (overrides DATABASE_URL)").option("-s, --schema <schema>", "Database schema to manage (can be specified multiple times, defaults to 'public')", collectSchemas, []).option("--auto-approve", "Skip confirmation prompt").option("--dry-run", "Show migration plan without executing changes").option("--lock-name <name>", "Advisory lock name to prevent concurrent migrations", "pgterra_migrate_execute").option("--lock-timeout <seconds>", "Maximum time to wait for advisory lock in seconds", "10").action(async (options) => {
|
|
26045
|
-
const
|
|
26046
|
-
await applyCommand(options,
|
|
25963
|
+
const config6 = loadConfig(options.url);
|
|
25964
|
+
await applyCommand(options, config6);
|
|
26047
25965
|
});
|
|
26048
25966
|
await program2.parseAsync();
|
|
26049
25967
|
}
|