velocious 1.0.40 → 1.0.42
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 +1 -1
- package/package.json +2 -1
- package/peak_flow.yml +8 -4
- package/spec/cli/commands/db/create-spec.js +1 -0
- package/spec/cli/commands/db/migrate-spec.js +28 -11
- package/spec/cli/commands/test/test-files-finder-spec.js +5 -4
- package/spec/database/record/create-spec.js +6 -0
- package/spec/database/record/destroy-spec.js +6 -3
- package/spec/database/record/find-spec.js +3 -1
- package/spec/database/record/query-spec.js +7 -3
- package/spec/database/record/translation-fallbacks-spec.js +1 -1
- package/spec/database/record/update-spec.js +2 -1
- package/spec/database/record/validations-spec.js +10 -6
- package/spec/database/transactions-spec.js +7 -5
- package/spec/dummy/index.js +18 -29
- package/spec/dummy/src/config/configuration.example.js +3 -2
- package/spec/dummy/src/config/configuration.peakflow.mariadb.js +3 -7
- package/spec/dummy/src/config/configuration.peakflow.mssql.js +3 -2
- package/spec/dummy/src/config/configuration.peakflow.pgsql.js +3 -7
- package/spec/dummy/src/config/configuration.peakflow.sqlite.js +3 -7
- package/spec/dummy/src/config/testing.js +34 -0
- package/spec/dummy/src/database/migrations/20250912183605-create-users.js +15 -0
- package/spec/dummy/src/database/migrations/20250912183606-create-authentication-tokens.js +15 -0
- package/spec/dummy/src/models/authentication-token.js +8 -0
- package/spec/dummy/src/models/task.js +2 -2
- package/spec/dummy/src/models/user.js +15 -0
- package/spec/dummy/src/routes/projects/controller.js +7 -1
- package/spec/http-server/client-spec.js +1 -1
- package/spec/http-server/get-spec.js +1 -1
- package/spec/http-server/post-spec.js +21 -8
- package/spec/http-server/root-get-spec.js +1 -1
- package/src/cli/commands/db/create.js +11 -8
- package/src/cli/commands/db/drop.js +19 -0
- package/src/cli/commands/db/migrate.js +1 -1
- package/src/cli/commands/db/reset.js +7 -1
- package/src/cli/commands/test.js +10 -4
- package/src/configuration.js +27 -6
- package/src/controller.js +7 -19
- package/src/database/drivers/base-column.js +22 -0
- package/src/database/drivers/base-columns-index.js +34 -0
- package/src/database/drivers/base-table.js +43 -0
- package/src/database/drivers/base.js +44 -16
- package/src/database/drivers/mssql/column.js +43 -2
- package/src/database/drivers/mssql/columns-index.js +9 -0
- package/src/database/drivers/mssql/index.js +26 -14
- package/src/database/drivers/mssql/table.js +16 -1
- package/src/database/drivers/mysql/column.js +47 -2
- package/src/database/drivers/mysql/columns-index.js +10 -0
- package/src/database/drivers/mysql/index.js +5 -8
- package/src/database/drivers/mysql/table.js +3 -1
- package/src/database/drivers/pgsql/column.js +37 -2
- package/src/database/drivers/pgsql/columns-index.js +4 -0
- package/src/database/drivers/pgsql/index.js +6 -5
- package/src/database/drivers/pgsql/table.js +3 -1
- package/src/database/drivers/sqlite/base.js +6 -4
- package/src/database/drivers/sqlite/column.js +46 -2
- package/src/database/drivers/sqlite/columns-index.js +22 -0
- package/src/database/drivers/sqlite/connection-sql-js.js +1 -1
- package/src/database/drivers/sqlite/table.js +3 -1
- package/src/database/migrator.js +27 -7
- package/src/database/query/create-index-base.js +10 -1
- package/src/database/query/create-table-base.js +56 -2
- package/src/database/query/drop-table-base.js +8 -2
- package/src/database/table-data/index.js +2 -1
- package/src/database/use-database.js +1 -1
- package/src/http-server/client/request-buffer/index.js +9 -5
- package/src/http-server/client/request.js +6 -6
- package/src/routes/base-route.js +11 -0
- package/src/routes/namespace-route.js +24 -0
- package/src/routes/resolver.js +1 -1
- package/src/templates/configuration.js +1 -1
- package/src/testing/test-runner.js +86 -26
- package/src/testing/test.js +155 -7
- package/src/utils/with-tracked-stack.js +5 -3
|
@@ -26,10 +26,6 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
disconnect() {
|
|
30
|
-
this.connection.end()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
29
|
async close() {
|
|
34
30
|
await this.connection.close()
|
|
35
31
|
this.connection = undefined
|
|
@@ -50,7 +46,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
createTableSql(tableData) {
|
|
53
|
-
const createArgs = Object.assign({tableData, driver: this})
|
|
49
|
+
const createArgs = Object.assign({tableData, driver: this, indexInCreateTable: false})
|
|
54
50
|
const createTable = new CreateTable(createArgs)
|
|
55
51
|
|
|
56
52
|
return createTable.toSql()
|
|
@@ -75,7 +71,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
75
71
|
primaryKeyType = () => "bigint"
|
|
76
72
|
|
|
77
73
|
async query(sql) {
|
|
78
|
-
let result, request
|
|
74
|
+
let result, request, tries = 0
|
|
79
75
|
|
|
80
76
|
if (this._currentTransaction) {
|
|
81
77
|
request = new mssql.Request(this._currentTransaction)
|
|
@@ -83,11 +79,22 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
83
79
|
request = mssql
|
|
84
80
|
}
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
while (true) {
|
|
83
|
+
tries++
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
result = await request.query(sql)
|
|
87
|
+
break
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error.message == "No connection is specified for that request." && tries <= 3) {
|
|
90
|
+
this.logger.log("Reconnecting to database")
|
|
91
|
+
await this.connect()
|
|
92
|
+
// Retry
|
|
93
|
+
} else {
|
|
94
|
+
// Re-throw error because the stack-trace is broken and can't be used for app-development.
|
|
95
|
+
throw new Error(`Query failed '${error.message}': ${sql}`)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
return result.recordsets[0]
|
|
@@ -154,12 +161,14 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
154
161
|
return tables
|
|
155
162
|
}
|
|
156
163
|
|
|
157
|
-
async getTableByName(tableName) {
|
|
164
|
+
async getTableByName(tableName, args) {
|
|
158
165
|
const result = await this.query(`SELECT [TABLE_NAME] FROM [INFORMATION_SCHEMA].[TABLES] WHERE [TABLE_CATALOG] = DB_NAME() AND [TABLE_SCHEMA] = 'dbo' AND [TABLE_NAME] = ${this.quote(tableName)}`)
|
|
159
166
|
|
|
160
|
-
if (
|
|
167
|
+
if (result[0]) {
|
|
168
|
+
return new Table(this, result[0])
|
|
169
|
+
}
|
|
161
170
|
|
|
162
|
-
|
|
171
|
+
if (args?.throwError !== false) throw new Error(`Couldn't find a table by that name: ${tableName}`)
|
|
163
172
|
}
|
|
164
173
|
|
|
165
174
|
async lastInsertID() {
|
|
@@ -184,6 +193,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
184
193
|
this._currentTransaction = new mssql.Transaction(this.connection)
|
|
185
194
|
|
|
186
195
|
await this._currentTransaction.begin()
|
|
196
|
+
this._transactionsCount++
|
|
187
197
|
}
|
|
188
198
|
|
|
189
199
|
async commitTransaction() {
|
|
@@ -191,6 +201,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
191
201
|
|
|
192
202
|
await this._currentTransaction.commit()
|
|
193
203
|
this._currentTransaction = null
|
|
204
|
+
this._transactionsCount--
|
|
194
205
|
}
|
|
195
206
|
|
|
196
207
|
async rollbackTransaction() {
|
|
@@ -199,6 +210,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
199
210
|
await this._currentTransaction.rollback()
|
|
200
211
|
|
|
201
212
|
this._currentTransaction = null
|
|
213
|
+
this._transactionsCount--
|
|
202
214
|
}
|
|
203
215
|
|
|
204
216
|
async startSavePoint(savePointName) {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import BaseTable from "../base-table.js"
|
|
1
2
|
import Column from "./column.js"
|
|
2
3
|
import {digg} from "diggerize"
|
|
3
4
|
import ForeignKey from "./foreign-key.js"
|
|
4
5
|
|
|
5
|
-
export default class VelociousDatabaseDriversMssqlTable {
|
|
6
|
+
export default class VelociousDatabaseDriversMssqlTable extends BaseTable {
|
|
6
7
|
constructor(driver, data) {
|
|
8
|
+
super()
|
|
7
9
|
this.data = data
|
|
8
10
|
this.driver = driver
|
|
9
11
|
}
|
|
@@ -62,4 +64,17 @@ export default class VelociousDatabaseDriversMssqlTable {
|
|
|
62
64
|
getName() {
|
|
63
65
|
return digg(this.data, "TABLE_NAME")
|
|
64
66
|
}
|
|
67
|
+
|
|
68
|
+
async truncate() {
|
|
69
|
+
try {
|
|
70
|
+
await this.getDriver().query(`TRUNCATE TABLE ${this.getOptions().quoteTableName(this.getName())}`)
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error.message.startsWith("Query failed 'Cannot truncate table")) {
|
|
73
|
+
// Truncate table is really buggy for some reason - fall back to delete all rows instead
|
|
74
|
+
await this.getDriver().query(`DELETE FROM ${this.getOptions().quoteTableName(this.getName())}`)
|
|
75
|
+
} else {
|
|
76
|
+
throw error
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
65
80
|
}
|
|
@@ -1,8 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
import BaseColumn from "../base-column.js"
|
|
2
|
+
import ColumnsIndex from "./columns-index.js"
|
|
3
|
+
import {digg} from "diggerize"
|
|
4
|
+
|
|
5
|
+
export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
|
|
2
6
|
constructor(table, data) {
|
|
7
|
+
super()
|
|
3
8
|
this.data = data
|
|
4
9
|
this.table = table
|
|
5
10
|
}
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
async getIndexes() {
|
|
13
|
+
const options = this.getOptions()
|
|
14
|
+
const sql = `
|
|
15
|
+
SELECT
|
|
16
|
+
TABLE_SCHEMA,
|
|
17
|
+
TABLE_NAME,
|
|
18
|
+
INDEX_NAME AS index_name,
|
|
19
|
+
COLUMN_NAME,
|
|
20
|
+
SEQ_IN_INDEX,
|
|
21
|
+
NON_UNIQUE,
|
|
22
|
+
INDEX_TYPE
|
|
23
|
+
FROM INFORMATION_SCHEMA.STATISTICS
|
|
24
|
+
WHERE TABLE_SCHEMA = DATABASE()
|
|
25
|
+
AND TABLE_NAME = ${options.quote(this.table.getName())}
|
|
26
|
+
AND COLUMN_NAME = ${options.quote(this.getName())}
|
|
27
|
+
`
|
|
28
|
+
const indexesRows = await this.getDriver().query(sql)
|
|
29
|
+
const indexes = []
|
|
30
|
+
|
|
31
|
+
for (const indexRow of indexesRows) {
|
|
32
|
+
if (indexRow.NON_UNIQUE == 1) {
|
|
33
|
+
indexRow.is_unique = false
|
|
34
|
+
} else {
|
|
35
|
+
indexRow.is_unique = true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (indexRow.index_name == "PRIMARY") {
|
|
39
|
+
indexRow.is_primary_key = true
|
|
40
|
+
} else {
|
|
41
|
+
indexRow.is_primary_key = false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const index = new ColumnsIndex(this.getTable(), indexRow)
|
|
45
|
+
|
|
46
|
+
indexes.push(index)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return indexes
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getName = () => digg(this, "data", "Field")
|
|
8
53
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import BaseColumnsIndex from "../base-columns-index.js"
|
|
2
|
+
import {digg} from "diggerize"
|
|
3
|
+
|
|
4
|
+
export default class VelociousDatabaseDriversMysqlColumn extends BaseColumnsIndex {
|
|
5
|
+
constructor(table, data) {
|
|
6
|
+
super()
|
|
7
|
+
this.data = data
|
|
8
|
+
this.table = table
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -22,8 +22,9 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
22
22
|
this.connection = connection
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
this.connection.end()
|
|
25
|
+
async close() {
|
|
26
|
+
await this.connection.end()
|
|
27
|
+
this.connection = undefined
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
connectArgs() {
|
|
@@ -40,11 +41,6 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
40
41
|
return connectArgs
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
async close() {
|
|
44
|
-
await this.connection.end()
|
|
45
|
-
this.connection = undefined
|
|
46
|
-
}
|
|
47
|
-
|
|
48
44
|
createDatabaseSql(databaseName, args) {
|
|
49
45
|
const createArgs = Object.assign({databaseName, driver: this}, args)
|
|
50
46
|
const createDatabase = new CreateDatabase(createArgs)
|
|
@@ -152,7 +148,8 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
152
148
|
}
|
|
153
149
|
|
|
154
150
|
async startTransaction() {
|
|
155
|
-
|
|
151
|
+
await this.query("START TRANSACTION")
|
|
152
|
+
this._transactionsCount++
|
|
156
153
|
}
|
|
157
154
|
|
|
158
155
|
updateSql({conditions, data, tableName}) {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import BaseTable from "../base-table.js"
|
|
1
2
|
import Column from "./column.js"
|
|
2
3
|
import ForeignKey from "./foreign-key.js"
|
|
3
4
|
|
|
4
|
-
export default class VelociousDatabaseDriversMysqlTable {
|
|
5
|
+
export default class VelociousDatabaseDriversMysqlTable extends BaseTable {
|
|
5
6
|
constructor(driver, data) {
|
|
7
|
+
super()
|
|
6
8
|
this.data = data
|
|
7
9
|
this.driver = driver
|
|
8
10
|
}
|
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
import BaseColumn from "../base-column.js"
|
|
2
|
+
import ColumnsIndex from "./columns-index.js"
|
|
3
|
+
import {digg} from "diggerize"
|
|
4
|
+
|
|
5
|
+
export default class VelociousDatabaseDriversPgsqlColumn extends BaseColumn {
|
|
2
6
|
constructor(table, data) {
|
|
7
|
+
super()
|
|
3
8
|
this.data = data
|
|
4
9
|
this.table = table
|
|
5
10
|
}
|
|
6
11
|
|
|
12
|
+
async getIndexes() {
|
|
13
|
+
const options = this.getOptions()
|
|
14
|
+
|
|
15
|
+
const indexesRows = await this.table.getDriver().query(`
|
|
16
|
+
SELECT
|
|
17
|
+
pg_attribute.attname AS column_name,
|
|
18
|
+
pg_index.indexrelid::regclass as index_name,
|
|
19
|
+
pg_class.relnamespace::regnamespace as schema_name,
|
|
20
|
+
pg_class.relname as table_name,
|
|
21
|
+
pg_index.indisprimary as is_primary_key,
|
|
22
|
+
pg_index.indisunique as is_unique
|
|
23
|
+
FROM pg_index
|
|
24
|
+
JOIN pg_class ON pg_class.oid = pg_index.indrelid
|
|
25
|
+
JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid AND pg_attribute.attnum = ANY(pg_index.indkey)
|
|
26
|
+
WHERE
|
|
27
|
+
pg_attribute.attname = ${options.quote(this.getName())} AND
|
|
28
|
+
pg_class.relname = ${options.quote(this.getTable().getName())}
|
|
29
|
+
`)
|
|
30
|
+
|
|
31
|
+
const indexes = []
|
|
32
|
+
|
|
33
|
+
for (const indexRow of indexesRows) {
|
|
34
|
+
const columnsIndex = new ColumnsIndex(this.getTable(), indexRow)
|
|
35
|
+
|
|
36
|
+
indexes.push(columnsIndex)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return indexes
|
|
40
|
+
}
|
|
41
|
+
|
|
7
42
|
getName() {
|
|
8
|
-
return this
|
|
43
|
+
return digg(this, "data", "column_name")
|
|
9
44
|
}
|
|
10
45
|
}
|
|
@@ -26,8 +26,8 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
26
26
|
this.connection = client
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
disconnect() {
|
|
30
|
-
this.connection.end()
|
|
29
|
+
async disconnect() {
|
|
30
|
+
await this.connection.end()
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
connectArgs() {
|
|
@@ -71,11 +71,11 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
async disableForeignKeys() {
|
|
74
|
-
await this.query("SET
|
|
74
|
+
await this.query("SET session_replication_role = 'replica'")
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
async enableForeignKeys() {
|
|
78
|
-
await this.query("SET
|
|
78
|
+
await this.query("SET session_replication_role = 'origin'")
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
dropTableSql(tableName, args = {}) {
|
|
@@ -161,7 +161,8 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
async startTransaction() {
|
|
164
|
-
|
|
164
|
+
await this.query("START TRANSACTION")
|
|
165
|
+
this._transactionsCount++
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
updateSql({conditions, data, tableName}) {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import BaseTable from "../base-table.js"
|
|
1
2
|
import Column from "./column.js"
|
|
2
3
|
import ForeignKey from "./foreign-key.js"
|
|
3
4
|
|
|
4
|
-
export default class VelociousDatabaseDriversPgsqlTable {
|
|
5
|
+
export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
|
|
5
6
|
constructor(driver, data) {
|
|
7
|
+
super()
|
|
6
8
|
this.data = data
|
|
7
9
|
this.driver = driver
|
|
8
10
|
}
|
|
@@ -54,18 +54,20 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
54
54
|
getType = () => "sqlite"
|
|
55
55
|
insertSql = (args) => new Insert(Object.assign({driver: this}, args)).toSql()
|
|
56
56
|
|
|
57
|
-
async getTableByName(tableName) {
|
|
57
|
+
async getTableByName(tableName, args) {
|
|
58
58
|
const result = await this.query(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${this.quote(tableName)} LIMIT 1`)
|
|
59
59
|
const row = result[0]
|
|
60
60
|
|
|
61
|
-
if (
|
|
61
|
+
if (row) {
|
|
62
|
+
return new Table({driver: this, row})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (args?.throwError !== false) {
|
|
62
66
|
const tables = await this.getTables()
|
|
63
67
|
const tableNames = tables.map((table) => table.getName())
|
|
64
68
|
|
|
65
69
|
throw new Error(`No table by that name: ${tableName} in ${tableNames.join(", ")}`)
|
|
66
70
|
}
|
|
67
|
-
|
|
68
|
-
return new Table({driver: this, row})
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
async getTables() {
|
|
@@ -1,7 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import BaseColumn from "../base-column.js"
|
|
2
|
+
import ColumnsIndex from "./columns-index.js"
|
|
3
|
+
|
|
4
|
+
export default class VelociousDatabaseDriversSqliteColumn extends BaseColumn {
|
|
5
|
+
constructor({column, driver, table}) {
|
|
6
|
+
super()
|
|
3
7
|
this.column = column
|
|
4
8
|
this.driver = driver
|
|
9
|
+
this.table = table
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async getIndexes() {
|
|
13
|
+
const table = this.getTable()
|
|
14
|
+
const rows = await this.getDriver().query(`PRAGMA index_list(${this.getOptions().quoteTableName(table.getName())})`)
|
|
15
|
+
const indexes = []
|
|
16
|
+
|
|
17
|
+
for (const row of rows) {
|
|
18
|
+
const columnsIndex = new ColumnsIndex(table, row)
|
|
19
|
+
const indexMasterData = await this.getDriver().query(`SELECT * FROM sqlite_master WHERE type = 'index' AND name = ${this.getOptions().quote(columnsIndex.getName())}`)
|
|
20
|
+
|
|
21
|
+
columnsIndex.columnNames = this._parseColumnsFromSQL(indexMasterData[0].sql)
|
|
22
|
+
|
|
23
|
+
indexes.push(columnsIndex)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return indexes
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
_parseColumnsFromSQL(sql) {
|
|
31
|
+
const columnsSQLMatch = sql.match(/\((.+?)\)/)
|
|
32
|
+
const columnsSQL = columnsSQLMatch[1].split(",")
|
|
33
|
+
const columnNames = []
|
|
34
|
+
|
|
35
|
+
for (const column of columnsSQL) {
|
|
36
|
+
const matchTicks = column.match(/`(.+)`/)
|
|
37
|
+
const matchQuotes = column.match(/"(.+)"/)
|
|
38
|
+
|
|
39
|
+
if (matchTicks) {
|
|
40
|
+
columnNames.push(matchTicks[1])
|
|
41
|
+
} else if (matchQuotes) {
|
|
42
|
+
columnNames.push(matchQuotes[1])
|
|
43
|
+
} else{
|
|
44
|
+
throw new Error(`Couldn't parse column part: ${column}`)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return columnNames
|
|
5
49
|
}
|
|
6
50
|
|
|
7
51
|
getName() {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import BaseColumnsIndex from "../base-columns-index.js"
|
|
2
|
+
import {digg} from "diggerize"
|
|
3
|
+
|
|
4
|
+
export default class VelociousDatabaseDriversSqliteColumn extends BaseColumnsIndex {
|
|
5
|
+
constructor(table, data) {
|
|
6
|
+
super()
|
|
7
|
+
this.data = data
|
|
8
|
+
this.table = table
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
getName() {
|
|
12
|
+
return digg(this, "data", "name")
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
isPrimaryKey() {
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
isUnique() {
|
|
20
|
+
return digg(this, "data", "unique") == 1
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -13,7 +13,7 @@ export default class VelociousDatabaseDriversSqliteConnectionSqlJs {
|
|
|
13
13
|
this.connection = undefined
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
disconnect = () => this.saveDatabase()
|
|
16
|
+
disconnect = async () => await this.saveDatabase()
|
|
17
17
|
|
|
18
18
|
async query(sql) {
|
|
19
19
|
const result = await query(this.connection, sql)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import BaseTable from "../base-table.js"
|
|
1
2
|
import Column from "./column.js"
|
|
2
3
|
import ForeignKey from "./foreign-key.js"
|
|
3
4
|
|
|
4
|
-
export default class VelociousDatabaseDriversSqliteTable {
|
|
5
|
+
export default class VelociousDatabaseDriversSqliteTable extends BaseTable {
|
|
5
6
|
constructor({driver, row}) {
|
|
7
|
+
super()
|
|
6
8
|
this.driver = driver
|
|
7
9
|
this.row = row
|
|
8
10
|
}
|
package/src/database/migrator.js
CHANGED
|
@@ -44,7 +44,7 @@ export default class VelociousDatabaseMigrator {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
async migrateFiles(files, importCallback) {
|
|
47
|
-
await this.configuration.
|
|
47
|
+
await this.configuration.ensureConnections(async () => {
|
|
48
48
|
for (const migration of files) {
|
|
49
49
|
await this.runMigrationFile({
|
|
50
50
|
migration,
|
|
@@ -90,7 +90,7 @@ export default class VelociousDatabaseMigrator {
|
|
|
90
90
|
.filter((migration) => Boolean(migration))
|
|
91
91
|
.sort((migration1, migration2) => migration1.date - migration2.date)
|
|
92
92
|
|
|
93
|
-
await this.configuration.
|
|
93
|
+
await this.configuration.ensureConnections(async () => {
|
|
94
94
|
for (const migration of files) {
|
|
95
95
|
await this.runMigrationFile({
|
|
96
96
|
migration,
|
|
@@ -120,8 +120,7 @@ export default class VelociousDatabaseMigrator {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
async migrationsTableExist(db) {
|
|
123
|
-
const
|
|
124
|
-
const schemaTable = tables.find((table) => table.getName() == "schema_migrations")
|
|
123
|
+
const schemaTable = await db.getTableByName("schema_migrations", {throwError: false})
|
|
125
124
|
|
|
126
125
|
if (!schemaTable) return false
|
|
127
126
|
|
|
@@ -166,9 +165,30 @@ export default class VelociousDatabaseMigrator {
|
|
|
166
165
|
const db = dbs[dbIdentifier]
|
|
167
166
|
|
|
168
167
|
await db.withDisabledForeignKeys(async () => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
while (true) {
|
|
169
|
+
const errors = []
|
|
170
|
+
let anyTableDropped = false
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
for (const table of await db.getTables()) {
|
|
174
|
+
this.logger.log(`Dropping table ${table.getName()}`)
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
await db.dropTable(table.getName(), {cascade: true})
|
|
178
|
+
anyTableDropped = true
|
|
179
|
+
} catch (error) {
|
|
180
|
+
errors.push(error)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
break
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (errors.length > 0 && anyTableDropped) {
|
|
187
|
+
// Retry
|
|
188
|
+
} else {
|
|
189
|
+
throw errors[0]
|
|
190
|
+
}
|
|
191
|
+
}
|
|
172
192
|
}
|
|
173
193
|
})
|
|
174
194
|
}
|
|
@@ -17,7 +17,16 @@ export default class VelociousDatabaseQueryCreateIndexBase extends QueryBase {
|
|
|
17
17
|
for (const columnIndex in this.columns) {
|
|
18
18
|
if (columnIndex > 0) indexName += "_and_"
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const column = this.columns[columnIndex]
|
|
21
|
+
let columnName
|
|
22
|
+
|
|
23
|
+
if (typeof column == "string") {
|
|
24
|
+
columnName = column
|
|
25
|
+
} else {
|
|
26
|
+
columnName = column.getName()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
indexName += columnName
|
|
21
30
|
}
|
|
22
31
|
|
|
23
32
|
return indexName
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import CreateIndexBase from "./create-index-base.js"
|
|
2
2
|
import * as inflection from "inflection"
|
|
3
3
|
import QueryBase from "./base.js"
|
|
4
|
+
import restArgsError from "../../utils/rest-args-error.js"
|
|
4
5
|
|
|
5
6
|
export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
6
7
|
constructor({driver, ifNotExists, indexInCreateTable = true, tableData}) {
|
|
@@ -48,6 +49,9 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
48
49
|
|
|
49
50
|
if (databaseType == "mssql" && type == "BOOLEAN") {
|
|
50
51
|
type = "BIT"
|
|
52
|
+
} else if (databaseType == "mssql" && type == "UUID") {
|
|
53
|
+
type = "VARCHAR"
|
|
54
|
+
maxlength ||= 36
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
if (databaseType == "sqlite" && column.getAutoIncrement() && column.getPrimaryKey()) {
|
|
@@ -79,7 +83,19 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
79
83
|
}
|
|
80
84
|
|
|
81
85
|
if (typeof column.getDefault() == "function") {
|
|
82
|
-
|
|
86
|
+
const defaultValue = column.getDefault()()
|
|
87
|
+
|
|
88
|
+
sql += ` DEFAULT (`
|
|
89
|
+
|
|
90
|
+
if (databaseType == "pgsql" && defaultValue == "UUID()") {
|
|
91
|
+
sql += "gen_random_uuid()"
|
|
92
|
+
} else if (databaseType == "mssql" && defaultValue == "UUID()") {
|
|
93
|
+
sql += "NEWID()"
|
|
94
|
+
} else {
|
|
95
|
+
sql += defaultValue
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
sql += ")"
|
|
83
99
|
} else if (column.getDefault()) {
|
|
84
100
|
sql += ` DEFAULT ${options.quote(column.getDefault())}`
|
|
85
101
|
}
|
|
@@ -125,6 +141,24 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
125
141
|
|
|
126
142
|
sql += ")"
|
|
127
143
|
}
|
|
144
|
+
|
|
145
|
+
for (const column of tableData.getColumns()) {
|
|
146
|
+
if (!column.getIndex()) continue
|
|
147
|
+
|
|
148
|
+
const indexName = `index_on_${column.getName()}`
|
|
149
|
+
|
|
150
|
+
sql += ","
|
|
151
|
+
|
|
152
|
+
const {unique, ...restIndexArgs} = column.getIndex()
|
|
153
|
+
|
|
154
|
+
restArgsError(restIndexArgs)
|
|
155
|
+
|
|
156
|
+
if (unique) {
|
|
157
|
+
sql += " UNIQUE"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
sql += ` INDEX ${options.quoteIndexName(indexName)} (${options.quoteColumnName(column.getName())})`
|
|
161
|
+
}
|
|
128
162
|
}
|
|
129
163
|
|
|
130
164
|
sql += ")"
|
|
@@ -147,8 +181,28 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
147
181
|
|
|
148
182
|
sqls.push(sql)
|
|
149
183
|
}
|
|
184
|
+
|
|
185
|
+
for (const column of tableData.getColumns()) {
|
|
186
|
+
if (!column.getIndex()) continue
|
|
187
|
+
|
|
188
|
+
const indexName = `index_on_${column.getName()}`
|
|
189
|
+
const {unique, ...restIndexArgs} = column.getIndex()
|
|
190
|
+
|
|
191
|
+
restArgsError(restIndexArgs)
|
|
192
|
+
|
|
193
|
+
const createIndexArgs = {
|
|
194
|
+
columns: [column.getName()],
|
|
195
|
+
driver: this.getDriver(),
|
|
196
|
+
name: indexName,
|
|
197
|
+
tableName: tableData.getName(),
|
|
198
|
+
unique
|
|
199
|
+
}
|
|
200
|
+
const sql = new CreateIndexBase(createIndexArgs).toSql()
|
|
201
|
+
|
|
202
|
+
sqls.push(sql)
|
|
203
|
+
}
|
|
150
204
|
}
|
|
151
205
|
|
|
152
|
-
return
|
|
206
|
+
return sqls
|
|
153
207
|
}
|
|
154
208
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import {digs} from "diggerize"
|
|
1
2
|
import QueryBase from "./base.js"
|
|
2
3
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
3
4
|
|
|
4
5
|
export default class VelociousDatabaseQueryDropTableBase extends QueryBase {
|
|
5
|
-
constructor({driver, ifExists, options, tableName, ...restArgs}) {
|
|
6
|
+
constructor({cascade, driver, ifExists, options, tableName, ...restArgs}) {
|
|
6
7
|
super({driver, options})
|
|
7
8
|
|
|
8
9
|
restArgsError(restArgs)
|
|
9
10
|
|
|
11
|
+
this.cascade = cascade
|
|
10
12
|
this.ifExists = ifExists
|
|
11
13
|
this.tableName = tableName
|
|
12
14
|
}
|
|
@@ -14,7 +16,7 @@ export default class VelociousDatabaseQueryDropTableBase extends QueryBase {
|
|
|
14
16
|
toSql() {
|
|
15
17
|
const databaseType = this.getDatabaseType()
|
|
16
18
|
const options = this.getOptions()
|
|
17
|
-
const {ifExists, tableName} = this
|
|
19
|
+
const {cascade, ifExists, tableName} = digs(this, "cascade", "ifExists", "tableName")
|
|
18
20
|
const sqls = []
|
|
19
21
|
let sql = ""
|
|
20
22
|
|
|
@@ -28,6 +30,10 @@ export default class VelociousDatabaseQueryDropTableBase extends QueryBase {
|
|
|
28
30
|
|
|
29
31
|
sql += ` ${options.quoteTableName(tableName)}`
|
|
30
32
|
|
|
33
|
+
if (cascade && databaseType == "pgsql") {
|
|
34
|
+
sql += " cascade"
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
if (databaseType == "mssql" && ifExists) {
|
|
32
38
|
sql += " END"
|
|
33
39
|
}
|