prisma-sql 1.69.0 → 1.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generator.cjs +294 -263
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +294 -263
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +542 -502
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +541 -503
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/generator.js
CHANGED
|
@@ -2312,7 +2312,7 @@ var require_package = __commonJS({
|
|
|
2312
2312
|
"package.json"(exports$1, module) {
|
|
2313
2313
|
module.exports = {
|
|
2314
2314
|
name: "prisma-sql",
|
|
2315
|
-
version: "1.
|
|
2315
|
+
version: "1.71.0",
|
|
2316
2316
|
description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
|
|
2317
2317
|
main: "dist/index.cjs",
|
|
2318
2318
|
module: "dist/index.js",
|
|
@@ -2378,13 +2378,13 @@ var require_package = __commonJS({
|
|
|
2378
2378
|
license: "MIT",
|
|
2379
2379
|
dependencies: {
|
|
2380
2380
|
"@dee-wan/schema-parser": "1.4.0",
|
|
2381
|
-
"@prisma/generator-helper": "^
|
|
2382
|
-
"@prisma/internals": "^
|
|
2381
|
+
"@prisma/generator-helper": "^6.19.2",
|
|
2382
|
+
"@prisma/internals": "^6.19.2"
|
|
2383
2383
|
},
|
|
2384
2384
|
devDependencies: {
|
|
2385
2385
|
"@faker-js/faker": "^10.2.0",
|
|
2386
|
-
"@prisma/adapter-better-sqlite3": "^
|
|
2387
|
-
"@prisma/adapter-pg": "^
|
|
2386
|
+
"@prisma/adapter-better-sqlite3": "^6.19.2",
|
|
2387
|
+
"@prisma/adapter-pg": "^6.19.2",
|
|
2388
2388
|
"@semantic-release/changelog": "^6.0.3",
|
|
2389
2389
|
"@semantic-release/git": "^10.0.1",
|
|
2390
2390
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -2398,8 +2398,8 @@ var require_package = __commonJS({
|
|
|
2398
2398
|
tsx: "^4.21.0",
|
|
2399
2399
|
typescript: "^5.9.3",
|
|
2400
2400
|
vitest: "^4.0.18",
|
|
2401
|
-
"@prisma/client": "
|
|
2402
|
-
prisma: "
|
|
2401
|
+
"@prisma/client": "6.19.2",
|
|
2402
|
+
prisma: "6.19.2"
|
|
2403
2403
|
},
|
|
2404
2404
|
engines: {
|
|
2405
2405
|
node: ">=16.0.0"
|
|
@@ -2408,243 +2408,6 @@ var require_package = __commonJS({
|
|
|
2408
2408
|
}
|
|
2409
2409
|
});
|
|
2410
2410
|
|
|
2411
|
-
// src/utils/normalize-value.ts
|
|
2412
|
-
var MAX_DEPTH = 20;
|
|
2413
|
-
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
2414
|
-
if (depth > MAX_DEPTH) {
|
|
2415
|
-
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
2416
|
-
}
|
|
2417
|
-
if (value instanceof Date) {
|
|
2418
|
-
return normalizeDateValue(value);
|
|
2419
|
-
}
|
|
2420
|
-
if (typeof value === "bigint") {
|
|
2421
|
-
return value.toString();
|
|
2422
|
-
}
|
|
2423
|
-
if (Array.isArray(value)) {
|
|
2424
|
-
return normalizeArrayValue(value, seen, depth);
|
|
2425
|
-
}
|
|
2426
|
-
if (value && typeof value === "object") {
|
|
2427
|
-
return normalizeObjectValue(value, seen, depth);
|
|
2428
|
-
}
|
|
2429
|
-
return value;
|
|
2430
|
-
}
|
|
2431
|
-
function normalizeDateValue(date) {
|
|
2432
|
-
const t = date.getTime();
|
|
2433
|
-
if (!Number.isFinite(t)) {
|
|
2434
|
-
throw new Error("Invalid Date value in SQL params");
|
|
2435
|
-
}
|
|
2436
|
-
return date.toISOString();
|
|
2437
|
-
}
|
|
2438
|
-
function normalizeArrayValue(value, seen, depth) {
|
|
2439
|
-
const arrRef = value;
|
|
2440
|
-
if (seen.has(arrRef)) {
|
|
2441
|
-
throw new Error("Circular reference in SQL params");
|
|
2442
|
-
}
|
|
2443
|
-
seen.add(arrRef);
|
|
2444
|
-
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
2445
|
-
seen.delete(arrRef);
|
|
2446
|
-
return out;
|
|
2447
|
-
}
|
|
2448
|
-
function normalizeObjectValue(value, seen, depth) {
|
|
2449
|
-
if (value instanceof Uint8Array) return value;
|
|
2450
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
2451
|
-
const proto = Object.getPrototypeOf(value);
|
|
2452
|
-
const isPlain = proto === Object.prototype || proto === null;
|
|
2453
|
-
if (!isPlain) return value;
|
|
2454
|
-
const obj = value;
|
|
2455
|
-
if (seen.has(obj)) {
|
|
2456
|
-
throw new Error("Circular reference in SQL params");
|
|
2457
|
-
}
|
|
2458
|
-
seen.add(obj);
|
|
2459
|
-
const out = {};
|
|
2460
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
2461
|
-
out[k] = normalizeValue(v, seen, depth + 1);
|
|
2462
|
-
}
|
|
2463
|
-
seen.delete(obj);
|
|
2464
|
-
return out;
|
|
2465
|
-
}
|
|
2466
|
-
|
|
2467
|
-
// src/sql-builder-dialect.ts
|
|
2468
|
-
var globalDialect = "postgres";
|
|
2469
|
-
function setGlobalDialect(dialect) {
|
|
2470
|
-
if (dialect !== "postgres" && dialect !== "sqlite") {
|
|
2471
|
-
throw new Error(
|
|
2472
|
-
`Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
|
|
2473
|
-
);
|
|
2474
|
-
}
|
|
2475
|
-
globalDialect = dialect;
|
|
2476
|
-
}
|
|
2477
|
-
function getGlobalDialect() {
|
|
2478
|
-
return globalDialect;
|
|
2479
|
-
}
|
|
2480
|
-
function assertNonEmpty(value, name) {
|
|
2481
|
-
if (!value || value.trim().length === 0) {
|
|
2482
|
-
throw new Error(`${name} is required and cannot be empty`);
|
|
2483
|
-
}
|
|
2484
|
-
}
|
|
2485
|
-
function arrayContains(column, value, arrayType, dialect) {
|
|
2486
|
-
assertNonEmpty(column, "arrayContains column");
|
|
2487
|
-
assertNonEmpty(value, "arrayContains value");
|
|
2488
|
-
if (dialect === "postgres") {
|
|
2489
|
-
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
2490
|
-
}
|
|
2491
|
-
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
2492
|
-
}
|
|
2493
|
-
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
2494
|
-
assertNonEmpty(column, "arrayOverlaps column");
|
|
2495
|
-
assertNonEmpty(value, "arrayOverlaps value");
|
|
2496
|
-
if (dialect === "postgres") {
|
|
2497
|
-
return `${column} && ${value}::${arrayType}`;
|
|
2498
|
-
}
|
|
2499
|
-
return `EXISTS (
|
|
2500
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
2501
|
-
JOIN json_each(${value}) AS val
|
|
2502
|
-
WHERE col.value = val.value
|
|
2503
|
-
)`;
|
|
2504
|
-
}
|
|
2505
|
-
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
2506
|
-
assertNonEmpty(column, "arrayContainsAll column");
|
|
2507
|
-
assertNonEmpty(value, "arrayContainsAll value");
|
|
2508
|
-
if (dialect === "postgres") {
|
|
2509
|
-
return `${column} @> ${value}::${arrayType}`;
|
|
2510
|
-
}
|
|
2511
|
-
return `NOT EXISTS (
|
|
2512
|
-
SELECT 1 FROM json_each(${value}) AS val
|
|
2513
|
-
WHERE NOT EXISTS (
|
|
2514
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
2515
|
-
WHERE col.value = val.value
|
|
2516
|
-
)
|
|
2517
|
-
)`;
|
|
2518
|
-
}
|
|
2519
|
-
function arrayIsEmpty(column, dialect) {
|
|
2520
|
-
assertNonEmpty(column, "arrayIsEmpty column");
|
|
2521
|
-
if (dialect === "postgres") {
|
|
2522
|
-
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
2523
|
-
}
|
|
2524
|
-
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
2525
|
-
}
|
|
2526
|
-
function arrayIsNotEmpty(column, dialect) {
|
|
2527
|
-
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
2528
|
-
if (dialect === "postgres") {
|
|
2529
|
-
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
2530
|
-
}
|
|
2531
|
-
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
2532
|
-
}
|
|
2533
|
-
function arrayEquals(column, value, arrayType, dialect) {
|
|
2534
|
-
assertNonEmpty(column, "arrayEquals column");
|
|
2535
|
-
assertNonEmpty(value, "arrayEquals value");
|
|
2536
|
-
if (dialect === "postgres") {
|
|
2537
|
-
return `${column} = ${value}::${arrayType}`;
|
|
2538
|
-
}
|
|
2539
|
-
return `json(${column}) = json(${value})`;
|
|
2540
|
-
}
|
|
2541
|
-
function caseInsensitiveLike(column, pattern, dialect) {
|
|
2542
|
-
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
2543
|
-
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
2544
|
-
if (dialect === "postgres") {
|
|
2545
|
-
return `${column} ILIKE ${pattern}`;
|
|
2546
|
-
}
|
|
2547
|
-
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
2548
|
-
}
|
|
2549
|
-
function caseInsensitiveEquals(column, value, dialect) {
|
|
2550
|
-
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
2551
|
-
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
2552
|
-
return `LOWER(${column}) = LOWER(${value})`;
|
|
2553
|
-
}
|
|
2554
|
-
function jsonExtractText(column, path, dialect) {
|
|
2555
|
-
assertNonEmpty(column, "jsonExtractText column");
|
|
2556
|
-
assertNonEmpty(path, "jsonExtractText path");
|
|
2557
|
-
if (dialect === "postgres") {
|
|
2558
|
-
const p = String(path).trim();
|
|
2559
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
2560
|
-
return `${column}#>>${pathExpr}`;
|
|
2561
|
-
}
|
|
2562
|
-
return `json_extract(${column}, ${path})`;
|
|
2563
|
-
}
|
|
2564
|
-
function jsonExtractNumeric(column, path, dialect) {
|
|
2565
|
-
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
2566
|
-
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
2567
|
-
if (dialect === "postgres") {
|
|
2568
|
-
const p = String(path).trim();
|
|
2569
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
2570
|
-
return `(${column}#>>${pathExpr})::numeric`;
|
|
2571
|
-
}
|
|
2572
|
-
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
2573
|
-
}
|
|
2574
|
-
function jsonToText(column, dialect) {
|
|
2575
|
-
assertNonEmpty(column, "jsonToText column");
|
|
2576
|
-
if (dialect === "postgres") {
|
|
2577
|
-
return `${column}::text`;
|
|
2578
|
-
}
|
|
2579
|
-
return column;
|
|
2580
|
-
}
|
|
2581
|
-
function inArray(column, value, dialect) {
|
|
2582
|
-
assertNonEmpty(column, "inArray column");
|
|
2583
|
-
assertNonEmpty(value, "inArray value");
|
|
2584
|
-
if (dialect === "postgres") {
|
|
2585
|
-
return `${column} = ANY(${value})`;
|
|
2586
|
-
}
|
|
2587
|
-
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
2588
|
-
}
|
|
2589
|
-
function notInArray(column, value, dialect) {
|
|
2590
|
-
assertNonEmpty(column, "notInArray column");
|
|
2591
|
-
assertNonEmpty(value, "notInArray value");
|
|
2592
|
-
if (dialect === "postgres") {
|
|
2593
|
-
return `${column} != ALL(${value})`;
|
|
2594
|
-
}
|
|
2595
|
-
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
2596
|
-
}
|
|
2597
|
-
function getArrayType(prismaType, dialect) {
|
|
2598
|
-
if (!prismaType || prismaType.length === 0) {
|
|
2599
|
-
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
2600
|
-
}
|
|
2601
|
-
if (dialect === "sqlite") {
|
|
2602
|
-
return "TEXT";
|
|
2603
|
-
}
|
|
2604
|
-
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
2605
|
-
switch (baseType) {
|
|
2606
|
-
case "String":
|
|
2607
|
-
return "text[]";
|
|
2608
|
-
case "Int":
|
|
2609
|
-
return "integer[]";
|
|
2610
|
-
case "Float":
|
|
2611
|
-
return "double precision[]";
|
|
2612
|
-
case "Decimal":
|
|
2613
|
-
return "numeric[]";
|
|
2614
|
-
case "Boolean":
|
|
2615
|
-
return "boolean[]";
|
|
2616
|
-
case "BigInt":
|
|
2617
|
-
return "bigint[]";
|
|
2618
|
-
case "DateTime":
|
|
2619
|
-
return "timestamptz[]";
|
|
2620
|
-
default:
|
|
2621
|
-
return `"${baseType}"[]`;
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
function jsonAgg(content, dialect) {
|
|
2625
|
-
assertNonEmpty(content, "jsonAgg content");
|
|
2626
|
-
if (dialect === "postgres") {
|
|
2627
|
-
return `json_agg(${content})`;
|
|
2628
|
-
}
|
|
2629
|
-
return `json_group_array(${content})`;
|
|
2630
|
-
}
|
|
2631
|
-
function jsonBuildObject(pairs, dialect) {
|
|
2632
|
-
const safePairs = (pairs != null ? pairs : "").trim();
|
|
2633
|
-
if (dialect === "postgres") {
|
|
2634
|
-
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
2635
|
-
}
|
|
2636
|
-
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
2637
|
-
}
|
|
2638
|
-
function prepareArrayParam(value, dialect) {
|
|
2639
|
-
if (!Array.isArray(value)) {
|
|
2640
|
-
throw new Error("prepareArrayParam requires array value");
|
|
2641
|
-
}
|
|
2642
|
-
if (dialect === "postgres") {
|
|
2643
|
-
return value.map((v) => normalizeValue(v));
|
|
2644
|
-
}
|
|
2645
|
-
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
2646
|
-
}
|
|
2647
|
-
|
|
2648
2411
|
// src/builder/shared/constants.ts
|
|
2649
2412
|
var IS_PRODUCTION = process.env.NODE_ENV === "production";
|
|
2650
2413
|
var SQL_SEPARATORS = Object.freeze({
|
|
@@ -3469,6 +3232,241 @@ function joinCondition(field, parentModel, childModel, parentAlias, childAlias)
|
|
|
3469
3232
|
function getModelByName(schemas, name) {
|
|
3470
3233
|
return schemas.find((m) => m.name === name);
|
|
3471
3234
|
}
|
|
3235
|
+
var MAX_DEPTH = 20;
|
|
3236
|
+
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
3237
|
+
if (depth > MAX_DEPTH) {
|
|
3238
|
+
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
3239
|
+
}
|
|
3240
|
+
if (value instanceof Date) {
|
|
3241
|
+
return normalizeDateValue(value);
|
|
3242
|
+
}
|
|
3243
|
+
if (typeof value === "bigint") {
|
|
3244
|
+
return value.toString();
|
|
3245
|
+
}
|
|
3246
|
+
if (Array.isArray(value)) {
|
|
3247
|
+
return normalizeArrayValue(value, seen, depth);
|
|
3248
|
+
}
|
|
3249
|
+
if (value && typeof value === "object") {
|
|
3250
|
+
return normalizeObjectValue(value, seen, depth);
|
|
3251
|
+
}
|
|
3252
|
+
return value;
|
|
3253
|
+
}
|
|
3254
|
+
function normalizeDateValue(date) {
|
|
3255
|
+
const t = date.getTime();
|
|
3256
|
+
if (!Number.isFinite(t)) {
|
|
3257
|
+
throw new Error("Invalid Date value in SQL params");
|
|
3258
|
+
}
|
|
3259
|
+
return date.toISOString();
|
|
3260
|
+
}
|
|
3261
|
+
function normalizeArrayValue(value, seen, depth) {
|
|
3262
|
+
const arrRef = value;
|
|
3263
|
+
if (seen.has(arrRef)) {
|
|
3264
|
+
throw new Error("Circular reference in SQL params");
|
|
3265
|
+
}
|
|
3266
|
+
seen.add(arrRef);
|
|
3267
|
+
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
3268
|
+
seen.delete(arrRef);
|
|
3269
|
+
return out;
|
|
3270
|
+
}
|
|
3271
|
+
function normalizeObjectValue(value, seen, depth) {
|
|
3272
|
+
if (value instanceof Uint8Array) return value;
|
|
3273
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
3274
|
+
const proto = Object.getPrototypeOf(value);
|
|
3275
|
+
const isPlain = proto === Object.prototype || proto === null;
|
|
3276
|
+
if (!isPlain) return value;
|
|
3277
|
+
const obj = value;
|
|
3278
|
+
if (seen.has(obj)) {
|
|
3279
|
+
throw new Error("Circular reference in SQL params");
|
|
3280
|
+
}
|
|
3281
|
+
seen.add(obj);
|
|
3282
|
+
const out = {};
|
|
3283
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
3284
|
+
out[k] = normalizeValue(v, seen, depth + 1);
|
|
3285
|
+
}
|
|
3286
|
+
seen.delete(obj);
|
|
3287
|
+
return out;
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
// src/sql-builder-dialect.ts
|
|
3291
|
+
var globalDialect = "postgres";
|
|
3292
|
+
function setGlobalDialect(dialect) {
|
|
3293
|
+
if (dialect !== "postgres" && dialect !== "sqlite") {
|
|
3294
|
+
throw new Error(
|
|
3295
|
+
`Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
|
|
3296
|
+
);
|
|
3297
|
+
}
|
|
3298
|
+
globalDialect = dialect;
|
|
3299
|
+
}
|
|
3300
|
+
function getGlobalDialect() {
|
|
3301
|
+
return globalDialect;
|
|
3302
|
+
}
|
|
3303
|
+
function assertNonEmpty(value, name) {
|
|
3304
|
+
if (!value || value.trim().length === 0) {
|
|
3305
|
+
throw new Error(`${name} is required and cannot be empty`);
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
function arrayContains(column, value, arrayType, dialect) {
|
|
3309
|
+
assertNonEmpty(column, "arrayContains column");
|
|
3310
|
+
assertNonEmpty(value, "arrayContains value");
|
|
3311
|
+
if (dialect === "postgres") {
|
|
3312
|
+
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
3313
|
+
}
|
|
3314
|
+
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
3315
|
+
}
|
|
3316
|
+
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
3317
|
+
assertNonEmpty(column, "arrayOverlaps column");
|
|
3318
|
+
assertNonEmpty(value, "arrayOverlaps value");
|
|
3319
|
+
if (dialect === "postgres") {
|
|
3320
|
+
return `${column} && ${value}::${arrayType}`;
|
|
3321
|
+
}
|
|
3322
|
+
return `EXISTS (
|
|
3323
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
3324
|
+
JOIN json_each(${value}) AS val
|
|
3325
|
+
WHERE col.value = val.value
|
|
3326
|
+
)`;
|
|
3327
|
+
}
|
|
3328
|
+
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
3329
|
+
assertNonEmpty(column, "arrayContainsAll column");
|
|
3330
|
+
assertNonEmpty(value, "arrayContainsAll value");
|
|
3331
|
+
if (dialect === "postgres") {
|
|
3332
|
+
return `${column} @> ${value}::${arrayType}`;
|
|
3333
|
+
}
|
|
3334
|
+
return `NOT EXISTS (
|
|
3335
|
+
SELECT 1 FROM json_each(${value}) AS val
|
|
3336
|
+
WHERE NOT EXISTS (
|
|
3337
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
3338
|
+
WHERE col.value = val.value
|
|
3339
|
+
)
|
|
3340
|
+
)`;
|
|
3341
|
+
}
|
|
3342
|
+
function arrayIsEmpty(column, dialect) {
|
|
3343
|
+
assertNonEmpty(column, "arrayIsEmpty column");
|
|
3344
|
+
if (dialect === "postgres") {
|
|
3345
|
+
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
3346
|
+
}
|
|
3347
|
+
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
3348
|
+
}
|
|
3349
|
+
function arrayIsNotEmpty(column, dialect) {
|
|
3350
|
+
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
3351
|
+
if (dialect === "postgres") {
|
|
3352
|
+
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
3353
|
+
}
|
|
3354
|
+
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
3355
|
+
}
|
|
3356
|
+
function arrayEquals(column, value, arrayType, dialect) {
|
|
3357
|
+
assertNonEmpty(column, "arrayEquals column");
|
|
3358
|
+
assertNonEmpty(value, "arrayEquals value");
|
|
3359
|
+
if (dialect === "postgres") {
|
|
3360
|
+
return `${column} = ${value}::${arrayType}`;
|
|
3361
|
+
}
|
|
3362
|
+
return `json(${column}) = json(${value})`;
|
|
3363
|
+
}
|
|
3364
|
+
function caseInsensitiveLike(column, pattern, dialect) {
|
|
3365
|
+
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
3366
|
+
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
3367
|
+
if (dialect === "postgres") {
|
|
3368
|
+
return `${column} ILIKE ${pattern}`;
|
|
3369
|
+
}
|
|
3370
|
+
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
3371
|
+
}
|
|
3372
|
+
function caseInsensitiveEquals(column, value, dialect) {
|
|
3373
|
+
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
3374
|
+
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
3375
|
+
return `LOWER(${column}) = LOWER(${value})`;
|
|
3376
|
+
}
|
|
3377
|
+
function jsonExtractText(column, path, dialect) {
|
|
3378
|
+
assertNonEmpty(column, "jsonExtractText column");
|
|
3379
|
+
assertNonEmpty(path, "jsonExtractText path");
|
|
3380
|
+
if (dialect === "postgres") {
|
|
3381
|
+
const p = String(path).trim();
|
|
3382
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
3383
|
+
return `${column}#>>${pathExpr}`;
|
|
3384
|
+
}
|
|
3385
|
+
return `json_extract(${column}, ${path})`;
|
|
3386
|
+
}
|
|
3387
|
+
function jsonExtractNumeric(column, path, dialect) {
|
|
3388
|
+
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
3389
|
+
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
3390
|
+
if (dialect === "postgres") {
|
|
3391
|
+
const p = String(path).trim();
|
|
3392
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
3393
|
+
return `(${column}#>>${pathExpr})::numeric`;
|
|
3394
|
+
}
|
|
3395
|
+
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
3396
|
+
}
|
|
3397
|
+
function jsonToText(column, dialect) {
|
|
3398
|
+
assertNonEmpty(column, "jsonToText column");
|
|
3399
|
+
if (dialect === "postgres") {
|
|
3400
|
+
return `${column}::text`;
|
|
3401
|
+
}
|
|
3402
|
+
return column;
|
|
3403
|
+
}
|
|
3404
|
+
function inArray(column, value, dialect) {
|
|
3405
|
+
assertNonEmpty(column, "inArray column");
|
|
3406
|
+
assertNonEmpty(value, "inArray value");
|
|
3407
|
+
if (dialect === "postgres") {
|
|
3408
|
+
return `${column} = ANY(${value})`;
|
|
3409
|
+
}
|
|
3410
|
+
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
3411
|
+
}
|
|
3412
|
+
function notInArray(column, value, dialect) {
|
|
3413
|
+
assertNonEmpty(column, "notInArray column");
|
|
3414
|
+
assertNonEmpty(value, "notInArray value");
|
|
3415
|
+
if (dialect === "postgres") {
|
|
3416
|
+
return `${column} != ALL(${value})`;
|
|
3417
|
+
}
|
|
3418
|
+
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
3419
|
+
}
|
|
3420
|
+
function getArrayType(prismaType, dialect) {
|
|
3421
|
+
if (!prismaType || prismaType.length === 0) {
|
|
3422
|
+
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
3423
|
+
}
|
|
3424
|
+
if (dialect === "sqlite") {
|
|
3425
|
+
return "TEXT";
|
|
3426
|
+
}
|
|
3427
|
+
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
3428
|
+
switch (baseType) {
|
|
3429
|
+
case "String":
|
|
3430
|
+
return "text[]";
|
|
3431
|
+
case "Int":
|
|
3432
|
+
return "integer[]";
|
|
3433
|
+
case "Float":
|
|
3434
|
+
return "double precision[]";
|
|
3435
|
+
case "Decimal":
|
|
3436
|
+
return "numeric[]";
|
|
3437
|
+
case "Boolean":
|
|
3438
|
+
return "boolean[]";
|
|
3439
|
+
case "BigInt":
|
|
3440
|
+
return "bigint[]";
|
|
3441
|
+
case "DateTime":
|
|
3442
|
+
return "timestamptz[]";
|
|
3443
|
+
default:
|
|
3444
|
+
return `"${baseType}"[]`;
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
function jsonAgg(content, dialect) {
|
|
3448
|
+
assertNonEmpty(content, "jsonAgg content");
|
|
3449
|
+
if (dialect === "postgres") {
|
|
3450
|
+
return `json_agg(${content})`;
|
|
3451
|
+
}
|
|
3452
|
+
return `json_group_array(${content})`;
|
|
3453
|
+
}
|
|
3454
|
+
function jsonBuildObject(pairs, dialect) {
|
|
3455
|
+
const safePairs = (pairs != null ? pairs : "").trim();
|
|
3456
|
+
if (dialect === "postgres") {
|
|
3457
|
+
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
3458
|
+
}
|
|
3459
|
+
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
3460
|
+
}
|
|
3461
|
+
function prepareArrayParam(value, dialect) {
|
|
3462
|
+
if (!Array.isArray(value)) {
|
|
3463
|
+
throw new Error("prepareArrayParam requires array value");
|
|
3464
|
+
}
|
|
3465
|
+
if (dialect === "postgres") {
|
|
3466
|
+
return value.map((v) => normalizeValue(v));
|
|
3467
|
+
}
|
|
3468
|
+
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
3469
|
+
}
|
|
3472
3470
|
function normalizeIntLike(name, v, opts = {}) {
|
|
3473
3471
|
var _a3, _b;
|
|
3474
3472
|
if (!isNotNullish(v)) return void 0;
|
|
@@ -4587,14 +4585,15 @@ function hasPaginationArgs(value) {
|
|
|
4587
4585
|
const obj = value;
|
|
4588
4586
|
return "take" in obj && obj.take != null || "skip" in obj && typeof obj.skip === "number" && obj.skip > 0;
|
|
4589
4587
|
}
|
|
4590
|
-
function buildCostTree(includeSpec, model, schemas) {
|
|
4588
|
+
function buildCostTree(includeSpec, model, schemas, depth = 0) {
|
|
4589
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return [];
|
|
4591
4590
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
4592
4591
|
const nodes = [];
|
|
4593
4592
|
for (const rel of relations) {
|
|
4594
4593
|
const fan = rel.isList ? getFanOut(model.name, rel.relName) : 1;
|
|
4595
4594
|
const take = rel.isList ? readTake(rel.value) : 1;
|
|
4596
4595
|
const eff = Math.min(fan, take);
|
|
4597
|
-
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(rel.nestedSpec, rel.relModel, schemas) : [];
|
|
4596
|
+
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(rel.nestedSpec, rel.relModel, schemas, depth + 1) : [];
|
|
4598
4597
|
nodes.push({
|
|
4599
4598
|
name: rel.relName,
|
|
4600
4599
|
fan,
|
|
@@ -4660,19 +4659,26 @@ function hasOnlyToOneRelations(includeSpec, model) {
|
|
|
4660
4659
|
}
|
|
4661
4660
|
return true;
|
|
4662
4661
|
}
|
|
4663
|
-
function countIncludeDepth(includeSpec, model, schemas) {
|
|
4662
|
+
function countIncludeDepth(includeSpec, model, schemas, depth = 0) {
|
|
4663
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return 0;
|
|
4664
4664
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
4665
4665
|
let maxDepth = 0;
|
|
4666
4666
|
for (const rel of relations) {
|
|
4667
4667
|
let childDepth = 1;
|
|
4668
4668
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
4669
|
-
childDepth += countIncludeDepth(
|
|
4669
|
+
childDepth += countIncludeDepth(
|
|
4670
|
+
rel.nestedSpec,
|
|
4671
|
+
rel.relModel,
|
|
4672
|
+
schemas,
|
|
4673
|
+
depth + 1
|
|
4674
|
+
);
|
|
4670
4675
|
}
|
|
4671
4676
|
if (childDepth > maxDepth) maxDepth = childDepth;
|
|
4672
4677
|
}
|
|
4673
4678
|
return maxDepth;
|
|
4674
4679
|
}
|
|
4675
|
-
function hasChildPaginationAnywhere(includeSpec, model, schemas) {
|
|
4680
|
+
function hasChildPaginationAnywhere(includeSpec, model, schemas, depth = 0) {
|
|
4681
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return false;
|
|
4676
4682
|
for (const [, value] of Object.entries(includeSpec)) {
|
|
4677
4683
|
if (value === false) continue;
|
|
4678
4684
|
if (hasPaginationArgs(value)) return true;
|
|
@@ -4680,7 +4686,12 @@ function hasChildPaginationAnywhere(includeSpec, model, schemas) {
|
|
|
4680
4686
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
4681
4687
|
for (const rel of relations) {
|
|
4682
4688
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
4683
|
-
if (hasChildPaginationAnywhere(
|
|
4689
|
+
if (hasChildPaginationAnywhere(
|
|
4690
|
+
rel.nestedSpec,
|
|
4691
|
+
rel.relModel,
|
|
4692
|
+
schemas,
|
|
4693
|
+
depth + 1
|
|
4694
|
+
)) {
|
|
4684
4695
|
return true;
|
|
4685
4696
|
}
|
|
4686
4697
|
}
|
|
@@ -8445,9 +8456,10 @@ function buildAggregateFields(args, alias, model) {
|
|
|
8445
8456
|
addAggregateFields(fields, args, alias, model);
|
|
8446
8457
|
return fields;
|
|
8447
8458
|
}
|
|
8448
|
-
function buildAggregateSql(args, whereResult, tableName, alias, model) {
|
|
8459
|
+
function buildAggregateSql(args, whereResult, tableName, alias, model, dialect) {
|
|
8449
8460
|
assertSafeAlias(alias);
|
|
8450
8461
|
assertSafeTableRef(tableName);
|
|
8462
|
+
const d = dialect != null ? dialect : getGlobalDialect();
|
|
8451
8463
|
const aggFields = buildAggregateFields(args, alias, model);
|
|
8452
8464
|
if (!isNonEmptyArray(aggFields)) {
|
|
8453
8465
|
throw new Error("buildAggregateSql requires at least one aggregate field");
|
|
@@ -8466,7 +8478,7 @@ function buildAggregateSql(args, whereResult, tableName, alias, model) {
|
|
|
8466
8478
|
if (whereClause) parts.push(whereClause);
|
|
8467
8479
|
const sql = parts.join(" ").trim();
|
|
8468
8480
|
validateSelectQuery(sql);
|
|
8469
|
-
|
|
8481
|
+
validateParamConsistencyByDialect(sql, whereResult.params, d);
|
|
8470
8482
|
return {
|
|
8471
8483
|
sql,
|
|
8472
8484
|
params: [...whereResult.params],
|
|
@@ -8545,7 +8557,7 @@ function buildGroupBySql(args, whereResult, tableName, alias, model, dialect) {
|
|
|
8545
8557
|
const allParams = [...whereResult.params, ...snapshot.params];
|
|
8546
8558
|
const allMappings = [...whereResult.paramMappings, ...snapshot.mappings];
|
|
8547
8559
|
validateSelectQuery(sql);
|
|
8548
|
-
|
|
8560
|
+
validateParamConsistencyByDialect(sql, allParams, d);
|
|
8549
8561
|
return {
|
|
8550
8562
|
sql,
|
|
8551
8563
|
params: allParams,
|
|
@@ -8562,7 +8574,7 @@ function assertNoNegativeTake(args) {
|
|
|
8562
8574
|
throw new Error("Negative take is not supported for count()");
|
|
8563
8575
|
}
|
|
8564
8576
|
}
|
|
8565
|
-
function buildSimpleCountSql(whereResult, tableName, alias) {
|
|
8577
|
+
function buildSimpleCountSql(whereResult, tableName, alias, dialect) {
|
|
8566
8578
|
const joinsPart = whereResult.joins && whereResult.joins.length > 0 ? whereResult.joins.join(" ") : "";
|
|
8567
8579
|
const whereClause = isValidWhereClause(whereResult.clause) ? SQL_TEMPLATES.WHERE + " " + whereResult.clause : "";
|
|
8568
8580
|
const parts = [
|
|
@@ -8578,7 +8590,7 @@ function buildSimpleCountSql(whereResult, tableName, alias) {
|
|
|
8578
8590
|
if (whereClause) parts.push(whereClause);
|
|
8579
8591
|
const sql = parts.join(" ").trim();
|
|
8580
8592
|
validateSelectQuery(sql);
|
|
8581
|
-
|
|
8593
|
+
validateParamConsistencyByDialect(sql, whereResult.params, dialect);
|
|
8582
8594
|
return {
|
|
8583
8595
|
sql,
|
|
8584
8596
|
params: [...whereResult.params],
|
|
@@ -8590,14 +8602,15 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
8590
8602
|
assertSafeTableRef(tableName);
|
|
8591
8603
|
const args = normalizeCountArgs(argsOrSkip);
|
|
8592
8604
|
assertNoNegativeTake(args);
|
|
8605
|
+
const d = dialect != null ? dialect : getGlobalDialect();
|
|
8593
8606
|
if (!model) {
|
|
8594
|
-
return buildSimpleCountSql(whereResult, tableName, alias);
|
|
8607
|
+
return buildSimpleCountSql(whereResult, tableName, alias, d);
|
|
8595
8608
|
}
|
|
8596
8609
|
const pkFields = getPrimaryKeyFields(model);
|
|
8597
8610
|
const distinctFields = isNonEmptyArray(args.distinct) ? args.distinct.map((x) => String(x)).filter((x) => x) : [];
|
|
8598
8611
|
const selectFields = distinctFields.length > 0 ? distinctFields : pkFields;
|
|
8599
8612
|
if (selectFields.length === 0) {
|
|
8600
|
-
return buildSimpleCountSql(whereResult, tableName, alias);
|
|
8613
|
+
return buildSimpleCountSql(whereResult, tableName, alias, d);
|
|
8601
8614
|
}
|
|
8602
8615
|
const select2 = {};
|
|
8603
8616
|
for (const f of selectFields) select2[f] = true;
|
|
@@ -8605,7 +8618,6 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
8605
8618
|
include: void 0,
|
|
8606
8619
|
select: select2
|
|
8607
8620
|
});
|
|
8608
|
-
const d = dialect != null ? dialect : getGlobalDialect();
|
|
8609
8621
|
const subSchemas = Array.isArray(schemas) && schemas.length > 0 ? schemas : [model];
|
|
8610
8622
|
const sub = buildSelectSql({
|
|
8611
8623
|
method: "findMany",
|
|
@@ -8621,7 +8633,7 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
8621
8633
|
"_count._all"
|
|
8622
8634
|
)} ${SQL_TEMPLATES.FROM} (${sub.sql}) ${SQL_TEMPLATES.AS} ${countAlias}`;
|
|
8623
8635
|
validateSelectQuery(sql);
|
|
8624
|
-
|
|
8636
|
+
validateParamConsistencyByDialect(sql, sub.params, d);
|
|
8625
8637
|
return {
|
|
8626
8638
|
sql,
|
|
8627
8639
|
params: sub.params,
|
|
@@ -8765,7 +8777,14 @@ function buildSqlResult(args) {
|
|
|
8765
8777
|
dialect
|
|
8766
8778
|
} = args;
|
|
8767
8779
|
if (method === "aggregate") {
|
|
8768
|
-
return buildAggregateSql(
|
|
8780
|
+
return buildAggregateSql(
|
|
8781
|
+
processed,
|
|
8782
|
+
whereResult,
|
|
8783
|
+
tableName,
|
|
8784
|
+
alias,
|
|
8785
|
+
modelDef,
|
|
8786
|
+
dialect
|
|
8787
|
+
);
|
|
8769
8788
|
}
|
|
8770
8789
|
if (method === "groupBy") {
|
|
8771
8790
|
return buildGroupBySql(
|
|
@@ -10017,6 +10036,8 @@ function generateImports(runtimeImportPath) {
|
|
|
10017
10036
|
createTransactionExecutor,
|
|
10018
10037
|
transformQueryResults,
|
|
10019
10038
|
normalizeValue,
|
|
10039
|
+
setNormalizeDateMode,
|
|
10040
|
+
detectSqliteDateMode,
|
|
10020
10041
|
planQueryStrategy,
|
|
10021
10042
|
executeWhereInSegments,
|
|
10022
10043
|
buildReducerConfig,
|
|
@@ -10389,7 +10410,11 @@ function generateExtension(runtimeImportPath) {
|
|
|
10389
10410
|
throw new Error(\`Generated code is for \${DIALECT}, but you provided \${actualDialect}\`)
|
|
10390
10411
|
}
|
|
10391
10412
|
|
|
10392
|
-
|
|
10413
|
+
if ((DIALECT as string) === 'sqlite') {
|
|
10414
|
+
setNormalizeDateMode(detectSqliteDateMode(client))
|
|
10415
|
+
}
|
|
10416
|
+
|
|
10417
|
+
async function executeQuery(
|
|
10393
10418
|
sql: string,
|
|
10394
10419
|
params: unknown[],
|
|
10395
10420
|
method: string,
|
|
@@ -10413,8 +10438,14 @@ async function executeQuery(
|
|
|
10413
10438
|
lateralMeta,
|
|
10414
10439
|
})
|
|
10415
10440
|
}
|
|
10416
|
-
|
|
10417
|
-
|
|
10441
|
+
|
|
10442
|
+
try {
|
|
10443
|
+
const result = executeSqliteQuery(client, sql, params, method)
|
|
10444
|
+
return result
|
|
10445
|
+
} catch (err) {
|
|
10446
|
+
console.log('[sqlite-debug] FAILED:', err instanceof Error ? err.message : err)
|
|
10447
|
+
throw err
|
|
10448
|
+
}
|
|
10418
10449
|
}
|
|
10419
10450
|
|
|
10420
10451
|
async function executeWhereInQuery(sql: string, params: unknown[]): Promise<unknown[]> {
|