uql-orm 0.61.0 → 0.63.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.
Files changed (106) hide show
  1. package/dist/browser/uql-browser.min.js.map +1 -1
  2. package/dist/bunSql/bunSql.util.d.ts +15 -15
  3. package/dist/bunSql/bunSql.util.js +22 -35
  4. package/dist/bunSql/bunSqlQuerier.d.ts +2 -2
  5. package/dist/bunSql/bunSqlQuerier.js +3 -3
  6. package/dist/bunSql/bunSqlQuerierPool.d.ts +1 -13
  7. package/dist/bunSql/bunSqlQuerierPool.js +3 -34
  8. package/dist/d1/d1Querier.d.ts +12 -4
  9. package/dist/d1/d1Querier.js +6 -11
  10. package/dist/d1/d1QuerierPool.d.ts +7 -3
  11. package/dist/d1/d1QuerierPool.js +5 -3
  12. package/dist/dialect/abstractSqlDialect.d.ts +12 -7
  13. package/dist/dialect/abstractSqlDialect.js +51 -50
  14. package/dist/dialect/mysqlLikeSqlDialect.js +1 -1
  15. package/dist/dialect/pgLikeSqlDialect.d.ts +1 -0
  16. package/dist/dialect/pgLikeSqlDialect.js +8 -7
  17. package/dist/dialect/queryContext.d.ts +5 -6
  18. package/dist/dialect/queryContext.js +8 -8
  19. package/dist/entity/decorator/entity.d.ts +6 -10
  20. package/dist/entity/decorator/entity.js +4 -8
  21. package/dist/entity/decorator/members.d.ts +3 -2
  22. package/dist/entity/decorator/members.js +1 -0
  23. package/dist/entity/metadata/definition.d.ts +2 -2
  24. package/dist/entity/metadata/definition.js +23 -26
  25. package/dist/libsql/libsqlDialect.d.ts +1 -1
  26. package/dist/libsql/libsqlDialect.js +1 -1
  27. package/dist/libsql/libsqlQuerierPool.d.ts +18 -9
  28. package/dist/libsql/libsqlQuerierPool.js +32 -20
  29. package/dist/migrate/builder/migrationBuilder.js +3 -5
  30. package/dist/migrate/builder/tableBuilder.js +2 -4
  31. package/dist/migrate/builder/types.d.ts +11 -3
  32. package/dist/migrate/codegen/index.d.ts +1 -1
  33. package/dist/migrate/codegen/index.js +1 -1
  34. package/dist/migrate/codegen/indexDecoratorSource.d.ts +1 -1
  35. package/dist/migrate/codegen/indexDecoratorSource.js +4 -6
  36. package/dist/migrate/codegen/migrationFile.d.ts +0 -4
  37. package/dist/migrate/codegen/migrationFile.js +0 -2
  38. package/dist/migrate/generator/definitionToNode.d.ts +8 -5
  39. package/dist/migrate/generator/definitionToNode.js +13 -4
  40. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -0
  41. package/dist/migrate/generator/mongoSchemaGenerator.js +6 -1
  42. package/dist/migrate/schemaGenerator.d.ts +5 -3
  43. package/dist/migrate/schemaGenerator.js +9 -2
  44. package/dist/mongo/mongoDialect.js +1 -1
  45. package/dist/mssql/mssqlDialect.js +3 -5
  46. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +5 -5
  47. package/dist/querier/abstractSharedHandleQuerierPool.js +5 -5
  48. package/dist/schema/schemaASTBuilder.d.ts +6 -1
  49. package/dist/schema/schemaASTBuilder.js +17 -16
  50. package/dist/sqlite/abstractSqliteQuerier.d.ts +11 -28
  51. package/dist/sqlite/abstractSqliteQuerier.js +14 -33
  52. package/dist/sqlite/bunSqliteAdapter.bun.d.ts +5 -4
  53. package/dist/sqlite/bunSqliteAdapter.bun.js +1 -1
  54. package/dist/sqlite/hranaQuerier.d.ts +6 -4
  55. package/dist/sqlite/hranaQuerier.js +4 -13
  56. package/dist/sqlite/index.d.ts +0 -1
  57. package/dist/sqlite/index.js +0 -1
  58. package/dist/sqlite/localSqliteQuerierPool.d.ts +14 -5
  59. package/dist/sqlite/nodeSqliteAdapter.d.ts +3 -4
  60. package/dist/sqlite/nodeSqliteAdapter.js +3 -6
  61. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -3
  62. package/dist/sqlite/nodeSqliteQuerierPool.js +3 -1
  63. package/dist/sqlite/sqliteDialect.d.ts +1 -1
  64. package/dist/sqlite/sqliteDialect.js +1 -1
  65. package/dist/sqlite/sqlitePragmas.d.ts +2 -11
  66. package/dist/sqlite/sqlitePragmas.js +1 -1
  67. package/dist/sqlite/sqliteQuerier.d.ts +29 -10
  68. package/dist/sqlite/sqliteQuerier.js +26 -4
  69. package/dist/sqlite/sqliteQuerierPool.d.ts +7 -3
  70. package/dist/sqlite/sqliteQuerierPool.js +12 -8
  71. package/dist/turso/index.d.ts +1 -0
  72. package/dist/turso/index.js +1 -0
  73. package/dist/turso/local.d.ts +1 -1
  74. package/dist/turso/local.js +1 -1
  75. package/dist/turso/tursoDialect.d.ts +4 -9
  76. package/dist/turso/tursoDialect.js +4 -12
  77. package/dist/turso/tursoLocalDialect.d.ts +10 -0
  78. package/dist/turso/tursoLocalDialect.js +13 -0
  79. package/dist/turso/tursoLocalQuerierPool.d.ts +8 -13
  80. package/dist/turso/tursoLocalQuerierPool.js +6 -5
  81. package/dist/turso/tursoQuerierPool.d.ts +15 -30
  82. package/dist/turso/tursoQuerierPool.js +13 -23
  83. package/dist/turso/tursoSessionQuerier.d.ts +57 -0
  84. package/dist/turso/tursoSessionQuerier.js +50 -0
  85. package/dist/type/dialect.d.ts +15 -6
  86. package/dist/type/entity.d.ts +108 -73
  87. package/dist/type/migration.d.ts +9 -2
  88. package/dist/type/query.d.ts +3 -3
  89. package/dist/type/queryLock.d.ts +7 -7
  90. package/dist/type/queryLock.js +8 -6
  91. package/dist/type/queryRaw.d.ts +30 -30
  92. package/dist/type/queryRaw.js +14 -9
  93. package/dist/util/ddlExpression.util.d.ts +8 -13
  94. package/dist/util/ddlExpression.util.js +14 -23
  95. package/dist/util/dialect.util.d.ts +1 -1
  96. package/dist/util/dialect.util.js +3 -4
  97. package/dist/util/field.util.d.ts +1 -1
  98. package/dist/util/raw.d.ts +24 -17
  99. package/dist/util/raw.js +46 -17
  100. package/dist/util/wideNumber.d.ts +2 -2
  101. package/dist/util/wideNumber.js +2 -2
  102. package/package.json +2 -2
  103. package/dist/sqlite/hranaQuerierPool.d.ts +0 -20
  104. package/dist/sqlite/hranaQuerierPool.js +0 -26
  105. package/dist/turso/tursoLocalQuerier.d.ts +0 -24
  106. package/dist/turso/tursoLocalQuerier.js +0 -20
@@ -222,7 +222,7 @@ export function hasVectorNear(where) {
222
222
  return Object.entries(where).some(([key, value]) => key === '$near' || hasVectorNear(value));
223
223
  }
224
224
  function indexCoversColumn(index, key) {
225
- return index.columns.some((entry) => !(entry instanceof QueryRaw) && entry.column === key);
225
+ return index.columns.some((entry) => entry.column === key);
226
226
  }
227
227
  /** `satisfies` ties this to {@link JsonUpdateOp}, so renaming an operator breaks it at compile time. */
228
228
  const JSON_UPDATE_OPS = [
@@ -293,8 +293,7 @@ export function applyFilters(meta, whereMap, opts) {
293
293
  if (!active) {
294
294
  continue;
295
295
  }
296
- const raw = filter.condition;
297
- const condition = typeof raw === 'function' ? raw(context) : raw;
296
+ const condition = typeof filter.where === 'function' ? filter.where(context) : filter.where;
298
297
  if (condition === undefined) {
299
298
  const onMissing = filter.onMissing ?? (filter.security ? 'throw' : 'skip');
300
299
  if (onMissing === 'throw') {
@@ -444,7 +443,7 @@ export function textSearchFields(meta, search) {
444
443
  }
445
444
  const fulltext = (meta.indexes ?? []).filter((index) => index.type === 'fulltext');
446
445
  if (fulltext.length === 1) {
447
- return fulltext[0].columns.map((entry) => entry.column);
446
+ return fulltext[0].columns.flatMap((entry) => (typeof entry.column === 'string' ? [entry.column] : []));
448
447
  }
449
448
  const name = entityName(meta);
450
449
  const declared = fulltext.length
@@ -32,7 +32,7 @@ export declare function isIntegerColumn(field: Pick<FieldOptions, 'type' | 'colu
32
32
  * Every read site asks this - the DDL skip, the projection, the `$where` and `ORDER BY` operands -
33
33
  * because an inlined field has no column to name, while a stored one is read like any other.
34
34
  */
35
- export declare function isInlinedExpression(field: FieldOptions): boolean;
35
+ export declare function isInlinedExpression<F extends FieldOptions>(field: F): field is F & Required<Pick<F, 'computed'>>;
36
36
  /**
37
37
  * Whether the database supplies this field's value, so no insert or update may write it: a stored
38
38
  * computed column *is* a real column, read like one, but writing to it is an error on every engine.
@@ -1,36 +1,43 @@
1
- import { QueryRaw, type QueryRawFn } from '../type/index.js';
1
+ import { type EntitySql, type EntityWhere, type EntityWhereMeta, QueryRaw, type QueryRawFn, type RefMap, type Type } from '../type/index.js';
2
2
  /**
3
3
  * Create a raw SQL expression.
4
4
  *
5
5
  * As a tagged template the literal text is emitted as written and every interpolation is resolved by
6
6
  * what it is, so a value cannot become SQL whatever it holds:
7
7
  *
8
- * | Interpolated | Becomes |
9
- * | :----------------- | :---------------------- |
10
- * | any value | a bound parameter |
11
- * | a {@link QueryRaw} | that fragment, in place |
8
+ * | Interpolated | Becomes |
9
+ * | :------------------ | :------------------------------------- |
10
+ * | any value | a bound parameter; in DDL, its literal |
11
+ * | a {@link ColumnRef} | its column, escaped and qualified |
12
+ * | a {@link QueryRaw} | that fragment, in place |
12
13
  *
13
14
  * ```ts
14
- * raw`GREATEST(0, "creditsAllowance" - ${amount})`
15
- * raw`CONCAT(${col('firstName')}, ' ', ${col('lastName')})`
15
+ * const user = refs(User);
16
+ * raw`GREATEST(0, ${user.creditsAllowance} - ${amount})`
17
+ * raw`CONCAT(${user.firstName}, ' ', ${user.lastName})`
16
18
  * raw`LOG10(${points})`.as('score')
17
19
  * ```
18
20
  *
19
21
  * The callback form remains for SQL a template cannot express, such as a sub-query generated through
20
- * `dialect.find(...)`. See {@link col} for a context-aware column reference.
22
+ * `dialect.find(...)`.
21
23
  *
22
24
  * **⚠️ Security:** the tag is safe because it binds; a callback is not, since it emits whatever it
23
25
  * writes, so never build one from user input. Inside a callback, bind with `ctx.addValue()`.
24
26
  */
25
27
  export declare function raw(strings: TemplateStringsArray, ...values: readonly unknown[]): QueryRaw;
26
- export declare function raw(value: QueryRawFn, alias?: string): QueryRaw;
28
+ export declare function raw(value: QueryRawFn): QueryRaw;
27
29
  /**
28
- * A column of the entity being queried, alias-qualified and escaped for the dialect. This is what a
29
- * template cannot know on its own: the alias is decided while the statement is built, not where the
30
- * expression is written.
31
- *
32
- * Takes the column name as it exists in the database, not the entity's field name: no entity metadata
33
- * is in scope here, so a naming strategy is not applied for you. `escapedPrefix` already carries its
34
- * trailing dot, which is the detail this exists to stop you getting wrong.
30
+ * The fields of `entity` as {@link ColumnRef}s, each rendering inside `raw` as its column: named the way
31
+ * the dialect names it, so the naming strategy and `@Field({ name })` apply, and qualified by the alias
32
+ * in scope. Metadata is read when a ref renders, so the map serves before the fields are registered.
33
+ */
34
+ export declare function refs<E>(entity: Type<E>): RefMap<E>;
35
+ /**
36
+ * The refs a definition's callbacks read: an index's, a check's, a computed field's. A member decorator
37
+ * sees no class, so these name no entity and resolve against the one rendering them.
35
38
  */
36
- export declare function col(column: string): QueryRaw;
39
+ export declare function memberRefs<E>(): RefMap<E>;
40
+ /** SQL a definition writes, a callback's refs read off {@link memberRefs}. */
41
+ export declare function entitySql<E>(sql: EntitySql<E>): QueryRaw;
42
+ /** A definition's predicate, its callback resolved the way {@link entitySql} resolves one. */
43
+ export declare function entityWhere<E>(where: EntityWhere<E>): EntityWhereMeta<E>;
package/dist/util/raw.js CHANGED
@@ -1,13 +1,9 @@
1
- import { QueryRaw } from '../type/index.js';
1
+ import { getMeta } from '../entity/metadata/definition.js';
2
+ import { ColumnRef, QueryRaw, } from '../type/index.js';
3
+ import { isInlinedExpression } from './field.util.js';
2
4
  export function raw(value, ...rest) {
3
- const [alias] = rest;
4
5
  if (!isTemplateStrings(value)) {
5
- return new QueryRaw(value, typeof alias === 'string' ? alias : undefined);
6
- }
7
- if (!rest.length) {
8
- // Nothing to bind, so this is the string form: keep it one, for the DDL paths that need to read
9
- // the expression back as text (an index expression cannot carry a parameter).
10
- return new QueryRaw(value[0]);
6
+ return new QueryRaw(value);
11
7
  }
12
8
  return new QueryRaw((opts) => {
13
9
  const { ctx } = opts;
@@ -24,16 +20,49 @@ export function raw(value, ...rest) {
24
20
  });
25
21
  }
26
22
  /**
27
- * A column of the entity being queried, alias-qualified and escaped for the dialect. This is what a
28
- * template cannot know on its own: the alias is decided while the statement is built, not where the
29
- * expression is written.
30
- *
31
- * Takes the column name as it exists in the database, not the entity's field name: no entity metadata
32
- * is in scope here, so a naming strategy is not applied for you. `escapedPrefix` already carries its
33
- * trailing dot, which is the detail this exists to stop you getting wrong.
23
+ * The fields of `entity` as {@link ColumnRef}s, each rendering inside `raw` as its column: named the way
24
+ * the dialect names it, so the naming strategy and `@Field({ name })` apply, and qualified by the alias
25
+ * in scope. Metadata is read when a ref renders, so the map serves before the fields are registered.
34
26
  */
35
- export function col(column) {
36
- return new QueryRaw(({ escapedPrefix, dialect }) => escapedPrefix + dialect.escapeId(column, true));
27
+ export function refs(entity) {
28
+ return new Proxy({}, { get: (_, key) => columnRef(entity, String(key)) });
29
+ }
30
+ const MEMBER_REFS = new Proxy({}, { get: (_, key) => columnRef(undefined, String(key)) });
31
+ /**
32
+ * The refs a definition's callbacks read: an index's, a check's, a computed field's. A member decorator
33
+ * sees no class, so these name no entity and resolve against the one rendering them.
34
+ */
35
+ export function memberRefs() {
36
+ return MEMBER_REFS;
37
+ }
38
+ /** SQL a definition writes, a callback's refs read off {@link memberRefs}. */
39
+ export function entitySql(sql) {
40
+ return sql instanceof QueryRaw ? sql : sql(memberRefs());
41
+ }
42
+ /** A definition's predicate, its callback resolved the way {@link entitySql} resolves one. */
43
+ export function entityWhere(where) {
44
+ return typeof where === 'function' ? where(memberRefs()) : where;
45
+ }
46
+ /** One field as SQL, against its own entity or, read off a definition, the entity rendering it. */
47
+ function columnRef(entity, key) {
48
+ return new ColumnRef(key, (opts) => {
49
+ const owner = entity ?? opts.entity;
50
+ if (!owner) {
51
+ throw new TypeError(`'${key}' was read off a definition's refs, so it renders only inside its entity's SQL`);
52
+ }
53
+ renderColumn(getMeta(owner), key, { ...opts, entity: owner });
54
+ });
55
+ }
56
+ /** A field's column, or the expression an inlined computed one stands for, as a `$where` on it reads it. */
57
+ function renderColumn(meta, key, opts) {
58
+ const field = meta.fields[key];
59
+ if (field && isInlinedExpression(field)) {
60
+ opts.ctx.append('(');
61
+ field.computed.render(opts);
62
+ opts.ctx.append(')');
63
+ return;
64
+ }
65
+ opts.ctx.append(opts.escapedPrefix + opts.dialect.escapeId(opts.dialect.columnOf(meta, key), true));
37
66
  }
38
67
  /** A tag call passes the frozen strings array, which carries its own `raw` counterpart. */
39
68
  function isTemplateStrings(value) {
@@ -8,7 +8,7 @@ import type { RawRow } from '../type/index.js';
8
8
  export declare function decodeWideNumber(value: string | bigint): number | string;
9
9
  /**
10
10
  * {@link decodeWideNumber} over every `bigint` cell of a row, for the drivers that hand a BIGINT back
11
- * as one (`bun:sql` with `bigint: true`, `mariadb`). In place: the row is the driver's fresh object, and
12
- * a copy per row cost more than the decode it carried.
11
+ * as one (`bun:sql`, `mariadb`, and every SQLite driver but D1). In place: the row is the driver's fresh
12
+ * object, and a copy per row cost more than the decode it carried.
13
13
  */
14
14
  export declare function decodeBigInts(row: RawRow): RawRow;
@@ -10,8 +10,8 @@ export function decodeWideNumber(value) {
10
10
  }
11
11
  /**
12
12
  * {@link decodeWideNumber} over every `bigint` cell of a row, for the drivers that hand a BIGINT back
13
- * as one (`bun:sql` with `bigint: true`, `mariadb`). In place: the row is the driver's fresh object, and
14
- * a copy per row cost more than the decode it carried.
13
+ * as one (`bun:sql`, `mariadb`, and every SQLite driver but D1). In place: the row is the driver's fresh
14
+ * object, and a copy per row cost more than the decode it carried.
15
15
  */
16
16
  export function decodeBigInts(row) {
17
17
  for (const key in row) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "homepage": "https://uql-orm.dev",
4
4
  "description": "The JSON-native TypeScript ORM for Bun, Browsers, Edge, Deno, Node, Workers. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, SQL Server, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
5
5
  "license": "MIT",
6
- "version": "0.61.0",
6
+ "version": "0.63.0",
7
7
  "type": "module",
8
8
  "engines": {
9
9
  "node": ">=24"
@@ -71,7 +71,7 @@
71
71
  "@nestjs/common": ">=10.0.0",
72
72
  "@nestjs/core": ">=10.0.0",
73
73
  "@tursodatabase/database": ">=0.7.0",
74
- "@tursodatabase/serverless": ">=1.0.0",
74
+ "@tursodatabase/serverless": ">=1.3.0",
75
75
  "better-sqlite3": ">=9.0.0",
76
76
  "express": ">=5.0.0",
77
77
  "mariadb": ">=3.0.0",
@@ -1,20 +0,0 @@
1
- import { AbstractSqlQuerierPool } from '../querier/index.js';
2
- import { type HranaClient, HranaQuerier } from './hranaQuerier.js';
3
- import type { SqliteDialect } from './sqliteDialect.js';
4
- /**
5
- * Pool for SQLite databases reached over the Hrana wire protocol (`@libsql/client`,
6
- * `@tursodatabase/serverless/compat`).
7
- *
8
- * @remarks The client is shared by every querier, since Hrana keeps no per-connection state: a
9
- * transaction takes its own session handle. It is resolved on first use rather than in the
10
- * constructor, so building a pool never throws when the optional driver peer is absent, which is what
11
- * lets a Workers bundle construct one at module scope.
12
- */
13
- export declare abstract class AbstractHranaQuerierPool<D extends SqliteDialect> extends AbstractSqlQuerierPool<HranaQuerier, D> {
14
- private client?;
15
- /** False when the caller injected their own client, in which case they own its lifecycle. */
16
- protected readonly ownsClient: boolean;
17
- protected abstract openClient(): Promise<HranaClient>;
18
- getQuerier(): Promise<HranaQuerier>;
19
- end(): Promise<void>;
20
- }
@@ -1,26 +0,0 @@
1
- import { AbstractSqlQuerierPool } from '../querier/index.js';
2
- import { HranaQuerier } from './hranaQuerier.js';
3
- /**
4
- * Pool for SQLite databases reached over the Hrana wire protocol (`@libsql/client`,
5
- * `@tursodatabase/serverless/compat`).
6
- *
7
- * @remarks The client is shared by every querier, since Hrana keeps no per-connection state: a
8
- * transaction takes its own session handle. It is resolved on first use rather than in the
9
- * constructor, so building a pool never throws when the optional driver peer is absent, which is what
10
- * lets a Workers bundle construct one at module scope.
11
- */
12
- export class AbstractHranaQuerierPool extends AbstractSqlQuerierPool {
13
- client;
14
- /** False when the caller injected their own client, in which case they own its lifecycle. */
15
- ownsClient = true;
16
- async getQuerier() {
17
- this.client ??= await this.openClient();
18
- return new HranaQuerier(this.client, this.dialect, this.extra);
19
- }
20
- async end() {
21
- if (this.ownsClient) {
22
- this.client?.close();
23
- }
24
- this.client = undefined;
25
- }
26
- }
@@ -1,24 +0,0 @@
1
- import { PreparedSqliteQuerier, type SqlitePreparedStatement } from '../sqlite/abstractSqliteQuerier.js';
2
- import type { SqliteDialect } from '../sqlite/sqliteDialect.js';
3
- import type { ExtraOptions } from '../type/index.js';
4
- /**
5
- * Structural subset of the `@tursodatabase/database` API actually used here, declared locally so
6
- * this package does not couple its published types to a pre-1.0 dependency.
7
- */
8
- export type TursoDatabase = {
9
- prepare(sql: string): Promise<SqlitePreparedStatement>;
10
- close(): Promise<void>;
11
- };
12
- /**
13
- * Querier for the embedded Turso engine.
14
- *
15
- * @remarks The engine exposes better-sqlite3 semantics (`reader`, `{changes, lastInsertRowid}`,
16
- * array-bound values) over an async API, so all it supplies is the awaited `prepare`.
17
- * `BEGIN`/`COMMIT` work as plain statements, leaving transactions to the base class.
18
- */
19
- export declare class TursoLocalQuerier extends PreparedSqliteQuerier {
20
- readonly db: TursoDatabase;
21
- readonly extra?: ExtraOptions | undefined;
22
- constructor(db: TursoDatabase, dialect: SqliteDialect, extra?: ExtraOptions | undefined);
23
- protected prepare(query: string): Promise<SqlitePreparedStatement>;
24
- }
@@ -1,20 +0,0 @@
1
- import { PreparedSqliteQuerier } from '../sqlite/abstractSqliteQuerier.js';
2
- /**
3
- * Querier for the embedded Turso engine.
4
- *
5
- * @remarks The engine exposes better-sqlite3 semantics (`reader`, `{changes, lastInsertRowid}`,
6
- * array-bound values) over an async API, so all it supplies is the awaited `prepare`.
7
- * `BEGIN`/`COMMIT` work as plain statements, leaving transactions to the base class.
8
- */
9
- export class TursoLocalQuerier extends PreparedSqliteQuerier {
10
- db;
11
- extra;
12
- constructor(db, dialect, extra) {
13
- super(dialect, extra);
14
- this.db = db;
15
- this.extra = extra;
16
- }
17
- prepare(query) {
18
- return this.db.prepare(query);
19
- }
20
- }