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.cjs
CHANGED
|
@@ -2323,7 +2323,7 @@ var require_package = __commonJS({
|
|
|
2323
2323
|
"package.json"(exports$1, module) {
|
|
2324
2324
|
module.exports = {
|
|
2325
2325
|
name: "prisma-sql",
|
|
2326
|
-
version: "1.
|
|
2326
|
+
version: "1.71.0",
|
|
2327
2327
|
description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
|
|
2328
2328
|
main: "dist/index.cjs",
|
|
2329
2329
|
module: "dist/index.js",
|
|
@@ -2389,13 +2389,13 @@ var require_package = __commonJS({
|
|
|
2389
2389
|
license: "MIT",
|
|
2390
2390
|
dependencies: {
|
|
2391
2391
|
"@dee-wan/schema-parser": "1.4.0",
|
|
2392
|
-
"@prisma/generator-helper": "^
|
|
2393
|
-
"@prisma/internals": "^
|
|
2392
|
+
"@prisma/generator-helper": "^6.19.2",
|
|
2393
|
+
"@prisma/internals": "^6.19.2"
|
|
2394
2394
|
},
|
|
2395
2395
|
devDependencies: {
|
|
2396
2396
|
"@faker-js/faker": "^10.2.0",
|
|
2397
|
-
"@prisma/adapter-better-sqlite3": "^
|
|
2398
|
-
"@prisma/adapter-pg": "^
|
|
2397
|
+
"@prisma/adapter-better-sqlite3": "^6.19.2",
|
|
2398
|
+
"@prisma/adapter-pg": "^6.19.2",
|
|
2399
2399
|
"@semantic-release/changelog": "^6.0.3",
|
|
2400
2400
|
"@semantic-release/git": "^10.0.1",
|
|
2401
2401
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -2409,8 +2409,8 @@ var require_package = __commonJS({
|
|
|
2409
2409
|
tsx: "^4.21.0",
|
|
2410
2410
|
typescript: "^5.9.3",
|
|
2411
2411
|
vitest: "^4.0.18",
|
|
2412
|
-
"@prisma/client": "
|
|
2413
|
-
prisma: "
|
|
2412
|
+
"@prisma/client": "6.19.2",
|
|
2413
|
+
prisma: "6.19.2"
|
|
2414
2414
|
},
|
|
2415
2415
|
engines: {
|
|
2416
2416
|
node: ">=16.0.0"
|
|
@@ -2419,243 +2419,6 @@ var require_package = __commonJS({
|
|
|
2419
2419
|
}
|
|
2420
2420
|
});
|
|
2421
2421
|
|
|
2422
|
-
// src/utils/normalize-value.ts
|
|
2423
|
-
var MAX_DEPTH = 20;
|
|
2424
|
-
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
2425
|
-
if (depth > MAX_DEPTH) {
|
|
2426
|
-
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
2427
|
-
}
|
|
2428
|
-
if (value instanceof Date) {
|
|
2429
|
-
return normalizeDateValue(value);
|
|
2430
|
-
}
|
|
2431
|
-
if (typeof value === "bigint") {
|
|
2432
|
-
return value.toString();
|
|
2433
|
-
}
|
|
2434
|
-
if (Array.isArray(value)) {
|
|
2435
|
-
return normalizeArrayValue(value, seen, depth);
|
|
2436
|
-
}
|
|
2437
|
-
if (value && typeof value === "object") {
|
|
2438
|
-
return normalizeObjectValue(value, seen, depth);
|
|
2439
|
-
}
|
|
2440
|
-
return value;
|
|
2441
|
-
}
|
|
2442
|
-
function normalizeDateValue(date) {
|
|
2443
|
-
const t = date.getTime();
|
|
2444
|
-
if (!Number.isFinite(t)) {
|
|
2445
|
-
throw new Error("Invalid Date value in SQL params");
|
|
2446
|
-
}
|
|
2447
|
-
return date.toISOString();
|
|
2448
|
-
}
|
|
2449
|
-
function normalizeArrayValue(value, seen, depth) {
|
|
2450
|
-
const arrRef = value;
|
|
2451
|
-
if (seen.has(arrRef)) {
|
|
2452
|
-
throw new Error("Circular reference in SQL params");
|
|
2453
|
-
}
|
|
2454
|
-
seen.add(arrRef);
|
|
2455
|
-
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
2456
|
-
seen.delete(arrRef);
|
|
2457
|
-
return out;
|
|
2458
|
-
}
|
|
2459
|
-
function normalizeObjectValue(value, seen, depth) {
|
|
2460
|
-
if (value instanceof Uint8Array) return value;
|
|
2461
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
2462
|
-
const proto = Object.getPrototypeOf(value);
|
|
2463
|
-
const isPlain = proto === Object.prototype || proto === null;
|
|
2464
|
-
if (!isPlain) return value;
|
|
2465
|
-
const obj = value;
|
|
2466
|
-
if (seen.has(obj)) {
|
|
2467
|
-
throw new Error("Circular reference in SQL params");
|
|
2468
|
-
}
|
|
2469
|
-
seen.add(obj);
|
|
2470
|
-
const out = {};
|
|
2471
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
2472
|
-
out[k] = normalizeValue(v, seen, depth + 1);
|
|
2473
|
-
}
|
|
2474
|
-
seen.delete(obj);
|
|
2475
|
-
return out;
|
|
2476
|
-
}
|
|
2477
|
-
|
|
2478
|
-
// src/sql-builder-dialect.ts
|
|
2479
|
-
var globalDialect = "postgres";
|
|
2480
|
-
function setGlobalDialect(dialect) {
|
|
2481
|
-
if (dialect !== "postgres" && dialect !== "sqlite") {
|
|
2482
|
-
throw new Error(
|
|
2483
|
-
`Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
|
|
2484
|
-
);
|
|
2485
|
-
}
|
|
2486
|
-
globalDialect = dialect;
|
|
2487
|
-
}
|
|
2488
|
-
function getGlobalDialect() {
|
|
2489
|
-
return globalDialect;
|
|
2490
|
-
}
|
|
2491
|
-
function assertNonEmpty(value, name) {
|
|
2492
|
-
if (!value || value.trim().length === 0) {
|
|
2493
|
-
throw new Error(`${name} is required and cannot be empty`);
|
|
2494
|
-
}
|
|
2495
|
-
}
|
|
2496
|
-
function arrayContains(column, value, arrayType, dialect) {
|
|
2497
|
-
assertNonEmpty(column, "arrayContains column");
|
|
2498
|
-
assertNonEmpty(value, "arrayContains value");
|
|
2499
|
-
if (dialect === "postgres") {
|
|
2500
|
-
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
2501
|
-
}
|
|
2502
|
-
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
2503
|
-
}
|
|
2504
|
-
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
2505
|
-
assertNonEmpty(column, "arrayOverlaps column");
|
|
2506
|
-
assertNonEmpty(value, "arrayOverlaps value");
|
|
2507
|
-
if (dialect === "postgres") {
|
|
2508
|
-
return `${column} && ${value}::${arrayType}`;
|
|
2509
|
-
}
|
|
2510
|
-
return `EXISTS (
|
|
2511
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
2512
|
-
JOIN json_each(${value}) AS val
|
|
2513
|
-
WHERE col.value = val.value
|
|
2514
|
-
)`;
|
|
2515
|
-
}
|
|
2516
|
-
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
2517
|
-
assertNonEmpty(column, "arrayContainsAll column");
|
|
2518
|
-
assertNonEmpty(value, "arrayContainsAll value");
|
|
2519
|
-
if (dialect === "postgres") {
|
|
2520
|
-
return `${column} @> ${value}::${arrayType}`;
|
|
2521
|
-
}
|
|
2522
|
-
return `NOT EXISTS (
|
|
2523
|
-
SELECT 1 FROM json_each(${value}) AS val
|
|
2524
|
-
WHERE NOT EXISTS (
|
|
2525
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
2526
|
-
WHERE col.value = val.value
|
|
2527
|
-
)
|
|
2528
|
-
)`;
|
|
2529
|
-
}
|
|
2530
|
-
function arrayIsEmpty(column, dialect) {
|
|
2531
|
-
assertNonEmpty(column, "arrayIsEmpty column");
|
|
2532
|
-
if (dialect === "postgres") {
|
|
2533
|
-
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
2534
|
-
}
|
|
2535
|
-
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
2536
|
-
}
|
|
2537
|
-
function arrayIsNotEmpty(column, dialect) {
|
|
2538
|
-
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
2539
|
-
if (dialect === "postgres") {
|
|
2540
|
-
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
2541
|
-
}
|
|
2542
|
-
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
2543
|
-
}
|
|
2544
|
-
function arrayEquals(column, value, arrayType, dialect) {
|
|
2545
|
-
assertNonEmpty(column, "arrayEquals column");
|
|
2546
|
-
assertNonEmpty(value, "arrayEquals value");
|
|
2547
|
-
if (dialect === "postgres") {
|
|
2548
|
-
return `${column} = ${value}::${arrayType}`;
|
|
2549
|
-
}
|
|
2550
|
-
return `json(${column}) = json(${value})`;
|
|
2551
|
-
}
|
|
2552
|
-
function caseInsensitiveLike(column, pattern, dialect) {
|
|
2553
|
-
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
2554
|
-
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
2555
|
-
if (dialect === "postgres") {
|
|
2556
|
-
return `${column} ILIKE ${pattern}`;
|
|
2557
|
-
}
|
|
2558
|
-
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
2559
|
-
}
|
|
2560
|
-
function caseInsensitiveEquals(column, value, dialect) {
|
|
2561
|
-
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
2562
|
-
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
2563
|
-
return `LOWER(${column}) = LOWER(${value})`;
|
|
2564
|
-
}
|
|
2565
|
-
function jsonExtractText(column, path, dialect) {
|
|
2566
|
-
assertNonEmpty(column, "jsonExtractText column");
|
|
2567
|
-
assertNonEmpty(path, "jsonExtractText path");
|
|
2568
|
-
if (dialect === "postgres") {
|
|
2569
|
-
const p = String(path).trim();
|
|
2570
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
2571
|
-
return `${column}#>>${pathExpr}`;
|
|
2572
|
-
}
|
|
2573
|
-
return `json_extract(${column}, ${path})`;
|
|
2574
|
-
}
|
|
2575
|
-
function jsonExtractNumeric(column, path, dialect) {
|
|
2576
|
-
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
2577
|
-
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
2578
|
-
if (dialect === "postgres") {
|
|
2579
|
-
const p = String(path).trim();
|
|
2580
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
2581
|
-
return `(${column}#>>${pathExpr})::numeric`;
|
|
2582
|
-
}
|
|
2583
|
-
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
2584
|
-
}
|
|
2585
|
-
function jsonToText(column, dialect) {
|
|
2586
|
-
assertNonEmpty(column, "jsonToText column");
|
|
2587
|
-
if (dialect === "postgres") {
|
|
2588
|
-
return `${column}::text`;
|
|
2589
|
-
}
|
|
2590
|
-
return column;
|
|
2591
|
-
}
|
|
2592
|
-
function inArray(column, value, dialect) {
|
|
2593
|
-
assertNonEmpty(column, "inArray column");
|
|
2594
|
-
assertNonEmpty(value, "inArray value");
|
|
2595
|
-
if (dialect === "postgres") {
|
|
2596
|
-
return `${column} = ANY(${value})`;
|
|
2597
|
-
}
|
|
2598
|
-
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
2599
|
-
}
|
|
2600
|
-
function notInArray(column, value, dialect) {
|
|
2601
|
-
assertNonEmpty(column, "notInArray column");
|
|
2602
|
-
assertNonEmpty(value, "notInArray value");
|
|
2603
|
-
if (dialect === "postgres") {
|
|
2604
|
-
return `${column} != ALL(${value})`;
|
|
2605
|
-
}
|
|
2606
|
-
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
2607
|
-
}
|
|
2608
|
-
function getArrayType(prismaType, dialect) {
|
|
2609
|
-
if (!prismaType || prismaType.length === 0) {
|
|
2610
|
-
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
2611
|
-
}
|
|
2612
|
-
if (dialect === "sqlite") {
|
|
2613
|
-
return "TEXT";
|
|
2614
|
-
}
|
|
2615
|
-
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
2616
|
-
switch (baseType) {
|
|
2617
|
-
case "String":
|
|
2618
|
-
return "text[]";
|
|
2619
|
-
case "Int":
|
|
2620
|
-
return "integer[]";
|
|
2621
|
-
case "Float":
|
|
2622
|
-
return "double precision[]";
|
|
2623
|
-
case "Decimal":
|
|
2624
|
-
return "numeric[]";
|
|
2625
|
-
case "Boolean":
|
|
2626
|
-
return "boolean[]";
|
|
2627
|
-
case "BigInt":
|
|
2628
|
-
return "bigint[]";
|
|
2629
|
-
case "DateTime":
|
|
2630
|
-
return "timestamptz[]";
|
|
2631
|
-
default:
|
|
2632
|
-
return `"${baseType}"[]`;
|
|
2633
|
-
}
|
|
2634
|
-
}
|
|
2635
|
-
function jsonAgg(content, dialect) {
|
|
2636
|
-
assertNonEmpty(content, "jsonAgg content");
|
|
2637
|
-
if (dialect === "postgres") {
|
|
2638
|
-
return `json_agg(${content})`;
|
|
2639
|
-
}
|
|
2640
|
-
return `json_group_array(${content})`;
|
|
2641
|
-
}
|
|
2642
|
-
function jsonBuildObject(pairs, dialect) {
|
|
2643
|
-
const safePairs = (pairs != null ? pairs : "").trim();
|
|
2644
|
-
if (dialect === "postgres") {
|
|
2645
|
-
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
2646
|
-
}
|
|
2647
|
-
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
2648
|
-
}
|
|
2649
|
-
function prepareArrayParam(value, dialect) {
|
|
2650
|
-
if (!Array.isArray(value)) {
|
|
2651
|
-
throw new Error("prepareArrayParam requires array value");
|
|
2652
|
-
}
|
|
2653
|
-
if (dialect === "postgres") {
|
|
2654
|
-
return value.map((v) => normalizeValue(v));
|
|
2655
|
-
}
|
|
2656
|
-
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
2657
|
-
}
|
|
2658
|
-
|
|
2659
2422
|
// src/builder/shared/constants.ts
|
|
2660
2423
|
var IS_PRODUCTION = process.env.NODE_ENV === "production";
|
|
2661
2424
|
var SQL_SEPARATORS = Object.freeze({
|
|
@@ -3480,6 +3243,241 @@ function joinCondition(field, parentModel, childModel, parentAlias, childAlias)
|
|
|
3480
3243
|
function getModelByName(schemas, name) {
|
|
3481
3244
|
return schemas.find((m) => m.name === name);
|
|
3482
3245
|
}
|
|
3246
|
+
var MAX_DEPTH = 20;
|
|
3247
|
+
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
3248
|
+
if (depth > MAX_DEPTH) {
|
|
3249
|
+
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
3250
|
+
}
|
|
3251
|
+
if (value instanceof Date) {
|
|
3252
|
+
return normalizeDateValue(value);
|
|
3253
|
+
}
|
|
3254
|
+
if (typeof value === "bigint") {
|
|
3255
|
+
return value.toString();
|
|
3256
|
+
}
|
|
3257
|
+
if (Array.isArray(value)) {
|
|
3258
|
+
return normalizeArrayValue(value, seen, depth);
|
|
3259
|
+
}
|
|
3260
|
+
if (value && typeof value === "object") {
|
|
3261
|
+
return normalizeObjectValue(value, seen, depth);
|
|
3262
|
+
}
|
|
3263
|
+
return value;
|
|
3264
|
+
}
|
|
3265
|
+
function normalizeDateValue(date) {
|
|
3266
|
+
const t = date.getTime();
|
|
3267
|
+
if (!Number.isFinite(t)) {
|
|
3268
|
+
throw new Error("Invalid Date value in SQL params");
|
|
3269
|
+
}
|
|
3270
|
+
return date.toISOString();
|
|
3271
|
+
}
|
|
3272
|
+
function normalizeArrayValue(value, seen, depth) {
|
|
3273
|
+
const arrRef = value;
|
|
3274
|
+
if (seen.has(arrRef)) {
|
|
3275
|
+
throw new Error("Circular reference in SQL params");
|
|
3276
|
+
}
|
|
3277
|
+
seen.add(arrRef);
|
|
3278
|
+
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
3279
|
+
seen.delete(arrRef);
|
|
3280
|
+
return out;
|
|
3281
|
+
}
|
|
3282
|
+
function normalizeObjectValue(value, seen, depth) {
|
|
3283
|
+
if (value instanceof Uint8Array) return value;
|
|
3284
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
3285
|
+
const proto = Object.getPrototypeOf(value);
|
|
3286
|
+
const isPlain = proto === Object.prototype || proto === null;
|
|
3287
|
+
if (!isPlain) return value;
|
|
3288
|
+
const obj = value;
|
|
3289
|
+
if (seen.has(obj)) {
|
|
3290
|
+
throw new Error("Circular reference in SQL params");
|
|
3291
|
+
}
|
|
3292
|
+
seen.add(obj);
|
|
3293
|
+
const out = {};
|
|
3294
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
3295
|
+
out[k] = normalizeValue(v, seen, depth + 1);
|
|
3296
|
+
}
|
|
3297
|
+
seen.delete(obj);
|
|
3298
|
+
return out;
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
// src/sql-builder-dialect.ts
|
|
3302
|
+
var globalDialect = "postgres";
|
|
3303
|
+
function setGlobalDialect(dialect) {
|
|
3304
|
+
if (dialect !== "postgres" && dialect !== "sqlite") {
|
|
3305
|
+
throw new Error(
|
|
3306
|
+
`Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
|
|
3307
|
+
);
|
|
3308
|
+
}
|
|
3309
|
+
globalDialect = dialect;
|
|
3310
|
+
}
|
|
3311
|
+
function getGlobalDialect() {
|
|
3312
|
+
return globalDialect;
|
|
3313
|
+
}
|
|
3314
|
+
function assertNonEmpty(value, name) {
|
|
3315
|
+
if (!value || value.trim().length === 0) {
|
|
3316
|
+
throw new Error(`${name} is required and cannot be empty`);
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
function arrayContains(column, value, arrayType, dialect) {
|
|
3320
|
+
assertNonEmpty(column, "arrayContains column");
|
|
3321
|
+
assertNonEmpty(value, "arrayContains value");
|
|
3322
|
+
if (dialect === "postgres") {
|
|
3323
|
+
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
3324
|
+
}
|
|
3325
|
+
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
3326
|
+
}
|
|
3327
|
+
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
3328
|
+
assertNonEmpty(column, "arrayOverlaps column");
|
|
3329
|
+
assertNonEmpty(value, "arrayOverlaps value");
|
|
3330
|
+
if (dialect === "postgres") {
|
|
3331
|
+
return `${column} && ${value}::${arrayType}`;
|
|
3332
|
+
}
|
|
3333
|
+
return `EXISTS (
|
|
3334
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
3335
|
+
JOIN json_each(${value}) AS val
|
|
3336
|
+
WHERE col.value = val.value
|
|
3337
|
+
)`;
|
|
3338
|
+
}
|
|
3339
|
+
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
3340
|
+
assertNonEmpty(column, "arrayContainsAll column");
|
|
3341
|
+
assertNonEmpty(value, "arrayContainsAll value");
|
|
3342
|
+
if (dialect === "postgres") {
|
|
3343
|
+
return `${column} @> ${value}::${arrayType}`;
|
|
3344
|
+
}
|
|
3345
|
+
return `NOT EXISTS (
|
|
3346
|
+
SELECT 1 FROM json_each(${value}) AS val
|
|
3347
|
+
WHERE NOT EXISTS (
|
|
3348
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
3349
|
+
WHERE col.value = val.value
|
|
3350
|
+
)
|
|
3351
|
+
)`;
|
|
3352
|
+
}
|
|
3353
|
+
function arrayIsEmpty(column, dialect) {
|
|
3354
|
+
assertNonEmpty(column, "arrayIsEmpty column");
|
|
3355
|
+
if (dialect === "postgres") {
|
|
3356
|
+
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
3357
|
+
}
|
|
3358
|
+
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
3359
|
+
}
|
|
3360
|
+
function arrayIsNotEmpty(column, dialect) {
|
|
3361
|
+
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
3362
|
+
if (dialect === "postgres") {
|
|
3363
|
+
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
3364
|
+
}
|
|
3365
|
+
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
3366
|
+
}
|
|
3367
|
+
function arrayEquals(column, value, arrayType, dialect) {
|
|
3368
|
+
assertNonEmpty(column, "arrayEquals column");
|
|
3369
|
+
assertNonEmpty(value, "arrayEquals value");
|
|
3370
|
+
if (dialect === "postgres") {
|
|
3371
|
+
return `${column} = ${value}::${arrayType}`;
|
|
3372
|
+
}
|
|
3373
|
+
return `json(${column}) = json(${value})`;
|
|
3374
|
+
}
|
|
3375
|
+
function caseInsensitiveLike(column, pattern, dialect) {
|
|
3376
|
+
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
3377
|
+
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
3378
|
+
if (dialect === "postgres") {
|
|
3379
|
+
return `${column} ILIKE ${pattern}`;
|
|
3380
|
+
}
|
|
3381
|
+
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
3382
|
+
}
|
|
3383
|
+
function caseInsensitiveEquals(column, value, dialect) {
|
|
3384
|
+
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
3385
|
+
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
3386
|
+
return `LOWER(${column}) = LOWER(${value})`;
|
|
3387
|
+
}
|
|
3388
|
+
function jsonExtractText(column, path, dialect) {
|
|
3389
|
+
assertNonEmpty(column, "jsonExtractText column");
|
|
3390
|
+
assertNonEmpty(path, "jsonExtractText path");
|
|
3391
|
+
if (dialect === "postgres") {
|
|
3392
|
+
const p = String(path).trim();
|
|
3393
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
3394
|
+
return `${column}#>>${pathExpr}`;
|
|
3395
|
+
}
|
|
3396
|
+
return `json_extract(${column}, ${path})`;
|
|
3397
|
+
}
|
|
3398
|
+
function jsonExtractNumeric(column, path, dialect) {
|
|
3399
|
+
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
3400
|
+
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
3401
|
+
if (dialect === "postgres") {
|
|
3402
|
+
const p = String(path).trim();
|
|
3403
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
3404
|
+
return `(${column}#>>${pathExpr})::numeric`;
|
|
3405
|
+
}
|
|
3406
|
+
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
3407
|
+
}
|
|
3408
|
+
function jsonToText(column, dialect) {
|
|
3409
|
+
assertNonEmpty(column, "jsonToText column");
|
|
3410
|
+
if (dialect === "postgres") {
|
|
3411
|
+
return `${column}::text`;
|
|
3412
|
+
}
|
|
3413
|
+
return column;
|
|
3414
|
+
}
|
|
3415
|
+
function inArray(column, value, dialect) {
|
|
3416
|
+
assertNonEmpty(column, "inArray column");
|
|
3417
|
+
assertNonEmpty(value, "inArray value");
|
|
3418
|
+
if (dialect === "postgres") {
|
|
3419
|
+
return `${column} = ANY(${value})`;
|
|
3420
|
+
}
|
|
3421
|
+
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
3422
|
+
}
|
|
3423
|
+
function notInArray(column, value, dialect) {
|
|
3424
|
+
assertNonEmpty(column, "notInArray column");
|
|
3425
|
+
assertNonEmpty(value, "notInArray value");
|
|
3426
|
+
if (dialect === "postgres") {
|
|
3427
|
+
return `${column} != ALL(${value})`;
|
|
3428
|
+
}
|
|
3429
|
+
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
3430
|
+
}
|
|
3431
|
+
function getArrayType(prismaType, dialect) {
|
|
3432
|
+
if (!prismaType || prismaType.length === 0) {
|
|
3433
|
+
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
3434
|
+
}
|
|
3435
|
+
if (dialect === "sqlite") {
|
|
3436
|
+
return "TEXT";
|
|
3437
|
+
}
|
|
3438
|
+
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
3439
|
+
switch (baseType) {
|
|
3440
|
+
case "String":
|
|
3441
|
+
return "text[]";
|
|
3442
|
+
case "Int":
|
|
3443
|
+
return "integer[]";
|
|
3444
|
+
case "Float":
|
|
3445
|
+
return "double precision[]";
|
|
3446
|
+
case "Decimal":
|
|
3447
|
+
return "numeric[]";
|
|
3448
|
+
case "Boolean":
|
|
3449
|
+
return "boolean[]";
|
|
3450
|
+
case "BigInt":
|
|
3451
|
+
return "bigint[]";
|
|
3452
|
+
case "DateTime":
|
|
3453
|
+
return "timestamptz[]";
|
|
3454
|
+
default:
|
|
3455
|
+
return `"${baseType}"[]`;
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
function jsonAgg(content, dialect) {
|
|
3459
|
+
assertNonEmpty(content, "jsonAgg content");
|
|
3460
|
+
if (dialect === "postgres") {
|
|
3461
|
+
return `json_agg(${content})`;
|
|
3462
|
+
}
|
|
3463
|
+
return `json_group_array(${content})`;
|
|
3464
|
+
}
|
|
3465
|
+
function jsonBuildObject(pairs, dialect) {
|
|
3466
|
+
const safePairs = (pairs != null ? pairs : "").trim();
|
|
3467
|
+
if (dialect === "postgres") {
|
|
3468
|
+
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
3469
|
+
}
|
|
3470
|
+
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
3471
|
+
}
|
|
3472
|
+
function prepareArrayParam(value, dialect) {
|
|
3473
|
+
if (!Array.isArray(value)) {
|
|
3474
|
+
throw new Error("prepareArrayParam requires array value");
|
|
3475
|
+
}
|
|
3476
|
+
if (dialect === "postgres") {
|
|
3477
|
+
return value.map((v) => normalizeValue(v));
|
|
3478
|
+
}
|
|
3479
|
+
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
3480
|
+
}
|
|
3483
3481
|
function normalizeIntLike(name, v, opts = {}) {
|
|
3484
3482
|
var _a3, _b;
|
|
3485
3483
|
if (!isNotNullish(v)) return void 0;
|
|
@@ -4598,14 +4596,15 @@ function hasPaginationArgs(value) {
|
|
|
4598
4596
|
const obj = value;
|
|
4599
4597
|
return "take" in obj && obj.take != null || "skip" in obj && typeof obj.skip === "number" && obj.skip > 0;
|
|
4600
4598
|
}
|
|
4601
|
-
function buildCostTree(includeSpec, model, schemas) {
|
|
4599
|
+
function buildCostTree(includeSpec, model, schemas, depth = 0) {
|
|
4600
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return [];
|
|
4602
4601
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
4603
4602
|
const nodes = [];
|
|
4604
4603
|
for (const rel of relations) {
|
|
4605
4604
|
const fan = rel.isList ? getFanOut(model.name, rel.relName) : 1;
|
|
4606
4605
|
const take = rel.isList ? readTake(rel.value) : 1;
|
|
4607
4606
|
const eff = Math.min(fan, take);
|
|
4608
|
-
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(rel.nestedSpec, rel.relModel, schemas) : [];
|
|
4607
|
+
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(rel.nestedSpec, rel.relModel, schemas, depth + 1) : [];
|
|
4609
4608
|
nodes.push({
|
|
4610
4609
|
name: rel.relName,
|
|
4611
4610
|
fan,
|
|
@@ -4671,19 +4670,26 @@ function hasOnlyToOneRelations(includeSpec, model) {
|
|
|
4671
4670
|
}
|
|
4672
4671
|
return true;
|
|
4673
4672
|
}
|
|
4674
|
-
function countIncludeDepth(includeSpec, model, schemas) {
|
|
4673
|
+
function countIncludeDepth(includeSpec, model, schemas, depth = 0) {
|
|
4674
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return 0;
|
|
4675
4675
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
4676
4676
|
let maxDepth = 0;
|
|
4677
4677
|
for (const rel of relations) {
|
|
4678
4678
|
let childDepth = 1;
|
|
4679
4679
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
4680
|
-
childDepth += countIncludeDepth(
|
|
4680
|
+
childDepth += countIncludeDepth(
|
|
4681
|
+
rel.nestedSpec,
|
|
4682
|
+
rel.relModel,
|
|
4683
|
+
schemas,
|
|
4684
|
+
depth + 1
|
|
4685
|
+
);
|
|
4681
4686
|
}
|
|
4682
4687
|
if (childDepth > maxDepth) maxDepth = childDepth;
|
|
4683
4688
|
}
|
|
4684
4689
|
return maxDepth;
|
|
4685
4690
|
}
|
|
4686
|
-
function hasChildPaginationAnywhere(includeSpec, model, schemas) {
|
|
4691
|
+
function hasChildPaginationAnywhere(includeSpec, model, schemas, depth = 0) {
|
|
4692
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return false;
|
|
4687
4693
|
for (const [, value] of Object.entries(includeSpec)) {
|
|
4688
4694
|
if (value === false) continue;
|
|
4689
4695
|
if (hasPaginationArgs(value)) return true;
|
|
@@ -4691,7 +4697,12 @@ function hasChildPaginationAnywhere(includeSpec, model, schemas) {
|
|
|
4691
4697
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
4692
4698
|
for (const rel of relations) {
|
|
4693
4699
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
4694
|
-
if (hasChildPaginationAnywhere(
|
|
4700
|
+
if (hasChildPaginationAnywhere(
|
|
4701
|
+
rel.nestedSpec,
|
|
4702
|
+
rel.relModel,
|
|
4703
|
+
schemas,
|
|
4704
|
+
depth + 1
|
|
4705
|
+
)) {
|
|
4695
4706
|
return true;
|
|
4696
4707
|
}
|
|
4697
4708
|
}
|
|
@@ -8456,9 +8467,10 @@ function buildAggregateFields(args, alias, model) {
|
|
|
8456
8467
|
addAggregateFields(fields, args, alias, model);
|
|
8457
8468
|
return fields;
|
|
8458
8469
|
}
|
|
8459
|
-
function buildAggregateSql(args, whereResult, tableName, alias, model) {
|
|
8470
|
+
function buildAggregateSql(args, whereResult, tableName, alias, model, dialect) {
|
|
8460
8471
|
assertSafeAlias(alias);
|
|
8461
8472
|
assertSafeTableRef(tableName);
|
|
8473
|
+
const d = dialect != null ? dialect : getGlobalDialect();
|
|
8462
8474
|
const aggFields = buildAggregateFields(args, alias, model);
|
|
8463
8475
|
if (!isNonEmptyArray(aggFields)) {
|
|
8464
8476
|
throw new Error("buildAggregateSql requires at least one aggregate field");
|
|
@@ -8477,7 +8489,7 @@ function buildAggregateSql(args, whereResult, tableName, alias, model) {
|
|
|
8477
8489
|
if (whereClause) parts.push(whereClause);
|
|
8478
8490
|
const sql = parts.join(" ").trim();
|
|
8479
8491
|
validateSelectQuery(sql);
|
|
8480
|
-
|
|
8492
|
+
validateParamConsistencyByDialect(sql, whereResult.params, d);
|
|
8481
8493
|
return {
|
|
8482
8494
|
sql,
|
|
8483
8495
|
params: [...whereResult.params],
|
|
@@ -8556,7 +8568,7 @@ function buildGroupBySql(args, whereResult, tableName, alias, model, dialect) {
|
|
|
8556
8568
|
const allParams = [...whereResult.params, ...snapshot.params];
|
|
8557
8569
|
const allMappings = [...whereResult.paramMappings, ...snapshot.mappings];
|
|
8558
8570
|
validateSelectQuery(sql);
|
|
8559
|
-
|
|
8571
|
+
validateParamConsistencyByDialect(sql, allParams, d);
|
|
8560
8572
|
return {
|
|
8561
8573
|
sql,
|
|
8562
8574
|
params: allParams,
|
|
@@ -8573,7 +8585,7 @@ function assertNoNegativeTake(args) {
|
|
|
8573
8585
|
throw new Error("Negative take is not supported for count()");
|
|
8574
8586
|
}
|
|
8575
8587
|
}
|
|
8576
|
-
function buildSimpleCountSql(whereResult, tableName, alias) {
|
|
8588
|
+
function buildSimpleCountSql(whereResult, tableName, alias, dialect) {
|
|
8577
8589
|
const joinsPart = whereResult.joins && whereResult.joins.length > 0 ? whereResult.joins.join(" ") : "";
|
|
8578
8590
|
const whereClause = isValidWhereClause(whereResult.clause) ? SQL_TEMPLATES.WHERE + " " + whereResult.clause : "";
|
|
8579
8591
|
const parts = [
|
|
@@ -8589,7 +8601,7 @@ function buildSimpleCountSql(whereResult, tableName, alias) {
|
|
|
8589
8601
|
if (whereClause) parts.push(whereClause);
|
|
8590
8602
|
const sql = parts.join(" ").trim();
|
|
8591
8603
|
validateSelectQuery(sql);
|
|
8592
|
-
|
|
8604
|
+
validateParamConsistencyByDialect(sql, whereResult.params, dialect);
|
|
8593
8605
|
return {
|
|
8594
8606
|
sql,
|
|
8595
8607
|
params: [...whereResult.params],
|
|
@@ -8601,14 +8613,15 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
8601
8613
|
assertSafeTableRef(tableName);
|
|
8602
8614
|
const args = normalizeCountArgs(argsOrSkip);
|
|
8603
8615
|
assertNoNegativeTake(args);
|
|
8616
|
+
const d = dialect != null ? dialect : getGlobalDialect();
|
|
8604
8617
|
if (!model) {
|
|
8605
|
-
return buildSimpleCountSql(whereResult, tableName, alias);
|
|
8618
|
+
return buildSimpleCountSql(whereResult, tableName, alias, d);
|
|
8606
8619
|
}
|
|
8607
8620
|
const pkFields = getPrimaryKeyFields(model);
|
|
8608
8621
|
const distinctFields = isNonEmptyArray(args.distinct) ? args.distinct.map((x) => String(x)).filter((x) => x) : [];
|
|
8609
8622
|
const selectFields = distinctFields.length > 0 ? distinctFields : pkFields;
|
|
8610
8623
|
if (selectFields.length === 0) {
|
|
8611
|
-
return buildSimpleCountSql(whereResult, tableName, alias);
|
|
8624
|
+
return buildSimpleCountSql(whereResult, tableName, alias, d);
|
|
8612
8625
|
}
|
|
8613
8626
|
const select2 = {};
|
|
8614
8627
|
for (const f of selectFields) select2[f] = true;
|
|
@@ -8616,7 +8629,6 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
8616
8629
|
include: void 0,
|
|
8617
8630
|
select: select2
|
|
8618
8631
|
});
|
|
8619
|
-
const d = dialect != null ? dialect : getGlobalDialect();
|
|
8620
8632
|
const subSchemas = Array.isArray(schemas) && schemas.length > 0 ? schemas : [model];
|
|
8621
8633
|
const sub = buildSelectSql({
|
|
8622
8634
|
method: "findMany",
|
|
@@ -8632,7 +8644,7 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
8632
8644
|
"_count._all"
|
|
8633
8645
|
)} ${SQL_TEMPLATES.FROM} (${sub.sql}) ${SQL_TEMPLATES.AS} ${countAlias}`;
|
|
8634
8646
|
validateSelectQuery(sql);
|
|
8635
|
-
|
|
8647
|
+
validateParamConsistencyByDialect(sql, sub.params, d);
|
|
8636
8648
|
return {
|
|
8637
8649
|
sql,
|
|
8638
8650
|
params: sub.params,
|
|
@@ -8776,7 +8788,14 @@ function buildSqlResult(args) {
|
|
|
8776
8788
|
dialect
|
|
8777
8789
|
} = args;
|
|
8778
8790
|
if (method === "aggregate") {
|
|
8779
|
-
return buildAggregateSql(
|
|
8791
|
+
return buildAggregateSql(
|
|
8792
|
+
processed,
|
|
8793
|
+
whereResult,
|
|
8794
|
+
tableName,
|
|
8795
|
+
alias,
|
|
8796
|
+
modelDef,
|
|
8797
|
+
dialect
|
|
8798
|
+
);
|
|
8780
8799
|
}
|
|
8781
8800
|
if (method === "groupBy") {
|
|
8782
8801
|
return buildGroupBySql(
|
|
@@ -10028,6 +10047,8 @@ function generateImports(runtimeImportPath) {
|
|
|
10028
10047
|
createTransactionExecutor,
|
|
10029
10048
|
transformQueryResults,
|
|
10030
10049
|
normalizeValue,
|
|
10050
|
+
setNormalizeDateMode,
|
|
10051
|
+
detectSqliteDateMode,
|
|
10031
10052
|
planQueryStrategy,
|
|
10032
10053
|
executeWhereInSegments,
|
|
10033
10054
|
buildReducerConfig,
|
|
@@ -10400,7 +10421,11 @@ function generateExtension(runtimeImportPath) {
|
|
|
10400
10421
|
throw new Error(\`Generated code is for \${DIALECT}, but you provided \${actualDialect}\`)
|
|
10401
10422
|
}
|
|
10402
10423
|
|
|
10403
|
-
|
|
10424
|
+
if ((DIALECT as string) === 'sqlite') {
|
|
10425
|
+
setNormalizeDateMode(detectSqliteDateMode(client))
|
|
10426
|
+
}
|
|
10427
|
+
|
|
10428
|
+
async function executeQuery(
|
|
10404
10429
|
sql: string,
|
|
10405
10430
|
params: unknown[],
|
|
10406
10431
|
method: string,
|
|
@@ -10424,8 +10449,14 @@ async function executeQuery(
|
|
|
10424
10449
|
lateralMeta,
|
|
10425
10450
|
})
|
|
10426
10451
|
}
|
|
10427
|
-
|
|
10428
|
-
|
|
10452
|
+
|
|
10453
|
+
try {
|
|
10454
|
+
const result = executeSqliteQuery(client, sql, params, method)
|
|
10455
|
+
return result
|
|
10456
|
+
} catch (err) {
|
|
10457
|
+
console.log('[sqlite-debug] FAILED:', err instanceof Error ? err.message : err)
|
|
10458
|
+
throw err
|
|
10459
|
+
}
|
|
10429
10460
|
}
|
|
10430
10461
|
|
|
10431
10462
|
async function executeWhereInQuery(sql: string, params: unknown[]): Promise<unknown[]> {
|