orez 0.2.30 → 0.2.32
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/cf-do/worker.d.ts +4 -0
- package/dist/cf-do/worker.d.ts.map +1 -1
- package/dist/cf-do/worker.js +45 -0
- package/dist/cf-do/worker.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/pg-proxy-do-backend.d.ts.map +1 -1
- package/dist/pg-proxy-do-backend.js +151 -18
- package/dist/pg-proxy-do-backend.js.map +1 -1
- package/package.json +2 -2
|
@@ -1033,6 +1033,18 @@ function equalityExpr(left, right) {
|
|
|
1033
1033
|
},
|
|
1034
1034
|
};
|
|
1035
1035
|
}
|
|
1036
|
+
function numericLiteralValue(value) {
|
|
1037
|
+
const literal = astLiteralValue(unwrapTypeCast(value));
|
|
1038
|
+
if (typeof literal !== 'number')
|
|
1039
|
+
return null;
|
|
1040
|
+
return Number.isFinite(literal) ? literal : null;
|
|
1041
|
+
}
|
|
1042
|
+
function isDivisionByMillis(value) {
|
|
1043
|
+
const expr = unwrapTypeCast(value)?.A_Expr;
|
|
1044
|
+
if (expr?.kind !== 'AEXPR_OP' || operatorName(expr) !== '/')
|
|
1045
|
+
return false;
|
|
1046
|
+
return numericLiteralValue(expr.rexpr) === 1000;
|
|
1047
|
+
}
|
|
1036
1048
|
function startsWithExpr(func, context) {
|
|
1037
1049
|
const args = func.args ?? [];
|
|
1038
1050
|
if (args.length < 2)
|
|
@@ -1130,6 +1142,14 @@ function postgresTimestampText(value) {
|
|
|
1130
1142
|
const withSpace = raw.replace('T', ' ');
|
|
1131
1143
|
return withSpace.endsWith('Z') ? `${withSpace.slice(0, -1)}+00` : withSpace;
|
|
1132
1144
|
}
|
|
1145
|
+
function epochMillisParamValue(value) {
|
|
1146
|
+
const millis = timestampMillisValue(value);
|
|
1147
|
+
if (millis !== null)
|
|
1148
|
+
return millis;
|
|
1149
|
+
const raw = value instanceof Date ? value.toISOString() : String(value);
|
|
1150
|
+
const date = new Date(raw);
|
|
1151
|
+
return Number.isFinite(date.getTime()) ? date.getTime() : value;
|
|
1152
|
+
}
|
|
1133
1153
|
function paramNumbersForOids(oids, matches) {
|
|
1134
1154
|
const numbers = new Set();
|
|
1135
1155
|
for (let index = 0; index < oids.length; index++) {
|
|
@@ -1750,8 +1770,12 @@ function rewriteNode(value, context) {
|
|
|
1750
1770
|
return rewriteNode(value.FuncCall.args[0], context);
|
|
1751
1771
|
}
|
|
1752
1772
|
if (name === 'to_timestamp' && value.FuncCall.args?.[0]) {
|
|
1773
|
+
const arg = value.FuncCall.args[0];
|
|
1774
|
+
if (isDivisionByMillis(arg)) {
|
|
1775
|
+
collectParamRefs(arg, (paramNumber) => context?.epochMillisParamNumbers?.add(paramNumber));
|
|
1776
|
+
}
|
|
1753
1777
|
return funcCallNode('datetime', [
|
|
1754
|
-
rewriteNode(
|
|
1778
|
+
rewriteNode(arg, context),
|
|
1755
1779
|
stringConst('unixepoch'),
|
|
1756
1780
|
]);
|
|
1757
1781
|
}
|
|
@@ -2201,19 +2225,45 @@ function normalizeAlterTable(stmt) {
|
|
|
2201
2225
|
const skipIfColumnMissingByCmd = new Map();
|
|
2202
2226
|
const schemaColumnsByCmd = new Map();
|
|
2203
2227
|
const metadataOnlySchemaColumns = [];
|
|
2228
|
+
const syntheticStatements = [];
|
|
2204
2229
|
for (const cmdNode of stmt.cmds ?? []) {
|
|
2205
2230
|
const cmd = cmdNode.AlterTableCmd;
|
|
2206
2231
|
if (!cmd)
|
|
2207
2232
|
continue;
|
|
2233
|
+
if (cmd.subtype === 'AT_AddConstraint') {
|
|
2234
|
+
const constraint = cmd.def?.Constraint;
|
|
2235
|
+
const contype = constraint?.contype;
|
|
2236
|
+
if (table &&
|
|
2237
|
+
(contype === 'CONSTR_UNIQUE' || contype === 'CONSTR_PRIMARY') &&
|
|
2238
|
+
Array.isArray(constraint.keys)) {
|
|
2239
|
+
const columns = constraint.keys.map(stringValue).filter(Boolean);
|
|
2240
|
+
if (columns.length) {
|
|
2241
|
+
const name = constraint.conname ||
|
|
2242
|
+
`${table}_${columns.join('_')}_${contype === 'CONSTR_PRIMARY' ? 'pkey' : 'key'}`;
|
|
2243
|
+
syntheticStatements.push({
|
|
2244
|
+
sql: `CREATE UNIQUE INDEX IF NOT EXISTS ${quoteIdentifier(name)} ON ${quoteIdentifier(table)} (${columns.map(quoteIdentifier).join(', ')})`,
|
|
2245
|
+
isDDL: true,
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
continue;
|
|
2250
|
+
}
|
|
2251
|
+
if (cmd.subtype === 'AT_DropConstraint') {
|
|
2252
|
+
if (cmd.name) {
|
|
2253
|
+
syntheticStatements.push({
|
|
2254
|
+
sql: `DROP INDEX IF EXISTS ${quoteIdentifier(cmd.name)}`,
|
|
2255
|
+
isDDL: true,
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
continue;
|
|
2259
|
+
}
|
|
2208
2260
|
if (cmd.subtype === 'AT_AlterColumnType') {
|
|
2209
2261
|
const schemaColumn = schemaColumnForAlterColumnType(tableRef, cmd);
|
|
2210
2262
|
if (schemaColumn)
|
|
2211
2263
|
metadataOnlySchemaColumns.push(schemaColumn);
|
|
2212
2264
|
continue;
|
|
2213
2265
|
}
|
|
2214
|
-
if (cmd.subtype === '
|
|
2215
|
-
cmd.subtype === 'AT_DropConstraint' ||
|
|
2216
|
-
cmd.subtype === 'AT_ReplicaIdentity' ||
|
|
2266
|
+
if (cmd.subtype === 'AT_ReplicaIdentity' ||
|
|
2217
2267
|
cmd.subtype?.startsWith('AT_AlterColumn') ||
|
|
2218
2268
|
cmd.subtype === 'AT_ColumnDefault' ||
|
|
2219
2269
|
cmd.subtype === 'AT_SetNotNull' ||
|
|
@@ -2244,6 +2294,7 @@ function normalizeAlterTable(stmt) {
|
|
|
2244
2294
|
skipIfColumnMissingByCmd,
|
|
2245
2295
|
schemaColumnsByCmd,
|
|
2246
2296
|
metadataOnlySchemaColumns,
|
|
2297
|
+
syntheticStatements,
|
|
2247
2298
|
};
|
|
2248
2299
|
}
|
|
2249
2300
|
function normalizeRename(stmt) {
|
|
@@ -2927,11 +2978,47 @@ function sqliteTriggerEvents(events) {
|
|
|
2927
2978
|
function sqliteTriggerName(base, event, eventCount) {
|
|
2928
2979
|
return eventCount === 1 ? base : `${base}_${event.toLowerCase()}`;
|
|
2929
2980
|
}
|
|
2981
|
+
function threadReplyCountTriggerStatements(node) {
|
|
2982
|
+
const table = publicationTableRefForRangeVar(node.relation);
|
|
2983
|
+
if (!table || table.table !== 'message')
|
|
2984
|
+
return null;
|
|
2985
|
+
const events = sqliteTriggerEvents(Number(node.events ?? 0));
|
|
2986
|
+
if (events.length === 0)
|
|
2987
|
+
return null;
|
|
2988
|
+
return events.map((event) => {
|
|
2989
|
+
const row = event === 'DELETE' ? 'OLD' : 'NEW';
|
|
2990
|
+
const triggerName = sqliteTriggerName(node.trigname, event, events.length);
|
|
2991
|
+
return {
|
|
2992
|
+
sql: `CREATE TRIGGER IF NOT EXISTS ${quoteIdentifier(triggerName)}
|
|
2993
|
+
AFTER ${event} ON ${quoteIdentifier(table.table)}
|
|
2994
|
+
FOR EACH ROW
|
|
2995
|
+
WHEN ${row}."threadId" IS NOT NULL
|
|
2996
|
+
BEGIN
|
|
2997
|
+
UPDATE "thread"
|
|
2998
|
+
SET "replyCount" = min(11, (
|
|
2999
|
+
SELECT COUNT(*)
|
|
3000
|
+
FROM "message"
|
|
3001
|
+
WHERE "threadId" = ${row}."threadId"
|
|
3002
|
+
AND "deleted" = 0
|
|
3003
|
+
AND "type" IS DISTINCT FROM 'draft'
|
|
3004
|
+
AND "id" IS DISTINCT FROM (
|
|
3005
|
+
SELECT "messageId" FROM "thread" WHERE "id" = ${row}."threadId"
|
|
3006
|
+
)
|
|
3007
|
+
))
|
|
3008
|
+
WHERE "id" = ${row}."threadId";
|
|
3009
|
+
END`,
|
|
3010
|
+
isDDL: true,
|
|
3011
|
+
};
|
|
3012
|
+
});
|
|
3013
|
+
}
|
|
2930
3014
|
function createTriggerStatements(node, context) {
|
|
2931
3015
|
const fnName = functionName({ funcname: node.funcname });
|
|
2932
3016
|
const fn = fnName ? context?.triggerFunctions?.get(fnName) : undefined;
|
|
2933
3017
|
if (!fn)
|
|
2934
3018
|
return null;
|
|
3019
|
+
if (fnName === 'updatethreadreplycount') {
|
|
3020
|
+
return threadReplyCountTriggerStatements(node);
|
|
3021
|
+
}
|
|
2935
3022
|
if (findKeywordOutsideQuotes(fn.body, 'TG_OP') >= 0 ||
|
|
2936
3023
|
findKeywordOutsideQuotes(fn.body, 'TG_ARGV') >= 0 ||
|
|
2937
3024
|
findKeywordOutsideQuotes(fn.body, 'TG_NAME') >= 0 ||
|
|
@@ -3055,13 +3142,16 @@ function rewriteParsedStatement(version, rawStmt, context) {
|
|
|
3055
3142
|
if (nodeType === 'AlterTableStmt') {
|
|
3056
3143
|
alterMetadata = normalizeAlterTable(node);
|
|
3057
3144
|
if (!node.cmds?.length) {
|
|
3058
|
-
|
|
3059
|
-
|
|
3145
|
+
const statements = [];
|
|
3146
|
+
if (alterMetadata.metadataOnlySchemaColumns.length) {
|
|
3147
|
+
statements.push({
|
|
3060
3148
|
sql: '',
|
|
3061
3149
|
isDDL: true,
|
|
3062
3150
|
schemaColumns: alterMetadata.metadataOnlySchemaColumns,
|
|
3063
|
-
}
|
|
3064
|
-
|
|
3151
|
+
});
|
|
3152
|
+
}
|
|
3153
|
+
statements.push(...alterMetadata.syntheticStatements);
|
|
3154
|
+
return statements.length ? statements : null;
|
|
3065
3155
|
}
|
|
3066
3156
|
}
|
|
3067
3157
|
else if (nodeType === 'CreateStmt') {
|
|
@@ -3113,7 +3203,8 @@ function rewriteParsedStatement(version, rawStmt, context) {
|
|
|
3113
3203
|
else {
|
|
3114
3204
|
rewriteNode(node, context);
|
|
3115
3205
|
}
|
|
3116
|
-
if (nodeType === 'AlterTableStmt' &&
|
|
3206
|
+
if (nodeType === 'AlterTableStmt' &&
|
|
3207
|
+
(node.cmds.length > 1 || alterMetadata?.syntheticStatements.length)) {
|
|
3117
3208
|
const statements = [];
|
|
3118
3209
|
if (alterMetadata?.metadataOnlySchemaColumns.length) {
|
|
3119
3210
|
statements.push({
|
|
@@ -3122,6 +3213,7 @@ function rewriteParsedStatement(version, rawStmt, context) {
|
|
|
3122
3213
|
schemaColumns: alterMetadata.metadataOnlySchemaColumns,
|
|
3123
3214
|
});
|
|
3124
3215
|
}
|
|
3216
|
+
statements.push(...(alterMetadata?.syntheticStatements ?? []));
|
|
3125
3217
|
statements.push(...node.cmds.map((cmdNode) => {
|
|
3126
3218
|
const singleStmt = {
|
|
3127
3219
|
[nodeType]: {
|
|
@@ -3141,6 +3233,11 @@ function rewriteParsedStatement(version, rawStmt, context) {
|
|
|
3141
3233
|
...(context?.jsonParamNumbers?.size
|
|
3142
3234
|
? { jsonParamNumbers: new Set(context.jsonParamNumbers) }
|
|
3143
3235
|
: null),
|
|
3236
|
+
...(context?.epochMillisParamNumbers?.size
|
|
3237
|
+
? {
|
|
3238
|
+
epochMillisParamNumbers: new Set(context.epochMillisParamNumbers),
|
|
3239
|
+
}
|
|
3240
|
+
: null),
|
|
3144
3241
|
...(cmdSchemaColumns?.length ? { schemaColumns: cmdSchemaColumns } : null),
|
|
3145
3242
|
...(skipIfColumnExists ? { skipIfColumnExists } : null),
|
|
3146
3243
|
...(skipIfColumnMissing ? { skipIfColumnMissing } : null),
|
|
@@ -3180,6 +3277,9 @@ function rewriteParsedStatement(version, rawStmt, context) {
|
|
|
3180
3277
|
...(context?.jsonParamNumbers?.size
|
|
3181
3278
|
? { jsonParamNumbers: new Set(context.jsonParamNumbers) }
|
|
3182
3279
|
: null),
|
|
3280
|
+
...(context?.epochMillisParamNumbers?.size
|
|
3281
|
+
? { epochMillisParamNumbers: new Set(context.epochMillisParamNumbers) }
|
|
3282
|
+
: null),
|
|
3183
3283
|
...(schemaColumns.length ? { schemaColumns } : null),
|
|
3184
3284
|
...(schemaMetadataChanges.length ? { schemaMetadataChanges } : null),
|
|
3185
3285
|
...(skipIfColumnExists ? { skipIfColumnExists } : null),
|
|
@@ -4803,6 +4903,7 @@ export class DoBackend {
|
|
|
4803
4903
|
if (rewritten && !rewritten.startsWith('--')) {
|
|
4804
4904
|
const arrayParamNumbers = new Set();
|
|
4805
4905
|
const jsonParamNumbers = new Set(inferredJsonParamNumbers);
|
|
4906
|
+
const epochMillisParamNumbers = new Set();
|
|
4806
4907
|
const schemaColumns = [];
|
|
4807
4908
|
const schemaMetadataChanges = [];
|
|
4808
4909
|
const publicationChanges = [];
|
|
@@ -4813,6 +4914,9 @@ export class DoBackend {
|
|
|
4813
4914
|
for (const number of statement.jsonParamNumbers ?? []) {
|
|
4814
4915
|
jsonParamNumbers.add(number);
|
|
4815
4916
|
}
|
|
4917
|
+
for (const number of statement.epochMillisParamNumbers ?? []) {
|
|
4918
|
+
epochMillisParamNumbers.add(number);
|
|
4919
|
+
}
|
|
4816
4920
|
schemaColumns.push(...(statement.schemaColumns ?? []));
|
|
4817
4921
|
schemaMetadataChanges.push(...(statement.schemaMetadataChanges ?? []));
|
|
4818
4922
|
publicationChanges.push(...(statement.publicationChanges ?? []));
|
|
@@ -4825,6 +4929,7 @@ export class DoBackend {
|
|
|
4825
4929
|
...(arrayParamNumbers.size ? { arrayParamNumbers } : null),
|
|
4826
4930
|
...(jsonParamNumbers.size ? { jsonParamNumbers } : null),
|
|
4827
4931
|
...(timestampParamNumbers.size ? { timestampParamNumbers } : null),
|
|
4932
|
+
...(epochMillisParamNumbers.size ? { epochMillisParamNumbers } : null),
|
|
4828
4933
|
...(booleanParamNumbers.size ? { booleanParamNumbers } : null),
|
|
4829
4934
|
...(schemaColumns.length ? { schemaColumns } : null),
|
|
4830
4935
|
...(schemaMetadataChanges.length ? { schemaMetadataChanges } : null),
|
|
@@ -4841,6 +4946,13 @@ export class DoBackend {
|
|
|
4841
4946
|
? { jsonParamNumbers: inferredJsonParamNumbers }
|
|
4842
4947
|
: null),
|
|
4843
4948
|
...(timestampParamNumbers.size ? { timestampParamNumbers } : null),
|
|
4949
|
+
...(rewrittenStatements.some((statement) => statement.epochMillisParamNumbers?.size)
|
|
4950
|
+
? {
|
|
4951
|
+
epochMillisParamNumbers: new Set(rewrittenStatements.flatMap((statement) => [
|
|
4952
|
+
...(statement.epochMillisParamNumbers ?? []),
|
|
4953
|
+
])),
|
|
4954
|
+
}
|
|
4955
|
+
: null),
|
|
4844
4956
|
...(booleanParamNumbers.size ? { booleanParamNumbers } : null),
|
|
4845
4957
|
schemaColumns: rewrittenStatements.flatMap((statement) => statement.schemaColumns ?? []),
|
|
4846
4958
|
schemaMetadataChanges: rewrittenStatements.flatMap((statement) => statement.schemaMetadataChanges ?? []),
|
|
@@ -4907,7 +5019,7 @@ export class DoBackend {
|
|
|
4907
5019
|
return buildCommandComplete('SET');
|
|
4908
5020
|
try {
|
|
4909
5021
|
if (isCatalogQuery(sql)) {
|
|
4910
|
-
const catalogSql = this.inlineParams(sql, portal.params, portal.arrayParamNumbers, portal.jsonParamNumbers, portal.timestampParamNumbers, portal.booleanParamNumbers);
|
|
5022
|
+
const catalogSql = this.inlineParams(sql, portal.params, portal.arrayParamNumbers, portal.jsonParamNumbers, portal.timestampParamNumbers, portal.epochMillisParamNumbers, portal.booleanParamNumbers);
|
|
4911
5023
|
const result = await this.handleCatalogQuery(catalogSql);
|
|
4912
5024
|
return concat(buildRowDescription(result.fields), ...result.rows.map((r) => buildDataRow(r, result.fields)), buildCommandComplete(`SELECT ${result.rows.length}`));
|
|
4913
5025
|
}
|
|
@@ -4918,7 +5030,7 @@ export class DoBackend {
|
|
|
4918
5030
|
await this.snapshotTransactionWrite(statement);
|
|
4919
5031
|
const tracking = statement ? this.trackingForStatement(statement) : undefined;
|
|
4920
5032
|
const execSql = tracking?.returningSQL ?? sql;
|
|
4921
|
-
const bound = this.sqliteBoundSQL(execSql, portal.params, portal.arrayParamNumbers, portal.jsonParamNumbers, portal.timestampParamNumbers, portal.booleanParamNumbers);
|
|
5033
|
+
const bound = this.sqliteBoundSQL(execSql, portal.params, portal.arrayParamNumbers, portal.jsonParamNumbers, portal.timestampParamNumbers, portal.epochMillisParamNumbers, portal.booleanParamNumbers);
|
|
4922
5034
|
const result = await this.doExecResult(bound.sql, bound.params, tracking ? this.trackingRequest(tracking) : undefined);
|
|
4923
5035
|
if (portal.schemaColumns?.length) {
|
|
4924
5036
|
await this.applyStatementMetadata([{ sql, schemaColumns: portal.schemaColumns }]);
|
|
@@ -5043,11 +5155,12 @@ export class DoBackend {
|
|
|
5043
5155
|
return { rows: [] };
|
|
5044
5156
|
}
|
|
5045
5157
|
if (isCatalogQuery(rewritten)) {
|
|
5046
|
-
const catalogSql = this.inlineStatementParams(rewritten, params, statements, inferredJsonParamNumbers, timestampParamNumbers, booleanParamNumbers);
|
|
5158
|
+
const catalogSql = this.inlineStatementParams(rewritten, params, statements, inferredJsonParamNumbers, timestampParamNumbers, new Set(), booleanParamNumbers);
|
|
5047
5159
|
return { rows: (await this.handleCatalogQuery(catalogSql)).rows };
|
|
5048
5160
|
}
|
|
5049
5161
|
const arrayParamNumbers = new Set();
|
|
5050
5162
|
const jsonParamNumbers = new Set(inferredJsonParamNumbers);
|
|
5163
|
+
const epochMillisParamNumbers = new Set();
|
|
5051
5164
|
for (const statement of statements) {
|
|
5052
5165
|
for (const number of statement.arrayParamNumbers ?? []) {
|
|
5053
5166
|
arrayParamNumbers.add(number);
|
|
@@ -5055,14 +5168,17 @@ export class DoBackend {
|
|
|
5055
5168
|
for (const number of statement.jsonParamNumbers ?? []) {
|
|
5056
5169
|
jsonParamNumbers.add(number);
|
|
5057
5170
|
}
|
|
5171
|
+
for (const number of statement.epochMillisParamNumbers ?? []) {
|
|
5172
|
+
epochMillisParamNumbers.add(number);
|
|
5173
|
+
}
|
|
5058
5174
|
}
|
|
5059
|
-
const bound = this.sqliteBoundSQL(rewritten, params, arrayParamNumbers, jsonParamNumbers, timestampParamNumbers, booleanParamNumbers);
|
|
5175
|
+
const bound = this.sqliteBoundSQL(rewritten, params, arrayParamNumbers, jsonParamNumbers, timestampParamNumbers, epochMillisParamNumbers, booleanParamNumbers);
|
|
5060
5176
|
const statement = statements.length === 1 ? statements[0] : undefined;
|
|
5061
5177
|
if (statement)
|
|
5062
5178
|
await this.snapshotTransactionWrite(statement);
|
|
5063
5179
|
const tracking = statement ? this.trackingForStatement(statement) : undefined;
|
|
5064
5180
|
const execBound = tracking
|
|
5065
|
-
? this.sqliteBoundSQL(tracking.returningSQL, params, arrayParamNumbers, jsonParamNumbers, timestampParamNumbers, booleanParamNumbers)
|
|
5181
|
+
? this.sqliteBoundSQL(tracking.returningSQL, params, arrayParamNumbers, jsonParamNumbers, timestampParamNumbers, epochMillisParamNumbers, booleanParamNumbers)
|
|
5066
5182
|
: bound;
|
|
5067
5183
|
const result = await this.doExecResult(execBound.sql, execBound.params, tracking ? this.trackingRequest(tracking) : undefined);
|
|
5068
5184
|
await this.applyStatementMetadata(statements);
|
|
@@ -5083,11 +5199,13 @@ export class DoBackend {
|
|
|
5083
5199
|
return cached;
|
|
5084
5200
|
const arrayParamNumbers = new Set();
|
|
5085
5201
|
const jsonParamNumbers = new Set();
|
|
5202
|
+
const epochMillisParamNumbers = new Set();
|
|
5086
5203
|
const statements = rewriteSQLStatements(sql, {
|
|
5087
5204
|
skippedFunctionNames: this.skippedFunctionNames,
|
|
5088
5205
|
triggerFunctions: this.triggerFunctions,
|
|
5089
5206
|
arrayParamNumbers,
|
|
5090
5207
|
jsonParamNumbers,
|
|
5208
|
+
epochMillisParamNumbers,
|
|
5091
5209
|
});
|
|
5092
5210
|
if (this.canCacheRewrite(statements)) {
|
|
5093
5211
|
this.rememberRewrite(key, statements);
|
|
@@ -5118,14 +5236,16 @@ export class DoBackend {
|
|
|
5118
5236
|
rewriteSQL(sql) {
|
|
5119
5237
|
const arrayParamNumbers = new Set();
|
|
5120
5238
|
const jsonParamNumbers = new Set();
|
|
5239
|
+
const epochMillisParamNumbers = new Set();
|
|
5121
5240
|
return rewriteSQL(sql, {
|
|
5122
5241
|
skippedFunctionNames: this.skippedFunctionNames,
|
|
5123
5242
|
triggerFunctions: this.triggerFunctions,
|
|
5124
5243
|
arrayParamNumbers,
|
|
5125
5244
|
jsonParamNumbers,
|
|
5245
|
+
epochMillisParamNumbers,
|
|
5126
5246
|
});
|
|
5127
5247
|
}
|
|
5128
|
-
inlineStatementParams(sql, params, statements, inferredJsonParamNumbers = new Set(), timestampParamNumbers = new Set(), booleanParamNumbers = new Set()) {
|
|
5248
|
+
inlineStatementParams(sql, params, statements, inferredJsonParamNumbers = new Set(), timestampParamNumbers = new Set(), epochMillisParamNumbers = new Set(), booleanParamNumbers = new Set()) {
|
|
5129
5249
|
if (!params?.length)
|
|
5130
5250
|
return sql;
|
|
5131
5251
|
const arrayParamNumbers = new Set();
|
|
@@ -5137,8 +5257,11 @@ export class DoBackend {
|
|
|
5137
5257
|
for (const number of statement.jsonParamNumbers ?? []) {
|
|
5138
5258
|
jsonParamNumbers.add(number);
|
|
5139
5259
|
}
|
|
5260
|
+
for (const number of statement.epochMillisParamNumbers ?? []) {
|
|
5261
|
+
epochMillisParamNumbers.add(number);
|
|
5262
|
+
}
|
|
5140
5263
|
}
|
|
5141
|
-
return this.inlineParams(sql, params, arrayParamNumbers, jsonParamNumbers, timestampParamNumbers, booleanParamNumbers);
|
|
5264
|
+
return this.inlineParams(sql, params, arrayParamNumbers, jsonParamNumbers, timestampParamNumbers, epochMillisParamNumbers, booleanParamNumbers);
|
|
5142
5265
|
}
|
|
5143
5266
|
async doExec(sql, params) {
|
|
5144
5267
|
return (await this.doExecResult(sql, params)).rows;
|
|
@@ -5837,6 +5960,12 @@ export class DoBackend {
|
|
|
5837
5960
|
sqlLiteral(val, options) {
|
|
5838
5961
|
if (val === null || val === undefined)
|
|
5839
5962
|
return 'NULL';
|
|
5963
|
+
if (options?.pgEpochMillisAsNumber) {
|
|
5964
|
+
const millis = epochMillisParamValue(val);
|
|
5965
|
+
if (typeof millis === 'number')
|
|
5966
|
+
return String(millis);
|
|
5967
|
+
val = millis;
|
|
5968
|
+
}
|
|
5840
5969
|
if (options?.pgTimestampAsText)
|
|
5841
5970
|
return `'${postgresTimestampText(val).replace(/'/g, "''")}'`;
|
|
5842
5971
|
if (options?.pgJsonAsJson) {
|
|
@@ -5872,7 +6001,7 @@ export class DoBackend {
|
|
|
5872
6001
|
return `'${val.replace(/'/g, "''")}'`;
|
|
5873
6002
|
return String(val);
|
|
5874
6003
|
}
|
|
5875
|
-
inlineParams(sql, params, arrayParamNumbers = new Set(), jsonParamNumbers = new Set(), timestampParamNumbers = new Set(), booleanParamNumbers = new Set()) {
|
|
6004
|
+
inlineParams(sql, params, arrayParamNumbers = new Set(), jsonParamNumbers = new Set(), timestampParamNumbers = new Set(), epochMillisParamNumbers = new Set(), booleanParamNumbers = new Set()) {
|
|
5876
6005
|
let out = '';
|
|
5877
6006
|
for (let i = 0; i < sql.length;) {
|
|
5878
6007
|
const ch = sql[i];
|
|
@@ -5951,6 +6080,7 @@ export class DoBackend {
|
|
|
5951
6080
|
pgArrayAsJson: arrayParamNumbers.has(number),
|
|
5952
6081
|
pgJsonAsJson: jsonParamNumbers.has(number),
|
|
5953
6082
|
pgTimestampAsText: timestampParamNumbers.has(number),
|
|
6083
|
+
pgEpochMillisAsNumber: epochMillisParamNumbers.has(number),
|
|
5954
6084
|
pgBooleanAsInteger: booleanParamNumbers.has(number),
|
|
5955
6085
|
})
|
|
5956
6086
|
: sql.slice(i, end);
|
|
@@ -5965,6 +6095,8 @@ export class DoBackend {
|
|
|
5965
6095
|
sqliteParamValue(value, options) {
|
|
5966
6096
|
if (value === null || value === undefined)
|
|
5967
6097
|
return null;
|
|
6098
|
+
if (options?.pgEpochMillisAsNumber)
|
|
6099
|
+
return epochMillisParamValue(value);
|
|
5968
6100
|
if (options?.pgTimestampAsText)
|
|
5969
6101
|
return postgresTimestampText(value);
|
|
5970
6102
|
if (options?.pgJsonAsJson)
|
|
@@ -5991,7 +6123,7 @@ export class DoBackend {
|
|
|
5991
6123
|
return JSON.stringify(value);
|
|
5992
6124
|
return value;
|
|
5993
6125
|
}
|
|
5994
|
-
sqliteBoundSQL(sql, params, arrayParamNumbers = new Set(), jsonParamNumbers = new Set(), timestampParamNumbers = new Set(), booleanParamNumbers = new Set()) {
|
|
6126
|
+
sqliteBoundSQL(sql, params, arrayParamNumbers = new Set(), jsonParamNumbers = new Set(), timestampParamNumbers = new Set(), epochMillisParamNumbers = new Set(), booleanParamNumbers = new Set()) {
|
|
5995
6127
|
if (!params?.length)
|
|
5996
6128
|
return { sql, params: [] };
|
|
5997
6129
|
let out = '';
|
|
@@ -6073,6 +6205,7 @@ export class DoBackend {
|
|
|
6073
6205
|
pgArrayAsJson: arrayParamNumbers.has(number),
|
|
6074
6206
|
pgJsonAsJson: jsonParamNumbers.has(number),
|
|
6075
6207
|
pgTimestampAsText: timestampParamNumbers.has(number),
|
|
6208
|
+
pgEpochMillisAsNumber: epochMillisParamNumbers.has(number),
|
|
6076
6209
|
pgBooleanAsInteger: booleanParamNumbers.has(number),
|
|
6077
6210
|
}));
|
|
6078
6211
|
}
|