prisma-sql 1.30.0 → 1.32.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 +118 -52
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +118 -52
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +129 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +130 -44
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +125 -184
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ParamMap, DirectiveProps, Model as Model$1 } from '@dee-wan/schema-parser';
|
|
2
2
|
export { convertDMMFToModels } from '@dee-wan/schema-parser';
|
|
3
|
+
import { DMMF } from '@prisma/generator-helper';
|
|
3
4
|
|
|
4
5
|
type SqlDialect = 'postgres' | 'sqlite';
|
|
5
6
|
declare function setGlobalDialect(dialect: SqlDialect): void;
|
|
@@ -64,7 +65,8 @@ interface SqlResult {
|
|
|
64
65
|
interface SpeedExtensionConfig {
|
|
65
66
|
postgres?: any;
|
|
66
67
|
sqlite?: any;
|
|
67
|
-
models
|
|
68
|
+
models?: Model$1[];
|
|
69
|
+
dmmf?: DMMF.Document;
|
|
68
70
|
debug?: boolean;
|
|
69
71
|
allowedModels?: string[];
|
|
70
72
|
onQuery?: (info: QueryInfo) => void;
|
|
@@ -77,14 +79,73 @@ interface QueryInfo {
|
|
|
77
79
|
duration: number;
|
|
78
80
|
}
|
|
79
81
|
declare function buildSQL(model: Model$1, models: Model$1[], method: PrismaMethod, args: Record<string, unknown>, dialect: SqlDialect): SqlResult;
|
|
82
|
+
/**
|
|
83
|
+
* Runtime-only Prisma extension for SQL acceleration.
|
|
84
|
+
*
|
|
85
|
+
* ⚠️ RECOMMENDED: Use generated extension instead for zero overhead!
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // RECOMMENDED: Generated extension (no models/dmmf needed)
|
|
89
|
+
* import { speedExtension } from './generated/sql'
|
|
90
|
+
* const prisma = new PrismaClient().$extends(
|
|
91
|
+
* speedExtension({ postgres: sql })
|
|
92
|
+
* )
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Runtime with pre-converted models
|
|
96
|
+
* import { speedExtension } from 'prisma-sql'
|
|
97
|
+
* import { MODELS } from './generated/sql'
|
|
98
|
+
* const prisma = new PrismaClient().$extends(
|
|
99
|
+
* speedExtension({ postgres: sql, models: MODELS })
|
|
100
|
+
* )
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* // Runtime with DMMF (auto-converts on startup)
|
|
104
|
+
* import { speedExtension } from 'prisma-sql'
|
|
105
|
+
* import { Prisma } from '@prisma/client'
|
|
106
|
+
* const prisma = new PrismaClient().$extends(
|
|
107
|
+
* speedExtension({ postgres: sql, dmmf: Prisma.dmmf })
|
|
108
|
+
* )
|
|
109
|
+
*/
|
|
80
110
|
declare function speedExtension(config: SpeedExtensionConfig): (prisma: any) => any;
|
|
81
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Create a SQL generator function from models.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* import { createToSQL } from 'prisma-sql'
|
|
116
|
+
* import { MODELS } from './generated/sql'
|
|
117
|
+
*
|
|
118
|
+
* const toSQL = createToSQL(MODELS, 'postgres')
|
|
119
|
+
* const { sql, params } = toSQL('User', 'findMany', {
|
|
120
|
+
* where: { status: 'ACTIVE' }
|
|
121
|
+
* })
|
|
122
|
+
*/
|
|
123
|
+
declare function createToSQL(modelsOrDmmf: Model$1[] | DMMF.Document, dialect: SqlDialect): (model: string, method: PrismaMethod, args?: Record<string, unknown>) => SqlResult;
|
|
82
124
|
interface PrismaSQLConfig<TClient> {
|
|
83
125
|
client: TClient;
|
|
84
|
-
models
|
|
126
|
+
models?: Model$1[];
|
|
127
|
+
dmmf?: DMMF.Document;
|
|
85
128
|
dialect: SqlDialect;
|
|
86
129
|
execute: (client: TClient, sql: string, params: unknown[]) => Promise<unknown[]>;
|
|
87
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Create a Prisma SQL client for environments where extensions aren't supported.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* import { createPrismaSQL } from 'prisma-sql'
|
|
136
|
+
* import { MODELS } from './generated/sql'
|
|
137
|
+
*
|
|
138
|
+
* const prismaSQL = createPrismaSQL({
|
|
139
|
+
* client: sql,
|
|
140
|
+
* models: MODELS,
|
|
141
|
+
* dialect: 'postgres',
|
|
142
|
+
* execute: (client, sql, params) => client.unsafe(sql, params)
|
|
143
|
+
* })
|
|
144
|
+
*
|
|
145
|
+
* const users = await prismaSQL.query('User', 'findMany', {
|
|
146
|
+
* where: { status: 'ACTIVE' }
|
|
147
|
+
* })
|
|
148
|
+
*/
|
|
88
149
|
declare function createPrismaSQL<TClient>(config: PrismaSQLConfig<TClient>): {
|
|
89
150
|
toSQL: (model: string, method: PrismaMethod, args?: Record<string, unknown>) => SqlResult;
|
|
90
151
|
query: <T = unknown[]>(model: string, method: PrismaMethod, args?: Record<string, unknown>) => Promise<T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ParamMap, DirectiveProps, Model as Model$1 } from '@dee-wan/schema-parser';
|
|
2
2
|
export { convertDMMFToModels } from '@dee-wan/schema-parser';
|
|
3
|
+
import { DMMF } from '@prisma/generator-helper';
|
|
3
4
|
|
|
4
5
|
type SqlDialect = 'postgres' | 'sqlite';
|
|
5
6
|
declare function setGlobalDialect(dialect: SqlDialect): void;
|
|
@@ -64,7 +65,8 @@ interface SqlResult {
|
|
|
64
65
|
interface SpeedExtensionConfig {
|
|
65
66
|
postgres?: any;
|
|
66
67
|
sqlite?: any;
|
|
67
|
-
models
|
|
68
|
+
models?: Model$1[];
|
|
69
|
+
dmmf?: DMMF.Document;
|
|
68
70
|
debug?: boolean;
|
|
69
71
|
allowedModels?: string[];
|
|
70
72
|
onQuery?: (info: QueryInfo) => void;
|
|
@@ -77,14 +79,73 @@ interface QueryInfo {
|
|
|
77
79
|
duration: number;
|
|
78
80
|
}
|
|
79
81
|
declare function buildSQL(model: Model$1, models: Model$1[], method: PrismaMethod, args: Record<string, unknown>, dialect: SqlDialect): SqlResult;
|
|
82
|
+
/**
|
|
83
|
+
* Runtime-only Prisma extension for SQL acceleration.
|
|
84
|
+
*
|
|
85
|
+
* ⚠️ RECOMMENDED: Use generated extension instead for zero overhead!
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // RECOMMENDED: Generated extension (no models/dmmf needed)
|
|
89
|
+
* import { speedExtension } from './generated/sql'
|
|
90
|
+
* const prisma = new PrismaClient().$extends(
|
|
91
|
+
* speedExtension({ postgres: sql })
|
|
92
|
+
* )
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Runtime with pre-converted models
|
|
96
|
+
* import { speedExtension } from 'prisma-sql'
|
|
97
|
+
* import { MODELS } from './generated/sql'
|
|
98
|
+
* const prisma = new PrismaClient().$extends(
|
|
99
|
+
* speedExtension({ postgres: sql, models: MODELS })
|
|
100
|
+
* )
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* // Runtime with DMMF (auto-converts on startup)
|
|
104
|
+
* import { speedExtension } from 'prisma-sql'
|
|
105
|
+
* import { Prisma } from '@prisma/client'
|
|
106
|
+
* const prisma = new PrismaClient().$extends(
|
|
107
|
+
* speedExtension({ postgres: sql, dmmf: Prisma.dmmf })
|
|
108
|
+
* )
|
|
109
|
+
*/
|
|
80
110
|
declare function speedExtension(config: SpeedExtensionConfig): (prisma: any) => any;
|
|
81
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Create a SQL generator function from models.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* import { createToSQL } from 'prisma-sql'
|
|
116
|
+
* import { MODELS } from './generated/sql'
|
|
117
|
+
*
|
|
118
|
+
* const toSQL = createToSQL(MODELS, 'postgres')
|
|
119
|
+
* const { sql, params } = toSQL('User', 'findMany', {
|
|
120
|
+
* where: { status: 'ACTIVE' }
|
|
121
|
+
* })
|
|
122
|
+
*/
|
|
123
|
+
declare function createToSQL(modelsOrDmmf: Model$1[] | DMMF.Document, dialect: SqlDialect): (model: string, method: PrismaMethod, args?: Record<string, unknown>) => SqlResult;
|
|
82
124
|
interface PrismaSQLConfig<TClient> {
|
|
83
125
|
client: TClient;
|
|
84
|
-
models
|
|
126
|
+
models?: Model$1[];
|
|
127
|
+
dmmf?: DMMF.Document;
|
|
85
128
|
dialect: SqlDialect;
|
|
86
129
|
execute: (client: TClient, sql: string, params: unknown[]) => Promise<unknown[]>;
|
|
87
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Create a Prisma SQL client for environments where extensions aren't supported.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* import { createPrismaSQL } from 'prisma-sql'
|
|
136
|
+
* import { MODELS } from './generated/sql'
|
|
137
|
+
*
|
|
138
|
+
* const prismaSQL = createPrismaSQL({
|
|
139
|
+
* client: sql,
|
|
140
|
+
* models: MODELS,
|
|
141
|
+
* dialect: 'postgres',
|
|
142
|
+
* execute: (client, sql, params) => client.unsafe(sql, params)
|
|
143
|
+
* })
|
|
144
|
+
*
|
|
145
|
+
* const users = await prismaSQL.query('User', 'findMany', {
|
|
146
|
+
* where: { status: 'ACTIVE' }
|
|
147
|
+
* })
|
|
148
|
+
*/
|
|
88
149
|
declare function createPrismaSQL<TClient>(config: PrismaSQLConfig<TClient>): {
|
|
89
150
|
toSQL: (model: string, method: PrismaMethod, args?: Record<string, unknown>) => SqlResult;
|
|
90
151
|
query: <T = unknown[]>(model: string, method: PrismaMethod, args?: Record<string, unknown>) => Promise<T>;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { convertDMMFToModels, isDynamicParameter, extractDynamicName } from '@dee-wan/schema-parser';
|
|
2
2
|
export { convertDMMFToModels } from '@dee-wan/schema-parser';
|
|
3
3
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -836,14 +836,54 @@ function quote(id) {
|
|
|
836
836
|
}
|
|
837
837
|
return id;
|
|
838
838
|
}
|
|
839
|
-
function
|
|
839
|
+
function pickDbFieldName(field) {
|
|
840
|
+
const candidates = [
|
|
841
|
+
field == null ? void 0 : field.dbName,
|
|
842
|
+
field == null ? void 0 : field.columnName,
|
|
843
|
+
field == null ? void 0 : field.databaseName,
|
|
844
|
+
field == null ? void 0 : field.mappedName
|
|
845
|
+
];
|
|
846
|
+
for (const c of candidates) {
|
|
847
|
+
if (typeof c === "string") {
|
|
848
|
+
const s = c.trim();
|
|
849
|
+
if (s.length > 0) return s;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
return void 0;
|
|
853
|
+
}
|
|
854
|
+
function resolveColumnName(model, fieldName) {
|
|
855
|
+
var _a;
|
|
856
|
+
if (!model) return fieldName;
|
|
857
|
+
const f = model.fields.find((x) => (x == null ? void 0 : x.name) === fieldName);
|
|
858
|
+
if (!f) return fieldName;
|
|
859
|
+
return (_a = pickDbFieldName(f)) != null ? _a : fieldName;
|
|
860
|
+
}
|
|
861
|
+
function quoteColumn(model, fieldName) {
|
|
862
|
+
return quote(resolveColumnName(model, fieldName));
|
|
863
|
+
}
|
|
864
|
+
function col(alias, field, model) {
|
|
840
865
|
if (isEmptyString(alias)) {
|
|
841
866
|
throw new Error("col: alias is required and cannot be empty");
|
|
842
867
|
}
|
|
843
868
|
if (isEmptyString(field)) {
|
|
844
869
|
throw new Error("col: field is required and cannot be empty");
|
|
845
870
|
}
|
|
846
|
-
|
|
871
|
+
const columnName = resolveColumnName(model, field);
|
|
872
|
+
return `${alias}.${quote(columnName)}`;
|
|
873
|
+
}
|
|
874
|
+
function colWithAlias(alias, field, model) {
|
|
875
|
+
if (isEmptyString(alias)) {
|
|
876
|
+
throw new Error("colWithAlias: alias is required and cannot be empty");
|
|
877
|
+
}
|
|
878
|
+
if (isEmptyString(field)) {
|
|
879
|
+
throw new Error("colWithAlias: field is required and cannot be empty");
|
|
880
|
+
}
|
|
881
|
+
const columnName = resolveColumnName(model, field);
|
|
882
|
+
const columnRef = `${alias}.${quote(columnName)}`;
|
|
883
|
+
if (columnName !== field) {
|
|
884
|
+
return `${columnRef} AS ${quote(field)}`;
|
|
885
|
+
}
|
|
886
|
+
return columnRef;
|
|
847
887
|
}
|
|
848
888
|
function sqlStringLiteral(value) {
|
|
849
889
|
if (containsControlChars(value)) {
|
|
@@ -946,7 +986,7 @@ function getReferenceFieldNames(field, foreignKeyCount) {
|
|
|
946
986
|
if (refs.length !== foreignKeyCount) return [];
|
|
947
987
|
return refs;
|
|
948
988
|
}
|
|
949
|
-
function joinCondition(field, parentAlias, childAlias) {
|
|
989
|
+
function joinCondition(field, parentModel, childModel, parentAlias, childAlias) {
|
|
950
990
|
const fkFields = normalizeKeyList(field.foreignKey);
|
|
951
991
|
if (fkFields.length === 0) {
|
|
952
992
|
throw createError(
|
|
@@ -965,8 +1005,8 @@ function joinCondition(field, parentAlias, childAlias) {
|
|
|
965
1005
|
for (let i = 0; i < fkFields.length; i++) {
|
|
966
1006
|
const fk = fkFields[i];
|
|
967
1007
|
const ref = refFields[i];
|
|
968
|
-
const left = field.isForeignKeyLocal ? `${childAlias}.${
|
|
969
|
-
const right = field.isForeignKeyLocal ? `${parentAlias}.${
|
|
1008
|
+
const left = field.isForeignKeyLocal ? `${childAlias}.${quoteColumn(childModel, ref)}` : `${childAlias}.${quoteColumn(childModel, fk)}`;
|
|
1009
|
+
const right = field.isForeignKeyLocal ? `${parentAlias}.${quoteColumn(parentModel, fk)}` : `${parentAlias}.${quoteColumn(parentModel, ref)}`;
|
|
970
1010
|
parts.push(`${left} = ${right}`);
|
|
971
1011
|
}
|
|
972
1012
|
return parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`;
|
|
@@ -1571,7 +1611,7 @@ function buildRelation(fieldName, value, ctx, whereBuilder) {
|
|
|
1571
1611
|
ctx.dialect
|
|
1572
1612
|
);
|
|
1573
1613
|
const relAlias = ctx.aliasGen.next(fieldName);
|
|
1574
|
-
const join = joinCondition(field, ctx.alias, relAlias);
|
|
1614
|
+
const join = joinCondition(field, ctx.model, relModel, ctx.alias, relAlias);
|
|
1575
1615
|
const args = {
|
|
1576
1616
|
fieldName,
|
|
1577
1617
|
value,
|
|
@@ -2316,12 +2356,12 @@ function readSkipTake(relArgs) {
|
|
|
2316
2356
|
const takeVal = hasTake ? normalizeIntegerOrDynamic("take", obj.take) : void 0;
|
|
2317
2357
|
return { hasSkip, hasTake, skipVal, takeVal };
|
|
2318
2358
|
}
|
|
2319
|
-
function buildOrderByFragment(entries, alias, dialect) {
|
|
2359
|
+
function buildOrderByFragment(entries, alias, dialect, model) {
|
|
2320
2360
|
if (entries.length === 0) return "";
|
|
2321
2361
|
const out = [];
|
|
2322
2362
|
for (const e of entries) {
|
|
2323
2363
|
const dir = e.direction.toUpperCase();
|
|
2324
|
-
const c = col(alias, e.field);
|
|
2364
|
+
const c = col(alias, e.field, model);
|
|
2325
2365
|
if (dialect === "postgres") {
|
|
2326
2366
|
const nulls = isNotNullish(e.nulls) ? ` NULLS ${e.nulls.toUpperCase()}` : "";
|
|
2327
2367
|
out.push(`${c} ${dir}${nulls}`);
|
|
@@ -2356,7 +2396,7 @@ function ensureCursorFieldsInOrder(orderEntries, cursorEntries) {
|
|
|
2356
2396
|
}
|
|
2357
2397
|
return out;
|
|
2358
2398
|
}
|
|
2359
|
-
function buildCursorFilterParts(cursor, cursorAlias, params) {
|
|
2399
|
+
function buildCursorFilterParts(cursor, cursorAlias, params, model) {
|
|
2360
2400
|
const entries = Object.entries(cursor);
|
|
2361
2401
|
if (entries.length === 0) {
|
|
2362
2402
|
throw new Error("cursor must have at least one field");
|
|
@@ -2378,8 +2418,9 @@ function buildCursorFilterParts(cursor, cursorAlias, params) {
|
|
|
2378
2418
|
placeholdersByField
|
|
2379
2419
|
};
|
|
2380
2420
|
}
|
|
2381
|
-
function cursorValueExpr(tableName, cursorAlias, cursorWhereSql, field) {
|
|
2382
|
-
|
|
2421
|
+
function cursorValueExpr(tableName, cursorAlias, cursorWhereSql, field, model) {
|
|
2422
|
+
const colName = quote(field);
|
|
2423
|
+
return `(SELECT ${cursorAlias}.${colName} ${SQL_TEMPLATES.FROM} ${tableName} ${cursorAlias} ${SQL_TEMPLATES.WHERE} ${cursorWhereSql} ${SQL_TEMPLATES.LIMIT} 1)`;
|
|
2383
2424
|
}
|
|
2384
2425
|
function buildCursorRowExistsExpr(tableName, cursorAlias, cursorWhereSql) {
|
|
2385
2426
|
return `EXISTS (${SQL_TEMPLATES.SELECT} 1 ${SQL_TEMPLATES.FROM} ${tableName} ${cursorAlias} ${SQL_TEMPLATES.WHERE} ${cursorWhereSql} ${SQL_TEMPLATES.LIMIT} 1)`;
|
|
@@ -2394,10 +2435,10 @@ function buildCursorInequalityExpr(columnExpr, direction, nulls, valueExpr) {
|
|
|
2394
2435
|
}
|
|
2395
2436
|
return `(CASE WHEN ${valueExpr} IS NULL THEN 0=1 ELSE ((${columnExpr} ${op} ${valueExpr}) OR (${columnExpr} IS NULL)) END)`;
|
|
2396
2437
|
}
|
|
2397
|
-
function buildOuterCursorMatch(cursor, outerAlias, placeholdersByField, params) {
|
|
2438
|
+
function buildOuterCursorMatch(cursor, outerAlias, placeholdersByField, params, model) {
|
|
2398
2439
|
const parts = [];
|
|
2399
2440
|
for (const [field, value] of Object.entries(cursor)) {
|
|
2400
|
-
const c = col(outerAlias, field);
|
|
2441
|
+
const c = col(outerAlias, field, model);
|
|
2401
2442
|
if (value === null) {
|
|
2402
2443
|
parts.push(`${c} IS NULL`);
|
|
2403
2444
|
continue;
|
|
@@ -2430,7 +2471,7 @@ function buildOrderEntries(orderBy) {
|
|
|
2430
2471
|
}
|
|
2431
2472
|
return entries;
|
|
2432
2473
|
}
|
|
2433
|
-
function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect) {
|
|
2474
|
+
function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect, model) {
|
|
2434
2475
|
var _a;
|
|
2435
2476
|
const d = dialect != null ? dialect : getGlobalDialect();
|
|
2436
2477
|
const cursorEntries = Object.entries(cursor);
|
|
@@ -2457,20 +2498,29 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
2457
2498
|
cursor,
|
|
2458
2499
|
alias,
|
|
2459
2500
|
placeholdersByField,
|
|
2460
|
-
params
|
|
2501
|
+
params,
|
|
2502
|
+
model
|
|
2461
2503
|
);
|
|
2462
2504
|
const orClauses = [];
|
|
2463
2505
|
for (let level = 0; level < orderEntries.length; level++) {
|
|
2464
2506
|
const andParts = [];
|
|
2465
2507
|
for (let i = 0; i < level; i++) {
|
|
2466
2508
|
const e2 = orderEntries[i];
|
|
2467
|
-
const c2 = col(alias, e2.field);
|
|
2468
|
-
const v2 = cursorValueExpr(
|
|
2509
|
+
const c2 = col(alias, e2.field, model);
|
|
2510
|
+
const v2 = cursorValueExpr(
|
|
2511
|
+
tableName,
|
|
2512
|
+
cursorAlias,
|
|
2513
|
+
cursorWhereSql,
|
|
2514
|
+
e2.field);
|
|
2469
2515
|
andParts.push(buildCursorEqualityExpr(c2, v2));
|
|
2470
2516
|
}
|
|
2471
2517
|
const e = orderEntries[level];
|
|
2472
|
-
const c = col(alias, e.field);
|
|
2473
|
-
const v = cursorValueExpr(
|
|
2518
|
+
const c = col(alias, e.field, model);
|
|
2519
|
+
const v = cursorValueExpr(
|
|
2520
|
+
tableName,
|
|
2521
|
+
cursorAlias,
|
|
2522
|
+
cursorWhereSql,
|
|
2523
|
+
e.field);
|
|
2474
2524
|
const nulls = (_a = e.nulls) != null ? _a : defaultNullsFor(d, e.direction);
|
|
2475
2525
|
andParts.push(buildCursorInequalityExpr(c, e.direction, nulls, v));
|
|
2476
2526
|
orClauses.push(`(${andParts.join(SQL_SEPARATORS.CONDITION_AND)})`);
|
|
@@ -2478,15 +2528,15 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
2478
2528
|
const exclusive = orClauses.join(SQL_SEPARATORS.CONDITION_OR);
|
|
2479
2529
|
return `(${existsExpr} ${SQL_SEPARATORS.CONDITION_AND} ((${exclusive})${SQL_SEPARATORS.CONDITION_OR}(${outerCursorMatch})))`;
|
|
2480
2530
|
}
|
|
2481
|
-
function buildOrderBy(orderBy, alias, dialect) {
|
|
2531
|
+
function buildOrderBy(orderBy, alias, dialect, model) {
|
|
2482
2532
|
const entries = buildOrderEntries(orderBy);
|
|
2483
2533
|
if (entries.length === 0) return "";
|
|
2484
2534
|
const d = dialect != null ? dialect : getGlobalDialect();
|
|
2485
|
-
return buildOrderByFragment(entries, alias, d);
|
|
2535
|
+
return buildOrderByFragment(entries, alias, d, model);
|
|
2486
2536
|
}
|
|
2487
|
-
function buildOrderByClause(args, alias, dialect) {
|
|
2537
|
+
function buildOrderByClause(args, alias, dialect, model) {
|
|
2488
2538
|
if (!isNotNullish(args.orderBy)) return "";
|
|
2489
|
-
const result = buildOrderBy(args.orderBy, alias, dialect);
|
|
2539
|
+
const result = buildOrderBy(args.orderBy, alias, dialect, model);
|
|
2490
2540
|
if (!isNonEmptyString(result)) {
|
|
2491
2541
|
throw new Error(
|
|
2492
2542
|
"buildOrderByClause: orderBy specified but produced empty result"
|
|
@@ -2571,7 +2621,7 @@ function buildDefaultScalarFields(model, alias) {
|
|
|
2571
2621
|
for (const f of model.fields) {
|
|
2572
2622
|
if (f.isRelation) continue;
|
|
2573
2623
|
const excluded = excludedPrefixes.some((p) => f.name.startsWith(p));
|
|
2574
|
-
if (!excluded) out.push(
|
|
2624
|
+
if (!excluded) out.push(colWithAlias(alias, f.name, model));
|
|
2575
2625
|
}
|
|
2576
2626
|
if (!isNonEmptyArray(out)) {
|
|
2577
2627
|
throw new Error(`Model ${model.name} has no selectable fields`);
|
|
@@ -2589,7 +2639,9 @@ function buildSelectFields(args, model, alias) {
|
|
|
2589
2639
|
const entries = toSelectEntries(args.select);
|
|
2590
2640
|
validateSelectKeys(entries, scalarSet, relationSet);
|
|
2591
2641
|
const { scalarSelected, hasRelationSelection, hasCount } = analyzeSelectEntries(entries, scalarSet, relationSet);
|
|
2592
|
-
const fields = scalarSelected.map(
|
|
2642
|
+
const fields = scalarSelected.map(
|
|
2643
|
+
(field) => colWithAlias(alias, field, model)
|
|
2644
|
+
);
|
|
2593
2645
|
if (!isNonEmptyArray(fields)) {
|
|
2594
2646
|
if (hasRelationSelection) return "";
|
|
2595
2647
|
if (!hasCount) {
|
|
@@ -2605,7 +2657,9 @@ function buildAllScalarParts(model, alias) {
|
|
|
2605
2657
|
}
|
|
2606
2658
|
const parts = [];
|
|
2607
2659
|
for (const field of scalarFields) {
|
|
2608
|
-
parts.push(
|
|
2660
|
+
parts.push(
|
|
2661
|
+
`${sqlStringLiteral(field.name)}, ${col(alias, field.name, model)}`
|
|
2662
|
+
);
|
|
2609
2663
|
}
|
|
2610
2664
|
return parts;
|
|
2611
2665
|
}
|
|
@@ -2618,12 +2672,12 @@ function validateRelationSelectKeys(entries, scalarNames, relationNames) {
|
|
|
2618
2672
|
throw new Error(`Select contains unknown fields: ${unknown.join(", ")}`);
|
|
2619
2673
|
}
|
|
2620
2674
|
}
|
|
2621
|
-
function buildSelectedScalarParts(entries, scalarNames, alias) {
|
|
2675
|
+
function buildSelectedScalarParts(entries, scalarNames, alias, model) {
|
|
2622
2676
|
const parts = [];
|
|
2623
2677
|
for (const [key, value] of entries) {
|
|
2624
2678
|
if (!scalarNames.has(key)) continue;
|
|
2625
2679
|
if (value === true) {
|
|
2626
|
-
parts.push(`${sqlStringLiteral(key)}, ${col(alias, key)}`);
|
|
2680
|
+
parts.push(`${sqlStringLiteral(key)}, ${col(alias, key, model)}`);
|
|
2627
2681
|
}
|
|
2628
2682
|
}
|
|
2629
2683
|
return parts;
|
|
@@ -2649,9 +2703,12 @@ function buildRelationSelect(relArgs, relModel, relAlias) {
|
|
|
2649
2703
|
);
|
|
2650
2704
|
const entries = toSelectEntries(sel);
|
|
2651
2705
|
validateRelationSelectKeys(entries, scalarNames, relationNames);
|
|
2652
|
-
return buildSelectedScalarParts(
|
|
2653
|
-
|
|
2654
|
-
|
|
2706
|
+
return buildSelectedScalarParts(
|
|
2707
|
+
entries,
|
|
2708
|
+
scalarNames,
|
|
2709
|
+
relAlias,
|
|
2710
|
+
relModel
|
|
2711
|
+
).join(SQL_SEPARATORS.FIELD_LIST);
|
|
2655
2712
|
}
|
|
2656
2713
|
return buildAllScalarParts(relModel, relAlias).join(SQL_SEPARATORS.FIELD_LIST);
|
|
2657
2714
|
}
|
|
@@ -2938,8 +2995,8 @@ function limitOneSql(sql, params, skipVal, scope) {
|
|
|
2938
2995
|
}
|
|
2939
2996
|
return `${sql} ${SQL_TEMPLATES.LIMIT} 1`;
|
|
2940
2997
|
}
|
|
2941
|
-
function buildOrderBySql(finalOrderByInput, relAlias, dialect) {
|
|
2942
|
-
return isNotNullish(finalOrderByInput) ? buildOrderBy(finalOrderByInput, relAlias, dialect) : "";
|
|
2998
|
+
function buildOrderBySql(finalOrderByInput, relAlias, dialect, relModel) {
|
|
2999
|
+
return isNotNullish(finalOrderByInput) ? buildOrderBy(finalOrderByInput, relAlias, dialect, relModel) : "";
|
|
2943
3000
|
}
|
|
2944
3001
|
function buildBaseSql(args) {
|
|
2945
3002
|
return `${SQL_TEMPLATES.SELECT} ${args.selectExpr} ${SQL_TEMPLATES.FROM} ${args.relTable} ${args.relAlias} ${args.joins} ${SQL_TEMPLATES.WHERE} ${args.joinPredicate}${args.whereClause}`;
|
|
@@ -3026,7 +3083,13 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
|
|
|
3026
3083
|
const relTable = getRelationTableReference(relModel, ctx.dialect);
|
|
3027
3084
|
const relAlias = ctx.aliasGen.next(relName);
|
|
3028
3085
|
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
3029
|
-
const joinPredicate = joinCondition(
|
|
3086
|
+
const joinPredicate = joinCondition(
|
|
3087
|
+
field,
|
|
3088
|
+
ctx.model,
|
|
3089
|
+
relModel,
|
|
3090
|
+
ctx.parentAlias,
|
|
3091
|
+
relAlias
|
|
3092
|
+
);
|
|
3030
3093
|
const whereInput = readWhereInput(relArgs);
|
|
3031
3094
|
const relSelect = buildSelectWithNestedIncludes(
|
|
3032
3095
|
relArgs,
|
|
@@ -3051,7 +3114,12 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
|
|
|
3051
3114
|
adjusted.orderByInput,
|
|
3052
3115
|
hasPagination
|
|
3053
3116
|
);
|
|
3054
|
-
const orderBySql = buildOrderBySql(
|
|
3117
|
+
const orderBySql = buildOrderBySql(
|
|
3118
|
+
finalOrderByInput,
|
|
3119
|
+
relAlias,
|
|
3120
|
+
ctx.dialect,
|
|
3121
|
+
relModel
|
|
3122
|
+
);
|
|
3055
3123
|
if (!isList) {
|
|
3056
3124
|
const sql = buildOneToOneIncludeSql({
|
|
3057
3125
|
relName,
|
|
@@ -4638,7 +4706,8 @@ function speedExtension(config) {
|
|
|
4638
4706
|
const {
|
|
4639
4707
|
postgres,
|
|
4640
4708
|
sqlite,
|
|
4641
|
-
models,
|
|
4709
|
+
models: providedModels,
|
|
4710
|
+
dmmf,
|
|
4642
4711
|
debug = false,
|
|
4643
4712
|
allowedModels,
|
|
4644
4713
|
onQuery
|
|
@@ -4651,11 +4720,19 @@ function speedExtension(config) {
|
|
|
4651
4720
|
"speedExtension cannot use both postgres and sqlite clients"
|
|
4652
4721
|
);
|
|
4653
4722
|
}
|
|
4654
|
-
|
|
4723
|
+
let models;
|
|
4724
|
+
if (providedModels) {
|
|
4725
|
+
models = providedModels;
|
|
4726
|
+
} else if (dmmf) {
|
|
4727
|
+
models = convertDMMFToModels(dmmf.datamodel);
|
|
4728
|
+
} else {
|
|
4655
4729
|
throw new Error(
|
|
4656
|
-
|
|
4730
|
+
'speedExtension requires either models or dmmf parameter.\n\n\u26A0\uFE0F RECOMMENDED APPROACH:\n Use the generated extension for zero runtime overhead:\n\n import { speedExtension } from "./generated/sql"\n const prisma = new PrismaClient().$extends(\n speedExtension({ postgres: sql })\n )\n\n 1. Add generator to schema.prisma:\n generator sql {\n provider = "prisma-sql-generator"\n }\n\n 2. Run: npx prisma generate\n\n 3. Import from generated file\n\n\u274C RUNTIME-ONLY MODE:\n If you cannot use the generator, provide models or dmmf:\n\n import { speedExtension } from "prisma-sql"\n import { MODELS } from "./generated/sql"\n const prisma = new PrismaClient().$extends(\n speedExtension({ postgres: sql, models: MODELS })\n )\n\n Or with DMMF (auto-converts on startup):\n\n import { Prisma } from "@prisma/client"\n const prisma = new PrismaClient().$extends(\n speedExtension({ postgres: sql, dmmf: Prisma.dmmf })\n )'
|
|
4657
4731
|
);
|
|
4658
4732
|
}
|
|
4733
|
+
if (!Array.isArray(models) || models.length === 0) {
|
|
4734
|
+
throw new Error("speedExtension: models array is empty or invalid");
|
|
4735
|
+
}
|
|
4659
4736
|
const dialect = postgres ? "postgres" : "sqlite";
|
|
4660
4737
|
const client = postgres || sqlite;
|
|
4661
4738
|
setGlobalDialect(dialect);
|
|
@@ -4683,7 +4760,7 @@ function speedExtension(config) {
|
|
|
4683
4760
|
methodHandlers[method] = createMethodHandler(method);
|
|
4684
4761
|
}
|
|
4685
4762
|
return prisma.$extends({
|
|
4686
|
-
name: "speed
|
|
4763
|
+
name: "prisma-sql-speed",
|
|
4687
4764
|
client: {
|
|
4688
4765
|
$original: prisma
|
|
4689
4766
|
},
|
|
@@ -4709,13 +4786,22 @@ function createToSQLFunction(models, dialect) {
|
|
|
4709
4786
|
return buildSQL(m, models, method, args, dialect);
|
|
4710
4787
|
};
|
|
4711
4788
|
}
|
|
4712
|
-
function createToSQL(
|
|
4789
|
+
function createToSQL(modelsOrDmmf, dialect) {
|
|
4790
|
+
const models = Array.isArray(modelsOrDmmf) ? modelsOrDmmf : convertDMMFToModels(modelsOrDmmf.datamodel);
|
|
4713
4791
|
return createToSQLFunction(models, dialect);
|
|
4714
4792
|
}
|
|
4715
4793
|
function createPrismaSQL(config) {
|
|
4716
|
-
const { client, models, dialect, execute } = config;
|
|
4717
|
-
|
|
4718
|
-
|
|
4794
|
+
const { client, models: providedModels, dmmf, dialect, execute } = config;
|
|
4795
|
+
let models;
|
|
4796
|
+
if (providedModels) {
|
|
4797
|
+
models = providedModels;
|
|
4798
|
+
} else if (dmmf) {
|
|
4799
|
+
models = convertDMMFToModels(dmmf.datamodel);
|
|
4800
|
+
} else {
|
|
4801
|
+
throw new Error("createPrismaSQL requires either models or dmmf parameter");
|
|
4802
|
+
}
|
|
4803
|
+
if (!Array.isArray(models) || models.length === 0) {
|
|
4804
|
+
throw new Error("createPrismaSQL: models array is empty or invalid");
|
|
4719
4805
|
}
|
|
4720
4806
|
const toSQL = createToSQLFunction(models, dialect);
|
|
4721
4807
|
function query(_0, _1) {
|