prisma-sql 1.7.0 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prisma-sql",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
package/readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # prisma-sql
2
2
 
3
- Speed up Prisma reads **2-7x** by executing queries via postgres.js instead of Prisma's query engine.
3
+ Speed up Prisma reads **2-7x** by executing queries via postgres.js or better-sqlite3 instead of Prisma's query engine.
4
4
 
5
5
  ```typescript
6
6
  import { convertDMMFToModels } from 'prisma-sql'
@@ -44,7 +44,82 @@ npm install prisma-sql better-sqlite3
44
44
 
45
45
  ## Quick Start
46
46
 
47
- ### PostgreSQL
47
+ You can use prisma-sql in two ways:
48
+
49
+ ### 1. Generator Mode (Recommended - Fastest)
50
+
51
+ Prebake SQL queries at build time for maximum performance.
52
+
53
+ **Add generator to schema:**
54
+
55
+ ```prisma
56
+ // schema.prisma
57
+ datasource db {
58
+ provider = "postgresql"
59
+ url = env("DATABASE_URL")
60
+ }
61
+
62
+ generator client {
63
+ provider = "prisma-client-js"
64
+ }
65
+
66
+ generator sql {
67
+ provider = "prisma-sql-generator"
68
+ // Dialect auto-detected from datasource.provider
69
+ }
70
+
71
+ model User {
72
+ id Int @id @default(autoincrement())
73
+ email String @unique
74
+ status String
75
+ posts Post[]
76
+
77
+ /// @sql.findMany({ where: { status: "ACTIVE" } })
78
+ /// @sql.findMany({ where: { status: "PENDING" } })
79
+ /// @sql.count({ where: { status: "ACTIVE" } })
80
+ }
81
+
82
+ model Post {
83
+ id Int @id @default(autoincrement())
84
+ title String
85
+ published Boolean
86
+ authorId Int
87
+ author User @relation(fields: [authorId], references: [id])
88
+
89
+ /// @sql.findMany({ where: { published: true }, include: { author: true } })
90
+ }
91
+ ```
92
+
93
+ **Generate and use:**
94
+
95
+ ```bash
96
+ npx prisma generate
97
+ ```
98
+
99
+ ```typescript
100
+ import { PrismaClient } from '@prisma/client'
101
+ import { createExtension } from '.prisma/client/sql'
102
+ import postgres from 'postgres'
103
+
104
+ const sql = postgres(process.env.DATABASE_URL)
105
+ const prisma = new PrismaClient().$extends(createExtension({ postgres: sql }))
106
+
107
+ // ⚡ PREBAKED - Uses pre-generated SQL (instant)
108
+ const activeUsers = await prisma.user.findMany({
109
+ where: { status: 'ACTIVE' },
110
+ })
111
+
112
+ // 🔨 RUNTIME - Generates SQL on-the-fly (still fast)
113
+ const searchUsers = await prisma.user.findMany({
114
+ where: { email: { contains: '@example.com' } },
115
+ })
116
+ ```
117
+
118
+ ### 2. Runtime Mode (Simpler, No Build Step)
119
+
120
+ Generate SQL on-the-fly without code generation.
121
+
122
+ **PostgreSQL:**
48
123
 
49
124
  ```typescript
50
125
  import { PrismaClient, Prisma } from '@prisma/client'
@@ -63,7 +138,7 @@ const users = await prisma.user.findMany({
63
138
  })
64
139
  ```
65
140
 
66
- ### SQLite
141
+ **SQLite:**
67
142
 
68
143
  ```typescript
69
144
  import { PrismaClient, Prisma } from '@prisma/client'
@@ -79,6 +154,167 @@ const prisma = new PrismaClient().$extends(
79
154
  const users = await prisma.user.findMany({ where: { status: 'ACTIVE' } })
80
155
  ```
81
156
 
157
+ ## Generator Mode vs Runtime Mode
158
+
159
+ ### Generator Mode (Recommended)
160
+
161
+ **Pros:**
162
+
163
+ - ⚡ **Fastest** - SQL pre-generated at build time
164
+ - 🎯 **Zero overhead** for known queries
165
+ - 🔨 **Auto-fallback** to runtime for unknown queries
166
+ - 📊 **Track performance** with `prebaked` flag
167
+
168
+ **Cons:**
169
+
170
+ - Requires `npx prisma generate` step
171
+ - Need to define common queries upfront
172
+
173
+ **When to use:**
174
+
175
+ - ✅ Production applications
176
+ - ✅ Known query patterns (dashboards, APIs)
177
+ - ✅ Want maximum performance
178
+ - ✅ Build step is acceptable
179
+
180
+ ### Runtime Mode
181
+
182
+ **Pros:**
183
+
184
+ - 🚀 **Simple** - no build step
185
+ - 🔧 **Flexible** - handles any query
186
+ - 📝 **Easy prototyping**
187
+
188
+ **Cons:**
189
+
190
+ - Small overhead (~0.2ms) for SQL generation
191
+ - Still 2-7x faster than Prisma
192
+
193
+ **When to use:**
194
+
195
+ - ✅ Rapid prototyping
196
+ - ✅ Fully dynamic queries
197
+ - ✅ No build step desired
198
+ - ✅ Query patterns unknown
199
+
200
+ ## Generator Mode Details
201
+
202
+ ### How It Works
203
+
204
+ ```
205
+ Build Time:
206
+ schema.prisma
207
+
208
+ /// @sql.findMany({ where: { status: "ACTIVE" } })
209
+
210
+ npx prisma generate
211
+
212
+ .prisma/client/sql/index.ts
213
+
214
+ QUERIES = {
215
+ User: {
216
+ '{"where":{"status":"ACTIVE"}}': {
217
+ sql: 'SELECT * FROM users WHERE status = $1',
218
+ params: ['ACTIVE'],
219
+ dynamicKeys: []
220
+ }
221
+ }
222
+ }
223
+
224
+ Runtime:
225
+ prisma.user.findMany({ where: { status: 'ACTIVE' } })
226
+
227
+ Normalize query → '{"where":{"status":"ACTIVE"}}'
228
+
229
+ QUERIES.User[query] found?
230
+
231
+ YES → ⚡ Use prebaked SQL (0.03ms overhead)
232
+
233
+ NO → 🔨 Generate SQL runtime (0.2ms overhead)
234
+
235
+ Execute via postgres.js/better-sqlite3
236
+ ```
237
+
238
+ ### Generator Configuration
239
+
240
+ ```prisma
241
+ generator sql {
242
+ provider = "prisma-sql-generator"
243
+
244
+ // Optional: Override auto-detected dialect (rarely needed)
245
+ // dialect = "postgres" // or "sqlite"
246
+
247
+ // Optional: Output directory (default: ../node_modules/.prisma/client/sql)
248
+ // output = "./generated/sql"
249
+
250
+ // Optional: Skip invalid directives instead of failing (default: false)
251
+ // skipInvalid = "true"
252
+ }
253
+ ```
254
+
255
+ ### Supported Directive Patterns
256
+
257
+ ```prisma
258
+ model User {
259
+ // Simple queries
260
+ /// @sql.findMany({ where: { status: "ACTIVE" } })
261
+ /// @sql.findFirst({ where: { email: "test@example.com" } })
262
+ /// @sql.findUnique({ where: { id: 1 } })
263
+
264
+ // With relations
265
+ /// @sql.findMany({ include: { posts: true } })
266
+ /// @sql.findMany({ include: { posts: { where: { published: true } } } })
267
+
268
+ // With pagination
269
+ /// @sql.findMany({ take: 10, skip: 20, orderBy: { createdAt: "desc" } })
270
+
271
+ // Aggregations
272
+ /// @sql.count({ where: { status: "ACTIVE" } })
273
+ /// @sql.aggregate({ _count: { _all: true }, _avg: { age: true } })
274
+ /// @sql.groupBy({ by: ["status"], _count: { _all: true } })
275
+
276
+ // Dynamic parameters
277
+ /// @sql.findMany({ where: { status: { $param: "status" } } })
278
+ /// @sql.findMany({ where: { age: { gte: { $param: "minAge" } } } })
279
+ }
280
+ ```
281
+
282
+ ### Dynamic Parameters
283
+
284
+ Use `$param` for runtime values:
285
+
286
+ ```prisma
287
+ model User {
288
+ /// @sql.findMany({ where: { status: { $param: "status" } } })
289
+ /// @sql.findMany({ where: { age: { gte: { $param: "minAge" } } } })
290
+ }
291
+ ```
292
+
293
+ ```typescript
294
+ // Prebaked SQL with runtime parameters
295
+ const users = await prisma.user.findMany({
296
+ where: { status: 'ACTIVE' }, // Matches directive with $param
297
+ })
298
+
299
+ // SQL: SELECT * FROM users WHERE status = $1
300
+ // Params: ['ACTIVE']
301
+ ```
302
+
303
+ ### Performance Tracking
304
+
305
+ ```typescript
306
+ const prisma = new PrismaClient().$extends(
307
+ createExtension({
308
+ postgres: sql,
309
+ debug: true,
310
+ onQuery: (info) => {
311
+ console.log(`${info.model}.${info.method}: ${info.duration}ms`)
312
+ console.log(info.prebaked ? '⚡ PREBAKED' : '🔨 RUNTIME')
313
+ },
314
+ }),
315
+ )
316
+ ```
317
+
82
318
  ## What Gets Faster
83
319
 
84
320
  **Accelerated (via raw SQL):**
@@ -613,7 +849,30 @@ const prisma = new PrismaClient()
613
849
  const users = await prisma.user.findMany()
614
850
  ```
615
851
 
616
- **After:**
852
+ **After (Generator Mode):**
853
+
854
+ ```prisma
855
+ // schema.prisma
856
+ generator sql {
857
+ provider = "prisma-sql-generator"
858
+ }
859
+
860
+ model User {
861
+ /// @sql.findMany({ where: { status: "ACTIVE" } })
862
+ }
863
+ ```
864
+
865
+ ```typescript
866
+ import { createExtension } from '.prisma/client/sql'
867
+ import postgres from 'postgres'
868
+
869
+ const sql = postgres(DATABASE_URL)
870
+ const prisma = new PrismaClient().$extends(createExtension({ postgres: sql }))
871
+
872
+ const users = await prisma.user.findMany({ where: { status: 'ACTIVE' } })
873
+ ```
874
+
875
+ **After (Runtime Mode):**
617
876
 
618
877
  ```typescript
619
878
  import postgres from 'postgres'
@@ -663,6 +922,48 @@ const users = await prisma.user.findMany({
663
922
  })
664
923
  ```
665
924
 
925
+ ## Local Development
926
+
927
+ ### Testing the Generator Locally
928
+
929
+ **1. Build the package:**
930
+
931
+ ```bash
932
+ cd prisma-sql
933
+ npm install
934
+ npm run build
935
+ ```
936
+
937
+ **2. Link globally:**
938
+
939
+ ```bash
940
+ npm link
941
+ ```
942
+
943
+ **3. Use in your project:**
944
+
945
+ ```bash
946
+ cd your-project
947
+ npm link prisma-sql
948
+ npx prisma generate
949
+ ```
950
+
951
+ **Alternative: Use file path directly in schema:**
952
+
953
+ ```prisma
954
+ generator sql {
955
+ provider = "node ../path/to/prisma-sql/dist/generator.cjs"
956
+ }
957
+ ```
958
+
959
+ **Unlink when done:**
960
+
961
+ ```bash
962
+ npm unlink prisma-sql # In your project
963
+ cd prisma-sql
964
+ npm unlink # In prisma-sql directory
965
+ ```
966
+
666
967
  ## Limitations
667
968
 
668
969
  ### Partially Supported
@@ -712,6 +1013,20 @@ const prisma = new PrismaClient().$extends(
712
1013
  )
713
1014
  ```
714
1015
 
1016
+ ### "Generator: Cannot find module"
1017
+
1018
+ The package hasn't been built or linked:
1019
+
1020
+ ```bash
1021
+ # In prisma-sql directory
1022
+ npm run build
1023
+ npm link
1024
+
1025
+ # In your project
1026
+ npm link prisma-sql
1027
+ npx prisma generate
1028
+ ```
1029
+
715
1030
  ### "Results don't match Prisma Client"
716
1031
 
717
1032
  Enable debug mode to inspect generated SQL:
@@ -732,7 +1047,7 @@ Compare with Prisma's query log:
732
1047
  new PrismaClient({ log: ['query'] })
733
1048
  ```
734
1049
 
735
- File an issue if results differ: https://github.com/dee-see/prisma-sql/issues
1050
+ File an issue if results differ: https://github.com/multipliedtwice/prisma-sql/issues
736
1051
 
737
1052
  ### "Connection pool exhausted"
738
1053
 
@@ -799,7 +1114,7 @@ A: The extension runs after middlewares. If you need middleware to see the actua
799
1114
  A: Yes. Those methods are unaffected. You also still have direct access to the postgres.js client.
800
1115
 
801
1116
  **Q: What's the overhead of SQL generation?**
802
- A: ~0.03-0.04ms per query. Even with this overhead, total time is 2-7x faster than Prisma.
1117
+ A: Generator mode: ~0.03ms (prebaked queries). Runtime mode: ~0.2ms. Even with this overhead, total time is 2-7x faster than Prisma.
803
1118
 
804
1119
  **Q: How do I benchmark my own queries?**
805
1120
  A: Use the `onQuery` callback to measure each query, or see the [Benchmarking](#benchmarking) section below.
@@ -807,8 +1122,12 @@ A: Use the `onQuery` callback to measure each query, or see the [Benchmarking](#
807
1122
  **Q: How does performance compare to Prisma v7?**
808
1123
  A: Prisma v7 introduced significant improvements (~39% faster than v6 on PostgreSQL, ~24% on SQLite), but this extension still provides 2-7x additional speedup over v7 depending on query complexity.
809
1124
 
1125
+ **Q: Should I use generator mode or runtime mode?**
1126
+ A: Generator mode is recommended for production (faster). Runtime mode is better for prototyping or fully dynamic queries.
1127
+
810
1128
  ## Examples
811
1129
 
1130
+ - [Generator Mode Example](./examples/generator-mode) - Complete working example
812
1131
  - [PostgreSQL E2E Tests](./tests/e2e/postgres.test.ts) - Comprehensive query examples
813
1132
  - [SQLite E2E Tests](./tests/e2e/sqlite.e2e.test.ts) - SQLite-specific queries
814
1133
  - [Runtime API Tests](./tests/e2e/runtime-api.test.ts) - All three APIs
@@ -816,7 +1135,7 @@ A: Prisma v7 introduced significant improvements (~39% faster than v6 on Postgre
816
1135
  To run examples locally:
817
1136
 
818
1137
  ```bash
819
- git clone https://github.com/dee-see/prisma-sql
1138
+ git clone https://github.com/multipliedtwice/prisma-sql
820
1139
  cd prisma-sql
821
1140
  npm install
822
1141
  npm test
@@ -855,7 +1174,7 @@ console.table(queries)
855
1174
  Or run the full test suite benchmarks:
856
1175
 
857
1176
  ```bash
858
- git clone https://github.com/dee-see/prisma-sql
1177
+ git clone https://github.com/multipliedtwice/prisma-sql
859
1178
  cd prisma-sql
860
1179
  npm install
861
1180
 
@@ -881,10 +1200,10 @@ PRs welcome! Priority areas:
881
1200
  Setup:
882
1201
 
883
1202
  ```bash
884
- git clone https://github.com/dee-see/prisma-sql
1203
+ git clone https://github.com/multipliedtwice/prisma-sql
885
1204
  cd prisma-sql
886
1205
  npm install
887
- npm run generate
1206
+ npm run build
888
1207
  npm test
889
1208
  ```
890
1209
 
@@ -936,8 +1255,8 @@ MIT
936
1255
  ## Links
937
1256
 
938
1257
  - [NPM Package](https://www.npmjs.com/package/prisma-sql)
939
- - [GitHub Repository](https://github.com/dee-see/prisma-sql)
940
- - [Issue Tracker](https://github.com/dee-see/prisma-sql/issues)
1258
+ - [GitHub Repository](https://github.com/multipliedtwice/prisma-sql)
1259
+ - [Issue Tracker](https://github.com/multipliedtwice/prisma-sql/issues)
941
1260
 
942
1261
  ---
943
1262