postgresdk 0.18.18 → 0.18.19
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/cli.js +50 -31
- package/dist/index.js +50 -31
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6241,6 +6241,12 @@ function getVectorDistanceOperator(metric?: string): string {
|
|
|
6241
6241
|
}
|
|
6242
6242
|
}
|
|
6243
6243
|
|
|
6244
|
+
/** Builds a SQL ORDER BY clause from parallel cols/dirs arrays. Returns "" when cols is empty. */
|
|
6245
|
+
function buildOrderBySQL(cols: string[], dirs: ("asc" | "desc")[]): string {
|
|
6246
|
+
if (cols.length === 0) return "";
|
|
6247
|
+
return \`ORDER BY \${cols.map((c, i) => \`"\${c}" \${(dirs[i] ?? "asc").toUpperCase()}\`).join(", ")}\`;
|
|
6248
|
+
}
|
|
6249
|
+
|
|
6244
6250
|
/**
|
|
6245
6251
|
* LIST operation - Get multiple records with optional filters and vector search
|
|
6246
6252
|
*/
|
|
@@ -6269,6 +6275,17 @@ export async function listRecords(
|
|
|
6269
6275
|
const distinctCols: string[] | null = distinctOn ? (Array.isArray(distinctOn) ? distinctOn : [distinctOn]) : null;
|
|
6270
6276
|
const _distinctOnColsSQL = distinctCols ? distinctCols.map(c => '"' + c + '"').join(', ') : '';
|
|
6271
6277
|
|
|
6278
|
+
// Pre-compute user order cols (reused in ORDER BY block and useSubquery check)
|
|
6279
|
+
const userOrderCols: string[] = orderBy ? (Array.isArray(orderBy) ? orderBy : [orderBy]) : [];
|
|
6280
|
+
|
|
6281
|
+
// Auto-detect subquery form: needed when distinctOn is set AND the caller wants to order
|
|
6282
|
+
// by a column outside of distinctOn (inline DISTINCT ON can't satisfy that without silently
|
|
6283
|
+
// overriding the requested ordering). Vector search always stays inline.
|
|
6284
|
+
const useSubquery: boolean =
|
|
6285
|
+
distinctCols !== null &&
|
|
6286
|
+
!vector &&
|
|
6287
|
+
userOrderCols.some(col => !distinctCols.includes(col));
|
|
6288
|
+
|
|
6272
6289
|
// Get distance operator if vector search
|
|
6273
6290
|
const distanceOp = vector ? getVectorDistanceOperator(vector.metric) : "";
|
|
6274
6291
|
|
|
@@ -6334,41 +6351,35 @@ export async function listRecords(
|
|
|
6334
6351
|
|
|
6335
6352
|
// Build ORDER BY clause
|
|
6336
6353
|
let orderBySQL = "";
|
|
6354
|
+
const userDirs: ("asc" | "desc")[] = userOrderCols.length > 0
|
|
6355
|
+
? (Array.isArray(order) ? order : (order ? Array(userOrderCols.length).fill(order) : Array(userOrderCols.length).fill("asc")))
|
|
6356
|
+
: [];
|
|
6357
|
+
|
|
6337
6358
|
if (vector) {
|
|
6338
|
-
//
|
|
6359
|
+
// Vector search always orders by distance; DISTINCT ON + vector stays inline
|
|
6339
6360
|
orderBySQL = \`ORDER BY "\${vector.field}" \${distanceOp} ($1)::vector\`;
|
|
6340
|
-
} else {
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6361
|
+
} else if (useSubquery) {
|
|
6362
|
+
// Subquery form: outer query gets the user's full ORDER BY.
|
|
6363
|
+
// Inner query only needs to satisfy PG's DISTINCT ON prefix requirement (built at query assembly).
|
|
6364
|
+
orderBySQL = buildOrderBySQL(userOrderCols, userDirs);
|
|
6365
|
+
} else if (distinctCols) {
|
|
6366
|
+
// Inline DISTINCT ON: prepend distinctCols as the leftmost ORDER BY prefix (PG requirement)
|
|
6346
6367
|
const finalCols: string[] = [];
|
|
6347
|
-
const finalDirs:
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
const userIdx = userCols.indexOf(col);
|
|
6353
|
-
finalCols.push(col);
|
|
6354
|
-
finalDirs.push(userIdx >= 0 ? (userDirs[userIdx] || "asc") : "asc");
|
|
6355
|
-
}
|
|
6356
|
-
// Append remaining user-specified cols not already covered by distinctOn
|
|
6357
|
-
for (let i = 0; i < userCols.length; i++) {
|
|
6358
|
-
if (!distinctCols.includes(userCols[i]!)) {
|
|
6359
|
-
finalCols.push(userCols[i]!);
|
|
6360
|
-
finalDirs.push(userDirs[i] || "asc");
|
|
6361
|
-
}
|
|
6362
|
-
}
|
|
6363
|
-
} else {
|
|
6364
|
-
finalCols.push(...userCols);
|
|
6365
|
-
finalDirs.push(...userDirs.map(d => d || "asc"));
|
|
6368
|
+
const finalDirs: ("asc" | "desc")[] = [];
|
|
6369
|
+
for (const col of distinctCols) {
|
|
6370
|
+
const userIdx = userOrderCols.indexOf(col);
|
|
6371
|
+
finalCols.push(col);
|
|
6372
|
+
finalDirs.push(userIdx >= 0 ? (userDirs[userIdx] ?? "asc") : "asc");
|
|
6366
6373
|
}
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6374
|
+
for (let i = 0; i < userOrderCols.length; i++) {
|
|
6375
|
+
if (!distinctCols.includes(userOrderCols[i]!)) {
|
|
6376
|
+
finalCols.push(userOrderCols[i]!);
|
|
6377
|
+
finalDirs.push(userDirs[i] ?? "asc");
|
|
6378
|
+
}
|
|
6371
6379
|
}
|
|
6380
|
+
orderBySQL = buildOrderBySQL(finalCols, finalDirs);
|
|
6381
|
+
} else {
|
|
6382
|
+
orderBySQL = buildOrderBySQL(userOrderCols, userDirs);
|
|
6372
6383
|
}
|
|
6373
6384
|
|
|
6374
6385
|
// Add limit and offset params
|
|
@@ -6385,7 +6396,15 @@ export async function listRecords(
|
|
|
6385
6396
|
const total = parseInt(countResult.rows[0].count, 10);
|
|
6386
6397
|
|
|
6387
6398
|
// Get paginated data
|
|
6388
|
-
|
|
6399
|
+
let text: string;
|
|
6400
|
+
if (useSubquery) {
|
|
6401
|
+
// Inner query: DISTINCT ON with only the distinctCols ORDER BY prefix (PG requirement).
|
|
6402
|
+
// Outer query: free ORDER BY from the user's full orderBy list, plus LIMIT/OFFSET.
|
|
6403
|
+
const innerQuery = \`SELECT DISTINCT ON (\${_distinctOnColsSQL}) \${baseColumns} FROM "\${ctx.table}" \${whereSQL} ORDER BY \${_distinctOnColsSQL}\`;
|
|
6404
|
+
text = \`SELECT * FROM (\${innerQuery}) __distinct \${orderBySQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
6405
|
+
} else {
|
|
6406
|
+
text = \`SELECT \${selectClause} FROM "\${ctx.table}" \${whereSQL} \${orderBySQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
6407
|
+
}
|
|
6389
6408
|
log.debug(\`LIST \${ctx.table} SQL:\`, text, "params:", allParams);
|
|
6390
6409
|
|
|
6391
6410
|
const { rows } = await ctx.pg.query(text, allParams);
|
package/dist/index.js
CHANGED
|
@@ -5280,6 +5280,12 @@ function getVectorDistanceOperator(metric?: string): string {
|
|
|
5280
5280
|
}
|
|
5281
5281
|
}
|
|
5282
5282
|
|
|
5283
|
+
/** Builds a SQL ORDER BY clause from parallel cols/dirs arrays. Returns "" when cols is empty. */
|
|
5284
|
+
function buildOrderBySQL(cols: string[], dirs: ("asc" | "desc")[]): string {
|
|
5285
|
+
if (cols.length === 0) return "";
|
|
5286
|
+
return \`ORDER BY \${cols.map((c, i) => \`"\${c}" \${(dirs[i] ?? "asc").toUpperCase()}\`).join(", ")}\`;
|
|
5287
|
+
}
|
|
5288
|
+
|
|
5283
5289
|
/**
|
|
5284
5290
|
* LIST operation - Get multiple records with optional filters and vector search
|
|
5285
5291
|
*/
|
|
@@ -5308,6 +5314,17 @@ export async function listRecords(
|
|
|
5308
5314
|
const distinctCols: string[] | null = distinctOn ? (Array.isArray(distinctOn) ? distinctOn : [distinctOn]) : null;
|
|
5309
5315
|
const _distinctOnColsSQL = distinctCols ? distinctCols.map(c => '"' + c + '"').join(', ') : '';
|
|
5310
5316
|
|
|
5317
|
+
// Pre-compute user order cols (reused in ORDER BY block and useSubquery check)
|
|
5318
|
+
const userOrderCols: string[] = orderBy ? (Array.isArray(orderBy) ? orderBy : [orderBy]) : [];
|
|
5319
|
+
|
|
5320
|
+
// Auto-detect subquery form: needed when distinctOn is set AND the caller wants to order
|
|
5321
|
+
// by a column outside of distinctOn (inline DISTINCT ON can't satisfy that without silently
|
|
5322
|
+
// overriding the requested ordering). Vector search always stays inline.
|
|
5323
|
+
const useSubquery: boolean =
|
|
5324
|
+
distinctCols !== null &&
|
|
5325
|
+
!vector &&
|
|
5326
|
+
userOrderCols.some(col => !distinctCols.includes(col));
|
|
5327
|
+
|
|
5311
5328
|
// Get distance operator if vector search
|
|
5312
5329
|
const distanceOp = vector ? getVectorDistanceOperator(vector.metric) : "";
|
|
5313
5330
|
|
|
@@ -5373,41 +5390,35 @@ export async function listRecords(
|
|
|
5373
5390
|
|
|
5374
5391
|
// Build ORDER BY clause
|
|
5375
5392
|
let orderBySQL = "";
|
|
5393
|
+
const userDirs: ("asc" | "desc")[] = userOrderCols.length > 0
|
|
5394
|
+
? (Array.isArray(order) ? order : (order ? Array(userOrderCols.length).fill(order) : Array(userOrderCols.length).fill("asc")))
|
|
5395
|
+
: [];
|
|
5396
|
+
|
|
5376
5397
|
if (vector) {
|
|
5377
|
-
//
|
|
5398
|
+
// Vector search always orders by distance; DISTINCT ON + vector stays inline
|
|
5378
5399
|
orderBySQL = \`ORDER BY "\${vector.field}" \${distanceOp} ($1)::vector\`;
|
|
5379
|
-
} else {
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5400
|
+
} else if (useSubquery) {
|
|
5401
|
+
// Subquery form: outer query gets the user's full ORDER BY.
|
|
5402
|
+
// Inner query only needs to satisfy PG's DISTINCT ON prefix requirement (built at query assembly).
|
|
5403
|
+
orderBySQL = buildOrderBySQL(userOrderCols, userDirs);
|
|
5404
|
+
} else if (distinctCols) {
|
|
5405
|
+
// Inline DISTINCT ON: prepend distinctCols as the leftmost ORDER BY prefix (PG requirement)
|
|
5385
5406
|
const finalCols: string[] = [];
|
|
5386
|
-
const finalDirs:
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
const userIdx = userCols.indexOf(col);
|
|
5392
|
-
finalCols.push(col);
|
|
5393
|
-
finalDirs.push(userIdx >= 0 ? (userDirs[userIdx] || "asc") : "asc");
|
|
5394
|
-
}
|
|
5395
|
-
// Append remaining user-specified cols not already covered by distinctOn
|
|
5396
|
-
for (let i = 0; i < userCols.length; i++) {
|
|
5397
|
-
if (!distinctCols.includes(userCols[i]!)) {
|
|
5398
|
-
finalCols.push(userCols[i]!);
|
|
5399
|
-
finalDirs.push(userDirs[i] || "asc");
|
|
5400
|
-
}
|
|
5401
|
-
}
|
|
5402
|
-
} else {
|
|
5403
|
-
finalCols.push(...userCols);
|
|
5404
|
-
finalDirs.push(...userDirs.map(d => d || "asc"));
|
|
5407
|
+
const finalDirs: ("asc" | "desc")[] = [];
|
|
5408
|
+
for (const col of distinctCols) {
|
|
5409
|
+
const userIdx = userOrderCols.indexOf(col);
|
|
5410
|
+
finalCols.push(col);
|
|
5411
|
+
finalDirs.push(userIdx >= 0 ? (userDirs[userIdx] ?? "asc") : "asc");
|
|
5405
5412
|
}
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5413
|
+
for (let i = 0; i < userOrderCols.length; i++) {
|
|
5414
|
+
if (!distinctCols.includes(userOrderCols[i]!)) {
|
|
5415
|
+
finalCols.push(userOrderCols[i]!);
|
|
5416
|
+
finalDirs.push(userDirs[i] ?? "asc");
|
|
5417
|
+
}
|
|
5410
5418
|
}
|
|
5419
|
+
orderBySQL = buildOrderBySQL(finalCols, finalDirs);
|
|
5420
|
+
} else {
|
|
5421
|
+
orderBySQL = buildOrderBySQL(userOrderCols, userDirs);
|
|
5411
5422
|
}
|
|
5412
5423
|
|
|
5413
5424
|
// Add limit and offset params
|
|
@@ -5424,7 +5435,15 @@ export async function listRecords(
|
|
|
5424
5435
|
const total = parseInt(countResult.rows[0].count, 10);
|
|
5425
5436
|
|
|
5426
5437
|
// Get paginated data
|
|
5427
|
-
|
|
5438
|
+
let text: string;
|
|
5439
|
+
if (useSubquery) {
|
|
5440
|
+
// Inner query: DISTINCT ON with only the distinctCols ORDER BY prefix (PG requirement).
|
|
5441
|
+
// Outer query: free ORDER BY from the user's full orderBy list, plus LIMIT/OFFSET.
|
|
5442
|
+
const innerQuery = \`SELECT DISTINCT ON (\${_distinctOnColsSQL}) \${baseColumns} FROM "\${ctx.table}" \${whereSQL} ORDER BY \${_distinctOnColsSQL}\`;
|
|
5443
|
+
text = \`SELECT * FROM (\${innerQuery}) __distinct \${orderBySQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
5444
|
+
} else {
|
|
5445
|
+
text = \`SELECT \${selectClause} FROM "\${ctx.table}" \${whereSQL} \${orderBySQL} LIMIT \${limitParam} OFFSET \${offsetParam}\`;
|
|
5446
|
+
}
|
|
5428
5447
|
log.debug(\`LIST \${ctx.table} SQL:\`, text, "params:", allParams);
|
|
5429
5448
|
|
|
5430
5449
|
const { rows } = await ctx.pg.query(text, allParams);
|