@egi/smart-db 2.6.5 → 3.0.4

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 (91) hide show
  1. package/README.md +355 -0
  2. package/assets/mysql/smart-db-core-update.001.sql +10 -0
  3. package/assets/oracle/smart-db-core-update.001.sql +13 -0
  4. package/assets/sqlite3/smart-db-core-update.001.sql +10 -0
  5. package/drivers/smart-db-better-sqlite3.d.ts +103 -16
  6. package/drivers/smart-db-better-sqlite3.js +1 -1
  7. package/drivers/smart-db-mysql.d.ts +53 -10
  8. package/drivers/smart-db-mysql.js +1 -1
  9. package/drivers/smart-db-oracle.d.ts +93 -20
  10. package/drivers/smart-db-oracle.js +1 -1
  11. package/helpers/extract-db-api.js +1 -1
  12. package/models/abstract-model.d.ts +39 -4
  13. package/models/abstract-model.js +1 -1
  14. package/models/mysql-tables-model.d.ts +109 -0
  15. package/models/mysql-tables-model.js +1 -0
  16. package/models/oracle-all-cons-columns-model.d.ts +55 -0
  17. package/models/oracle-all-cons-columns-model.js +1 -0
  18. package/models/oracle-all-constraints-model.d.ts +177 -0
  19. package/models/oracle-all-constraints-model.js +1 -0
  20. package/models/oracle-all-dependencies-model.d.ts +77 -0
  21. package/models/oracle-all-dependencies-model.js +1 -0
  22. package/models/oracle-all-objects-model.d.ts +201 -0
  23. package/models/oracle-all-objects-model.js +1 -0
  24. package/models/oracle-all-tab-columns-model.d.ts +305 -0
  25. package/models/oracle-all-tab-columns-model.js +1 -0
  26. package/models/oracle-all-triggers-model.d.ts +187 -0
  27. package/models/oracle-all-triggers-model.js +1 -0
  28. package/{models.generated/smart-db-user-tab-columns-view-model.d.ts → models/smart-db-all-tab-columns-view-model.d.ts} +14 -6
  29. package/models/smart-db-all-tab-columns-view-model.js +1 -0
  30. package/models/smart-db-core-table-model.d.ts +24 -22
  31. package/models/smart-db-core-table-model.js +1 -1
  32. package/models/smart-db-dictionary.d.ts +2 -10
  33. package/models/smart-db-dictionary.js +1 -1
  34. package/models/smart-db-log-model.d.ts +25 -8
  35. package/models/smart-db-log-model.js +1 -1
  36. package/models/smart-db-test-table-model.d.ts +79 -0
  37. package/models/smart-db-test-table-model.js +1 -0
  38. package/models/smart-db-user-tab-columns-view-model.d.ts +2 -0
  39. package/models/smart-db-user-tab-columns-view-model.js +1 -1
  40. package/models/smart-db-version-model.d.ts +25 -8
  41. package/models/smart-db-version-model.js +1 -1
  42. package/models/smart-db-version-view-model.d.ts +27 -8
  43. package/models/smart-db-version-view-model.js +1 -1
  44. package/models/sqlite-master-model.d.ts +14 -12
  45. package/models/sqlite-master-model.js +1 -1
  46. package/models/sqlite-sequence-model.d.ts +9 -7
  47. package/models/sqlite-sequence-model.js +1 -1
  48. package/package.json +40 -56
  49. package/smart-db-api.d.ts +2 -1
  50. package/smart-db-api.js +1 -1
  51. package/smart-db-browser.d.ts +5 -0
  52. package/smart-db-browser.js +1 -0
  53. package/smart-db-globals.d.ts +37 -5
  54. package/smart-db-globals.js +1 -1
  55. package/smart-db-interfaces.d.ts +330 -40
  56. package/smart-db-interfaces.js +1 -1
  57. package/smart-db-sql-build-data.d.ts +10 -1
  58. package/smart-db-sql-build-data.js +1 -1
  59. package/smart-db-upgrade-manager.d.ts +6 -4
  60. package/smart-db-upgrade-manager.js +1 -1
  61. package/smart-db.d.ts +451 -55
  62. package/smart-db.js +1 -1
  63. package/smart-error.d.ts +9 -28
  64. package/smart-error.js +1 -1
  65. package/smart-tools.d.ts +178 -0
  66. package/smart-tools.js +1 -0
  67. package/drivers/smart-db-mysql2.d.ts +0 -20
  68. package/drivers/smart-db-mysql2.js +0 -1
  69. package/drivers/smart-db-sqlite3.d.ts +0 -23
  70. package/drivers/smart-db-sqlite3.js +0 -1
  71. package/models/oracle-cat-model.d.ts +0 -23
  72. package/models/oracle-cat-model.js +0 -1
  73. package/models/oracle-user-tab-columns-model.d.ts +0 -39
  74. package/models/oracle-user-tab-columns-model.js +0 -1
  75. package/models/oracle-user-tab-columns-view-model.d.ts +0 -43
  76. package/models/oracle-user-tab-columns-view-model.js +0 -1
  77. package/models.generated/abstract-model.d.ts +0 -23
  78. package/models.generated/abstract-model.js +0 -1
  79. package/models.generated/smart-db-core-table-model.d.ts +0 -41
  80. package/models.generated/smart-db-core-table-model.js +0 -1
  81. package/models.generated/smart-db-dictionary.d.ts +0 -14
  82. package/models.generated/smart-db-dictionary.js +0 -1
  83. package/models.generated/smart-db-log-model.d.ts +0 -82
  84. package/models.generated/smart-db-log-model.js +0 -1
  85. package/models.generated/smart-db-user-tab-columns-view-model.js +0 -1
  86. package/models.generated/smart-db-version-model.d.ts +0 -82
  87. package/models.generated/smart-db-version-model.js +0 -1
  88. package/models.generated/smart-db-version-view-model.d.ts +0 -90
  89. package/models.generated/smart-db-version-view-model.js +0 -1
  90. package/smart-db-log.d.ts +0 -40
  91. package/smart-db-log.js +0 -1
package/README.md ADDED
@@ -0,0 +1,355 @@
1
+ # smart-db
2
+
3
+ A unified, type-safe ORM abstraction layer for SQLite (better-sqlite3), MySQL, and Oracle. Provides a single API across all three databases with both synchronous and asynchronous access, a composable SQL builder, schema versioning, and optional database-backed logging.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @egi/smart-db
9
+ ```
10
+
11
+ Install only the driver(s) you need:
12
+
13
+ ```bash
14
+ npm install better-sqlite3 # SQLite
15
+ npm install mysql2 # MySQL
16
+ npm install oracledb # Oracle
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### SQLite
22
+
23
+ ```typescript
24
+ import { SmartDbBetterSqlite3 } from "@egi/smart-db/drivers/smart-db-better-sqlite3";
25
+
26
+ const db = new SmartDbBetterSqlite3(
27
+ { filename: "./my-database.db" },
28
+ { module: "my-app", onReady: (db, err) => { /* ... */ } }
29
+ );
30
+ ```
31
+
32
+ ### MySQL
33
+
34
+ ```typescript
35
+ import { SmartDbMysql } from "@egi/smart-db/drivers/smart-db-mysql";
36
+
37
+ const db = new SmartDbMysql(
38
+ { host: "localhost", user: "root", password: "secret", database: "mydb" },
39
+ { module: "my-app", onReady: (db, err) => { /* ... */ } }
40
+ );
41
+ ```
42
+
43
+ ### Oracle
44
+
45
+ ```typescript
46
+ import { SmartDbOracle } from "@egi/smart-db/drivers/smart-db-oracle";
47
+
48
+ const db = new SmartDbOracle(
49
+ { user: "hr", password: "secret", connectString: "localhost/XEPDB1" },
50
+ { module: "my-app", onReady: (db, err) => { /* ... */ } }
51
+ );
52
+ ```
53
+
54
+ ## Waiting for the Database
55
+
56
+ All drivers signal readiness asynchronously via an RxJS `BehaviorSubject`. Use `databaseReady()` before running queries, or pass `onReady` in options.
57
+
58
+ ```typescript
59
+ await db.databaseReady();
60
+
61
+ // or subscribe to state changes:
62
+ db.onReady.subscribe(state => console.log(state));
63
+ ```
64
+
65
+ ## Models
66
+
67
+ Models map TypeScript classes to database tables. Generate them from a live schema using the CLI (see [Schema Extraction](#schema-extraction)), or write them manually:
68
+
69
+ ```typescript
70
+ import { AbstractModel, ModelAttributeMap } from "@egi/smart-db";
71
+
72
+ interface UserData {
73
+ user_id: number;
74
+ user_name: string;
75
+ }
76
+
77
+ class UserModel extends AbstractModel<UserModel, UserData> {
78
+ static readonly attributeMap: ModelAttributeMap = {
79
+ id: { attribute: "_id", alias: "user_id", type: "number", typeScriptStyle: true },
80
+ name: { attribute: "_name", alias: "user_name", type: "string", typeScriptStyle: true },
81
+ };
82
+
83
+ static getTableName() { return "users"; }
84
+ static getPrimaryKey() { return "user_id"; }
85
+ static getClassName() { return "UserModel"; }
86
+ static getPkSequenceName(){ return ""; }
87
+ static from(other: any) { const m = new UserModel(); m.assign(other); return m; }
88
+
89
+ private _id: number;
90
+ private _name: string;
91
+
92
+ get id() { return this._id; }
93
+ set id(v) { this._id = v; }
94
+ get name() { return this._name; }
95
+ set name(v){ this._name = v; }
96
+
97
+ clone() { return UserModel.from(this); }
98
+ getClassName() { return UserModel.getClassName(); }
99
+ getTableName() { return UserModel.getTableName(); }
100
+ getPrimaryKey() { return UserModel.getPrimaryKey(); }
101
+ getPkSequenceName(){ return UserModel.getPkSequenceName(); }
102
+ getAttributeMap() { return UserModel.attributeMap; }
103
+ }
104
+ ```
105
+
106
+ ## CRUD Operations
107
+
108
+ All methods have async and sync variants. Sync variants return `false` on error; async variants throw. SQLite supports both; MySQL and Oracle are async-only.
109
+
110
+ ### Insert
111
+
112
+ ```typescript
113
+ const newId = await db.insert(UserModel, { name: "Alice" });
114
+ const newId = db.insertSync(UserModel, { name: "Alice" }); // SQLite only
115
+ ```
116
+
117
+ ### Query
118
+
119
+ ```typescript
120
+ // All rows
121
+ const users = await db.getAll(UserModel);
122
+
123
+ // With WHERE
124
+ const admins = await db.getAll(UserModel, { role: "admin" });
125
+
126
+ // First match
127
+ const user = await db.getFirst(UserModel, { id: 42 });
128
+
129
+ // Full options
130
+ const results = await db.get(UserModel, {
131
+ where: { status: "active" },
132
+ orderBy: ["name asc"],
133
+ limit: { limit: 10, offset: 20 },
134
+ });
135
+ ```
136
+
137
+ ### Update
138
+
139
+ ```typescript
140
+ const affected = await db.update(UserModel, { name: "Bob" }, { id: 42 });
141
+ ```
142
+
143
+ ### Delete
144
+
145
+ ```typescript
146
+ const deleted = await db.delete(UserModel, { id: 42 });
147
+ ```
148
+
149
+ ### Raw SQL
150
+
151
+ ```typescript
152
+ const rows = await db.query("SELECT * FROM users WHERE id = ?", [42]);
153
+ await db.exec("CREATE INDEX idx_name ON users(name)");
154
+ ```
155
+
156
+ ## WHERE Clauses
157
+
158
+ WHERE conditions are plain objects. Keys are model attribute names; values can be literals or operator descriptors from `smart-db-globals`.
159
+
160
+ ```typescript
161
+ import { GT, LT, IN, LIKE, IS_NULL, BETWEEN, NE } from "@egi/smart-db";
162
+
163
+ // Simple equality
164
+ const where = { status: "active" };
165
+
166
+ // Operators
167
+ const where = {
168
+ age: GT(18),
169
+ score: BETWEEN(80, 100),
170
+ name: LIKE("%smith%"),
171
+ role: IN(["admin", "editor"]),
172
+ deletedAt: IS_NULL(),
173
+ };
174
+
175
+ // Nested AND / OR
176
+ const where = {
177
+ and: [
178
+ { status: "active" },
179
+ { or: [{ role: "admin" }, { role: "editor" }] },
180
+ ],
181
+ };
182
+ ```
183
+
184
+ ## SQL Helper Functions
185
+
186
+ Imported from `@egi/smart-db` (all re-exported from `smart-db-globals`):
187
+
188
+ | Function | SQL equivalent |
189
+ |---|---|
190
+ | `GT(v)` | `> v` |
191
+ | `GE(v)` | `>= v` |
192
+ | `LT(v)` | `< v` |
193
+ | `LE(v)` | `<= v` |
194
+ | `NE(v)` | `!= v` |
195
+ | `IN([...])` | `IN (...)` |
196
+ | `NOT_IN([...])` | `NOT IN (...)` |
197
+ | `LIKE(v)` | `LIKE v` |
198
+ | `NOT_LIKE(v)` | `NOT LIKE v` |
199
+ | `IS_NULL()` | `IS NULL` |
200
+ | `IS_NOT_NULL()` | `IS NOT NULL` |
201
+ | `BETWEEN(min, max)` | `BETWEEN min AND max` |
202
+ | `LITERAL(expr)` | raw SQL fragment |
203
+ | `COUNT(field?, alias?)` | `COUNT(*)` / `COUNT(field)` |
204
+ | `SUM / MIN / MAX / AVG` | aggregate functions |
205
+ | `COALESCE([...], alias?)` | `COALESCE(...)` |
206
+ | `FIELD(name, alias?)` | column reference |
207
+ | `VALUE(val, alias?)` | scalar value in SELECT |
208
+
209
+ ## Advanced Queries
210
+
211
+ ### Aggregates and Field Selection
212
+
213
+ ```typescript
214
+ import { COUNT, SUM, FIELD } from "@egi/smart-db";
215
+
216
+ const stats = await db.get(UserModel, {
217
+ fields: [COUNT("*", "total"), SUM("score", "totalScore")],
218
+ groupBy: "role",
219
+ });
220
+ ```
221
+
222
+ ### UNION / INTERSECT / MINUS
223
+
224
+ ```typescript
225
+ const results = await db.get(UserModel, {
226
+ where: { role: "admin" },
227
+ union: [{ model: UserModel, where: { role: "superadmin" } }],
228
+ orderBy: "name asc",
229
+ });
230
+ ```
231
+
232
+ ### Distinct and Count
233
+
234
+ ```typescript
235
+ const count = await db.get(UserModel, { count: true });
236
+ const unique = await db.get(UserModel, { distinct: true, fields: "role" });
237
+ ```
238
+
239
+ ## Transactions
240
+
241
+ ```typescript
242
+ try {
243
+ await db.insert(OrderModel, order);
244
+ await db.insert(OrderLineModel, line);
245
+ await db.commit();
246
+ } catch (err) {
247
+ await db.rollback();
248
+ }
249
+ ```
250
+
251
+ ## Schema Versioning
252
+
253
+ SmartDB tracks schema versions per module. SQL upgrade scripts are picked up automatically on init:
254
+
255
+ ```
256
+ sql/
257
+ my-app-init.sql # Run once on first init
258
+ my-app-update.001.sql # Applied in order when version is outdated
259
+ my-app-update.002.sql
260
+ ```
261
+
262
+ Pass `sqlFilesDirectory` and `module` in options:
263
+
264
+ ```typescript
265
+ new SmartDbBetterSqlite3(config, {
266
+ module: "my-app",
267
+ sqlFilesDirectory: "./sql",
268
+ });
269
+ ```
270
+
271
+ Use `skipAutoUpgrade: true` to disable automatic execution.
272
+
273
+ ## Schema Extraction
274
+
275
+ Generate typed model files from a live database:
276
+
277
+ ```bash
278
+ # SQLite
279
+ npm run extract:sqlite:api
280
+
281
+ # Oracle
282
+ npm run extract:oracle:api
283
+
284
+ # Arbitrary (via CLI)
285
+ extract-db-api --database mydb --username user --password pass
286
+ ```
287
+
288
+ ## Logging
289
+
290
+ ```typescript
291
+ import { SmartSeverityLevel } from "@egi/smart-db";
292
+
293
+ new SmartDbBetterSqlite3(config, {
294
+ logOptions: {
295
+ level: SmartSeverityLevel.Info,
296
+ dbLogging: true, // also persist logs to smart_db_log table
297
+ },
298
+ silent: true, // suppress all console output (Fatal only)
299
+ });
300
+ ```
301
+
302
+ ## Browser Usage
303
+
304
+ The browser entry point exports only `AbstractModel` and `SmartDbDictionary` — no drivers, no Node.js APIs:
305
+
306
+ ```typescript
307
+ import { AbstractModel } from "@egi/smart-db"; // resolves to smart-db-browser.js
308
+ ```
309
+
310
+ ## Date / Time Handling
311
+
312
+ SmartDB applies a consistent timezone rule across all three drivers, controlled by the `dateTimeMode` option:
313
+
314
+ | Mode | TIMESTAMP columns | DATE / DATETIME columns |
315
+ |---|---|---|
316
+ | `"rule"` *(default)* | stored as UTC | stored as local time |
317
+ | `"utc"` | stored as UTC | stored as UTC |
318
+ | `"local"` | stored as local time | stored as local time |
319
+ | `"none"` | no conversion (driver default) | no conversion (driver default) |
320
+
321
+ ```typescript
322
+ // Store all dates in UTC
323
+ new SmartDbMysql(config, { dateTimeMode: "utc" });
324
+
325
+ // Disable conversion entirely (e.g. when the DB session already handles it)
326
+ new SmartDbOracle(config, { dateTimeMode: "none" });
327
+ ```
328
+
329
+ The MySQL driver issues `SET time_zone = '+00:00'` on connect for `"rule"` and `"utc"` modes. For `"local"` and `"none"` it does not, preserving the server's default timezone.
330
+
331
+ ## Date Utilities
332
+
333
+ ```typescript
334
+ import { toSmartDbDate, toSmartDbTimestamp, smartDbToDate } from "@egi/smart-db";
335
+
336
+ toSmartDbDate(new Date()) // "2024-03-15 14:30:00"
337
+ toSmartDbTimestamp(new Date()) // "2024-03-15 14:30:00.000"
338
+ smartDbToDate("2024-03-15 14:30:00") // Date object
339
+ ```
340
+
341
+ ## Options Reference
342
+
343
+ | Option | Type | Description |
344
+ |---|---|---|
345
+ | `module` | `string \| string[]` | Module name(s) for schema versioning |
346
+ | `sqlFilesDirectory` | `string` | Directory for SQL upgrade scripts |
347
+ | `onReady` | `(db, err?) => void` | Callback when DB reaches READY or ERROR |
348
+ | `delayInit` | `boolean` | Skip `initDb()` in constructor; call manually |
349
+ | `connectOnly` | `boolean` | Connect without running upgrade scripts |
350
+ | `skipAutoUpgrade` | `boolean` | Skip schema version checks on init |
351
+ | `smartDbDictionary` | `typeof SmartDbDictionary` | Register model dictionaries |
352
+ | `silent` | `boolean` | Suppress all logging below Fatal |
353
+ | `needsExplicitEscape` | `boolean` | Enable explicit escaping (Oracle) |
354
+ | `dateTimeMode` | `SmartDbDateTimeMode` | Date/time timezone rule — see [Date / Time Handling](#date--time-handling) |
355
+ | `logOptions` | `SmartLogOptions` | Logging configuration |
@@ -0,0 +1,10 @@
1
+ drop table smart_db_core_table;
2
+
3
+ update smart_db_version
4
+ set ver_sequence = 1,
5
+ ver_version = '2',
6
+ ver_sub_version = '0',
7
+ ver_revision = '0',
8
+ ver_release_type = null
9
+ where ver_module = 'smart-db-core';
10
+
@@ -0,0 +1,13 @@
1
+ drop sequence smart_db_core_table_seq;
2
+ drop trigger smart_db_core_table_ins;
3
+ drop table smart_db_core_table;
4
+ drop view smart_db_user_tab_columns_view;
5
+
6
+ update smart_db_version
7
+ set ver_sequence = 1,
8
+ ver_version = '2',
9
+ ver_sub_version = '0',
10
+ ver_revision = '0',
11
+ ver_release_type = null
12
+ where ver_module = 'smart-db-core';
13
+
@@ -0,0 +1,10 @@
1
+ drop table if exists smart_db_core_table;
2
+
3
+ update smart_db_version
4
+ set ver_sequence = 1,
5
+ ver_version = '2',
6
+ ver_sub_version = '0',
7
+ ver_revision = '0',
8
+ ver_release_type = null
9
+ where ver_module = 'smart-db-core';
10
+
@@ -1,31 +1,118 @@
1
- import BetterSqlite3 from "better-sqlite3";
1
+ import * as BetterSqlite3 from "better-sqlite3";
2
2
  import { AbstractModel } from "../models/abstract-model";
3
3
  import { SmartDb } from "../smart-db";
4
- import { GenericModelData, SmartDbRunResult, SmartDbTableInfo } from "../smart-db-interfaces";
4
+ import { GenericModelData, ModelClass, SmartDbOptions, SmartDbRunResult, SmartDbTableInfo, SqlValueType } from "../smart-db-interfaces";
5
5
  import { SmartDbSqlBuildData } from "../smart-db-sql-build-data";
6
- declare type VariableArgFunction = (...params: any[]) => any;
7
- export declare class SmartDbBetterSqlite3 extends SmartDb {
8
- protected db: BetterSqlite3.Database;
9
- constructor(connectorOrDb: string | BetterSqlite3.Database, options?: BetterSqlite3.Options);
6
+ type VariableArgFunction = (...params: any[]) => any;
7
+ export type SmartDbBetterSqlite3Options = SmartDbOptions<SmartDbBetterSqlite3>;
8
+ /** Configuration for {@link SmartDbBetterSqlite3}. Extends the better-sqlite3 `Options` with a required `filename`. */
9
+ interface BetterSqlite3Config extends BetterSqlite3.Options {
10
+ /** Path to the SQLite database file, or `":memory:"` for an in-memory database. */
11
+ filename: string;
12
+ }
13
+ /**
14
+ * SmartDB driver for SQLite via the `better-sqlite3` library.
15
+ *
16
+ * This is the only driver that supports **synchronous** operations (`getSync`, `insertSync`, etc.)
17
+ * in addition to the standard async API. The connection is opened synchronously in the constructor
18
+ * and the database transitions to `CONNECTED` before `initDb()` runs.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const db = new SmartDbBetterSqlite3(
23
+ * { filename: "./my.db" },
24
+ * { module: "my-app", sqlFilesDirectory: "./sql", onReady: (db, err) => { ... } }
25
+ * );
26
+ * await db.databaseReady();
27
+ * ```
28
+ */
29
+ export declare class SmartDbBetterSqlite3 extends SmartDb<SmartDbBetterSqlite3> {
30
+ /**
31
+ * Opens the SQLite database file and transitions to `CONNECTED` synchronously.
32
+ * `initDb()` is called immediately afterwards (unless `delayInit: true` is set),
33
+ * running any pending schema upgrade scripts before the state reaches `READY`.
34
+ *
35
+ * @param config - Database file path and better-sqlite3 open options.
36
+ * @param options - SmartDB options (module, SQL directory, callbacks, etc.).
37
+ */
38
+ constructor(config: BetterSqlite3Config, options?: SmartDbBetterSqlite3Options);
39
+ /**
40
+ * Registers a custom aggregate function with the SQLite connection.
41
+ * Delegates directly to `better-sqlite3` `Database.aggregate()`.
42
+ *
43
+ * @param name - Name of the aggregate function as it will appear in SQL.
44
+ * @param options - Step/result callbacks and options passed to better-sqlite3.
45
+ * @returns `true` on success, `false` if an error occurred (check {@link getLastError}).
46
+ */
10
47
  aggregate(name: string, options: BetterSqlite3.AggregateOptions): boolean;
48
+ /**
49
+ * Creates an online backup of the database to `destinationFile`.
50
+ * Delegates to `better-sqlite3` `Database.backup()` and wraps the result in a Promise.
51
+ *
52
+ * @param destinationFile - Path to the destination backup file.
53
+ * @param options - Optional better-sqlite3 backup options (e.g. progress callback, rate).
54
+ * @returns Resolves with backup metadata on success, rejects with the last error on failure.
55
+ */
11
56
  backup(destinationFile: string, options?: BetterSqlite3.BackupOptions): Promise<BetterSqlite3.BackupMetadata>;
12
- closeSync(): boolean;
13
- commitSync(): void;
57
+ /**
58
+ * Toggles safe-integer mode for the connection. When enabled, 64-bit integers are
59
+ * returned as `BigInt` instead of `number` to avoid precision loss.
60
+ *
61
+ * @param toggleState - `true` to enable, `false` to disable. Omit to read the current state.
62
+ * @returns `true` on success, `false` if an error occurred.
63
+ */
14
64
  defaultSafeIntegers(toggleState?: boolean): boolean;
15
- execSync(script: string): boolean;
16
- existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): boolean;
65
+ /**
66
+ * Registers a custom scalar function with the SQLite connection.
67
+ * The callback receives SQL argument values and returns the result.
68
+ *
69
+ * @param name - Name of the function as it will appear in SQL.
70
+ * @param options - Registration options (deterministic, varargs, etc.) or the callback directly.
71
+ * @param cb - The function implementation (only required when `options` is not a function).
72
+ * @returns `true` on success, `false` if an error occurred.
73
+ */
17
74
  func(name: string, options: BetterSqlite3.RegistrationOptions, cb: VariableArgFunction): boolean;
18
75
  getDatabaseType(): string;
19
76
  getTableInfo(tableName: string): Promise<SmartDbTableInfo>;
77
+ getDb(): BetterSqlite3.Database;
78
+ protected db: BetterSqlite3.Database;
79
+ get supportSyncCalls(): boolean;
80
+ closeSync(): boolean;
81
+ commitSync(): void;
82
+ execSync(script: string, params?: SqlValueType[]): boolean;
83
+ querySync(script: string, params?: SqlValueType[]): GenericModelData[];
84
+ existsSync<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, type?: "view" | "table" | "index", indexTableName?: string): boolean;
20
85
  hasTransaction(): boolean;
21
- loadExtension(path: string): boolean;
22
- pragma(source: string, options?: BetterSqlite3.PragmaOptions): unknown;
23
86
  rollbackSync(): void;
24
- transaction<F extends VariableArgFunction>(fn: F): boolean;
87
+ protected statementGetAllSync(buildData: SmartDbSqlBuildData): any[];
88
+ protected statementGetSync(buildData: SmartDbSqlBuildData): unknown;
25
89
  protected statementRun(buildData: SmartDbSqlBuildData, retry?: number): Promise<SmartDbRunResult>;
26
90
  protected statementRunSync(buildData: SmartDbSqlBuildData): SmartDbRunResult;
27
- protected statementGetSync(buildData: SmartDbSqlBuildData): any;
28
- protected statementGetAllSync(buildData: SmartDbSqlBuildData): any[];
29
- get supportSyncCalls(): boolean;
91
+ /**
92
+ * Loads a compiled SQLite extension from the given shared-library path.
93
+ *
94
+ * @param path - Filesystem path to the `.so` / `.dylib` / `.dll` extension file.
95
+ * @returns `true` on success, `false` if loading failed (check {@link getLastError}).
96
+ */
97
+ loadExtension(path: string): boolean;
98
+ /**
99
+ * Executes a SQLite PRAGMA statement and returns the result.
100
+ *
101
+ * @param source - The PRAGMA expression, e.g. `"journal_mode = WAL"` or `"table_info(users)"`.
102
+ * @param options - Optional better-sqlite3 pragma options (e.g. `simple: true` to return a scalar).
103
+ * @returns The pragma result, or `false` if an error occurred.
104
+ */
105
+ pragma(source: string, options?: BetterSqlite3.PragmaOptions): unknown;
106
+ /**
107
+ * Wraps a function in a better-sqlite3 transaction and registers it with the connection.
108
+ * The returned transaction function can be called multiple times; each call runs atomically.
109
+ * For a simple one-shot transaction use `beginTransaction()` / `commitSync()` / `rollbackSync()`.
110
+ *
111
+ * @param fn - The function to wrap. Receives the same arguments passed to the transaction function.
112
+ * @returns `true` on success, `false` if registration failed.
113
+ */
114
+ transaction<F extends VariableArgFunction>(fn: F): boolean;
115
+ /** Begins an explicit transaction by executing `BEGIN TRANSACTION`. */
116
+ beginTransaction(): void;
30
117
  }
31
118
  export {};
@@ -1 +1 @@
1
- import BetterSqlite3 from"better-sqlite3";import _ from"lodash";import{SqliteMasterModel}from"../models/sqlite-master-model";import{SmartDb}from"../smart-db";export class SmartDbBetterSqlite3 extends SmartDb{constructor(t,e){_.isString(t)?(super(t),this.db=new BetterSqlite3(t,e)):(super(null),this.db=t,this.db.inTransaction),this.isReady=!0}aggregate(t,e){return!!this.saveExecute((()=>this.db.aggregate(t,e)))}backup(t,e){return new Promise(((s,r)=>{const n=this.saveExecute((()=>this.db.backup(t,e)));0==n?r(this.getLastError()):s(n)}))}closeSync(){return this.smartDbLog.setDb(null),this.isReady=!1,!!this.db.close()}commitSync(){this.db.inTransaction&&this.db.exec("commit")}defaultSafeIntegers(t){return!!this.saveExecute((()=>this.db.defaultSafeIntegers(t)))}execSync(t){return!!this.saveExecute((()=>this.db.exec(t)))}existsSync(t,e,s){let r=!1;const n=_.isString(t)?t:t.getTableName(),a=this.getFirstSync(SqliteMasterModel,{name:n,type:e,tblName:s});if(!1===a)throw this.getLastError();return r=!!a,r}func(t,e,s){return this.saveExecute((()=>{let r;return r=_.isFunction(e)?this.db.function(t,e):this.db.function(t,e,s),r}))}getDatabaseType(){return"sqlite3"}getTableInfo(t){return new Promise((e=>{const s=this.pragma(`table_info(${t})`);let r=[];s&&(r=s.map((t=>({cid:t.cid,name:t.name,type:t.type,notNull:0!==t.notnull,defaultValue:t.dflt_value,isPk:0!==t.pk}))),e({name:t,fields:r}))}))}hasTransaction(){return this.db.inTransaction}loadExtension(t){return!!this.saveExecute((()=>this.db.loadExtension(t)))}pragma(t,e){return this.saveExecute((()=>this.db.pragma(t,e)))}rollbackSync(){this.db.inTransaction&&this.db.exec("rollback")}transaction(t){return!!this.saveExecute((()=>this.db.transaction(t)))}statementRun(t,e=0){return new Promise(((s,r)=>{try{s(this.statementRunSync(t))}catch(n){"SQLITE_BUSY"==n.code&&e<10?setTimeout((()=>{this.statementRun(t,e+1).then((t=>{s(t)})).catch((t=>{r(t)}))}),100):(this.lastError=n,r(n))}}))}statementRunSync(t){const e=this.db.prepare(t.sql),s=e&&e.run(t.values);return s&&{changes:s.changes,affected:s.changes,lastId:s.lastInsertRowid}}statementGetSync(t){const e=this.db.prepare(t.sql);return e&&e.get(t.values)}statementGetAllSync(t){const e=this.db.prepare(t.sql);return e&&e.all(t.values)}get supportSyncCalls(){return!0}}
1
+ "use strict";var __extends=this&&this.__extends||function(){var t=function(e,r){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])},t(e,r)};return function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.SmartDbBetterSqlite3=void 0;var BetterSqlite3=require("better-sqlite3"),sqlite_master_model_1=require("../models/sqlite-master-model"),smart_db_1=require("../smart-db"),smart_db_interfaces_1=require("../smart-db-interfaces"),SmartDbBetterSqlite3=function(t){function e(e,r){var n=t.call(this,e.filename,r)||this;return n.readyState=smart_db_interfaces_1.SmartDbReadyState.PREPARING,n.db=new BetterSqlite3(e.filename,e),n.readyState=smart_db_interfaces_1.SmartDbReadyState.CONNECTED,n}return __extends(e,t),e.prototype.aggregate=function(t,e){var r=this;return!!this.saveExecute(function(){return r.db.aggregate(t,e)})},e.prototype.backup=function(t,e){var r=this;return new Promise(function(n,o){var a=r.saveExecute(function(){return r.db.backup(t,e)});0==a?o(r.getLastError()):n(a)})},e.prototype.defaultSafeIntegers=function(t){var e=this;return!!this.saveExecute(function(){return e.db.defaultSafeIntegers(t)})},e.prototype.func=function(t,e,r){var n=this;return this.saveExecute(function(){return!!("function"==typeof e?n.db.function(t,e):n.db.function(t,e,r))})},e.prototype.getDatabaseType=function(){return"sqlite3"},e.prototype.getTableInfo=function(t){var e=this;return new Promise(function(r,n){var o=e.pragma("table_info(".concat(t,")")),a=[];o?(a=o.map(function(t){var e=t.type.toUpperCase(),r=e.match(/^([^(]+)/);return{cid:t.cid,name:t.name,dbType:r?r[1]:e,dbFullType:e,notNull:0!==t.notnull,defaultValue:t.dflt_value,isPk:0!==t.pk}}),r({name:t,fields:a})):n("no such table '".concat(t,"'"))})},e.prototype.getDb=function(){return this.db},Object.defineProperty(e.prototype,"supportSyncCalls",{get:function(){return!0},enumerable:!1,configurable:!0}),e.prototype.closeSync=function(){return this.log.setDbWriter(null),this.readyState=smart_db_interfaces_1.SmartDbReadyState.CLOSED,!!this.db.close()},e.prototype.commitSync=function(){this.db.inTransaction&&this.db.exec("commit")},e.prototype.execSync=function(t,e){var r=this;return!!this.saveExecute(function(){return e&&e.length>0?r.db.prepare(t).run(e):r.db.exec(t)})},e.prototype.querySync=function(t,e){var r=this;return this.saveExecute(function(){var n=r.db.prepare(t);return n&&n.all(null!=e?e:[])})},e.prototype.existsSync=function(t,e,r){var n="string"==typeof t?t:t.getTableName(),o=this.getFirstSync(sqlite_master_model_1.SqliteMasterModel,{name:n,type:e,tblName:r});if(!1===o)throw this.getLastError();return!!o},e.prototype.hasTransaction=function(){return this.db.inTransaction},e.prototype.rollbackSync=function(){this.db.inTransaction&&this.db.exec("rollback")},e.prototype.statementGetAllSync=function(t){var e=this.db.prepare(t.sql);return e&&e.all(t.values)},e.prototype.statementGetSync=function(t){var e=this.db.prepare(t.sql);return e&&e.get(t.values)},e.prototype.statementRun=function(t,e){var r=this;return void 0===e&&(e=0),new Promise(function(n,o){try{n(r.statementRunSync(t))}catch(a){"SQLITE_BUSY"==a.code&&e<10?setTimeout(function(){r.statementRun(t,e+1).then(function(t){n(t)}).catch(function(t){o(t)})},100):(r.lastError=a,o(a))}})},e.prototype.statementRunSync=function(t){var e=this.db.prepare(t.sql),r=e&&e.run(t.values);return r&&{changes:r.changes,affected:r.changes,lastId:r.lastInsertRowid}},e.prototype.loadExtension=function(t){var e=this;return!!this.saveExecute(function(){return e.db.loadExtension(t)})},e.prototype.pragma=function(t,e){var r=this;return this.saveExecute(function(){return r.db.pragma(t,e)})},e.prototype.transaction=function(t){var e=this;return!!this.saveExecute(function(){return e.db.transaction(t)})},e.prototype.beginTransaction=function(){this.db.exec("begin transaction")},e}(smart_db_1.SmartDb);exports.SmartDbBetterSqlite3=SmartDbBetterSqlite3;
@@ -1,20 +1,63 @@
1
- import Mysql, { Connection, ConnectionConfig } from "mysql";
1
+ import * as Mysql from "mysql2";
2
+ import { ConnectionOptions } from "mysql2";
2
3
  import { AbstractModel } from "../models/abstract-model";
3
4
  import { SmartDb } from "../smart-db";
4
- import { GenericModelData, SmartDbRunResult, SmartDbTableInfo } from "../smart-db-interfaces";
5
+ import { GenericModelData, ModelClass, SmartDbOptions, SmartDbRunResult, SmartDbTableInfo, SqlValueType } from "../smart-db-interfaces";
5
6
  import { SmartDbSqlBuildData } from "../smart-db-sql-build-data";
6
- export declare class SmartDbMysql extends SmartDb {
7
+ export type SmartDbMysqlOptions = SmartDbOptions<SmartDbMysql>;
8
+ /**
9
+ * SmartDB driver for MySQL / MariaDB via the `mysql2` library.
10
+ *
11
+ * All operations are **async-only** — there are no sync variants.
12
+ * The constructor creates the connection and, for `"rule"` and `"utc"` date-time modes,
13
+ * immediately issues `SET time_zone = '+00:00'` so that all timestamps are stored and
14
+ * retrieved in UTC. The ready-state transitions to `CONNECTED` once that query completes.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const db = new SmartDbMysql(
19
+ * { host: "localhost", user: "root", password: "secret", database: "mydb" },
20
+ * { module: "my-app", sqlFilesDirectory: "./sql", onReady: (db, err) => { ... } }
21
+ * );
22
+ * await db.databaseReady();
23
+ * ```
24
+ */
25
+ export declare class SmartDbMysql extends SmartDb<SmartDbMysql> {
26
+ /**
27
+ * Creates a mysql2 connection and transitions to `CONNECTED`.
28
+ * For `dateTimeMode` `"rule"` (default) and `"utc"`, `SET time_zone = '+00:00'` is issued
29
+ * before `CONNECTED` is set; an error during that query puts the instance into `ERROR` state.
30
+ *
31
+ * @param config - mysql2 `ConnectionOptions` (host, user, password, database, port, etc.).
32
+ * @param options - SmartDB options (module, SQL directory, dateTimeMode, callbacks, etc.).
33
+ */
34
+ constructor(config: ConnectionOptions, options?: SmartDbMysqlOptions);
35
+ getDatabaseType(): string;
36
+ getTableInfo(tableName: string): Promise<SmartDbTableInfo>;
37
+ getDb(): Mysql.Connection;
7
38
  protected db: Mysql.Connection;
8
- constructor(connectorOrDb: string | ConnectionConfig | Connection);
9
- close(): Promise<boolean>;
10
39
  commit(): Promise<void>;
11
- exec(script: string): Promise<void>;
12
- exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | (new () => T), type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
13
- getDatabaseType(): string;
40
+ exec(script: string, params?: SqlValueType[]): Promise<void>;
41
+ query(script: string, params?: SqlValueType[]): Promise<GenericModelData[]>;
42
+ exists<T extends AbstractModel<T, D>, D extends GenericModelData>(modelClass: string | ModelClass<T>, type?: "view" | "table" | "index", indexTableName?: string): Promise<boolean>;
14
43
  getDbQuote(): string;
15
- getTableInfo(tableName: string): Promise<SmartDbTableInfo>;
16
44
  rollback(): Promise<void>;
17
- protected statementRun(buildData: SmartDbSqlBuildData): Promise<SmartDbRunResult>;
18
45
  protected statementGet<T extends object>(buildData: SmartDbSqlBuildData): Promise<T>;
19
46
  protected statementGetAll<T>(buildData: SmartDbSqlBuildData): Promise<T[]>;
47
+ protected statementRun(buildData: SmartDbSqlBuildData): Promise<SmartDbRunResult>;
48
+ /**
49
+ * mysql2 interprets date strings returned by MySQL (in UTC due to `SET time_zone = '+00:00'`) as local
50
+ * time, introducing an offset equal to the local timezone. This method removes that offset, restoring the
51
+ * intended UTC value — mirroring the same correction applied in the Oracle driver.
52
+ * Which column types are corrected depends on `dateTimeMode`:
53
+ * - `"rule"` — only TIMESTAMP columns (wire type 7); DATE / DATETIME are in local time intentionally.
54
+ * - `"utc"` — TIMESTAMP (7), DATE (10), and DATETIME (12); all were written as UTC.
55
+ * - `"local"` / `"none"` — no correction applied.
56
+ *
57
+ * @param rows
58
+ * @param fields
59
+ * @private
60
+ */
61
+ private adjustResultTimestamps;
62
+ close(): Promise<boolean>;
20
63
  }
@@ -1 +1 @@
1
- import _ from"lodash";import Mysql from"mysql";import{SmartDb}from"../smart-db";export class SmartDbMysql extends SmartDb{constructor(t){t.config&&t.connect?(super(t.config),this.db=t):(super(t),this.db=Mysql.createConnection(t))}close(){return new Promise((t=>{this.db.end((r=>{this.isReady=!1,r?(this.lastError=r,t(!1)):t(!0)}))}))}commit(){return new Promise(((t,r)=>{this.db.commit((e=>{e?(this.lastError=e,r(e)):t()}))}))}exec(t){return new Promise(((r,e)=>{try{this.db.query(t,((t,s,o)=>{t?(this.lastError=t,e(t)):r()}))}catch(t){this.lastError=t,e(t)}}))}exists(t,r,e){return new Promise(((r,e)=>{const s=_.isString(t)?t:t.getTableName();this.db.query(`show tables like '${s}'`,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s.length>0)}))}))}getDatabaseType(){return"mysql"}getDbQuote(){return"`"}getTableInfo(t){throw new Error("Method not implemented (getTableInfo)")}rollback(){return new Promise(((t,r)=>{this.db.rollback((e=>{e?(this.lastError=e,r(e)):t()}))}))}statementRun(t){return new Promise(((r,e)=>{this.db.query(t.sql,t.values,((t,s,o)=>{if(t)this.lastError=t,e(t);else{const t={changes:s.changedRows,affected:s.affectedRows,lastId:s.insertId};r(t)}}))}))}statementGet(t){return new Promise(((r,e)=>{try{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s[0])}))}catch(t){this.lastError=t,e(t)}}))}statementGetAll(t){return new Promise(((r,e)=>{this.db.query(t.sql,t.values,((t,s,o)=>{t?(this.lastError=t,e(t)):r(s&&s)}))}))}}
1
+ "use strict";var __extends=this&&this.__extends||function(){var t=function(e,r){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])},t(e,r)};return function(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}}(),__awaiter=this&&this.__awaiter||function(t,e,r,n){return new(r||(r=Promise))(function(o,a){function i(t){try{s(n.next(t))}catch(t){a(t)}}function u(t){try{s(n.throw(t))}catch(t){a(t)}}function s(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r(function(t){t(e)})).then(i,u)}s((n=n.apply(t,e||[])).next())})},__generator=this&&this.__generator||function(t,e){var r,n,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return i.next=u(0),i.throw=u(1),i.return=u(2),"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function u(u){return function(s){return function(u){if(r)throw new TypeError("Generator is already executing.");for(;i&&(i=0,u[0]&&(a=0)),a;)try{if(r=1,n&&(o=2&u[0]?n.return:u[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,u[1])).done)return o;switch(n=0,o&&(u=[2&u[0],o.value]),u[0]){case 0:case 1:o=u;break;case 4:return a.label++,{value:u[1],done:!1};case 5:a.label++,n=u[1],u=[0];continue;case 7:u=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==u[0]&&2!==u[0])){a=0;continue}if(3===u[0]&&(!o||u[1]>o[0]&&u[1]<o[3])){a.label=u[1];break}if(6===u[0]&&a.label<o[1]){a.label=o[1],o=u;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(u);break}o[2]&&a.ops.pop(),a.trys.pop();continue}u=e.call(t,a)}catch(t){u=[6,t],n=0}finally{r=o=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,s])}}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SmartDbMysql=void 0;var Mysql=require("mysql2"),smart_db_1=require("../smart-db"),smart_db_interfaces_1=require("../smart-db-interfaces"),SmartDbMysql=function(t){function e(e,r){var n,o,a=this,i=e.user+"@"+e.host+":"+(null!==(n=e.port)&&void 0!==n?n:3306);e.database&&e.database!=e.user&&(i+="/"+e.database),(a=t.call(this,i,r)||this).readyState=smart_db_interfaces_1.SmartDbReadyState.PREPARING,a.db=Mysql.createConnection(e);var u=null!==(o=null==r?void 0:r.dateTimeMode)&&void 0!==o?o:"rule";return"rule"==u||"utc"==u?a.db.query("SET time_zone = '+00:00'",function(t){t?(a.lastError=t,a.readyState=smart_db_interfaces_1.SmartDbReadyState.ERROR):a.readyState=smart_db_interfaces_1.SmartDbReadyState.CONNECTED}):a.readyState=smart_db_interfaces_1.SmartDbReadyState.CONNECTED,a}return __extends(e,t),e.prototype.getDatabaseType=function(){return"mysql"},e.prototype.getTableInfo=function(t){var e=this;return new Promise(function(r,n){e.db.query({sql:"describe ".concat(t)},function(o,a){if(o)e.lastError=o,n(o);else{var i=[];a&&(i=a.map(function(t,e){var r=t.Type.toUpperCase(),n=r.match(/^([^(]+)/);return{cid:e,name:t.Field,dbType:n?n[1]:r,dbFullType:r,notNull:"NO"==t.Null,defaultValue:t.Default,isPk:"PRI"==t.Key}})),r({name:t,fields:i})}})})},e.prototype.getDb=function(){return this.db},e.prototype.commit=function(){var t=this;return new Promise(function(e,r){t.db.commit(function(n){n?(t.lastError=n,r(n)):e()})})},e.prototype.exec=function(t,e){return __awaiter(this,void 0,void 0,function(){var r=this;return __generator(this,function(n){return[2,new Promise(function(n,o){try{r.db.query(t,null!=e?e:[],function(t,e,a){t?(r.lastError=t,o(t)):n()})}catch(t){r.lastError=t,o(t)}})]})})},e.prototype.query=function(t,e){return __awaiter(this,void 0,void 0,function(){var r=this;return __generator(this,function(n){return[2,new Promise(function(n,o){try{r.db.query(t,null!=e?e:[],function(t,e){t?(r.lastError=t,o(t)):n(e)})}catch(t){r.lastError=t,o(t)}})]})})},e.prototype.exists=function(t,e,r){var n=this;return new Promise(function(e,r){var o="string"==typeof t?t:t.getTableName();n.db.query("show tables like '".concat(o,"'"),function(t,o,a){t?(n.lastError=t,r(t)):e(o&&o.length>0)})})},e.prototype.getDbQuote=function(){return"`"},e.prototype.rollback=function(){var t=this;return new Promise(function(e,r){try{t.db.rollback(function(){e()})}catch(t){r(t)}})},e.prototype.statementGet=function(t){var e=this;return new Promise(function(r,n){try{e.db.query(t.sql,t.values,function(t,o,a){t?(e.lastError=t,n(t)):(e.adjustResultTimestamps(o,a),r(o&&o[0]))})}catch(t){e.lastError=t,n(t)}})},e.prototype.statementGetAll=function(t){var e=this;return new Promise(function(r,n){e.db.query(t.sql,t.values,function(t,o,a){t?(e.lastError=t,n(t)):(e.adjustResultTimestamps(o,a),r(o))})})},e.prototype.statementRun=function(t){var e=this;return new Promise(function(r,n){e.db.query(t.sql,t.values,function(t,o,a){if(t)e.lastError=t,n(t);else{var i=o,u={changes:i.affectedRows,affected:i.affectedRows,lastId:i.insertId};r(u)}})})},e.prototype.adjustResultTimestamps=function(t,e){var r,n=null!==(r=this.options.dateTimeMode)&&void 0!==r?r:"rule";if(t&&e&&("rule"==n||"utc"==n)){var o="utc"==n?[7,10,12]:[7],a=e.filter(function(t){return o.includes(t.type)}).map(function(t){return t.name});a.length>0&&t.forEach(function(t){a.forEach(function(e){var r=t[e];r instanceof Date&&(t[e]=new Date(r.getTime()-6e4*r.getTimezoneOffset()))})})}},e.prototype.close=function(){var t=this;return new Promise(function(e){t.db.end(function(r){t.readyState=smart_db_interfaces_1.SmartDbReadyState.CLOSED,r?(t.lastError=r,e(!1)):e(!0)})})},e}(smart_db_1.SmartDb);exports.SmartDbMysql=SmartDbMysql;