forge-sql-orm 2.1.0 → 2.1.2

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.
@@ -1,11 +1,13 @@
1
1
  import {
2
+ MySqlRawQueryResult,
2
3
  MySqlRemoteDatabase,
3
4
  MySqlRemotePreparedQueryHKT,
4
5
  MySqlRemoteQueryResultHKT,
5
6
  } from "drizzle-orm/mysql-proxy";
6
- import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
7
+
8
+ import { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
7
9
  import { applyFromDriverTransform, ForgeSqlOrmOptions, mapSelectFieldsWithAlias } from "../../..";
8
- import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
10
+ import { MySqlSelectBase, MySqlSelectBuilder } from "drizzle-orm/mysql-core";
9
11
  import type { MySqlTable } from "drizzle-orm/mysql-core/table";
10
12
  import {
11
13
  MySqlDeleteBase,
@@ -17,16 +19,54 @@ import {
17
19
  cacheApplicationContext,
18
20
  evictLocalCacheQuery,
19
21
  getQueryLocalCacheQuery,
20
- saveTableIfInsideCacheContext,
21
22
  saveQueryLocalCacheQuery,
23
+ saveTableIfInsideCacheContext,
22
24
  } from "../../../utils/cacheContextUtils";
25
+ import { BuildQueryConfig, isSQLWrapper, SQLWrapper } from "drizzle-orm/sql/sql";
26
+ import type { MySqlQueryResultKind } from "drizzle-orm/mysql-core/session";
27
+ import { getTableColumns, Query } from "drizzle-orm";
28
+ import { MySqlDialect } from "drizzle-orm/mysql-core/dialect";
29
+ import type {
30
+ GetSelectTableName,
31
+ GetSelectTableSelection,
32
+ } from "drizzle-orm/query-builders/select.types";
33
+
34
+ // ============================================================================
35
+ // TYPES AND INTERFACES
36
+ // ============================================================================
23
37
 
24
- // Types for better type safety
25
- type QueryBuilder = {
38
+ /**
39
+ * Base interface for query builders that can be executed
40
+ */
41
+ interface QueryBuilder {
26
42
  execute: (...args: any[]) => Promise<any>;
27
43
  then?: (onfulfilled?: any, onrejected?: any) => Promise<any>;
28
44
  toSQL?: () => any;
29
- };
45
+ }
46
+
47
+ /**
48
+ * Error codes that should not trigger cache clearing
49
+ */
50
+ const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"] as const;
51
+
52
+ /**
53
+ * Error codes that should trigger cache clearing
54
+ */
55
+ const CACHE_CLEARING_ERROR_CODES = ["DEADLOCK", "LOCK_WAIT_TIMEOUT", "CONNECTION_ERROR"] as const;
56
+
57
+ /**
58
+ * Error message patterns that should not trigger cache clearing
59
+ */
60
+ const NON_CACHE_CLEARING_PATTERNS = [/validation/i, /constraint/i] as const;
61
+
62
+ /**
63
+ * Error message patterns that should trigger cache clearing
64
+ */
65
+ const CACHE_CLEARING_PATTERNS = [/timeout/i, /connection/i] as const;
66
+
67
+ // ============================================================================
68
+ // CACHE MANAGEMENT UTILITIES
69
+ // ============================================================================
30
70
 
31
71
  /**
32
72
  * Determines whether cache should be cleared based on the error type.
@@ -37,22 +77,23 @@ type QueryBuilder = {
37
77
  */
38
78
  function shouldClearCacheOnError(error: any): boolean {
39
79
  // Don't clear cache for client-side errors (validation, etc.)
80
+ if (error?.code && NON_CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
81
+ return false;
82
+ }
83
+
40
84
  if (
41
- error?.code === "VALIDATION_ERROR" ||
42
- error?.code === "CONSTRAINT_ERROR" ||
43
- (error?.message && /validation/i.exec(error.message))
85
+ error?.message &&
86
+ NON_CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))
44
87
  ) {
45
88
  return false;
46
89
  }
47
90
 
48
91
  // Clear cache for database-level errors that might affect data consistency
49
- if (
50
- error?.code === "DEADLOCK" ||
51
- error?.code === "LOCK_WAIT_TIMEOUT" ||
52
- error?.code === "CONNECTION_ERROR" ||
53
- (error?.message && /timeout/i.exec(error.message)) ||
54
- (error?.message && /connection/i.exec(error.message))
55
- ) {
92
+ if (error?.code && CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
93
+ return true;
94
+ }
95
+
96
+ if (error?.message && CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
56
97
  return true;
57
98
  }
58
99
 
@@ -60,30 +101,138 @@ function shouldClearCacheOnError(error: any): boolean {
60
101
  return true;
61
102
  }
62
103
 
104
+ // ============================================================================
105
+ // EXPORTED TYPES
106
+ // ============================================================================
107
+
108
+ /**
109
+ * Type for select queries with field aliasing
110
+ */
63
111
  export type SelectAliasedType = <TSelection extends SelectedFields>(
64
112
  fields: TSelection,
65
113
  ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
66
114
 
115
+ /**
116
+ * Type for select distinct queries with field aliasing
117
+ */
67
118
  export type SelectAliasedDistinctType = <TSelection extends SelectedFields>(
68
119
  fields: TSelection,
69
120
  ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
70
121
 
122
+ /**
123
+ * Type for select queries with field aliasing and caching
124
+ */
71
125
  export type SelectAliasedCacheableType = <TSelection extends SelectedFields>(
72
126
  fields: TSelection,
73
127
  cacheTtl?: number,
74
128
  ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
75
129
 
130
+ /**
131
+ * Type for select distinct queries with field aliasing and caching
132
+ */
76
133
  export type SelectAliasedDistinctCacheableType = <TSelection extends SelectedFields>(
77
134
  fields: TSelection,
78
135
  cacheTtl?: number,
79
136
  ) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
80
137
 
138
+ /**
139
+ * Type for select queries from table with field aliasing
140
+ */
141
+ export type SelectAllFromAliasedType = <T extends MySqlTable>(
142
+ table: T,
143
+ ) => MySqlSelectBase<
144
+ GetSelectTableName<T>,
145
+ T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
146
+ T["_"]["columns"] extends undefined ? "single" : "partial",
147
+ MySqlRemotePreparedQueryHKT,
148
+ GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
149
+ false,
150
+ never,
151
+ any
152
+ >;
153
+
154
+ /**
155
+ * Type for select distinct queries from table with field aliasing
156
+ */
157
+ export type SelectAllDistinctFromAliasedType = <T extends MySqlTable>(
158
+ table: T,
159
+ ) => MySqlSelectBase<
160
+ GetSelectTableName<T>,
161
+ T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
162
+ T["_"]["columns"] extends undefined ? "single" : "partial",
163
+ MySqlRemotePreparedQueryHKT,
164
+ GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
165
+ false,
166
+ never,
167
+ any
168
+ >;
169
+
170
+ /**
171
+ * Type for select queries from table with field aliasing and caching
172
+ */
173
+ export type SelectAllFromCacheableAliasedType = <T extends MySqlTable>(
174
+ table: T,
175
+ cacheTtl?: number,
176
+ ) => MySqlSelectBase<
177
+ GetSelectTableName<T>,
178
+ T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
179
+ T["_"]["columns"] extends undefined ? "single" : "partial",
180
+ MySqlRemotePreparedQueryHKT,
181
+ GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
182
+ false,
183
+ never,
184
+ any
185
+ >;
186
+
187
+ /**
188
+ * Type for select distinct queries from table with field aliasing and caching
189
+ */
190
+ export type SelectAllDistinctFromCacheableAliasedType = <T extends MySqlTable>(
191
+ table: T,
192
+ cacheTtl?: number,
193
+ ) => MySqlSelectBase<
194
+ GetSelectTableName<T>,
195
+ T["_"]["columns"] extends undefined ? GetSelectTableSelection<T> : T["_"]["columns"],
196
+ T["_"]["columns"] extends undefined ? "single" : "partial",
197
+ MySqlRemotePreparedQueryHKT,
198
+ GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
199
+ false,
200
+ never,
201
+ any
202
+ >;
203
+
204
+ /**
205
+ * Type for executing raw SQL queries with local cache
206
+ */
207
+ export type ExecuteQuery = (
208
+ query: SQLWrapper | string,
209
+ ) => Promise<MySqlQueryResultKind<MySqlRemoteQueryResultHKT, unknown>>;
210
+
211
+ /**
212
+ * Type for executing raw SQL queries with local and global cache
213
+ */
214
+ export type ExecuteQueryCacheable = (
215
+ query: SQLWrapper | string,
216
+ cacheTtl?: number,
217
+ ) => Promise<MySqlQueryResultKind<MySqlRemoteQueryResultHKT, unknown>>;
218
+
219
+ /**
220
+ * Type for insert operations with cache eviction
221
+ */
81
222
  export type InsertAndEvictCacheType = <TTable extends MySqlTable>(
82
223
  table: TTable,
83
224
  ) => MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>;
225
+
226
+ /**
227
+ * Type for update operations with cache eviction
228
+ */
84
229
  export type UpdateAndEvictCacheType = <TTable extends MySqlTable>(
85
230
  table: TTable,
86
231
  ) => MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>;
232
+
233
+ /**
234
+ * Type for delete operations with cache eviction
235
+ */
87
236
  export type DeleteAndEvictCacheType = <TTable extends MySqlTable>(
88
237
  table: TTable,
89
238
  ) => MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>;
@@ -295,7 +444,7 @@ async function handleCachedQuery(
295
444
  onrejected?: any,
296
445
  ): Promise<any> {
297
446
  try {
298
- const localCached = await getQueryLocalCacheQuery(target);
447
+ const localCached = await getQueryLocalCacheQuery(target, options);
299
448
  if (localCached) {
300
449
  return onfulfilled?.(localCached);
301
450
  }
@@ -305,7 +454,7 @@ async function handleCachedQuery(
305
454
  }
306
455
  const rows = await target.execute();
307
456
  const transformed = applyFromDriverTransform(rows, selections, aliasMap);
308
- await saveQueryLocalCacheQuery(target, transformed);
457
+ await saveQueryLocalCacheQuery(target, transformed, options);
309
458
  await setCacheResult(target, options, transformed, cacheTtl).catch((cacheError) => {
310
459
  // Log cache error but don't fail the query
311
460
  console.warn("Cache set error:", cacheError);
@@ -321,6 +470,7 @@ async function handleCachedQuery(
321
470
  * Handles non-cached query execution.
322
471
  *
323
472
  * @param target - The query target
473
+ * @param options - ForgeSQL ORM options
324
474
  * @param selections - Field selections
325
475
  * @param aliasMap - Field alias mapping
326
476
  * @param onfulfilled - Success callback
@@ -329,19 +479,20 @@ async function handleCachedQuery(
329
479
  */
330
480
  async function handleNonCachedQuery(
331
481
  target: any,
482
+ options: any,
332
483
  selections: any,
333
484
  aliasMap: any,
334
485
  onfulfilled?: any,
335
486
  onrejected?: any,
336
487
  ): Promise<any> {
337
488
  try {
338
- const localCached = await getQueryLocalCacheQuery(target);
489
+ const localCached = await getQueryLocalCacheQuery(target, options);
339
490
  if (localCached) {
340
491
  return onfulfilled?.(localCached);
341
492
  }
342
493
  const rows = await target.execute();
343
494
  const transformed = applyFromDriverTransform(rows, selections, aliasMap);
344
- await saveQueryLocalCacheQuery(target, transformed);
495
+ await saveQueryLocalCacheQuery(target, transformed, options);
345
496
  return onfulfilled?.(transformed);
346
497
  } catch (error) {
347
498
  return onrejected?.(error);
@@ -394,7 +545,14 @@ function createAliasedSelectBuilder<TSelection extends SelectedFields>(
394
545
  onrejected,
395
546
  );
396
547
  } else {
397
- return handleNonCachedQuery(target, selections, aliasMap, onfulfilled, onrejected);
548
+ return handleNonCachedQuery(
549
+ target,
550
+ options,
551
+ selections,
552
+ aliasMap,
553
+ onfulfilled,
554
+ onrejected,
555
+ );
398
556
  }
399
557
  };
400
558
  }
@@ -421,7 +579,13 @@ function createAliasedSelectBuilder<TSelection extends SelectedFields>(
421
579
  return wrapBuilder(builder);
422
580
  }
423
581
 
424
- // Default options for better type safety
582
+ // ============================================================================
583
+ // CONFIGURATION AND CONSTANTS
584
+ // ============================================================================
585
+
586
+ /**
587
+ * Default options for ForgeSQL ORM
588
+ */
425
589
  const DEFAULT_OPTIONS: ForgeSqlOrmOptions = {
426
590
  logRawSqlQuery: false,
427
591
  disableOptimisticLocking: false,
@@ -430,7 +594,77 @@ const DEFAULT_OPTIONS: ForgeSqlOrmOptions = {
430
594
  cacheEntityQueryName: "sql",
431
595
  cacheEntityExpirationName: "expiration",
432
596
  cacheEntityDataName: "data",
433
- };
597
+ } as const;
598
+
599
+ // ============================================================================
600
+ // QUERY BUILDER FACTORIES
601
+ // ============================================================================
602
+
603
+ /**
604
+ * Creates a raw SQL query executor with caching support
605
+ */
606
+ function createRawQueryExecutor(
607
+ db: MySqlRemoteDatabase<any>,
608
+ options: ForgeSqlOrmOptions,
609
+ useGlobalCache: boolean = false,
610
+ ) {
611
+ return async function <T extends { [column: string]: any }>(
612
+ query: SQLWrapper | string,
613
+ cacheTtl?: number,
614
+ ): Promise<MySqlRawQueryResult> {
615
+ let sql: Query;
616
+
617
+ if (isSQLWrapper(query)) {
618
+ const sqlWrapper = query as SQLWrapper;
619
+ sql = sqlWrapper
620
+ .getSQL()
621
+ .toQuery(
622
+ (db as unknown as { dialect: MySqlDialect }).dialect as unknown as BuildQueryConfig,
623
+ );
624
+ } else {
625
+ sql = {
626
+ sql: query,
627
+ params: [],
628
+ };
629
+ }
630
+
631
+ // Check local cache first
632
+ const localCacheResult = await getQueryLocalCacheQuery(sql, options);
633
+ if (localCacheResult) {
634
+ return localCacheResult as MySqlRawQueryResult;
635
+ }
636
+
637
+ // Check global cache if enabled
638
+ if (useGlobalCache) {
639
+ const cacheResult = await getFromCache({ toSQL: () => sql }, options);
640
+ if (cacheResult) {
641
+ return cacheResult as MySqlRawQueryResult;
642
+ }
643
+ }
644
+
645
+ // Execute query
646
+ const results = await db.execute<T>(query);
647
+
648
+ // Save to local cache
649
+ await saveQueryLocalCacheQuery(sql, results, options);
650
+
651
+ // Save to global cache if enabled
652
+ if (useGlobalCache) {
653
+ await setCacheResult(
654
+ { toSQL: () => sql },
655
+ options,
656
+ results,
657
+ cacheTtl ?? options.cacheTTL ?? 120,
658
+ );
659
+ }
660
+
661
+ return results;
662
+ };
663
+ }
664
+
665
+ // ============================================================================
666
+ // MAIN PATCH FUNCTION
667
+ // ============================================================================
434
668
 
435
669
  /**
436
670
  * Patches a Drizzle database instance with additional methods for aliased selects and cache management.
@@ -465,6 +699,10 @@ export function patchDbWithSelectAliased(
465
699
  } {
466
700
  const newOptions = { ...DEFAULT_OPTIONS, ...options };
467
701
 
702
+ // ============================================================================
703
+ // SELECT METHODS WITH FIELD ALIASING
704
+ // ============================================================================
705
+
468
706
  // Select aliased without cache
469
707
  db.selectAliased = function <TSelection extends SelectedFields>(fields: TSelection) {
470
708
  return createAliasedSelectBuilder(
@@ -476,17 +714,6 @@ export function patchDbWithSelectAliased(
476
714
  );
477
715
  };
478
716
 
479
- // Select aliased distinct without cache
480
- db.selectAliasedDistinct = function <TSelection extends SelectedFields>(fields: TSelection) {
481
- return createAliasedSelectBuilder(
482
- db,
483
- fields,
484
- (selections) => db.selectDistinct(selections),
485
- false,
486
- newOptions,
487
- );
488
- };
489
-
490
717
  // Select aliased with cache
491
718
  db.selectAliasedCacheable = function <TSelection extends SelectedFields>(
492
719
  fields: TSelection,
@@ -502,6 +729,17 @@ export function patchDbWithSelectAliased(
502
729
  );
503
730
  };
504
731
 
732
+ // Select aliased distinct without cache
733
+ db.selectAliasedDistinct = function <TSelection extends SelectedFields>(fields: TSelection) {
734
+ return createAliasedSelectBuilder(
735
+ db,
736
+ fields,
737
+ (selections) => db.selectDistinct(selections),
738
+ false,
739
+ newOptions,
740
+ );
741
+ };
742
+
505
743
  // Select aliased distinct with cache
506
744
  db.selectAliasedDistinctCacheable = function <TSelection extends SelectedFields>(
507
745
  fields: TSelection,
@@ -517,10 +755,81 @@ export function patchDbWithSelectAliased(
517
755
  );
518
756
  };
519
757
 
758
+ // ============================================================================
759
+ // TABLE-BASED SELECT METHODS
760
+ // ============================================================================
761
+
762
+ /**
763
+ * Creates a select query builder for all columns from a table with field aliasing support.
764
+ * This is a convenience method that automatically selects all columns from the specified table.
765
+ *
766
+ * @param table - The table to select from
767
+ * @returns Select query builder with all table columns and field aliasing support
768
+ * @example
769
+ * ```typescript
770
+ * const users = await db.selectFrom(userTable).where(eq(userTable.id, 1));
771
+ * ```
772
+ */
773
+ db.selectFrom = function <T extends MySqlTable>(table: T) {
774
+ return db.selectAliased(getTableColumns(table)).from(table);
775
+ };
776
+
777
+ /**
778
+ * Creates a select query builder for all columns from a table with field aliasing and caching support.
779
+ * This is a convenience method that automatically selects all columns from the specified table with caching enabled.
780
+ *
781
+ * @param table - The table to select from
782
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
783
+ * @returns Select query builder with all table columns, field aliasing, and caching support
784
+ * @example
785
+ * ```typescript
786
+ * const users = await db.selectFromCacheable(userTable, 300).where(eq(userTable.id, 1));
787
+ * ```
788
+ */
789
+ db.selectFromCacheable = function <T extends MySqlTable>(table: T, cacheTtl?: number) {
790
+ return db.selectAliasedCacheable(getTableColumns(table), cacheTtl).from(table);
791
+ };
792
+
793
+ /**
794
+ * Creates a select distinct query builder for all columns from a table with field aliasing support.
795
+ * This is a convenience method that automatically selects all distinct columns from the specified table.
796
+ *
797
+ * @param table - The table to select from
798
+ * @returns Select distinct query builder with all table columns and field aliasing support
799
+ * @example
800
+ * ```typescript
801
+ * const uniqueUsers = await db.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
802
+ * ```
803
+ */
804
+ db.selectDistinctFrom = function <T extends MySqlTable>(table: T) {
805
+ return db.selectAliasedDistinct(getTableColumns(table)).from(table);
806
+ };
807
+
808
+ /**
809
+ * Creates a select distinct query builder for all columns from a table with field aliasing and caching support.
810
+ * This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
811
+ *
812
+ * @param table - The table to select from
813
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
814
+ * @returns Select distinct query builder with all table columns, field aliasing, and caching support
815
+ * @example
816
+ * ```typescript
817
+ * const uniqueUsers = await db.selectDistinctFromCacheable(userTable, 300).where(eq(userTable.status, 'active'));
818
+ * ```
819
+ */
820
+ db.selectDistinctFromCacheable = function <T extends MySqlTable>(table: T, cacheTtl?: number) {
821
+ return db.selectAliasedDistinctCacheable(getTableColumns(table), cacheTtl).from(table);
822
+ };
823
+
824
+ // ============================================================================
825
+ // CACHE-AWARE MODIFY OPERATIONS
826
+ // ============================================================================
827
+
520
828
  // Insert with cache context support (participates in cache clearing when used within cache context)
521
829
  db.insertWithCacheContext = function <TTable extends MySqlTable>(table: TTable) {
522
830
  return insertAndEvictCacheBuilder(db, table, newOptions, false);
523
831
  };
832
+
524
833
  // Insert with cache eviction
525
834
  db.insertAndEvictCache = function <TTable extends MySqlTable>(table: TTable) {
526
835
  return insertAndEvictCacheBuilder(db, table, newOptions, true);
@@ -530,6 +839,7 @@ export function patchDbWithSelectAliased(
530
839
  db.updateWithCacheContext = function <TTable extends MySqlTable>(table: TTable) {
531
840
  return updateAndEvictCacheBuilder(db, table, newOptions, false);
532
841
  };
842
+
533
843
  // Update with cache eviction
534
844
  db.updateAndEvictCache = function <TTable extends MySqlTable>(table: TTable) {
535
845
  return updateAndEvictCacheBuilder(db, table, newOptions, true);
@@ -539,10 +849,53 @@ export function patchDbWithSelectAliased(
539
849
  db.deleteWithCacheContext = function <TTable extends MySqlTable>(table: TTable) {
540
850
  return deleteAndEvictCacheBuilder(db, table, newOptions, false);
541
851
  };
852
+
542
853
  // Delete with cache eviction
543
854
  db.deleteAndEvictCache = function <TTable extends MySqlTable>(table: TTable) {
544
855
  return deleteAndEvictCacheBuilder(db, table, newOptions, true);
545
856
  };
546
857
 
858
+ // ============================================================================
859
+ // RAW SQL QUERY EXECUTORS
860
+ // ============================================================================
861
+
862
+ /**
863
+ * Executes a raw SQL query with local cache support.
864
+ * This method provides local caching for raw SQL queries within the current invocation context.
865
+ * Results are cached locally and will be returned from cache on subsequent identical queries.
866
+ *
867
+ * @param query - The SQL query to execute (SQLWrapper or string)
868
+ * @returns Promise with query results
869
+ * @example
870
+ * ```typescript
871
+ * // Using SQLWrapper
872
+ * const result = await db.executeQuery(sql`SELECT * FROM users WHERE id = ${userId}`);
873
+ *
874
+ * // Using string
875
+ * const result = await db.executeQuery("SELECT * FROM users WHERE status = 'active'");
876
+ * ```
877
+ */
878
+ db.executeQuery = createRawQueryExecutor(db, newOptions, false);
879
+
880
+ /**
881
+ * Executes a raw SQL query with both local and global cache support.
882
+ * This method provides comprehensive caching for raw SQL queries:
883
+ * - Local cache: Within the current invocation context
884
+ * - Global cache: Cross-invocation caching using @forge/kvs
885
+ *
886
+ * @param query - The SQL query to execute (SQLWrapper or string)
887
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
888
+ * @returns Promise with query results
889
+ * @example
890
+ * ```typescript
891
+ * // Using SQLWrapper with custom TTL
892
+ * const result = await db.executeQueryCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
893
+ *
894
+ * // Using string with default TTL
895
+ * const result = await db.executeQueryCacheable("SELECT * FROM users WHERE status = 'active'");
896
+ * ```
897
+ */
898
+ db.executeQueryCacheable = createRawQueryExecutor(db, newOptions, true);
899
+
547
900
  return db;
548
901
  }
@@ -1,10 +1,16 @@
1
1
  import {
2
2
  DeleteAndEvictCacheType,
3
+ ExecuteQuery,
4
+ ExecuteQueryCacheable,
3
5
  InsertAndEvictCacheType,
4
6
  SelectAliasedCacheableType,
5
7
  SelectAliasedDistinctCacheableType,
6
8
  SelectAliasedDistinctType,
7
9
  SelectAliasedType,
10
+ SelectAllDistinctFromAliasedType,
11
+ SelectAllDistinctFromCacheableAliasedType,
12
+ SelectAllFromAliasedType,
13
+ SelectAllFromCacheableAliasedType,
8
14
  UpdateAndEvictCacheType,
9
15
  } from "./additionalActions";
10
16
 
@@ -20,6 +26,21 @@ declare module "drizzle-orm/mysql-proxy" {
20
26
  */
21
27
  selectAliasedDistinct: SelectAliasedDistinctType;
22
28
 
29
+ /**
30
+ * Select with field aliasing support for all table columns
31
+ */
32
+ selectFrom: SelectAllFromAliasedType;
33
+
34
+ /**
35
+ * Select distinct with field aliasing support for all table columns
36
+ */
37
+ selectDistinctFrom: SelectAllDistinctFromAliasedType;
38
+
39
+ /**
40
+ * Execute raw SQL query with local cache support
41
+ */
42
+ executeQuery: ExecuteQuery;
43
+
23
44
  /**
24
45
  * Select with field aliasing and caching support
25
46
  */
@@ -30,6 +51,21 @@ declare module "drizzle-orm/mysql-proxy" {
30
51
  */
31
52
  selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
32
53
 
54
+ /**
55
+ * Select with field aliasing and caching support for all table columns
56
+ */
57
+ selectFromCacheable: SelectAllFromCacheableAliasedType;
58
+
59
+ /**
60
+ * Select distinct with field aliasing and caching support for all table columns
61
+ */
62
+ selectDistinctFromCacheable: SelectAllDistinctFromCacheableAliasedType;
63
+
64
+ /**
65
+ * Execute raw SQL query with both local and global cache support
66
+ */
67
+ executeQueryCacheable: ExecuteQueryCacheable;
68
+
33
69
  /**
34
70
  * Insert operation with cache context support.
35
71
  * Participates in cache clearing when used within executeWithCacheContext().