@atscript/db-sqlite 0.1.151 → 0.1.153
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +35 -16
- package/dist/index.d.cts +22 -2
- package/dist/index.d.mts +22 -2
- package/dist/index.mjs +36 -17
- package/package.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -334,6 +334,7 @@ const sqliteDialect = {
|
|
|
334
334
|
calendarBucket: sqliteCalendarBucket,
|
|
335
335
|
jsonExtract: sqliteJsonExtract,
|
|
336
336
|
castDouble: (expr) => `CAST(${expr} AS REAL)`,
|
|
337
|
+
nullsPlacementSyntax: true,
|
|
337
338
|
createViewPrefix: "CREATE VIEW IF NOT EXISTS"
|
|
338
339
|
};
|
|
339
340
|
/**
|
|
@@ -793,6 +794,10 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
793
794
|
supportsAggregateExpressions() {
|
|
794
795
|
return true;
|
|
795
796
|
}
|
|
797
|
+
/** `$nulls` / `@db.sort.nulls` NULL placement — `NULLS FIRST` / `NULLS LAST`. */
|
|
798
|
+
supportsNullsPlacement() {
|
|
799
|
+
return true;
|
|
800
|
+
}
|
|
796
801
|
/** Computed view columns and first-row joins. */
|
|
797
802
|
viewCapabilities() {
|
|
798
803
|
return _atscript_db.ALL_VIEW_CAPABILITIES;
|
|
@@ -818,7 +823,9 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
818
823
|
super();
|
|
819
824
|
this.driver = driver;
|
|
820
825
|
this._gate = getSqliteTxGate(driver);
|
|
821
|
-
|
|
826
|
+
const { viewJoinPruning, ...txOptions } = options ?? {};
|
|
827
|
+
this._txOptions = txOptions;
|
|
828
|
+
this.viewJoinPruning = viewJoinPruning !== false;
|
|
822
829
|
this.driver.exec("PRAGMA foreign_keys = ON");
|
|
823
830
|
this._hasBucketFn = registerBucketFunction(driver);
|
|
824
831
|
}
|
|
@@ -955,6 +962,17 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
955
962
|
return super.resolveTableName(false);
|
|
956
963
|
}
|
|
957
964
|
/**
|
|
965
|
+
* The FROM source of a read of this adapter's table or view: a managed
|
|
966
|
+
* view read that needs only some of its LEFT joins reads an inline,
|
|
967
|
+
* pruned definition (`viewReadSource`, since 0.1.153) — SQLite omits an
|
|
968
|
+
* unused LEFT JOIN only in a non-aggregate query, so a view's `COUNT(*)`
|
|
969
|
+
* and aggregates otherwise probe every join. Off with `viewJoinPruning: false`.
|
|
970
|
+
*/
|
|
971
|
+
_readSource(query, kind, partitionBy) {
|
|
972
|
+
const name = this.resolveTableName();
|
|
973
|
+
return this.viewJoinPruning ? (0, _atscript_db_sql_tools.viewReadSource)(sqliteDialect, this._table, name, query, kind, partitionBy) : name;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
958
976
|
* Relational predicates (`$some` / `$none`) render as correlated
|
|
959
977
|
* `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
|
|
960
978
|
*
|
|
@@ -1057,13 +1075,13 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1057
1075
|
...query.controls,
|
|
1058
1076
|
$limit: 1
|
|
1059
1077
|
};
|
|
1060
|
-
const { sql, params } = buildSelect(this.
|
|
1078
|
+
const { sql, params } = buildSelect(this._readSource(query, "rows"), where, controls);
|
|
1061
1079
|
this._log(sql, params);
|
|
1062
1080
|
return this._stmt(() => this.driver.get(sql, params));
|
|
1063
1081
|
}
|
|
1064
1082
|
async findMany(query) {
|
|
1065
1083
|
const where = buildWhere(query.filter);
|
|
1066
|
-
const { sql, params } = buildSelect(this.
|
|
1084
|
+
const { sql, params } = buildSelect(this._readSource(query, "rows"), where, query.controls);
|
|
1067
1085
|
this._log(sql, params);
|
|
1068
1086
|
return this._stmt(() => this.driver.all(sql, params));
|
|
1069
1087
|
}
|
|
@@ -1073,7 +1091,7 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1073
1091
|
*/
|
|
1074
1092
|
async findManyPerPartition(query, partitionBy) {
|
|
1075
1093
|
const where = buildWhere(query.filter);
|
|
1076
|
-
const { sql, params } = (0, _atscript_db_sql_tools.buildPartitionedSelect)(sqliteDialect, this.
|
|
1094
|
+
const { sql, params } = (0, _atscript_db_sql_tools.buildPartitionedSelect)(sqliteDialect, this._readSource(query, "rows", partitionBy), where, query.controls, partitionBy);
|
|
1077
1095
|
this._log(sql, params);
|
|
1078
1096
|
return (0, _atscript_db_sql_tools.stripPartitionRowNumber)(await this._stmt(() => this.driver.all(sql, params)));
|
|
1079
1097
|
}
|
|
@@ -1085,9 +1103,8 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1085
1103
|
async findManyWithCount(query) {
|
|
1086
1104
|
if (this.findMany !== SqliteAdapter.prototype.findMany || this.count !== SqliteAdapter.prototype.count) return super.findManyWithCount(query);
|
|
1087
1105
|
const where = buildWhere(query.filter);
|
|
1088
|
-
const
|
|
1089
|
-
const
|
|
1090
|
-
const countSql = `SELECT COUNT(*) as cnt FROM "${esc(tableName)}" WHERE ${where.sql}`;
|
|
1106
|
+
const { sql, params } = buildSelect(this._readSource(query, "rows"), where, query.controls);
|
|
1107
|
+
const countSql = this._countSql(query, where);
|
|
1091
1108
|
this._log(sql, params);
|
|
1092
1109
|
this._log(countSql, where.params);
|
|
1093
1110
|
return this._stmt(() => ({
|
|
@@ -1095,15 +1112,19 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1095
1112
|
count: this.driver.get(countSql, where.params)?.cnt ?? 0
|
|
1096
1113
|
}));
|
|
1097
1114
|
}
|
|
1115
|
+
/** `SELECT COUNT(*) as cnt FROM <source> WHERE <where>` of a count read. */
|
|
1116
|
+
_countSql(query, where) {
|
|
1117
|
+
return `SELECT COUNT(*) as cnt FROM ${(0, _atscript_db_sql_tools.fromSourceSql)(sqliteDialect, this._readSource(query, "count"))} WHERE ${where.sql}`;
|
|
1118
|
+
}
|
|
1098
1119
|
async count(query) {
|
|
1099
1120
|
const where = buildWhere(query.filter);
|
|
1100
|
-
const sql =
|
|
1121
|
+
const sql = this._countSql(query, where);
|
|
1101
1122
|
this._log(sql, where.params);
|
|
1102
1123
|
return (await this._stmt(() => this.driver.get(sql, where.params)))?.cnt ?? 0;
|
|
1103
1124
|
}
|
|
1104
1125
|
async aggregate(query) {
|
|
1105
|
-
const tableName = this.resolveTableName();
|
|
1106
1126
|
const search = (0, _atscript_db_agg.resolveAggregateSearch)(query.controls);
|
|
1127
|
+
const tableName = search ? this.resolveTableName() : this._readSource(query, "aggregate");
|
|
1107
1128
|
const where = search ? andWhere(this._buildSearchPredicate(search.text, search.indexName), buildWhere(query.filter)) : buildWhere(query.filter);
|
|
1108
1129
|
if (query.controls.$count) {
|
|
1109
1130
|
const { sql, params } = buildAggregateCount(tableName, where, query.controls);
|
|
@@ -1512,11 +1533,8 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1512
1533
|
if (controls.$select?.asArray?.length) cols = controls.$select.asArray.map((c) => `t."${esc(c)}"`).join(", ");
|
|
1513
1534
|
let sql = `SELECT ${cols} ${base.fromWhere}`;
|
|
1514
1535
|
const params = [...base.params];
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
for (const [col, dir] of Object.entries(controls.$sort)) orderParts.push(`t."${esc(col)}" ${dir === -1 ? "DESC" : "ASC"}`);
|
|
1518
|
-
if (orderParts.length > 0) sql += ` ORDER BY ${orderParts.join(", ")}`;
|
|
1519
|
-
}
|
|
1536
|
+
const orderBy = (0, _atscript_db_sql_tools.orderByList)(sqliteDialect, controls.$sort, controls.$nulls, "t.");
|
|
1537
|
+
if (orderBy) sql += ` ORDER BY ${orderBy}`;
|
|
1520
1538
|
if (controls.$limit !== void 0) {
|
|
1521
1539
|
sql += ` LIMIT ?`;
|
|
1522
1540
|
params.push(controls.$limit);
|
|
@@ -1998,11 +2016,12 @@ function normalizeSqliteDefault(value) {
|
|
|
1998
2016
|
//#endregion
|
|
1999
2017
|
//#region src/index.ts
|
|
2000
2018
|
function createAdapter(connection, options) {
|
|
2001
|
-
const { transactionWaitTimeoutMs, transactionWaitWarnMs, ...driverOptions } = options ?? {};
|
|
2019
|
+
const { transactionWaitTimeoutMs, transactionWaitWarnMs, viewJoinPruning, ...driverOptions } = options ?? {};
|
|
2002
2020
|
const driver = new BetterSqlite3Driver(connection, driverOptions);
|
|
2003
2021
|
const adapterOptions = {
|
|
2004
2022
|
transactionWaitTimeoutMs,
|
|
2005
|
-
transactionWaitWarnMs
|
|
2023
|
+
transactionWaitWarnMs,
|
|
2024
|
+
viewJoinPruning
|
|
2006
2025
|
};
|
|
2007
2026
|
return new _atscript_db.DbSpace(() => new SqliteAdapter(driver, adapterOptions), { onClose: () => driver.close() });
|
|
2008
2027
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -162,8 +162,16 @@ interface SqliteTxWaitOptions {
|
|
|
162
162
|
/** Logger for the wait warning (the adapter passes its own). */
|
|
163
163
|
logger?: TGenericLogger;
|
|
164
164
|
}
|
|
165
|
-
/** Options accepted by `SqliteAdapter` / `createAdapter
|
|
166
|
-
type SqliteAdapterOptions = Pick<SqliteTxWaitOptions, "transactionWaitTimeoutMs" | "transactionWaitWarnMs"
|
|
165
|
+
/** Options accepted by `SqliteAdapter` / `createAdapter`: the transaction gate's, plus `viewJoinPruning`. */
|
|
166
|
+
type SqliteAdapterOptions = Pick<SqliteTxWaitOptions, "transactionWaitTimeoutMs" | "transactionWaitWarnMs"> & {
|
|
167
|
+
/**
|
|
168
|
+
* Read a managed view through an inline definition without the LEFT joins
|
|
169
|
+
* the query does not need (default `true`) — see the views guide,
|
|
170
|
+
* "Performance". `false` always reads the stored view by name.
|
|
171
|
+
* @since 0.1.153
|
|
172
|
+
*/
|
|
173
|
+
viewJoinPruning?: boolean;
|
|
174
|
+
};
|
|
167
175
|
/**
|
|
168
176
|
* One waiter for the gate, created once per `_stmt` / `acquire` call and kept
|
|
169
177
|
* across wake-ups: the timeout and warn timers are armed ONCE with an absolute
|
|
@@ -289,6 +297,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
289
297
|
aggregateFns(): ReadonlySet<AggregateFn>;
|
|
290
298
|
/** Arithmetic in an aggregate `$select` (`{ $expr }`, `{ $fn, $expr }`). */
|
|
291
299
|
supportsAggregateExpressions(): boolean;
|
|
300
|
+
/** `$nulls` / `@db.sort.nulls` NULL placement — `NULLS FIRST` / `NULLS LAST`. */
|
|
301
|
+
supportsNullsPlacement(): boolean;
|
|
292
302
|
/** Computed view columns and first-row joins. */
|
|
293
303
|
viewCapabilities(): ReadonlySet<TViewCapability>;
|
|
294
304
|
/** INSERT text per column signature (rows of one table share a handful of shapes). */
|
|
@@ -343,6 +353,14 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
343
353
|
protected _rollbackTransaction(state: unknown): Promise<void>;
|
|
344
354
|
/** SQLite does not use schemas — override to always exclude schema. */
|
|
345
355
|
resolveTableName(): string;
|
|
356
|
+
/**
|
|
357
|
+
* The FROM source of a read of this adapter's table or view: a managed
|
|
358
|
+
* view read that needs only some of its LEFT joins reads an inline,
|
|
359
|
+
* pruned definition (`viewReadSource`, since 0.1.153) — SQLite omits an
|
|
360
|
+
* unused LEFT JOIN only in a non-aggregate query, so a view's `COUNT(*)`
|
|
361
|
+
* and aggregates otherwise probe every join. Off with `viewJoinPruning: false`.
|
|
362
|
+
*/
|
|
363
|
+
private _readSource;
|
|
346
364
|
/**
|
|
347
365
|
* Relational predicates (`$some` / `$none`) render as correlated
|
|
348
366
|
* `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
|
|
@@ -383,6 +401,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
383
401
|
data: Array<Record<string, unknown>>;
|
|
384
402
|
count: number;
|
|
385
403
|
}>;
|
|
404
|
+
/** `SELECT COUNT(*) as cnt FROM <source> WHERE <where>` of a count read. */
|
|
405
|
+
private _countSql;
|
|
386
406
|
count(query: DbQuery): Promise<number>;
|
|
387
407
|
aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
|
|
388
408
|
updateOne(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, expectedVersion?: number, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
|
package/dist/index.d.mts
CHANGED
|
@@ -162,8 +162,16 @@ interface SqliteTxWaitOptions {
|
|
|
162
162
|
/** Logger for the wait warning (the adapter passes its own). */
|
|
163
163
|
logger?: TGenericLogger;
|
|
164
164
|
}
|
|
165
|
-
/** Options accepted by `SqliteAdapter` / `createAdapter
|
|
166
|
-
type SqliteAdapterOptions = Pick<SqliteTxWaitOptions, "transactionWaitTimeoutMs" | "transactionWaitWarnMs"
|
|
165
|
+
/** Options accepted by `SqliteAdapter` / `createAdapter`: the transaction gate's, plus `viewJoinPruning`. */
|
|
166
|
+
type SqliteAdapterOptions = Pick<SqliteTxWaitOptions, "transactionWaitTimeoutMs" | "transactionWaitWarnMs"> & {
|
|
167
|
+
/**
|
|
168
|
+
* Read a managed view through an inline definition without the LEFT joins
|
|
169
|
+
* the query does not need (default `true`) — see the views guide,
|
|
170
|
+
* "Performance". `false` always reads the stored view by name.
|
|
171
|
+
* @since 0.1.153
|
|
172
|
+
*/
|
|
173
|
+
viewJoinPruning?: boolean;
|
|
174
|
+
};
|
|
167
175
|
/**
|
|
168
176
|
* One waiter for the gate, created once per `_stmt` / `acquire` call and kept
|
|
169
177
|
* across wake-ups: the timeout and warn timers are armed ONCE with an absolute
|
|
@@ -289,6 +297,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
289
297
|
aggregateFns(): ReadonlySet<AggregateFn>;
|
|
290
298
|
/** Arithmetic in an aggregate `$select` (`{ $expr }`, `{ $fn, $expr }`). */
|
|
291
299
|
supportsAggregateExpressions(): boolean;
|
|
300
|
+
/** `$nulls` / `@db.sort.nulls` NULL placement — `NULLS FIRST` / `NULLS LAST`. */
|
|
301
|
+
supportsNullsPlacement(): boolean;
|
|
292
302
|
/** Computed view columns and first-row joins. */
|
|
293
303
|
viewCapabilities(): ReadonlySet<TViewCapability>;
|
|
294
304
|
/** INSERT text per column signature (rows of one table share a handful of shapes). */
|
|
@@ -343,6 +353,14 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
343
353
|
protected _rollbackTransaction(state: unknown): Promise<void>;
|
|
344
354
|
/** SQLite does not use schemas — override to always exclude schema. */
|
|
345
355
|
resolveTableName(): string;
|
|
356
|
+
/**
|
|
357
|
+
* The FROM source of a read of this adapter's table or view: a managed
|
|
358
|
+
* view read that needs only some of its LEFT joins reads an inline,
|
|
359
|
+
* pruned definition (`viewReadSource`, since 0.1.153) — SQLite omits an
|
|
360
|
+
* unused LEFT JOIN only in a non-aggregate query, so a view's `COUNT(*)`
|
|
361
|
+
* and aggregates otherwise probe every join. Off with `viewJoinPruning: false`.
|
|
362
|
+
*/
|
|
363
|
+
private _readSource;
|
|
346
364
|
/**
|
|
347
365
|
* Relational predicates (`$some` / `$none`) render as correlated
|
|
348
366
|
* `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
|
|
@@ -383,6 +401,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
383
401
|
data: Array<Record<string, unknown>>;
|
|
384
402
|
count: number;
|
|
385
403
|
}>;
|
|
404
|
+
/** `SELECT COUNT(*) as cnt FROM <source> WHERE <where>` of a count read. */
|
|
405
|
+
private _countSql;
|
|
386
406
|
count(query: DbQuery): Promise<number>;
|
|
387
407
|
aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
|
|
388
408
|
updateOne(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, expectedVersion?: number, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, BaseDbAdapter, DbError, DbSpace, defaultFulltextIndex, describeFulltext, fkColumns, searchIndexNotFoundMessage, searchTermInteger, splitFulltextFields, vectorIndexNotFoundMessage } from "@atscript/db";
|
|
3
3
|
import { resolveAggregateSearch } from "@atscript/db/agg";
|
|
4
|
-
import { EMPTY_AND, InsertSqlCache, SEARCH_SOURCE_ALIAS, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildPartitionedSelect, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, geoWindowFromControls, jsonDollarPath, orFragment, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue } from "@atscript/db-sql-tools";
|
|
4
|
+
import { EMPTY_AND, InsertSqlCache, SEARCH_SOURCE_ALIAS, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildPartitionedSelect, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, fromSourceSql, geoWindowFromControls, jsonDollarPath, orFragment, orderByList, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue, viewReadSource } from "@atscript/db-sql-tools";
|
|
5
5
|
import { bucketer } from "@uniqu/core";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
//#region src/better-sqlite3-driver.ts
|
|
@@ -333,6 +333,7 @@ const sqliteDialect = {
|
|
|
333
333
|
calendarBucket: sqliteCalendarBucket,
|
|
334
334
|
jsonExtract: sqliteJsonExtract,
|
|
335
335
|
castDouble: (expr) => `CAST(${expr} AS REAL)`,
|
|
336
|
+
nullsPlacementSyntax: true,
|
|
336
337
|
createViewPrefix: "CREATE VIEW IF NOT EXISTS"
|
|
337
338
|
};
|
|
338
339
|
/**
|
|
@@ -792,6 +793,10 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
792
793
|
supportsAggregateExpressions() {
|
|
793
794
|
return true;
|
|
794
795
|
}
|
|
796
|
+
/** `$nulls` / `@db.sort.nulls` NULL placement — `NULLS FIRST` / `NULLS LAST`. */
|
|
797
|
+
supportsNullsPlacement() {
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
795
800
|
/** Computed view columns and first-row joins. */
|
|
796
801
|
viewCapabilities() {
|
|
797
802
|
return ALL_VIEW_CAPABILITIES;
|
|
@@ -817,7 +822,9 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
817
822
|
super();
|
|
818
823
|
this.driver = driver;
|
|
819
824
|
this._gate = getSqliteTxGate(driver);
|
|
820
|
-
|
|
825
|
+
const { viewJoinPruning, ...txOptions } = options ?? {};
|
|
826
|
+
this._txOptions = txOptions;
|
|
827
|
+
this.viewJoinPruning = viewJoinPruning !== false;
|
|
821
828
|
this.driver.exec("PRAGMA foreign_keys = ON");
|
|
822
829
|
this._hasBucketFn = registerBucketFunction(driver);
|
|
823
830
|
}
|
|
@@ -954,6 +961,17 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
954
961
|
return super.resolveTableName(false);
|
|
955
962
|
}
|
|
956
963
|
/**
|
|
964
|
+
* The FROM source of a read of this adapter's table or view: a managed
|
|
965
|
+
* view read that needs only some of its LEFT joins reads an inline,
|
|
966
|
+
* pruned definition (`viewReadSource`, since 0.1.153) — SQLite omits an
|
|
967
|
+
* unused LEFT JOIN only in a non-aggregate query, so a view's `COUNT(*)`
|
|
968
|
+
* and aggregates otherwise probe every join. Off with `viewJoinPruning: false`.
|
|
969
|
+
*/
|
|
970
|
+
_readSource(query, kind, partitionBy) {
|
|
971
|
+
const name = this.resolveTableName();
|
|
972
|
+
return this.viewJoinPruning ? viewReadSource(sqliteDialect, this._table, name, query, kind, partitionBy) : name;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
957
975
|
* Relational predicates (`$some` / `$none`) render as correlated
|
|
958
976
|
* `[NOT] EXISTS` subqueries — in reads and in mutation filters alike.
|
|
959
977
|
*
|
|
@@ -1056,13 +1074,13 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1056
1074
|
...query.controls,
|
|
1057
1075
|
$limit: 1
|
|
1058
1076
|
};
|
|
1059
|
-
const { sql, params } = buildSelect$1(this.
|
|
1077
|
+
const { sql, params } = buildSelect$1(this._readSource(query, "rows"), where, controls);
|
|
1060
1078
|
this._log(sql, params);
|
|
1061
1079
|
return this._stmt(() => this.driver.get(sql, params));
|
|
1062
1080
|
}
|
|
1063
1081
|
async findMany(query) {
|
|
1064
1082
|
const where = buildWhere(query.filter);
|
|
1065
|
-
const { sql, params } = buildSelect$1(this.
|
|
1083
|
+
const { sql, params } = buildSelect$1(this._readSource(query, "rows"), where, query.controls);
|
|
1066
1084
|
this._log(sql, params);
|
|
1067
1085
|
return this._stmt(() => this.driver.all(sql, params));
|
|
1068
1086
|
}
|
|
@@ -1072,7 +1090,7 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1072
1090
|
*/
|
|
1073
1091
|
async findManyPerPartition(query, partitionBy) {
|
|
1074
1092
|
const where = buildWhere(query.filter);
|
|
1075
|
-
const { sql, params } = buildPartitionedSelect(sqliteDialect, this.
|
|
1093
|
+
const { sql, params } = buildPartitionedSelect(sqliteDialect, this._readSource(query, "rows", partitionBy), where, query.controls, partitionBy);
|
|
1076
1094
|
this._log(sql, params);
|
|
1077
1095
|
return stripPartitionRowNumber(await this._stmt(() => this.driver.all(sql, params)));
|
|
1078
1096
|
}
|
|
@@ -1084,9 +1102,8 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1084
1102
|
async findManyWithCount(query) {
|
|
1085
1103
|
if (this.findMany !== SqliteAdapter.prototype.findMany || this.count !== SqliteAdapter.prototype.count) return super.findManyWithCount(query);
|
|
1086
1104
|
const where = buildWhere(query.filter);
|
|
1087
|
-
const
|
|
1088
|
-
const
|
|
1089
|
-
const countSql = `SELECT COUNT(*) as cnt FROM "${esc(tableName)}" WHERE ${where.sql}`;
|
|
1105
|
+
const { sql, params } = buildSelect$1(this._readSource(query, "rows"), where, query.controls);
|
|
1106
|
+
const countSql = this._countSql(query, where);
|
|
1090
1107
|
this._log(sql, params);
|
|
1091
1108
|
this._log(countSql, where.params);
|
|
1092
1109
|
return this._stmt(() => ({
|
|
@@ -1094,15 +1111,19 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1094
1111
|
count: this.driver.get(countSql, where.params)?.cnt ?? 0
|
|
1095
1112
|
}));
|
|
1096
1113
|
}
|
|
1114
|
+
/** `SELECT COUNT(*) as cnt FROM <source> WHERE <where>` of a count read. */
|
|
1115
|
+
_countSql(query, where) {
|
|
1116
|
+
return `SELECT COUNT(*) as cnt FROM ${fromSourceSql(sqliteDialect, this._readSource(query, "count"))} WHERE ${where.sql}`;
|
|
1117
|
+
}
|
|
1097
1118
|
async count(query) {
|
|
1098
1119
|
const where = buildWhere(query.filter);
|
|
1099
|
-
const sql =
|
|
1120
|
+
const sql = this._countSql(query, where);
|
|
1100
1121
|
this._log(sql, where.params);
|
|
1101
1122
|
return (await this._stmt(() => this.driver.get(sql, where.params)))?.cnt ?? 0;
|
|
1102
1123
|
}
|
|
1103
1124
|
async aggregate(query) {
|
|
1104
|
-
const tableName = this.resolveTableName();
|
|
1105
1125
|
const search = resolveAggregateSearch(query.controls);
|
|
1126
|
+
const tableName = search ? this.resolveTableName() : this._readSource(query, "aggregate");
|
|
1106
1127
|
const where = search ? andWhere(this._buildSearchPredicate(search.text, search.indexName), buildWhere(query.filter)) : buildWhere(query.filter);
|
|
1107
1128
|
if (query.controls.$count) {
|
|
1108
1129
|
const { sql, params } = buildAggregateCount$1(tableName, where, query.controls);
|
|
@@ -1511,11 +1532,8 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1511
1532
|
if (controls.$select?.asArray?.length) cols = controls.$select.asArray.map((c) => `t."${esc(c)}"`).join(", ");
|
|
1512
1533
|
let sql = `SELECT ${cols} ${base.fromWhere}`;
|
|
1513
1534
|
const params = [...base.params];
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
for (const [col, dir] of Object.entries(controls.$sort)) orderParts.push(`t."${esc(col)}" ${dir === -1 ? "DESC" : "ASC"}`);
|
|
1517
|
-
if (orderParts.length > 0) sql += ` ORDER BY ${orderParts.join(", ")}`;
|
|
1518
|
-
}
|
|
1535
|
+
const orderBy = orderByList(sqliteDialect, controls.$sort, controls.$nulls, "t.");
|
|
1536
|
+
if (orderBy) sql += ` ORDER BY ${orderBy}`;
|
|
1519
1537
|
if (controls.$limit !== void 0) {
|
|
1520
1538
|
sql += ` LIMIT ?`;
|
|
1521
1539
|
params.push(controls.$limit);
|
|
@@ -1997,11 +2015,12 @@ function normalizeSqliteDefault(value) {
|
|
|
1997
2015
|
//#endregion
|
|
1998
2016
|
//#region src/index.ts
|
|
1999
2017
|
function createAdapter(connection, options) {
|
|
2000
|
-
const { transactionWaitTimeoutMs, transactionWaitWarnMs, ...driverOptions } = options ?? {};
|
|
2018
|
+
const { transactionWaitTimeoutMs, transactionWaitWarnMs, viewJoinPruning, ...driverOptions } = options ?? {};
|
|
2001
2019
|
const driver = new BetterSqlite3Driver(connection, driverOptions);
|
|
2002
2020
|
const adapterOptions = {
|
|
2003
2021
|
transactionWaitTimeoutMs,
|
|
2004
|
-
transactionWaitWarnMs
|
|
2022
|
+
transactionWaitWarnMs,
|
|
2023
|
+
viewJoinPruning
|
|
2005
2024
|
};
|
|
2006
2025
|
return new DbSpace(() => new SqliteAdapter(driver, adapterOptions), { onClose: () => driver.close() });
|
|
2007
2026
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/db-sqlite",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.153",
|
|
4
4
|
"description": "SQLite adapter for @atscript/db with swappable driver support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atscript",
|
|
@@ -36,21 +36,21 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@atscript/core": "^0.1.
|
|
40
|
-
"@atscript/typescript": "^0.1.
|
|
39
|
+
"@atscript/core": "^0.1.103",
|
|
40
|
+
"@atscript/typescript": "^0.1.103",
|
|
41
41
|
"@types/better-sqlite3": "^7.6.13",
|
|
42
|
-
"@uniqu/core": "^0.1.
|
|
42
|
+
"@uniqu/core": "^0.1.15",
|
|
43
43
|
"better-sqlite3": "^12.6.2",
|
|
44
44
|
"sqlite-vec": "^0.1.9",
|
|
45
|
-
"unplugin-atscript": "^0.1.
|
|
45
|
+
"unplugin-atscript": "^0.1.103"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@atscript/core": "^0.1.
|
|
49
|
-
"@atscript/typescript": "^0.1.
|
|
50
|
-
"@uniqu/core": "^0.1.
|
|
48
|
+
"@atscript/core": "^0.1.103",
|
|
49
|
+
"@atscript/typescript": "^0.1.103",
|
|
50
|
+
"@uniqu/core": "^0.1.15",
|
|
51
51
|
"better-sqlite3": ">=11.0.0",
|
|
52
|
-
"@atscript/db": "^0.1.
|
|
53
|
-
"@atscript/db-sql-tools": "^0.1.
|
|
52
|
+
"@atscript/db": "^0.1.153",
|
|
53
|
+
"@atscript/db-sql-tools": "^0.1.153"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"better-sqlite3": {
|