forge-sql-orm 2.0.30 → 2.1.1
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/README.md +1410 -81
- package/dist/ForgeSQLORM.js +1456 -60
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +1440 -61
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLAnalyseOperations.d.ts +1 -1
- package/dist/core/ForgeSQLAnalyseOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLCacheOperations.d.ts +119 -0
- package/dist/core/ForgeSQLCacheOperations.d.ts.map +1 -0
- package/dist/core/ForgeSQLCrudOperations.d.ts +38 -22
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +248 -13
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +394 -19
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts +90 -0
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -0
- package/dist/utils/cacheContextUtils.d.ts +123 -0
- package/dist/utils/cacheContextUtils.d.ts.map +1 -0
- package/dist/utils/cacheUtils.d.ts +56 -0
- package/dist/utils/cacheUtils.d.ts.map +1 -0
- package/dist/utils/sqlUtils.d.ts +8 -0
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts +46 -0
- package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts.map +1 -0
- package/dist/webtriggers/index.d.ts +1 -0
- package/dist/webtriggers/index.d.ts.map +1 -1
- package/package.json +15 -12
- package/src/core/ForgeSQLAnalyseOperations.ts +1 -1
- package/src/core/ForgeSQLCacheOperations.ts +195 -0
- package/src/core/ForgeSQLCrudOperations.ts +49 -40
- package/src/core/ForgeSQLORM.ts +743 -34
- package/src/core/ForgeSQLQueryBuilder.ts +456 -20
- package/src/index.ts +1 -1
- package/src/lib/drizzle/extensions/additionalActions.ts +852 -0
- package/src/lib/drizzle/extensions/types.d.ts +99 -10
- package/src/utils/cacheContextUtils.ts +212 -0
- package/src/utils/cacheUtils.ts +403 -0
- package/src/utils/sqlUtils.ts +42 -0
- package/src/webtriggers/clearCacheSchedulerTrigger.ts +79 -0
- package/src/webtriggers/index.ts +1 -0
- package/dist/lib/drizzle/extensions/selectAliased.d.ts +0 -9
- package/dist/lib/drizzle/extensions/selectAliased.d.ts.map +0 -1
- package/src/lib/drizzle/extensions/selectAliased.ts +0 -72
package/src/core/ForgeSQLORM.ts
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import { ForgeSQLCrudOperations } from "./ForgeSQLCrudOperations";
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
VerioningModificationForgeSQL,
|
|
4
4
|
ForgeSqlOperation,
|
|
5
5
|
ForgeSqlOrmOptions,
|
|
6
6
|
SchemaAnalyzeForgeSql,
|
|
7
7
|
SchemaSqlForgeSql,
|
|
8
8
|
} from "./ForgeSQLQueryBuilder";
|
|
9
9
|
import { ForgeSQLSelectOperations } from "./ForgeSQLSelectOperations";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
drizzle,
|
|
12
|
+
MySqlRemoteDatabase,
|
|
13
|
+
MySqlRemotePreparedQueryHKT,
|
|
14
|
+
MySqlRemoteQueryResultHKT,
|
|
15
|
+
} from "drizzle-orm/mysql-proxy";
|
|
11
16
|
import { createForgeDriverProxy } from "../utils/forgeDriverProxy";
|
|
12
17
|
import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
13
18
|
import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
|
|
14
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
DeleteAndEvictCacheType,
|
|
21
|
+
InsertAndEvictCacheType,
|
|
22
|
+
patchDbWithSelectAliased,
|
|
23
|
+
SelectAliasedCacheableType,
|
|
24
|
+
SelectAliasedDistinctCacheableType,
|
|
25
|
+
SelectAliasedDistinctType,
|
|
26
|
+
SelectAliasedType,
|
|
27
|
+
UpdateAndEvictCacheType,
|
|
28
|
+
} from "../lib/drizzle/extensions/additionalActions";
|
|
15
29
|
import { ForgeSQLAnalyseOperation } from "./ForgeSQLAnalyseOperations";
|
|
30
|
+
import { ForgeSQLCacheOperations } from "./ForgeSQLCacheOperations";
|
|
31
|
+
import type { MySqlTable } from "drizzle-orm/mysql-core/table";
|
|
32
|
+
import {
|
|
33
|
+
MySqlDeleteBase,
|
|
34
|
+
MySqlInsertBuilder,
|
|
35
|
+
MySqlUpdateBuilder,
|
|
36
|
+
} from "drizzle-orm/mysql-core/query-builders";
|
|
37
|
+
import { cacheApplicationContext, localCacheApplicationContext } from "../utils/cacheContextUtils";
|
|
38
|
+
import { clearTablesCache } from "../utils/cacheUtils";
|
|
39
|
+
import { SQLWrapper } from "drizzle-orm/sql/sql";
|
|
40
|
+
import { WithSubquery } from "drizzle-orm/subquery";
|
|
16
41
|
|
|
17
42
|
/**
|
|
18
43
|
* Implementation of ForgeSQLORM that uses Drizzle ORM for query building.
|
|
@@ -22,16 +47,22 @@ import { ForgeSQLAnalyseOperation } from "./ForgeSQLAnalyseOperations";
|
|
|
22
47
|
class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
23
48
|
private static instance: ForgeSQLORMImpl | null = null;
|
|
24
49
|
private readonly drizzle: MySqlRemoteDatabase<any> & {
|
|
25
|
-
selectAliased:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
50
|
+
selectAliased: SelectAliasedType;
|
|
51
|
+
selectAliasedDistinct: SelectAliasedDistinctType;
|
|
52
|
+
selectAliasedCacheable: SelectAliasedCacheableType;
|
|
53
|
+
selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
|
|
54
|
+
insertWithCacheContext: InsertAndEvictCacheType;
|
|
55
|
+
insertAndEvictCache: InsertAndEvictCacheType;
|
|
56
|
+
updateAndEvictCache: UpdateAndEvictCacheType;
|
|
57
|
+
updateWithCacheContext: UpdateAndEvictCacheType;
|
|
58
|
+
deleteAndEvictCache: DeleteAndEvictCacheType;
|
|
59
|
+
deleteWithCacheContext: DeleteAndEvictCacheType;
|
|
31
60
|
};
|
|
32
|
-
private readonly crudOperations:
|
|
61
|
+
private readonly crudOperations: VerioningModificationForgeSQL;
|
|
33
62
|
private readonly fetchOperations: SchemaSqlForgeSql;
|
|
34
63
|
private readonly analyzeOperations: SchemaAnalyzeForgeSql;
|
|
64
|
+
private readonly cacheOperations: ForgeSQLCacheOperations;
|
|
65
|
+
private readonly options: ForgeSqlOrmOptions;
|
|
35
66
|
|
|
36
67
|
/**
|
|
37
68
|
* Private constructor to enforce singleton behavior.
|
|
@@ -42,7 +73,13 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
42
73
|
const newOptions: ForgeSqlOrmOptions = options ?? {
|
|
43
74
|
logRawSqlQuery: false,
|
|
44
75
|
disableOptimisticLocking: false,
|
|
76
|
+
cacheWrapTable: true,
|
|
77
|
+
cacheTTL: 120,
|
|
78
|
+
cacheEntityQueryName: "sql",
|
|
79
|
+
cacheEntityExpirationName: "expiration",
|
|
80
|
+
cacheEntityDataName: "data",
|
|
45
81
|
};
|
|
82
|
+
this.options = newOptions;
|
|
46
83
|
if (newOptions.logRawSqlQuery) {
|
|
47
84
|
console.debug("Initializing ForgeSQLORM...");
|
|
48
85
|
}
|
|
@@ -50,21 +87,191 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
50
87
|
const proxiedDriver = createForgeDriverProxy(newOptions.hints, newOptions.logRawSqlQuery);
|
|
51
88
|
this.drizzle = patchDbWithSelectAliased(
|
|
52
89
|
drizzle(proxiedDriver, { logger: newOptions.logRawSqlQuery }),
|
|
90
|
+
newOptions,
|
|
53
91
|
);
|
|
54
92
|
this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
|
|
55
93
|
this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
|
|
56
94
|
this.analyzeOperations = new ForgeSQLAnalyseOperation(this);
|
|
95
|
+
this.cacheOperations = new ForgeSQLCacheOperations(newOptions, this);
|
|
57
96
|
} catch (error) {
|
|
58
97
|
console.error("ForgeSQLORM initialization failed:", error);
|
|
59
98
|
throw error;
|
|
60
99
|
}
|
|
61
100
|
}
|
|
62
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Executes operations within a cache context that collects cache eviction events.
|
|
104
|
+
* All clearCache calls within the context are collected and executed in batch at the end.
|
|
105
|
+
* Queries executed within this context will bypass cache for tables that were marked for clearing.
|
|
106
|
+
*
|
|
107
|
+
* This is useful for:
|
|
108
|
+
* - Batch operations that affect multiple tables
|
|
109
|
+
* - Transaction-like operations where you want to clear cache only at the end
|
|
110
|
+
* - Performance optimization by reducing cache clear operations
|
|
111
|
+
*
|
|
112
|
+
* @param cacheContext - Function containing operations that may trigger cache evictions
|
|
113
|
+
* @returns Promise that resolves when all operations and cache clearing are complete
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* await forgeSQL.executeWithCacheContext(async () => {
|
|
118
|
+
* await forgeSQL.modifyWithVersioning().insert(users, userData);
|
|
119
|
+
* await forgeSQL.modifyWithVersioning().insert(orders, orderData);
|
|
120
|
+
* // Cache for both users and orders tables will be cleared at the end
|
|
121
|
+
* });
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
executeWithCacheContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
125
|
+
return this.executeWithCacheContextAndReturnValue<void>(cacheContext);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Executes operations within a cache context and returns a value.
|
|
130
|
+
* All clearCache calls within the context are collected and executed in batch at the end.
|
|
131
|
+
* Queries executed within this context will bypass cache for tables that were marked for clearing.
|
|
132
|
+
*
|
|
133
|
+
* @param cacheContext - Function containing operations that may trigger cache evictions
|
|
134
|
+
* @returns Promise that resolves to the return value of the cacheContext function
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const result = await forgeSQL.executeWithCacheContextAndReturnValue(async () => {
|
|
139
|
+
* await forgeSQL.modifyWithVersioning().insert(users, userData);
|
|
140
|
+
* return await forgeSQL.fetch().executeQueryOnlyOne(selectUserQuery);
|
|
141
|
+
* });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
async executeWithCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
145
|
+
return await this.executeWithLocalCacheContextAndReturnValue(
|
|
146
|
+
async () =>
|
|
147
|
+
await cacheApplicationContext.run(cacheApplicationContext.getStore() ?? { tables: new Set<string>() }, async () => {
|
|
148
|
+
try {
|
|
149
|
+
return await cacheContext();
|
|
150
|
+
} finally {
|
|
151
|
+
await clearTablesCache(
|
|
152
|
+
Array.from(cacheApplicationContext.getStore()?.tables ?? []),
|
|
153
|
+
this.options,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Executes operations within a local cache context and returns a value.
|
|
161
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
162
|
+
*
|
|
163
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
164
|
+
* @returns Promise that resolves to the return value of the cacheContext function
|
|
165
|
+
*/
|
|
166
|
+
async executeWithLocalCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
167
|
+
return await localCacheApplicationContext.run(localCacheApplicationContext.getStore() ?? { cache: {} }, async () => {
|
|
168
|
+
return await cacheContext();
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Executes operations within a local cache context.
|
|
174
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
175
|
+
*
|
|
176
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
177
|
+
* @returns Promise that resolves when all operations are complete
|
|
178
|
+
*/
|
|
179
|
+
executeWithLocalContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
180
|
+
return this.executeWithLocalCacheContextAndReturnValue<void>(cacheContext);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Creates an insert query builder.
|
|
184
|
+
*
|
|
185
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
186
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
187
|
+
*
|
|
188
|
+
* @param table - The table to insert into
|
|
189
|
+
* @returns Insert query builder (no versioning, no cache management)
|
|
190
|
+
*/
|
|
191
|
+
insert<TTable extends MySqlTable>(
|
|
192
|
+
table: TTable,
|
|
193
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
194
|
+
return this.drizzle.insertWithCacheContext(table);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Creates an insert query builder that automatically evicts cache after execution.
|
|
198
|
+
*
|
|
199
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
200
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
201
|
+
*
|
|
202
|
+
* @param table - The table to insert into
|
|
203
|
+
* @returns Insert query builder with automatic cache eviction (no versioning)
|
|
204
|
+
*/
|
|
205
|
+
insertAndEvictCache<TTable extends MySqlTable>(
|
|
206
|
+
table: TTable,
|
|
207
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
208
|
+
return this.drizzle.insertAndEvictCache(table);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Creates an update query builder that automatically evicts cache after execution.
|
|
213
|
+
*
|
|
214
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
215
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
216
|
+
*
|
|
217
|
+
* @param table - The table to update
|
|
218
|
+
* @returns Update query builder with automatic cache eviction (no versioning)
|
|
219
|
+
*/
|
|
220
|
+
updateAndEvictCache<TTable extends MySqlTable>(
|
|
221
|
+
table: TTable,
|
|
222
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
223
|
+
return this.drizzle.updateAndEvictCache(table);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Creates an update query builder.
|
|
228
|
+
*
|
|
229
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
230
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
231
|
+
*
|
|
232
|
+
* @param table - The table to update
|
|
233
|
+
* @returns Update query builder (no versioning, no cache management)
|
|
234
|
+
*/
|
|
235
|
+
update<TTable extends MySqlTable>(
|
|
236
|
+
table: TTable,
|
|
237
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
238
|
+
return this.drizzle.updateWithCacheContext(table);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Creates a delete query builder.
|
|
243
|
+
*
|
|
244
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
245
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
246
|
+
*
|
|
247
|
+
* @param table - The table to delete from
|
|
248
|
+
* @returns Delete query builder (no versioning, no cache management)
|
|
249
|
+
*/
|
|
250
|
+
delete<TTable extends MySqlTable>(
|
|
251
|
+
table: TTable,
|
|
252
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
253
|
+
return this.drizzle.deleteWithCacheContext(table);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Creates a delete query builder that automatically evicts cache after execution.
|
|
257
|
+
*
|
|
258
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
259
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
260
|
+
*
|
|
261
|
+
* @param table - The table to delete from
|
|
262
|
+
* @returns Delete query builder with automatic cache eviction (no versioning)
|
|
263
|
+
*/
|
|
264
|
+
deleteAndEvictCache<TTable extends MySqlTable>(
|
|
265
|
+
table: TTable,
|
|
266
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
267
|
+
return this.drizzle.deleteAndEvictCache(table);
|
|
268
|
+
}
|
|
269
|
+
|
|
63
270
|
/**
|
|
64
271
|
* Create the modify operations instance.
|
|
65
272
|
* @returns modify operations.
|
|
66
273
|
*/
|
|
67
|
-
|
|
274
|
+
modifyWithVersioning(): VerioningModificationForgeSQL {
|
|
68
275
|
return this.crudOperations;
|
|
69
276
|
}
|
|
70
277
|
|
|
@@ -78,14 +285,6 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
78
285
|
return ForgeSQLORMImpl.instance;
|
|
79
286
|
}
|
|
80
287
|
|
|
81
|
-
/**
|
|
82
|
-
* Retrieves the CRUD operations instance.
|
|
83
|
-
* @returns CRUD operations.
|
|
84
|
-
*/
|
|
85
|
-
crud(): CRUDForgeSQL {
|
|
86
|
-
return this.modify();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
288
|
/**
|
|
90
289
|
* Retrieves the fetch operations instance.
|
|
91
290
|
* @returns Fetch operations.
|
|
@@ -93,10 +292,29 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
93
292
|
fetch(): SchemaSqlForgeSql {
|
|
94
293
|
return this.fetchOperations;
|
|
95
294
|
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Provides query analysis capabilities including EXPLAIN ANALYZE and slow query analysis.
|
|
298
|
+
* @returns {SchemaAnalyzeForgeSql} Interface for analyzing query performance
|
|
299
|
+
*/
|
|
96
300
|
analyze(): SchemaAnalyzeForgeSql {
|
|
97
301
|
return this.analyzeOperations;
|
|
98
302
|
}
|
|
99
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Provides schema-level SQL operations with optimistic locking/versioning and automatic cache eviction.
|
|
306
|
+
*
|
|
307
|
+
* This method returns operations that use `modifyWithVersioning()` internally, providing:
|
|
308
|
+
* - Optimistic locking support
|
|
309
|
+
* - Automatic version field management
|
|
310
|
+
* - Cache eviction after successful operations
|
|
311
|
+
*
|
|
312
|
+
* @returns {ForgeSQLCacheOperations} Interface for executing versioned SQL operations with cache management
|
|
313
|
+
*/
|
|
314
|
+
modifyWithVersioningAndEvictCache(): ForgeSQLCacheOperations {
|
|
315
|
+
return this.cacheOperations;
|
|
316
|
+
}
|
|
317
|
+
|
|
100
318
|
/**
|
|
101
319
|
* Returns a Drizzle query builder instance.
|
|
102
320
|
*
|
|
@@ -106,7 +324,18 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
106
324
|
*
|
|
107
325
|
* @returns A Drizzle query builder instance for query construction only.
|
|
108
326
|
*/
|
|
109
|
-
getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> {
|
|
327
|
+
getDrizzleQueryBuilder(): MySqlRemoteDatabase<Record<string, unknown>> & {
|
|
328
|
+
selectAliased: SelectAliasedType;
|
|
329
|
+
selectAliasedDistinct: SelectAliasedDistinctType;
|
|
330
|
+
selectAliasedCacheable: SelectAliasedCacheableType;
|
|
331
|
+
selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
|
|
332
|
+
insertWithCacheContext: InsertAndEvictCacheType;
|
|
333
|
+
insertAndEvictCache: InsertAndEvictCacheType;
|
|
334
|
+
updateAndEvictCache: UpdateAndEvictCacheType;
|
|
335
|
+
updateWithCacheContext: UpdateAndEvictCacheType;
|
|
336
|
+
deleteAndEvictCache: DeleteAndEvictCacheType;
|
|
337
|
+
deleteWithCacheContext: DeleteAndEvictCacheType;
|
|
338
|
+
} {
|
|
110
339
|
return this.drizzle;
|
|
111
340
|
}
|
|
112
341
|
|
|
@@ -159,6 +388,209 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
159
388
|
}
|
|
160
389
|
return this.drizzle.selectAliasedDistinct(fields);
|
|
161
390
|
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Creates a cacheable select query with unique field aliases to prevent field name collisions in joins.
|
|
394
|
+
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
395
|
+
*
|
|
396
|
+
* @template TSelection - The type of the selected fields
|
|
397
|
+
* @param {TSelection} fields - Object containing the fields to select, with table schemas as values
|
|
398
|
+
* @param {number} cacheTTL - cache ttl optional default is 60 sec.
|
|
399
|
+
* @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A select query builder with unique field aliases
|
|
400
|
+
* @throws {Error} If fields parameter is empty
|
|
401
|
+
* @example
|
|
402
|
+
* ```typescript
|
|
403
|
+
* await forgeSQL
|
|
404
|
+
* .selectCacheable({user: users, order: orders},60)
|
|
405
|
+
* .from(orders)
|
|
406
|
+
* .innerJoin(users, eq(orders.userId, users.id));
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
selectCacheable<TSelection extends SelectedFields>(
|
|
410
|
+
fields: TSelection,
|
|
411
|
+
cacheTTL?: number,
|
|
412
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
413
|
+
if (!fields) {
|
|
414
|
+
throw new Error("fields is empty");
|
|
415
|
+
}
|
|
416
|
+
return this.drizzle.selectAliasedCacheable(fields, cacheTTL);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Creates a cacheable distinct select query with unique field aliases to prevent field name collisions in joins.
|
|
421
|
+
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
422
|
+
*
|
|
423
|
+
* @template TSelection - The type of the selected fields
|
|
424
|
+
* @param {TSelection} fields - Object containing the fields to select, with table schemas as values
|
|
425
|
+
* @param {number} cacheTTL - cache ttl optional default is 60 sec.
|
|
426
|
+
* @returns {MySqlSelectBuilder<TSelection, MySql2PreparedQueryHKT>} A distinct select query builder with unique field aliases
|
|
427
|
+
* @throws {Error} If fields parameter is empty
|
|
428
|
+
* @example
|
|
429
|
+
* ```typescript
|
|
430
|
+
* await forgeSQL
|
|
431
|
+
* .selectDistinctCacheable({user: users, order: orders}, 60)
|
|
432
|
+
* .from(orders)
|
|
433
|
+
* .innerJoin(users, eq(orders.userId, users.id));
|
|
434
|
+
* ```
|
|
435
|
+
*/
|
|
436
|
+
selectDistinctCacheable<TSelection extends SelectedFields>(
|
|
437
|
+
fields: TSelection,
|
|
438
|
+
cacheTTL?: number,
|
|
439
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
440
|
+
if (!fields) {
|
|
441
|
+
throw new Error("fields is empty");
|
|
442
|
+
}
|
|
443
|
+
return this.drizzle.selectAliasedDistinctCacheable(fields, cacheTTL);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Creates a select query builder for all columns from a table with field aliasing support.
|
|
448
|
+
* This is a convenience method that automatically selects all columns from the specified table.
|
|
449
|
+
*
|
|
450
|
+
* @template T - The type of the table
|
|
451
|
+
* @param table - The table to select from
|
|
452
|
+
* @returns Select query builder with all table columns and field aliasing support
|
|
453
|
+
* @example
|
|
454
|
+
* ```typescript
|
|
455
|
+
* const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
selectFrom<T extends MySqlTable>(table: T) {
|
|
459
|
+
return this.drizzle.selectFrom(table);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Creates a select distinct query builder for all columns from a table with field aliasing support.
|
|
464
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table.
|
|
465
|
+
*
|
|
466
|
+
* @template T - The type of the table
|
|
467
|
+
* @param table - The table to select from
|
|
468
|
+
* @returns Select distinct query builder with all table columns and field aliasing support
|
|
469
|
+
* @example
|
|
470
|
+
* ```typescript
|
|
471
|
+
* const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
|
|
472
|
+
* ```
|
|
473
|
+
*/
|
|
474
|
+
selectDistinctFrom<T extends MySqlTable>(table: T) {
|
|
475
|
+
return this.drizzle.selectDistinctFrom(table);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
|
|
480
|
+
* This is a convenience method that automatically selects all columns from the specified table with caching enabled.
|
|
481
|
+
*
|
|
482
|
+
* @template T - The type of the table
|
|
483
|
+
* @param table - The table to select from
|
|
484
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
485
|
+
* @returns Select query builder with all table columns, field aliasing, and caching support
|
|
486
|
+
* @example
|
|
487
|
+
* ```typescript
|
|
488
|
+
* const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
|
|
489
|
+
* ```
|
|
490
|
+
*/
|
|
491
|
+
selectCacheableFrom<T extends MySqlTable>(table: T, cacheTTL?: number) {
|
|
492
|
+
return this.drizzle.selectFromCacheable(table, cacheTTL);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
|
|
497
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
|
|
498
|
+
*
|
|
499
|
+
* @template T - The type of the table
|
|
500
|
+
* @param table - The table to select from
|
|
501
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
502
|
+
* @returns Select distinct query builder with all table columns, field aliasing, and caching support
|
|
503
|
+
* @example
|
|
504
|
+
* ```typescript
|
|
505
|
+
* const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
508
|
+
selectDistinctCacheableFrom<T extends MySqlTable>(table: T, cacheTTL?: number) {
|
|
509
|
+
return this.drizzle.selectDistinctFromCacheable(table, cacheTTL);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Executes a raw SQL query with local cache support.
|
|
514
|
+
* This method provides local caching for raw SQL queries within the current invocation context.
|
|
515
|
+
* Results are cached locally and will be returned from cache on subsequent identical queries.
|
|
516
|
+
*
|
|
517
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
518
|
+
* @returns Promise with query results
|
|
519
|
+
* @example
|
|
520
|
+
* ```typescript
|
|
521
|
+
* // Using SQLWrapper
|
|
522
|
+
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
523
|
+
*
|
|
524
|
+
* // Using string
|
|
525
|
+
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
526
|
+
* ```
|
|
527
|
+
*/
|
|
528
|
+
execute(query: SQLWrapper | string) {
|
|
529
|
+
return this.drizzle.executeQuery(query);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Executes a raw SQL query with both local and global cache support.
|
|
534
|
+
* This method provides comprehensive caching for raw SQL queries:
|
|
535
|
+
* - Local cache: Within the current invocation context
|
|
536
|
+
* - Global cache: Cross-invocation caching using @forge/kvs
|
|
537
|
+
*
|
|
538
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
539
|
+
* @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
|
|
540
|
+
* @returns Promise with query results
|
|
541
|
+
* @example
|
|
542
|
+
* ```typescript
|
|
543
|
+
* // Using SQLWrapper with custom TTL
|
|
544
|
+
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
545
|
+
*
|
|
546
|
+
* // Using string with default TTL
|
|
547
|
+
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
executeCacheable(query: SQLWrapper | string, cacheTtl?: number) {
|
|
551
|
+
return this.drizzle.executeQueryCacheable(query, cacheTtl);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Creates a Common Table Expression (CTE) builder for complex queries.
|
|
556
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
557
|
+
*
|
|
558
|
+
* @returns WithBuilder for creating CTEs
|
|
559
|
+
* @example
|
|
560
|
+
* ```typescript
|
|
561
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
562
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
563
|
+
* .from(users)
|
|
564
|
+
* .groupBy(users.id)
|
|
565
|
+
* );
|
|
566
|
+
* ```
|
|
567
|
+
*/
|
|
568
|
+
get $with() {
|
|
569
|
+
return this.drizzle.$with;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Creates a query builder that uses Common Table Expressions (CTEs).
|
|
574
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
575
|
+
*
|
|
576
|
+
* @param queries - Array of CTE queries created with $with()
|
|
577
|
+
* @returns Query builder with CTE support
|
|
578
|
+
* @example
|
|
579
|
+
* ```typescript
|
|
580
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
581
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
582
|
+
* .from(users)
|
|
583
|
+
* .groupBy(users.id)
|
|
584
|
+
* );
|
|
585
|
+
*
|
|
586
|
+
* const result = await forgeSQL.with(withQuery)
|
|
587
|
+
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
588
|
+
* .from(withQuery);
|
|
589
|
+
* ```
|
|
590
|
+
*/
|
|
591
|
+
with(...queries: WithSubquery[]) {
|
|
592
|
+
return this.drizzle.with(...queries);
|
|
593
|
+
}
|
|
162
594
|
}
|
|
163
595
|
|
|
164
596
|
/**
|
|
@@ -172,6 +604,204 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
172
604
|
this.ormInstance = ForgeSQLORMImpl.getInstance(options);
|
|
173
605
|
}
|
|
174
606
|
|
|
607
|
+
selectCacheable<TSelection extends SelectedFields>(
|
|
608
|
+
fields: TSelection,
|
|
609
|
+
cacheTTL?: number,
|
|
610
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
611
|
+
return this.ormInstance.selectCacheable(fields, cacheTTL);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
selectDistinctCacheable<TSelection extends SelectedFields>(
|
|
615
|
+
fields: TSelection,
|
|
616
|
+
cacheTTL?: number,
|
|
617
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
618
|
+
return this.ormInstance.selectDistinctCacheable(fields, cacheTTL);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Creates a select query builder for all columns from a table with field aliasing support.
|
|
623
|
+
* This is a convenience method that automatically selects all columns from the specified table.
|
|
624
|
+
*
|
|
625
|
+
* @template T - The type of the table
|
|
626
|
+
* @param table - The table to select from
|
|
627
|
+
* @returns Select query builder with all table columns and field aliasing support
|
|
628
|
+
* @example
|
|
629
|
+
* ```typescript
|
|
630
|
+
* const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
|
|
631
|
+
* ```
|
|
632
|
+
*/
|
|
633
|
+
selectFrom<T extends MySqlTable>(table: T) {
|
|
634
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectFrom(table);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Creates a select distinct query builder for all columns from a table with field aliasing support.
|
|
639
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table.
|
|
640
|
+
*
|
|
641
|
+
* @template T - The type of the table
|
|
642
|
+
* @param table - The table to select from
|
|
643
|
+
* @returns Select distinct query builder with all table columns and field aliasing support
|
|
644
|
+
* @example
|
|
645
|
+
* ```typescript
|
|
646
|
+
* const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
selectDistinctFrom<T extends MySqlTable>(table: T) {
|
|
650
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFrom(table);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
|
|
655
|
+
* This is a convenience method that automatically selects all columns from the specified table with caching enabled.
|
|
656
|
+
*
|
|
657
|
+
* @template T - The type of the table
|
|
658
|
+
* @param table - The table to select from
|
|
659
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
660
|
+
* @returns Select query builder with all table columns, field aliasing, and caching support
|
|
661
|
+
* @example
|
|
662
|
+
* ```typescript
|
|
663
|
+
* const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
|
|
664
|
+
* ```
|
|
665
|
+
*/
|
|
666
|
+
selectCacheableFrom<T extends MySqlTable>(table: T, cacheTTL?: number) {
|
|
667
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectFromCacheable(table, cacheTTL);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/**
|
|
671
|
+
* Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
|
|
672
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
|
|
673
|
+
*
|
|
674
|
+
* @template T - The type of the table
|
|
675
|
+
* @param table - The table to select from
|
|
676
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
677
|
+
* @returns Select distinct query builder with all table columns, field aliasing, and caching support
|
|
678
|
+
* @example
|
|
679
|
+
* ```typescript
|
|
680
|
+
* const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
|
|
681
|
+
* ```
|
|
682
|
+
*/
|
|
683
|
+
selectDistinctCacheableFrom<T extends MySqlTable>(table: T, cacheTTL?: number) {
|
|
684
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFromCacheable(table, cacheTTL);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
executeWithCacheContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
688
|
+
return this.ormInstance.executeWithCacheContext(cacheContext);
|
|
689
|
+
}
|
|
690
|
+
executeWithCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
691
|
+
return this.ormInstance.executeWithCacheContextAndReturnValue(cacheContext);
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Executes operations within a local cache context.
|
|
695
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
696
|
+
*
|
|
697
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
698
|
+
* @returns Promise that resolves when all operations are complete
|
|
699
|
+
*/
|
|
700
|
+
executeWithLocalContext(cacheContext: () => Promise<void>): Promise<void> {
|
|
701
|
+
return this.ormInstance.executeWithLocalContext(cacheContext);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Executes operations within a local cache context and returns a value.
|
|
706
|
+
* This provides in-memory caching for select queries within a single request scope.
|
|
707
|
+
*
|
|
708
|
+
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
709
|
+
* @returns Promise that resolves to the return value of the cacheContext function
|
|
710
|
+
*/
|
|
711
|
+
executeWithLocalCacheContextAndReturnValue<T>(cacheContext: () => Promise<T>): Promise<T> {
|
|
712
|
+
return this.ormInstance.executeWithLocalCacheContextAndReturnValue(cacheContext);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Creates an insert query builder.
|
|
717
|
+
*
|
|
718
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
719
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
720
|
+
*
|
|
721
|
+
* @param table - The table to insert into
|
|
722
|
+
* @returns Insert query builder (no versioning, no cache management)
|
|
723
|
+
*/
|
|
724
|
+
insert<TTable extends MySqlTable>(
|
|
725
|
+
table: TTable,
|
|
726
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
727
|
+
return this.ormInstance.insert(table);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Creates an insert query builder that automatically evicts cache after execution.
|
|
732
|
+
*
|
|
733
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
734
|
+
* For versioned inserts, use `modifyWithVersioning().insert()` or `modifyWithVersioningAndEvictCache().insert()` instead.
|
|
735
|
+
*
|
|
736
|
+
* @param table - The table to insert into
|
|
737
|
+
* @returns Insert query builder with automatic cache eviction (no versioning)
|
|
738
|
+
*/
|
|
739
|
+
insertAndEvictCache<TTable extends MySqlTable>(
|
|
740
|
+
table: TTable,
|
|
741
|
+
): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
742
|
+
return this.ormInstance.insertAndEvictCache(table);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Creates an update query builder.
|
|
747
|
+
*
|
|
748
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
749
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
750
|
+
*
|
|
751
|
+
* @param table - The table to update
|
|
752
|
+
* @returns Update query builder (no versioning, no cache management)
|
|
753
|
+
*/
|
|
754
|
+
update<TTable extends MySqlTable>(
|
|
755
|
+
table: TTable,
|
|
756
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
757
|
+
return this.ormInstance.update(table);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/**
|
|
761
|
+
* Creates an update query builder that automatically evicts cache after execution.
|
|
762
|
+
*
|
|
763
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
764
|
+
* For versioned updates, use `modifyWithVersioning().updateById()` or `modifyWithVersioningAndEvictCache().updateById()` instead.
|
|
765
|
+
*
|
|
766
|
+
* @param table - The table to update
|
|
767
|
+
* @returns Update query builder with automatic cache eviction (no versioning)
|
|
768
|
+
*/
|
|
769
|
+
updateAndEvictCache<TTable extends MySqlTable>(
|
|
770
|
+
table: TTable,
|
|
771
|
+
): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
772
|
+
return this.ormInstance.updateAndEvictCache(table);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Creates a delete query builder.
|
|
777
|
+
*
|
|
778
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
779
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
780
|
+
*
|
|
781
|
+
* @param table - The table to delete from
|
|
782
|
+
* @returns Delete query builder (no versioning, no cache management)
|
|
783
|
+
*/
|
|
784
|
+
delete<TTable extends MySqlTable>(
|
|
785
|
+
table: TTable,
|
|
786
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
787
|
+
return this.ormInstance.delete(table);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Creates a delete query builder that automatically evicts cache after execution.
|
|
792
|
+
*
|
|
793
|
+
* ⚠️ **IMPORTANT**: This method does NOT support optimistic locking/versioning.
|
|
794
|
+
* For versioned deletes, use `modifyWithVersioning().deleteById()` or `modifyWithVersioningAndEvictCache().deleteById()` instead.
|
|
795
|
+
*
|
|
796
|
+
* @param table - The table to delete from
|
|
797
|
+
* @returns Delete query builder with automatic cache eviction (no versioning)
|
|
798
|
+
*/
|
|
799
|
+
deleteAndEvictCache<TTable extends MySqlTable>(
|
|
800
|
+
table: TTable,
|
|
801
|
+
): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
|
|
802
|
+
return this.ormInstance.deleteAndEvictCache(table);
|
|
803
|
+
}
|
|
804
|
+
|
|
175
805
|
/**
|
|
176
806
|
* Creates a select query with unique field aliases to prevent field name collisions in joins.
|
|
177
807
|
* This is particularly useful when working with Atlassian Forge SQL, which collapses fields with the same name in joined tables.
|
|
@@ -216,20 +846,12 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
216
846
|
return this.ormInstance.selectDistinct(fields);
|
|
217
847
|
}
|
|
218
848
|
|
|
219
|
-
/**
|
|
220
|
-
* Proxies the `crud` method from `ForgeSQLORMImpl`.
|
|
221
|
-
* @returns CRUD operations.
|
|
222
|
-
*/
|
|
223
|
-
crud(): CRUDForgeSQL {
|
|
224
|
-
return this.ormInstance.modify();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
849
|
/**
|
|
228
850
|
* Proxies the `modify` method from `ForgeSQLORMImpl`.
|
|
229
851
|
* @returns Modify operations.
|
|
230
852
|
*/
|
|
231
|
-
|
|
232
|
-
return this.ormInstance.
|
|
853
|
+
modifyWithVersioning(): VerioningModificationForgeSQL {
|
|
854
|
+
return this.ormInstance.modifyWithVersioning();
|
|
233
855
|
}
|
|
234
856
|
|
|
235
857
|
/**
|
|
@@ -248,18 +870,105 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
248
870
|
return this.ormInstance.analyze();
|
|
249
871
|
}
|
|
250
872
|
|
|
873
|
+
/**
|
|
874
|
+
* Provides schema-level SQL cacheable operations with type safety.
|
|
875
|
+
* @returns {ForgeSQLCacheOperations} Interface for executing schema-bound SQL queries
|
|
876
|
+
*/
|
|
877
|
+
modifyWithVersioningAndEvictCache(): ForgeSQLCacheOperations {
|
|
878
|
+
return this.ormInstance.modifyWithVersioningAndEvictCache();
|
|
879
|
+
}
|
|
880
|
+
|
|
251
881
|
/**
|
|
252
882
|
* Returns a Drizzle query builder instance.
|
|
253
883
|
*
|
|
254
|
-
* ⚠️ IMPORTANT: This method should be used ONLY for query building purposes.
|
|
255
|
-
* The returned instance should NOT be used for direct database connections or query execution.
|
|
256
|
-
* All database operations should be performed through Forge SQL's executeRawSQL or executeRawUpdateSQL methods.
|
|
257
|
-
*
|
|
258
884
|
* @returns A Drizzle query builder instance for query construction only.
|
|
259
885
|
*/
|
|
260
886
|
getDrizzleQueryBuilder() {
|
|
261
887
|
return this.ormInstance.getDrizzleQueryBuilder();
|
|
262
888
|
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Executes a raw SQL query with local cache support.
|
|
892
|
+
* This method provides local caching for raw SQL queries within the current invocation context.
|
|
893
|
+
* Results are cached locally and will be returned from cache on subsequent identical queries.
|
|
894
|
+
*
|
|
895
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
896
|
+
* @returns Promise with query results
|
|
897
|
+
* @example
|
|
898
|
+
* ```typescript
|
|
899
|
+
* // Using SQLWrapper
|
|
900
|
+
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
901
|
+
*
|
|
902
|
+
* // Using string
|
|
903
|
+
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
904
|
+
* ```
|
|
905
|
+
*/
|
|
906
|
+
execute(query: SQLWrapper | string) {
|
|
907
|
+
return this.ormInstance.getDrizzleQueryBuilder().executeQuery(query);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Executes a raw SQL query with both local and global cache support.
|
|
912
|
+
* This method provides comprehensive caching for raw SQL queries:
|
|
913
|
+
* - Local cache: Within the current invocation context
|
|
914
|
+
* - Global cache: Cross-invocation caching using @forge/kvs
|
|
915
|
+
*
|
|
916
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
917
|
+
* @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
|
|
918
|
+
* @returns Promise with query results
|
|
919
|
+
* @example
|
|
920
|
+
* ```typescript
|
|
921
|
+
* // Using SQLWrapper with custom TTL
|
|
922
|
+
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
923
|
+
*
|
|
924
|
+
* // Using string with default TTL
|
|
925
|
+
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
926
|
+
* ```
|
|
927
|
+
*/
|
|
928
|
+
executeCacheable(query: SQLWrapper | string, cacheTtl?: number) {
|
|
929
|
+
return this.ormInstance.getDrizzleQueryBuilder().executeQueryCacheable(query, cacheTtl);
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/**
|
|
933
|
+
* Creates a Common Table Expression (CTE) builder for complex queries.
|
|
934
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
935
|
+
*
|
|
936
|
+
* @returns WithBuilder for creating CTEs
|
|
937
|
+
* @example
|
|
938
|
+
* ```typescript
|
|
939
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
940
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
941
|
+
* .from(users)
|
|
942
|
+
* .groupBy(users.id)
|
|
943
|
+
* );
|
|
944
|
+
* ```
|
|
945
|
+
*/
|
|
946
|
+
get $with() {
|
|
947
|
+
return this.ormInstance.getDrizzleQueryBuilder().$with;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* Creates a query builder that uses Common Table Expressions (CTEs).
|
|
952
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
953
|
+
*
|
|
954
|
+
* @param queries - Array of CTE queries created with $with()
|
|
955
|
+
* @returns Query builder with CTE support
|
|
956
|
+
* @example
|
|
957
|
+
* ```typescript
|
|
958
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
959
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
960
|
+
* .from(users)
|
|
961
|
+
* .groupBy(users.id)
|
|
962
|
+
* );
|
|
963
|
+
*
|
|
964
|
+
* const result = await forgeSQL.with(withQuery)
|
|
965
|
+
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
966
|
+
* .from(withQuery);
|
|
967
|
+
* ```
|
|
968
|
+
*/
|
|
969
|
+
with(...queries: WithSubquery[]) {
|
|
970
|
+
return this.ormInstance.getDrizzleQueryBuilder().with(...queries);
|
|
971
|
+
}
|
|
263
972
|
}
|
|
264
973
|
|
|
265
974
|
export default ForgeSQLORM;
|