@remix-run/data-table-sqlite 0.1.0 → 0.2.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.
- package/README.md +8 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/adapter.d.ts +87 -8
- package/dist/lib/adapter.d.ts.map +1 -1
- package/dist/lib/adapter.js +501 -20
- package/dist/lib/sql-compiler.d.ts +2 -7
- package/dist/lib/sql-compiler.d.ts.map +1 -1
- package/dist/lib/sql-compiler.js +50 -80
- package/package.json +6 -7
- package/src/index.ts +1 -1
- package/src/lib/adapter.ts +606 -38
- package/src/lib/sql-compiler.ts +66 -105
package/dist/lib/adapter.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { getTablePrimaryKey } from '@remix-run/data-table';
|
|
2
|
-
import {
|
|
2
|
+
import { isDataManipulationOperation as isDataManipulationOperationHelper, quoteLiteral as quoteLiteralHelper, quoteTableRef as quoteTableRefHelper, } from '@remix-run/data-table/sql-helpers';
|
|
3
|
+
import { compileSqliteOperation } from "./sql-compiler.js";
|
|
3
4
|
/**
|
|
4
5
|
* `DatabaseAdapter` implementation for Better SQLite3.
|
|
5
6
|
*/
|
|
6
7
|
export class SqliteDatabaseAdapter {
|
|
8
|
+
/**
|
|
9
|
+
* The SQL dialect identifier reported by this adapter.
|
|
10
|
+
*/
|
|
7
11
|
dialect = 'sqlite';
|
|
12
|
+
/**
|
|
13
|
+
* Feature flags describing the sqlite behaviors supported by this adapter.
|
|
14
|
+
*/
|
|
8
15
|
capabilities;
|
|
9
16
|
#database;
|
|
10
17
|
#transactions = new Set();
|
|
@@ -15,35 +22,107 @@ export class SqliteDatabaseAdapter {
|
|
|
15
22
|
returning: options?.capabilities?.returning ?? true,
|
|
16
23
|
savepoints: options?.capabilities?.savepoints ?? true,
|
|
17
24
|
upsert: options?.capabilities?.upsert ?? true,
|
|
25
|
+
transactionalDdl: options?.capabilities?.transactionalDdl ?? true,
|
|
26
|
+
migrationLock: options?.capabilities?.migrationLock ?? false,
|
|
18
27
|
};
|
|
19
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Compiles a data or migration operation to sqlite SQL statements.
|
|
31
|
+
* @param operation Operation to compile.
|
|
32
|
+
* @returns Compiled SQL statements.
|
|
33
|
+
*/
|
|
34
|
+
compileSql(operation) {
|
|
35
|
+
if (isDataManipulationOperation(operation)) {
|
|
36
|
+
let compiled = compileSqliteOperation(operation);
|
|
37
|
+
return [{ text: compiled.text, values: compiled.values }];
|
|
38
|
+
}
|
|
39
|
+
return compileSqliteMigrationOperations(operation);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Executes a sqlite data-manipulation request.
|
|
43
|
+
* @param request Request to execute.
|
|
44
|
+
* @returns Execution result.
|
|
45
|
+
*/
|
|
20
46
|
async execute(request) {
|
|
21
|
-
if (request.
|
|
47
|
+
if (request.operation.kind === 'insertMany' && request.operation.values.length === 0) {
|
|
22
48
|
return {
|
|
23
49
|
affectedRows: 0,
|
|
24
50
|
insertId: undefined,
|
|
25
|
-
rows: request.
|
|
51
|
+
rows: request.operation.returning ? [] : undefined,
|
|
26
52
|
};
|
|
27
53
|
}
|
|
28
|
-
let statement =
|
|
54
|
+
let statement = this.compileSql(request.operation)[0];
|
|
29
55
|
let prepared = this.#database.prepare(statement.text);
|
|
30
56
|
if (prepared.reader) {
|
|
31
57
|
let rows = normalizeRows(prepared.all(...statement.values));
|
|
32
|
-
if (request.
|
|
58
|
+
if (request.operation.kind === 'count' || request.operation.kind === 'exists') {
|
|
33
59
|
rows = normalizeCountRows(rows);
|
|
34
60
|
}
|
|
35
61
|
return {
|
|
36
62
|
rows,
|
|
37
|
-
affectedRows: normalizeAffectedRowsForReader(request.
|
|
38
|
-
insertId: normalizeInsertIdForReader(request.
|
|
63
|
+
affectedRows: normalizeAffectedRowsForReader(request.operation.kind, rows),
|
|
64
|
+
insertId: normalizeInsertIdForReader(request.operation.kind, request.operation, rows),
|
|
39
65
|
};
|
|
40
66
|
}
|
|
41
67
|
let result = prepared.run(...statement.values);
|
|
42
68
|
return {
|
|
43
|
-
affectedRows: normalizeAffectedRowsForRun(request.
|
|
44
|
-
insertId: normalizeInsertIdForRun(request.
|
|
69
|
+
affectedRows: normalizeAffectedRowsForRun(request.operation.kind, result),
|
|
70
|
+
insertId: normalizeInsertIdForRun(request.operation.kind, request.operation, result),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Executes sqlite migration operations.
|
|
75
|
+
* @param request Migration request to execute.
|
|
76
|
+
* @returns Migration result.
|
|
77
|
+
*/
|
|
78
|
+
async migrate(request) {
|
|
79
|
+
let statements = this.compileSql(request.operation);
|
|
80
|
+
for (let statement of statements) {
|
|
81
|
+
let prepared = this.#database.prepare(statement.text);
|
|
82
|
+
prepared.run(...statement.values);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
affectedOperations: statements.length,
|
|
45
86
|
};
|
|
46
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Checks whether a table exists in sqlite.
|
|
90
|
+
* @param table Table reference to inspect.
|
|
91
|
+
* @param transaction Optional transaction token.
|
|
92
|
+
* @returns `true` when the table exists.
|
|
93
|
+
*/
|
|
94
|
+
async hasTable(table, transaction) {
|
|
95
|
+
if (transaction) {
|
|
96
|
+
this.#assertTransaction(transaction);
|
|
97
|
+
}
|
|
98
|
+
let masterTable = table.schema
|
|
99
|
+
? quoteIdentifier(table.schema) + '.sqlite_master'
|
|
100
|
+
: 'sqlite_master';
|
|
101
|
+
let statement = this.#database.prepare('select 1 from ' + masterTable + ' where type = ? and name = ? limit 1');
|
|
102
|
+
let row = statement.get('table', table.name);
|
|
103
|
+
return row !== undefined;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Checks whether a column exists in sqlite.
|
|
107
|
+
* @param table Table reference to inspect.
|
|
108
|
+
* @param column Column name to look up.
|
|
109
|
+
* @param transaction Optional transaction token.
|
|
110
|
+
* @returns `true` when the column exists.
|
|
111
|
+
*/
|
|
112
|
+
async hasColumn(table, column, transaction) {
|
|
113
|
+
if (transaction) {
|
|
114
|
+
this.#assertTransaction(transaction);
|
|
115
|
+
}
|
|
116
|
+
let schemaPrefix = table.schema ? quoteIdentifier(table.schema) + '.' : '';
|
|
117
|
+
let statement = this.#database.prepare('pragma ' + schemaPrefix + 'table_info(' + quoteIdentifier(table.name) + ')');
|
|
118
|
+
let rows = statement.all();
|
|
119
|
+
return rows.some((row) => row.name === column);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Starts a sqlite transaction.
|
|
123
|
+
* @param options Transaction options.
|
|
124
|
+
* @returns Transaction token.
|
|
125
|
+
*/
|
|
47
126
|
async beginTransaction(options) {
|
|
48
127
|
if (options?.isolationLevel === 'read uncommitted') {
|
|
49
128
|
this.#database.pragma('read_uncommitted = true');
|
|
@@ -54,24 +133,52 @@ export class SqliteDatabaseAdapter {
|
|
|
54
133
|
this.#transactions.add(token.id);
|
|
55
134
|
return token;
|
|
56
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Commits an open sqlite transaction.
|
|
138
|
+
* @param token Transaction token to commit.
|
|
139
|
+
* @returns A promise that resolves when the transaction is committed.
|
|
140
|
+
*/
|
|
57
141
|
async commitTransaction(token) {
|
|
58
142
|
this.#assertTransaction(token);
|
|
59
143
|
this.#database.exec('commit');
|
|
60
144
|
this.#transactions.delete(token.id);
|
|
61
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Rolls back an open sqlite transaction.
|
|
148
|
+
* @param token Transaction token to roll back.
|
|
149
|
+
* @returns A promise that resolves when the transaction is rolled back.
|
|
150
|
+
*/
|
|
62
151
|
async rollbackTransaction(token) {
|
|
63
152
|
this.#assertTransaction(token);
|
|
64
153
|
this.#database.exec('rollback');
|
|
65
154
|
this.#transactions.delete(token.id);
|
|
66
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Creates a savepoint in an open sqlite transaction.
|
|
158
|
+
* @param token Transaction token to use.
|
|
159
|
+
* @param name Savepoint name.
|
|
160
|
+
* @returns A promise that resolves when the savepoint is created.
|
|
161
|
+
*/
|
|
67
162
|
async createSavepoint(token, name) {
|
|
68
163
|
this.#assertTransaction(token);
|
|
69
164
|
this.#database.exec('savepoint ' + quoteIdentifier(name));
|
|
70
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Rolls back to a savepoint in an open sqlite transaction.
|
|
168
|
+
* @param token Transaction token to use.
|
|
169
|
+
* @param name Savepoint name.
|
|
170
|
+
* @returns A promise that resolves when the rollback completes.
|
|
171
|
+
*/
|
|
71
172
|
async rollbackToSavepoint(token, name) {
|
|
72
173
|
this.#assertTransaction(token);
|
|
73
174
|
this.#database.exec('rollback to savepoint ' + quoteIdentifier(name));
|
|
74
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Releases a savepoint in an open sqlite transaction.
|
|
178
|
+
* @param token Transaction token to use.
|
|
179
|
+
* @param name Savepoint name.
|
|
180
|
+
* @returns A promise that resolves when the savepoint is released.
|
|
181
|
+
*/
|
|
75
182
|
async releaseSavepoint(token, name) {
|
|
76
183
|
this.#assertTransaction(token);
|
|
77
184
|
this.#database.exec('release savepoint ' + quoteIdentifier(name));
|
|
@@ -87,6 +194,16 @@ export class SqliteDatabaseAdapter {
|
|
|
87
194
|
* @param database Better SQLite3 database instance.
|
|
88
195
|
* @param options Optional adapter capability overrides.
|
|
89
196
|
* @returns A configured sqlite adapter.
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* import BetterSqlite3 from 'better-sqlite3'
|
|
200
|
+
* import { createDatabase } from 'remix/data-table'
|
|
201
|
+
* import { createSqliteDatabaseAdapter } from 'remix/data-table-sqlite'
|
|
202
|
+
*
|
|
203
|
+
* let sqlite = new BetterSqlite3('./data/app.db')
|
|
204
|
+
* let adapter = createSqliteDatabaseAdapter(sqlite)
|
|
205
|
+
* let db = createDatabase(adapter)
|
|
206
|
+
* ```
|
|
90
207
|
*/
|
|
91
208
|
export function createSqliteDatabaseAdapter(database, options) {
|
|
92
209
|
return new SqliteDatabaseAdapter(database, options);
|
|
@@ -121,16 +238,16 @@ function normalizeCountRows(rows) {
|
|
|
121
238
|
});
|
|
122
239
|
}
|
|
123
240
|
function normalizeAffectedRowsForReader(kind, rows) {
|
|
124
|
-
if (
|
|
241
|
+
if (isWriteOperationKind(kind)) {
|
|
125
242
|
return rows.length;
|
|
126
243
|
}
|
|
127
244
|
return undefined;
|
|
128
245
|
}
|
|
129
|
-
function normalizeInsertIdForReader(kind,
|
|
130
|
-
if (!
|
|
246
|
+
function normalizeInsertIdForReader(kind, operation, rows) {
|
|
247
|
+
if (!isInsertOperationKind(kind) || !isInsertOperation(operation)) {
|
|
131
248
|
return undefined;
|
|
132
249
|
}
|
|
133
|
-
let primaryKey = getTablePrimaryKey(
|
|
250
|
+
let primaryKey = getTablePrimaryKey(operation.table);
|
|
134
251
|
if (primaryKey.length !== 1) {
|
|
135
252
|
return undefined;
|
|
136
253
|
}
|
|
@@ -144,11 +261,11 @@ function normalizeAffectedRowsForRun(kind, result) {
|
|
|
144
261
|
}
|
|
145
262
|
return result.changes;
|
|
146
263
|
}
|
|
147
|
-
function normalizeInsertIdForRun(kind,
|
|
148
|
-
if (!
|
|
264
|
+
function normalizeInsertIdForRun(kind, operation, result) {
|
|
265
|
+
if (!isInsertOperationKind(kind) || !isInsertOperation(operation)) {
|
|
149
266
|
return undefined;
|
|
150
267
|
}
|
|
151
|
-
if (getTablePrimaryKey(
|
|
268
|
+
if (getTablePrimaryKey(operation.table).length !== 1) {
|
|
152
269
|
return undefined;
|
|
153
270
|
}
|
|
154
271
|
return result.lastInsertRowid;
|
|
@@ -156,16 +273,380 @@ function normalizeInsertIdForRun(kind, statement, result) {
|
|
|
156
273
|
function quoteIdentifier(value) {
|
|
157
274
|
return '"' + value.replace(/"/g, '""') + '"';
|
|
158
275
|
}
|
|
159
|
-
function
|
|
276
|
+
function quoteTableRef(table) {
|
|
277
|
+
return quoteTableRefHelper(table, quoteIdentifier);
|
|
278
|
+
}
|
|
279
|
+
function quoteLiteral(value) {
|
|
280
|
+
return quoteLiteralHelper(value, { booleansAsIntegers: true });
|
|
281
|
+
}
|
|
282
|
+
function isWriteOperationKind(kind) {
|
|
160
283
|
return (kind === 'insert' ||
|
|
161
284
|
kind === 'insertMany' ||
|
|
162
285
|
kind === 'update' ||
|
|
163
286
|
kind === 'delete' ||
|
|
164
287
|
kind === 'upsert');
|
|
165
288
|
}
|
|
166
|
-
function
|
|
289
|
+
function isInsertOperationKind(kind) {
|
|
167
290
|
return kind === 'insert' || kind === 'insertMany' || kind === 'upsert';
|
|
168
291
|
}
|
|
169
|
-
function
|
|
170
|
-
return (
|
|
292
|
+
function isInsertOperation(operation) {
|
|
293
|
+
return (operation.kind === 'insert' || operation.kind === 'insertMany' || operation.kind === 'upsert');
|
|
294
|
+
}
|
|
295
|
+
function isDataManipulationOperation(operation) {
|
|
296
|
+
return isDataManipulationOperationHelper(operation);
|
|
297
|
+
}
|
|
298
|
+
function compileSqliteMigrationOperations(operation) {
|
|
299
|
+
if (operation.kind === 'raw') {
|
|
300
|
+
return [{ text: operation.sql.text, values: [...operation.sql.values] }];
|
|
301
|
+
}
|
|
302
|
+
if (operation.kind === 'createTable') {
|
|
303
|
+
let columns = Object.keys(operation.columns).map((columnName) => quoteIdentifier(columnName) + ' ' + compileSqliteColumn(operation.columns[columnName]));
|
|
304
|
+
let constraints = [];
|
|
305
|
+
if (operation.primaryKey) {
|
|
306
|
+
constraints.push('constraint ' +
|
|
307
|
+
quoteIdentifier(operation.primaryKey.name) +
|
|
308
|
+
' primary key (' +
|
|
309
|
+
operation.primaryKey.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
310
|
+
')');
|
|
311
|
+
}
|
|
312
|
+
for (let unique of operation.uniques ?? []) {
|
|
313
|
+
constraints.push('constraint ' +
|
|
314
|
+
quoteIdentifier(unique.name) +
|
|
315
|
+
' ' +
|
|
316
|
+
'unique (' +
|
|
317
|
+
unique.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
318
|
+
')');
|
|
319
|
+
}
|
|
320
|
+
for (let check of operation.checks ?? []) {
|
|
321
|
+
constraints.push('constraint ' + quoteIdentifier(check.name) + ' ' + 'check (' + check.expression + ')');
|
|
322
|
+
}
|
|
323
|
+
for (let foreignKey of operation.foreignKeys ?? []) {
|
|
324
|
+
let clause = 'constraint ' +
|
|
325
|
+
quoteIdentifier(foreignKey.name) +
|
|
326
|
+
' ' +
|
|
327
|
+
'foreign key (' +
|
|
328
|
+
foreignKey.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
329
|
+
') references ' +
|
|
330
|
+
quoteTableRef(foreignKey.references.table) +
|
|
331
|
+
' (' +
|
|
332
|
+
foreignKey.references.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
333
|
+
')';
|
|
334
|
+
if (foreignKey.onDelete) {
|
|
335
|
+
clause += ' on delete ' + foreignKey.onDelete;
|
|
336
|
+
}
|
|
337
|
+
if (foreignKey.onUpdate) {
|
|
338
|
+
clause += ' on update ' + foreignKey.onUpdate;
|
|
339
|
+
}
|
|
340
|
+
constraints.push(clause);
|
|
341
|
+
}
|
|
342
|
+
return [
|
|
343
|
+
{
|
|
344
|
+
text: 'create table ' +
|
|
345
|
+
(operation.ifNotExists ? 'if not exists ' : '') +
|
|
346
|
+
quoteTableRef(operation.table) +
|
|
347
|
+
' (' +
|
|
348
|
+
[...columns, ...constraints].join(', ') +
|
|
349
|
+
')',
|
|
350
|
+
values: [],
|
|
351
|
+
},
|
|
352
|
+
];
|
|
353
|
+
}
|
|
354
|
+
if (operation.kind === 'alterTable') {
|
|
355
|
+
let statements = [];
|
|
356
|
+
for (let change of operation.changes) {
|
|
357
|
+
let sql = 'alter table ' + quoteTableRef(operation.table) + ' ';
|
|
358
|
+
if (change.kind === 'addColumn') {
|
|
359
|
+
sql +=
|
|
360
|
+
'add column ' +
|
|
361
|
+
quoteIdentifier(change.column) +
|
|
362
|
+
' ' +
|
|
363
|
+
compileSqliteColumn(change.definition);
|
|
364
|
+
}
|
|
365
|
+
else if (change.kind === 'changeColumn') {
|
|
366
|
+
sql +=
|
|
367
|
+
'alter column ' +
|
|
368
|
+
quoteIdentifier(change.column) +
|
|
369
|
+
' type ' +
|
|
370
|
+
compileSqliteColumnType(change.definition);
|
|
371
|
+
}
|
|
372
|
+
else if (change.kind === 'renameColumn') {
|
|
373
|
+
sql += 'rename column ' + quoteIdentifier(change.from) + ' to ' + quoteIdentifier(change.to);
|
|
374
|
+
}
|
|
375
|
+
else if (change.kind === 'dropColumn') {
|
|
376
|
+
sql += 'drop column ' + quoteIdentifier(change.column);
|
|
377
|
+
}
|
|
378
|
+
else if (change.kind === 'addPrimaryKey') {
|
|
379
|
+
sql +=
|
|
380
|
+
'add primary key (' +
|
|
381
|
+
change.constraint.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
382
|
+
')';
|
|
383
|
+
}
|
|
384
|
+
else if (change.kind === 'dropPrimaryKey') {
|
|
385
|
+
sql += 'drop primary key';
|
|
386
|
+
}
|
|
387
|
+
else if (change.kind === 'addUnique') {
|
|
388
|
+
sql +=
|
|
389
|
+
'add ' +
|
|
390
|
+
'constraint ' +
|
|
391
|
+
quoteIdentifier(change.constraint.name) +
|
|
392
|
+
' ' +
|
|
393
|
+
'unique (' +
|
|
394
|
+
change.constraint.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
395
|
+
')';
|
|
396
|
+
}
|
|
397
|
+
else if (change.kind === 'dropUnique') {
|
|
398
|
+
sql += 'drop constraint ' + quoteIdentifier(change.name);
|
|
399
|
+
}
|
|
400
|
+
else if (change.kind === 'addForeignKey') {
|
|
401
|
+
sql +=
|
|
402
|
+
'add ' +
|
|
403
|
+
'constraint ' +
|
|
404
|
+
quoteIdentifier(change.constraint.name) +
|
|
405
|
+
' ' +
|
|
406
|
+
'foreign key (' +
|
|
407
|
+
change.constraint.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
408
|
+
') references ' +
|
|
409
|
+
quoteTableRef(change.constraint.references.table) +
|
|
410
|
+
' (' +
|
|
411
|
+
change.constraint.references.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
412
|
+
')';
|
|
413
|
+
}
|
|
414
|
+
else if (change.kind === 'dropForeignKey') {
|
|
415
|
+
sql += 'drop constraint ' + quoteIdentifier(change.name);
|
|
416
|
+
}
|
|
417
|
+
else if (change.kind === 'addCheck') {
|
|
418
|
+
sql +=
|
|
419
|
+
'add ' +
|
|
420
|
+
'constraint ' +
|
|
421
|
+
quoteIdentifier(change.constraint.name) +
|
|
422
|
+
' ' +
|
|
423
|
+
'check (' +
|
|
424
|
+
change.constraint.expression +
|
|
425
|
+
')';
|
|
426
|
+
}
|
|
427
|
+
else if (change.kind === 'dropCheck') {
|
|
428
|
+
sql += 'drop constraint ' + quoteIdentifier(change.name);
|
|
429
|
+
}
|
|
430
|
+
else if (change.kind === 'setTableComment') {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
statements.push({ text: sql, values: [] });
|
|
437
|
+
}
|
|
438
|
+
return statements;
|
|
439
|
+
}
|
|
440
|
+
if (operation.kind === 'renameTable') {
|
|
441
|
+
return [
|
|
442
|
+
{
|
|
443
|
+
text: 'alter table ' +
|
|
444
|
+
quoteTableRef(operation.from) +
|
|
445
|
+
' rename to ' +
|
|
446
|
+
quoteIdentifier(operation.to.name),
|
|
447
|
+
values: [],
|
|
448
|
+
},
|
|
449
|
+
];
|
|
450
|
+
}
|
|
451
|
+
if (operation.kind === 'dropTable') {
|
|
452
|
+
return [
|
|
453
|
+
{
|
|
454
|
+
text: 'drop table ' + (operation.ifExists ? 'if exists ' : '') + quoteTableRef(operation.table),
|
|
455
|
+
values: [],
|
|
456
|
+
},
|
|
457
|
+
];
|
|
458
|
+
}
|
|
459
|
+
if (operation.kind === 'createIndex') {
|
|
460
|
+
return [
|
|
461
|
+
{
|
|
462
|
+
text: 'create ' +
|
|
463
|
+
(operation.index.unique ? 'unique ' : '') +
|
|
464
|
+
'index ' +
|
|
465
|
+
(operation.ifNotExists ? 'if not exists ' : '') +
|
|
466
|
+
quoteIdentifier(operation.index.name) +
|
|
467
|
+
' on ' +
|
|
468
|
+
quoteTableRef(operation.index.table) +
|
|
469
|
+
' (' +
|
|
470
|
+
operation.index.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
471
|
+
')' +
|
|
472
|
+
(operation.index.where ? ' where ' + operation.index.where : ''),
|
|
473
|
+
values: [],
|
|
474
|
+
},
|
|
475
|
+
];
|
|
476
|
+
}
|
|
477
|
+
if (operation.kind === 'dropIndex') {
|
|
478
|
+
return [
|
|
479
|
+
{
|
|
480
|
+
text: 'drop index ' +
|
|
481
|
+
(operation.ifExists ? 'if exists ' : '') +
|
|
482
|
+
quoteIdentifier(operation.name),
|
|
483
|
+
values: [],
|
|
484
|
+
},
|
|
485
|
+
];
|
|
486
|
+
}
|
|
487
|
+
if (operation.kind === 'renameIndex') {
|
|
488
|
+
return [
|
|
489
|
+
{
|
|
490
|
+
text: 'alter table ' +
|
|
491
|
+
quoteTableRef(operation.table) +
|
|
492
|
+
' rename index ' +
|
|
493
|
+
quoteIdentifier(operation.from) +
|
|
494
|
+
' to ' +
|
|
495
|
+
quoteIdentifier(operation.to),
|
|
496
|
+
values: [],
|
|
497
|
+
},
|
|
498
|
+
];
|
|
499
|
+
}
|
|
500
|
+
if (operation.kind === 'addForeignKey') {
|
|
501
|
+
return [
|
|
502
|
+
{
|
|
503
|
+
text: 'alter table ' +
|
|
504
|
+
quoteTableRef(operation.table) +
|
|
505
|
+
' add ' +
|
|
506
|
+
'constraint ' +
|
|
507
|
+
quoteIdentifier(operation.constraint.name) +
|
|
508
|
+
' ' +
|
|
509
|
+
'foreign key (' +
|
|
510
|
+
operation.constraint.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
511
|
+
') references ' +
|
|
512
|
+
quoteTableRef(operation.constraint.references.table) +
|
|
513
|
+
' (' +
|
|
514
|
+
operation.constraint.references.columns
|
|
515
|
+
.map((column) => quoteIdentifier(column))
|
|
516
|
+
.join(', ') +
|
|
517
|
+
')' +
|
|
518
|
+
(operation.constraint.onDelete ? ' on delete ' + operation.constraint.onDelete : '') +
|
|
519
|
+
(operation.constraint.onUpdate ? ' on update ' + operation.constraint.onUpdate : ''),
|
|
520
|
+
values: [],
|
|
521
|
+
},
|
|
522
|
+
];
|
|
523
|
+
}
|
|
524
|
+
if (operation.kind === 'dropForeignKey') {
|
|
525
|
+
return [
|
|
526
|
+
{
|
|
527
|
+
text: 'alter table ' +
|
|
528
|
+
quoteTableRef(operation.table) +
|
|
529
|
+
' drop constraint ' +
|
|
530
|
+
quoteIdentifier(operation.name),
|
|
531
|
+
values: [],
|
|
532
|
+
},
|
|
533
|
+
];
|
|
534
|
+
}
|
|
535
|
+
if (operation.kind === 'addCheck') {
|
|
536
|
+
return [
|
|
537
|
+
{
|
|
538
|
+
text: 'alter table ' +
|
|
539
|
+
quoteTableRef(operation.table) +
|
|
540
|
+
' add ' +
|
|
541
|
+
'constraint ' +
|
|
542
|
+
quoteIdentifier(operation.constraint.name) +
|
|
543
|
+
' ' +
|
|
544
|
+
'check (' +
|
|
545
|
+
operation.constraint.expression +
|
|
546
|
+
')',
|
|
547
|
+
values: [],
|
|
548
|
+
},
|
|
549
|
+
];
|
|
550
|
+
}
|
|
551
|
+
if (operation.kind === 'dropCheck') {
|
|
552
|
+
return [
|
|
553
|
+
{
|
|
554
|
+
text: 'alter table ' +
|
|
555
|
+
quoteTableRef(operation.table) +
|
|
556
|
+
' drop constraint ' +
|
|
557
|
+
quoteIdentifier(operation.name),
|
|
558
|
+
values: [],
|
|
559
|
+
},
|
|
560
|
+
];
|
|
561
|
+
}
|
|
562
|
+
throw new Error('Unsupported data migration operation kind');
|
|
563
|
+
}
|
|
564
|
+
function compileSqliteColumn(definition) {
|
|
565
|
+
let parts = [compileSqliteColumnType(definition)];
|
|
566
|
+
if (definition.nullable === false) {
|
|
567
|
+
parts.push('not null');
|
|
568
|
+
}
|
|
569
|
+
if (definition.default) {
|
|
570
|
+
if (definition.default.kind === 'now') {
|
|
571
|
+
parts.push('default current_timestamp');
|
|
572
|
+
}
|
|
573
|
+
else if (definition.default.kind === 'sql') {
|
|
574
|
+
parts.push('default ' + definition.default.expression);
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
parts.push('default ' + quoteLiteral(definition.default.value));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (definition.primaryKey) {
|
|
581
|
+
parts.push('primary key');
|
|
582
|
+
}
|
|
583
|
+
if (definition.unique) {
|
|
584
|
+
parts.push('unique');
|
|
585
|
+
}
|
|
586
|
+
if (definition.computed) {
|
|
587
|
+
parts.push('generated always as (' + definition.computed.expression + ')');
|
|
588
|
+
parts.push(definition.computed.stored ? 'stored' : 'virtual');
|
|
589
|
+
}
|
|
590
|
+
if (definition.references) {
|
|
591
|
+
let clause = 'references ' +
|
|
592
|
+
quoteTableRef(definition.references.table) +
|
|
593
|
+
' (' +
|
|
594
|
+
definition.references.columns.map((column) => quoteIdentifier(column)).join(', ') +
|
|
595
|
+
')';
|
|
596
|
+
if (definition.references.onDelete) {
|
|
597
|
+
clause += ' on delete ' + definition.references.onDelete;
|
|
598
|
+
}
|
|
599
|
+
if (definition.references.onUpdate) {
|
|
600
|
+
clause += ' on update ' + definition.references.onUpdate;
|
|
601
|
+
}
|
|
602
|
+
parts.push(clause);
|
|
603
|
+
}
|
|
604
|
+
if (definition.checks && definition.checks.length > 0) {
|
|
605
|
+
for (let check of definition.checks) {
|
|
606
|
+
parts.push('check (' + check.expression + ')');
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return parts.join(' ');
|
|
610
|
+
}
|
|
611
|
+
function compileSqliteColumnType(definition) {
|
|
612
|
+
if (definition.type === 'varchar') {
|
|
613
|
+
return 'text';
|
|
614
|
+
}
|
|
615
|
+
if (definition.type === 'text') {
|
|
616
|
+
return 'text';
|
|
617
|
+
}
|
|
618
|
+
if (definition.type === 'integer') {
|
|
619
|
+
return 'integer';
|
|
620
|
+
}
|
|
621
|
+
if (definition.type === 'bigint') {
|
|
622
|
+
return 'integer';
|
|
623
|
+
}
|
|
624
|
+
if (definition.type === 'decimal') {
|
|
625
|
+
return 'numeric';
|
|
626
|
+
}
|
|
627
|
+
if (definition.type === 'boolean') {
|
|
628
|
+
return 'integer';
|
|
629
|
+
}
|
|
630
|
+
if (definition.type === 'uuid') {
|
|
631
|
+
return 'text';
|
|
632
|
+
}
|
|
633
|
+
if (definition.type === 'date') {
|
|
634
|
+
return 'text';
|
|
635
|
+
}
|
|
636
|
+
if (definition.type === 'time') {
|
|
637
|
+
return 'text';
|
|
638
|
+
}
|
|
639
|
+
if (definition.type === 'timestamp') {
|
|
640
|
+
return 'text';
|
|
641
|
+
}
|
|
642
|
+
if (definition.type === 'json') {
|
|
643
|
+
return 'text';
|
|
644
|
+
}
|
|
645
|
+
if (definition.type === 'binary') {
|
|
646
|
+
return 'blob';
|
|
647
|
+
}
|
|
648
|
+
if (definition.type === 'enum') {
|
|
649
|
+
return 'text';
|
|
650
|
+
}
|
|
651
|
+
return 'text';
|
|
171
652
|
}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
text: string;
|
|
4
|
-
values: unknown[];
|
|
5
|
-
};
|
|
6
|
-
export declare function compileSqliteStatement(statement: AdapterStatement): CompiledSql;
|
|
7
|
-
export {};
|
|
1
|
+
import type { DataManipulationOperation, SqlStatement } from '@remix-run/data-table';
|
|
2
|
+
export declare function compileSqliteOperation(operation: DataManipulationOperation): SqlStatement;
|
|
8
3
|
//# sourceMappingURL=sql-compiler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-compiler.d.ts","sourceRoot":"","sources":["../../src/lib/sql-compiler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"sql-compiler.d.ts","sourceRoot":"","sources":["../../src/lib/sql-compiler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAa,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAe/F,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,yBAAyB,GAAG,YAAY,CAuGzF"}
|