velocious 1.0.45 → 1.0.47
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/package.json +2 -3
- package/spec/cli/commands/db/migrate-spec.js +12 -6
- package/spec/dummy/src/database/migrations/20250915085450-change-authentication-tokens-user-id-nullable.js +11 -0
- package/src/cli/base-command.js +2 -1
- package/src/cli/commands/test.js +2 -0
- package/src/cli/index.js +1 -1
- package/src/configuration.js +2 -3
- package/src/database/drivers/base-column.js +29 -0
- package/src/database/drivers/base-table.js +15 -0
- package/src/database/drivers/mssql/column.js +22 -0
- package/src/database/drivers/mssql/index.js +9 -1
- package/src/database/drivers/mssql/sql/alter-table.js +4 -0
- package/src/database/drivers/mssql/table.js +1 -1
- package/src/database/drivers/mysql/column.js +34 -1
- package/src/database/drivers/mysql/index.js +9 -1
- package/src/database/drivers/mysql/sql/alter-table.js +4 -0
- package/src/database/drivers/pgsql/column.js +22 -0
- package/src/database/drivers/pgsql/index.js +10 -2
- package/src/database/drivers/pgsql/sql/alter-table.js +4 -0
- package/src/database/drivers/sqlite/base.js +5 -5
- package/src/database/drivers/sqlite/column.js +28 -36
- package/src/database/drivers/sqlite/columns-index.js +12 -0
- package/src/database/drivers/sqlite/index.js +1 -1
- package/src/database/drivers/sqlite/query.js +1 -2
- package/src/database/drivers/sqlite/sql/alter-table.js +72 -1
- package/src/database/drivers/sqlite/table.js +38 -0
- package/src/database/migration/index.js +11 -4
- package/src/database/query/alter-table-base.js +27 -7
- package/src/database/query/create-table-base.js +9 -82
- package/src/database/record/index.js +14 -3
- package/src/database/table-data/index.js +138 -34
- package/src/http-server/worker-handler/index.js +1 -0
- package/src/http-server/worker-handler/worker-thread.js +3 -2
- package/spec/support/jasmine.json +0 -12
package/package.json
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
"velocious": "bin/velocious.js"
|
|
4
4
|
},
|
|
5
5
|
"name": "velocious",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.47",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"test": "
|
|
9
|
+
"test": "VELOCIOUS_TEST_DIR=../ cd spec/dummy && npx velocious test",
|
|
10
10
|
"velocious": "asd"
|
|
11
11
|
},
|
|
12
12
|
"type": "module",
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"description": "",
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"awaitery": "^1.0.1",
|
|
26
|
-
"jasmine": "^5.0.2",
|
|
27
26
|
"mssql": "^11.0.1",
|
|
28
27
|
"mysql": "^2.18.1",
|
|
29
28
|
"node-fetch": "^3.3.1",
|
|
@@ -43,9 +43,9 @@ describe("Cli - Commands - db:migrate", () => {
|
|
|
43
43
|
// It creates unique indexes
|
|
44
44
|
const authenticationTokensTable = await dbs.default.getTableByName("authentication_tokens")
|
|
45
45
|
const tokenColumn = await authenticationTokensTable.getColumnByName("token")
|
|
46
|
-
const tokenIndex = await tokenColumn.getIndexByName("
|
|
46
|
+
const tokenIndex = await tokenColumn.getIndexByName("index_on_authentication_tokens_token")
|
|
47
47
|
|
|
48
|
-
expect(tokenIndex.getName()).toEqual("
|
|
48
|
+
expect(tokenIndex.getName()).toEqual("index_on_authentication_tokens_token")
|
|
49
49
|
expect(tokenIndex.isPrimaryKey()).toBeFalse()
|
|
50
50
|
expect(tokenIndex.isUnique()).toBeTrue()
|
|
51
51
|
|
|
@@ -64,8 +64,6 @@ describe("Cli - Commands - db:migrate", () => {
|
|
|
64
64
|
}
|
|
65
65
|
})
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
67
|
expect(projectForeignKey.getTableName()).toEqual("tasks")
|
|
70
68
|
expect(projectForeignKey.getColumnName()).toEqual("project_id")
|
|
71
69
|
expect(projectForeignKey.getReferencedTableName()).toEqual("projects")
|
|
@@ -84,7 +82,15 @@ describe("Cli - Commands - db:migrate", () => {
|
|
|
84
82
|
]
|
|
85
83
|
)
|
|
86
84
|
|
|
87
|
-
expect(uniqunize(defaultSchemaMigrations.sort())).toEqual([
|
|
85
|
+
expect(uniqunize(defaultSchemaMigrations.sort())).toEqual([
|
|
86
|
+
"20230728075328",
|
|
87
|
+
"20230728075329",
|
|
88
|
+
"20250605133926",
|
|
89
|
+
"20250903112845",
|
|
90
|
+
"20250912183605",
|
|
91
|
+
"20250912183606",
|
|
92
|
+
"20250915085450"
|
|
93
|
+
])
|
|
88
94
|
} else {
|
|
89
95
|
expect(tablesResult.sort()).toEqual(
|
|
90
96
|
[
|
|
@@ -99,7 +105,7 @@ describe("Cli - Commands - db:migrate", () => {
|
|
|
99
105
|
]
|
|
100
106
|
)
|
|
101
107
|
|
|
102
|
-
expect(defaultSchemaMigrations.sort()).toEqual(["20230728075328", "20230728075329", "20250605133926", "20250903112845", "20250912183605", "20250912183606"])
|
|
108
|
+
expect(defaultSchemaMigrations.sort()).toEqual(["20230728075328", "20230728075329", "20250605133926", "20250903112845", "20250912183605", "20250912183606", "20250915085450"])
|
|
103
109
|
}
|
|
104
110
|
})
|
|
105
111
|
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Migration from "../../../../../src/database/migration/index.js"
|
|
2
|
+
|
|
3
|
+
export default class ChangeAuthenticationTokensUserIdNullable extends Migration {
|
|
4
|
+
async up() {
|
|
5
|
+
await this.changeColumnNull("authentication_tokens", "user_id", true)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async down() {
|
|
9
|
+
await this.changeColumnNull("authentication_tokens", "user_id", false)
|
|
10
|
+
}
|
|
11
|
+
}
|
package/src/cli/base-command.js
CHANGED
|
@@ -7,5 +7,6 @@ export default class VelociousCliBaseCommand {
|
|
|
7
7
|
this.processArgs = args.processArgs
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
directory
|
|
10
|
+
directory() { return digg(this, "configuration").getDirectory() }
|
|
11
|
+
getConfiguration() { return this.configuration }
|
|
11
12
|
}
|
package/src/cli/commands/test.js
CHANGED
|
@@ -4,6 +4,8 @@ import TestRunner from "../../testing/test-runner.js"
|
|
|
4
4
|
|
|
5
5
|
export default class VelociousCliCommandsTest extends BaseCommand {
|
|
6
6
|
async execute() {
|
|
7
|
+
this.getConfiguration().setEnvironment("test")
|
|
8
|
+
|
|
7
9
|
const directory = process.env.VELOCIOUS_TEST_DIR || this.directory()
|
|
8
10
|
const testFilesFinder = new TestFilesFinder({directory, processArgs: this.processArgs})
|
|
9
11
|
const testFiles = await testFilesFinder.findTestFiles()
|
package/src/cli/index.js
CHANGED
package/src/configuration.js
CHANGED
|
@@ -78,11 +78,10 @@ export default class VelociousConfiguration {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
getEnvironment() { return digg(this, "_environment") }
|
|
81
|
+
setEnvironment(newEnvironment) { this._environment = newEnvironment }
|
|
81
82
|
|
|
82
83
|
getLocaleFallbacks = () => this.localeFallbacks
|
|
83
|
-
setLocaleFallbacks(newLocaleFallbacks) {
|
|
84
|
-
this.localeFallbacks = newLocaleFallbacks
|
|
85
|
-
}
|
|
84
|
+
setLocaleFallbacks(newLocaleFallbacks) { this.localeFallbacks = newLocaleFallbacks }
|
|
86
85
|
|
|
87
86
|
getLocale() {
|
|
88
87
|
if (typeof this.locale == "function") {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import TableData, {TableColumn} from "../table-data/index.js"
|
|
2
|
+
|
|
1
3
|
export default class VelociousDatabaseDriversBaseColumn {
|
|
2
4
|
async getIndexByName(indexName) {
|
|
3
5
|
const indexes = await this.getIndexes()
|
|
@@ -6,6 +8,23 @@ export default class VelociousDatabaseDriversBaseColumn {
|
|
|
6
8
|
return index
|
|
7
9
|
}
|
|
8
10
|
|
|
11
|
+
async changeNullable(nullable) {
|
|
12
|
+
const tableData = new TableData(this.getTable().getName())
|
|
13
|
+
const column = this.getTableDataColumn()
|
|
14
|
+
|
|
15
|
+
column.setNull(nullable)
|
|
16
|
+
|
|
17
|
+
tableData.addColumn(column)
|
|
18
|
+
|
|
19
|
+
const sqls = await this.getDriver().alterTableSql(tableData)
|
|
20
|
+
|
|
21
|
+
console.log({sqls})
|
|
22
|
+
|
|
23
|
+
for (const sql of sqls) {
|
|
24
|
+
await this.getDriver().query(sql)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
9
28
|
getDriver() {
|
|
10
29
|
return this.getTable().getDriver()
|
|
11
30
|
}
|
|
@@ -19,4 +38,14 @@ export default class VelociousDatabaseDriversBaseColumn {
|
|
|
19
38
|
|
|
20
39
|
return this.table
|
|
21
40
|
}
|
|
41
|
+
|
|
42
|
+
getTableDataColumn() {
|
|
43
|
+
return new TableColumn(this.getName(), {
|
|
44
|
+
default: this.getDefault(),
|
|
45
|
+
isNewColumn: false,
|
|
46
|
+
maxLength: this.getMaxLength(),
|
|
47
|
+
null: this.getNull(),
|
|
48
|
+
type: this.getType()
|
|
49
|
+
})
|
|
50
|
+
}
|
|
22
51
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {digg} from "diggerize"
|
|
2
|
+
import TableData from "../table-data/index.js"
|
|
2
3
|
|
|
3
4
|
export default class VelociousDatabaseDriversBaseTable {
|
|
4
5
|
async getColumnByName(columnName) {
|
|
@@ -18,6 +19,20 @@ export default class VelociousDatabaseDriversBaseTable {
|
|
|
18
19
|
return this.getDriver().options()
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
async getTableData() {
|
|
23
|
+
const tableData = new TableData(this.getName())
|
|
24
|
+
|
|
25
|
+
for (const column of await this.getColumns()) {
|
|
26
|
+
tableData.addColumn(column.getTableDataColumn())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for (const index of await this.getIndexes()) {
|
|
30
|
+
tableData.addIndex(index.getTableDataIndex())
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return tableData
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
async rowsCount() {
|
|
22
37
|
const result = await this.getDriver().query(`SELECT COUNT(*) AS count FROM ${this.getOptions().quoteTableName(this.getName())}`)
|
|
23
38
|
|
|
@@ -45,7 +45,29 @@ export default class VelociousDatabaseDriversMssqlColumn extends BaseColumn {
|
|
|
45
45
|
return indexes
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
getDefault() {
|
|
49
|
+
return digg(this, "data", "COLUMN_DEFAULT")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getMaxLength() {
|
|
53
|
+
return digg(this, "data", "CHARACTER_MAXIMUM_LENGTH")
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
getName() {
|
|
49
57
|
return digg(this, "data", "COLUMN_NAME")
|
|
50
58
|
}
|
|
59
|
+
|
|
60
|
+
getNull() {
|
|
61
|
+
const nullValue = digg(this, "data", "IS_NULLABLE")
|
|
62
|
+
|
|
63
|
+
if (nullValue == "NO") {
|
|
64
|
+
return false
|
|
65
|
+
} else {
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getType() {
|
|
71
|
+
return digg(this, "data", "DATA_TYPE")
|
|
72
|
+
}
|
|
51
73
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import AlterTable from "./sql/alter-table.js"
|
|
1
2
|
import Base from "../base.js"
|
|
2
3
|
import CreateDatabase from "./sql/create-database.js"
|
|
3
4
|
import CreateIndex from "./sql/create-index.js"
|
|
@@ -32,6 +33,13 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
32
33
|
this.connection = undefined
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
async alterTableSql(tableData) {
|
|
37
|
+
const alterArgs = {tableData, driver: this}
|
|
38
|
+
const alterTable = new AlterTable(alterArgs)
|
|
39
|
+
|
|
40
|
+
return await alterTable.toSqls()
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
createDatabaseSql(databaseName, args) {
|
|
36
44
|
const createArgs = Object.assign({databaseName, driver: this}, args)
|
|
37
45
|
const createDatabase = new CreateDatabase(createArgs)
|
|
@@ -47,7 +55,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
createTableSql(tableData) {
|
|
50
|
-
const createArgs =
|
|
58
|
+
const createArgs = {tableData, driver: this, indexInCreateTable: false}
|
|
51
59
|
const createTable = new CreateTable(createArgs)
|
|
52
60
|
|
|
53
61
|
return createTable.toSql()
|
|
@@ -11,7 +11,7 @@ export default class VelociousDatabaseDriversMssqlTable extends BaseTable {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async getColumns() {
|
|
14
|
-
const result = await this.driver.query(`SELECT
|
|
14
|
+
const result = await this.driver.query(`SELECT * FROM [INFORMATION_SCHEMA].[COLUMNS] WHERE [TABLE_NAME] = ${this.driver.quote(this.getName())}`)
|
|
15
15
|
const columns = []
|
|
16
16
|
|
|
17
17
|
for (const data of result) {
|
|
@@ -49,5 +49,38 @@ export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
|
|
|
49
49
|
return indexes
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
getDefault() { return digg(this, "data", "Default") }
|
|
53
|
+
|
|
54
|
+
getMaxLength() {
|
|
55
|
+
const type = digg(this, "data", "Type")
|
|
56
|
+
const match = type.match(/\((\d+)\)$/)
|
|
57
|
+
|
|
58
|
+
if (match) {
|
|
59
|
+
const maxLength = parseInt(match[1])
|
|
60
|
+
|
|
61
|
+
return maxLength
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getName() { return digg(this, "data", "Field") }
|
|
66
|
+
|
|
67
|
+
getNull() {
|
|
68
|
+
const nullValue = digg(this, "data", "Null")
|
|
69
|
+
|
|
70
|
+
if (nullValue == "NO") {
|
|
71
|
+
return false
|
|
72
|
+
} else if (nullValue == "YES") {
|
|
73
|
+
return true
|
|
74
|
+
} else {
|
|
75
|
+
throw new Error(`Unknown null value: ${nullValue}`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getType() {
|
|
80
|
+
const type = digg(this, "data", "Type")
|
|
81
|
+
const match = type.match(/^(.+)\((\d+)\)$/)
|
|
82
|
+
const columnType = match[1]
|
|
83
|
+
|
|
84
|
+
return columnType
|
|
85
|
+
}
|
|
53
86
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import AlterTable from "./sql/alter-table.js"
|
|
1
2
|
import Base from "../base.js"
|
|
2
3
|
import connectConnection from "./connect-connection.js"
|
|
3
4
|
import CreateDatabase from "./sql/create-database.js"
|
|
@@ -41,6 +42,13 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
41
42
|
return connectArgs
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
async alterTableSql(tableData) {
|
|
46
|
+
const alterArgs = {tableData, driver: this}
|
|
47
|
+
const alterTable = new AlterTable(alterArgs)
|
|
48
|
+
|
|
49
|
+
return await alterTable.toSqls()
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
createDatabaseSql(databaseName, args) {
|
|
45
53
|
const createArgs = Object.assign({databaseName, driver: this}, args)
|
|
46
54
|
const createDatabase = new CreateDatabase(createArgs)
|
|
@@ -56,7 +64,7 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
createTableSql(tableData) {
|
|
59
|
-
const createArgs =
|
|
67
|
+
const createArgs = {tableData, driver: this}
|
|
60
68
|
const createTable = new CreateTable(createArgs)
|
|
61
69
|
|
|
62
70
|
return createTable.toSql()
|
|
@@ -39,7 +39,29 @@ export default class VelociousDatabaseDriversPgsqlColumn extends BaseColumn {
|
|
|
39
39
|
return indexes
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
getDefault() {
|
|
43
|
+
return digg(this, "data", "column_default")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getMaxLength() {
|
|
47
|
+
return digg(this, "data", "character_maximum_length")
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
getName() {
|
|
43
51
|
return digg(this, "data", "column_name")
|
|
44
52
|
}
|
|
53
|
+
|
|
54
|
+
getNull() {
|
|
55
|
+
const nullValue = digg(this, "data", "is_nullable")
|
|
56
|
+
|
|
57
|
+
if (nullValue == "NO") {
|
|
58
|
+
return false
|
|
59
|
+
} else {
|
|
60
|
+
return true
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getType() {
|
|
65
|
+
return digg(this, "data", "data_type")
|
|
66
|
+
}
|
|
45
67
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import AlterTable from "./sql/alter-table.js"
|
|
1
2
|
import Base from "../base.js"
|
|
2
|
-
import {Client
|
|
3
|
+
import {Client} from "pg"
|
|
3
4
|
import CreateDatabase from "./sql/create-database.js"
|
|
4
5
|
import CreateIndex from "./sql/create-index.js"
|
|
5
6
|
import CreateTable from "./sql/create-table.js"
|
|
@@ -49,6 +50,13 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
49
50
|
this.connection = undefined
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
async alterTableSql(tableData) {
|
|
54
|
+
const alterArgs = {tableData, driver: this}
|
|
55
|
+
const alterTable = new AlterTable(alterArgs)
|
|
56
|
+
|
|
57
|
+
return await alterTable.toSqls()
|
|
58
|
+
}
|
|
59
|
+
|
|
52
60
|
createDatabaseSql(databaseName, args) {
|
|
53
61
|
const createArgs = Object.assign({databaseName, driver: this}, args)
|
|
54
62
|
const createDatabase = new CreateDatabase(createArgs)
|
|
@@ -64,7 +72,7 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
createTableSql(tableData) {
|
|
67
|
-
const createArgs =
|
|
75
|
+
const createArgs = {tableData, driver: this, indexInCreateTable: false}
|
|
68
76
|
const createTable = new CreateTable(createArgs)
|
|
69
77
|
|
|
70
78
|
return createTable.toSql()
|
|
@@ -14,11 +14,11 @@ import Table from "./table.js"
|
|
|
14
14
|
import Update from "./sql/update.js"
|
|
15
15
|
|
|
16
16
|
export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
17
|
-
alterTableSql(
|
|
18
|
-
const
|
|
19
|
-
const alterTable = new AlterTable(
|
|
17
|
+
async alterTableSql(tableData) {
|
|
18
|
+
const alterArgs = {driver: this, tableData}
|
|
19
|
+
const alterTable = new AlterTable(alterArgs)
|
|
20
20
|
|
|
21
|
-
return alterTable.toSqls()
|
|
21
|
+
return await alterTable.toSqls()
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
createIndexSql(indexData) {
|
|
@@ -29,7 +29,7 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
createTableSql(tableData) {
|
|
32
|
-
const createArgs =
|
|
32
|
+
const createArgs = {tableData, driver: this, indexInCreateTable: false}
|
|
33
33
|
const createTable = new CreateTable(createArgs)
|
|
34
34
|
|
|
35
35
|
return createTable.toSql()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import {digg} from "diggerize"
|
|
1
2
|
import BaseColumn from "../base-column.js"
|
|
2
|
-
import ColumnsIndex from "./columns-index.js"
|
|
3
3
|
|
|
4
4
|
export default class VelociousDatabaseDriversSqliteColumn extends BaseColumn {
|
|
5
5
|
constructor({column, driver, table}) {
|
|
@@ -10,59 +10,51 @@ export default class VelociousDatabaseDriversSqliteColumn extends BaseColumn {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
async getIndexes() {
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const indexes = []
|
|
13
|
+
const indexes = await this.getTable().getIndexes()
|
|
14
|
+
const indexesForColumn = indexes.filter((index) => index.getColumnNames().includes(this.getName()))
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
}
|
|
16
|
+
return indexesForColumn
|
|
17
|
+
}
|
|
25
18
|
|
|
26
|
-
|
|
19
|
+
getDefault() {
|
|
20
|
+
return digg(this, "column", "dflt_value")
|
|
27
21
|
}
|
|
28
22
|
|
|
23
|
+
getName() {
|
|
24
|
+
const name = digg(this, "column", "name")
|
|
25
|
+
|
|
26
|
+
if (!name) throw new Error("No name given for SQLite column")
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const columnsSQL = columnsSQLMatch[1].split(",")
|
|
33
|
-
const columnNames = []
|
|
28
|
+
return name
|
|
29
|
+
}
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
getMaxLength() {
|
|
32
|
+
const columnType = digg(this, "column", "type")
|
|
33
|
+
const match = columnType.match(/(.*)\((\d+)\)$/)
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
} else if (matchQuotes) {
|
|
42
|
-
columnNames.push(matchQuotes[1])
|
|
43
|
-
} else{
|
|
44
|
-
throw new Error(`Couldn't parse column part: ${column}`)
|
|
45
|
-
}
|
|
35
|
+
if (match) {
|
|
36
|
+
return parseInt(match[2])
|
|
46
37
|
}
|
|
47
|
-
|
|
48
|
-
return columnNames
|
|
49
38
|
}
|
|
50
39
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
throw new Error("No name given for SQLite column")
|
|
54
|
-
}
|
|
40
|
+
getNull() {
|
|
41
|
+
const notNullValue = digg(this, "column", "notnull")
|
|
55
42
|
|
|
56
|
-
|
|
43
|
+
if (notNullValue === 1) {
|
|
44
|
+
return false
|
|
45
|
+
} else {
|
|
46
|
+
return true
|
|
47
|
+
}
|
|
57
48
|
}
|
|
58
49
|
|
|
59
50
|
getType() {
|
|
60
|
-
const
|
|
51
|
+
const columnType = digg(this, "column", "type")
|
|
52
|
+
const match = columnType.match(/(.*)\((\d+)\)$/)
|
|
61
53
|
|
|
62
54
|
if (match) {
|
|
63
55
|
return match[1].toLowerCase()
|
|
64
56
|
}
|
|
65
57
|
|
|
66
|
-
return
|
|
58
|
+
return columnType.toLowerCase()
|
|
67
59
|
}
|
|
68
60
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BaseColumnsIndex from "../base-columns-index.js"
|
|
2
2
|
import {digg} from "diggerize"
|
|
3
|
+
import {TableIndex} from "../../table-data/index.js"
|
|
3
4
|
|
|
4
5
|
export default class VelociousDatabaseDriversSqliteColumn extends BaseColumnsIndex {
|
|
5
6
|
constructor(table, data) {
|
|
@@ -8,10 +9,21 @@ export default class VelociousDatabaseDriversSqliteColumn extends BaseColumnsInd
|
|
|
8
9
|
this.table = table
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
getColumnNames() {
|
|
13
|
+
return digg(this, "data", "columnNames")
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
getName() {
|
|
12
17
|
return digg(this, "data", "name")
|
|
13
18
|
}
|
|
14
19
|
|
|
20
|
+
getTableDataIndex() {
|
|
21
|
+
return new TableIndex(this.getColumnNames(), {
|
|
22
|
+
name: this.getName(),
|
|
23
|
+
unique: this.isUnique()
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
15
27
|
isPrimaryKey() {
|
|
16
28
|
return false
|
|
17
29
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export default async function query(connection, sql) {
|
|
2
|
-
const rows = []
|
|
3
2
|
let result
|
|
4
3
|
|
|
5
4
|
try {
|
|
@@ -13,7 +12,7 @@ export default async function query(connection, sql) {
|
|
|
13
12
|
|
|
14
13
|
error.message += `\n\n${sqlInErrorMessage}`
|
|
15
14
|
|
|
16
|
-
throw error
|
|
15
|
+
throw new Error(error.message)
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
return result
|
|
@@ -1,4 +1,75 @@
|
|
|
1
1
|
import AlterTableBase from "../../../query/alter-table-base.js"
|
|
2
|
+
import CreateIndexBase from "../../../query/create-index-base.js"
|
|
3
|
+
import {digs} from "diggerize"
|
|
4
|
+
import restArgsError from "../../../../utils/rest-args-error.js"
|
|
5
|
+
import TableData from "../../../table-data/index.js"
|
|
2
6
|
|
|
3
|
-
export default class
|
|
7
|
+
export default class VelociousDatabaseConnectionDriversSqliteSqlAlterTable extends AlterTableBase {
|
|
8
|
+
constructor({driver, tableData, ...restArgs}) {
|
|
9
|
+
restArgsError(restArgs)
|
|
10
|
+
|
|
11
|
+
if (!(tableData instanceof TableData)) throw new Error("Invalid table data was given")
|
|
12
|
+
|
|
13
|
+
super({driver, tableData})
|
|
14
|
+
this.tableData = tableData
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async toSqls() {
|
|
18
|
+
const {tableData} = digs(this, "tableData")
|
|
19
|
+
const table = await this.getDriver().getTableByName(tableData.getName())
|
|
20
|
+
const currentTableData = await table.getTableData()
|
|
21
|
+
const options = this.getOptions()
|
|
22
|
+
const tableName = tableData.getName()
|
|
23
|
+
const tempTableName = `${tableData.getName()}AlterTableTemp`
|
|
24
|
+
const oldColumnNames = currentTableData.getColumns().filter((column) => !column.isNewColumn()).map((column) => column.getName())
|
|
25
|
+
const oldColumnsSQL = oldColumnNames.map((name) => options.quoteColumnName(name)).join(", ")
|
|
26
|
+
|
|
27
|
+
tableData.setName(tempTableName)
|
|
28
|
+
|
|
29
|
+
const newTableData = new TableData(tempTableName)
|
|
30
|
+
|
|
31
|
+
for (const tableDataColumn of currentTableData.getColumns()) {
|
|
32
|
+
const newTableDataColumn = newTableData.getColumns().find((newTableDataColumn) => newTableDataColumn.getName() == tableDataColumn.getName())
|
|
33
|
+
|
|
34
|
+
newTableData.addColumn(newTableDataColumn || tableDataColumn)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const createNewTableSQL = this.getDriver().createTableSql(newTableData)
|
|
38
|
+
const insertSQL = `INSERT INTO ${options.quoteTableName(tempTableName)} (${oldColumnsSQL}) SELECT ${oldColumnsSQL} FROM ${options.quoteTableName(tableName)}`
|
|
39
|
+
const dropTableSQL = `DROP TABLE ${options.quoteTableName(tableName)}`
|
|
40
|
+
const renameTableSQL = `ALTER TABLE ${options.quoteTableName(tempTableName)} RENAME TO ${options.quoteTableName(tableName)}`
|
|
41
|
+
const sqls = []
|
|
42
|
+
|
|
43
|
+
for (const sql of createNewTableSQL) {
|
|
44
|
+
sqls.push(sql)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
sqls.push(insertSQL)
|
|
48
|
+
sqls.push(dropTableSQL)
|
|
49
|
+
sqls.push(renameTableSQL)
|
|
50
|
+
|
|
51
|
+
for (const tableDataIndex of currentTableData.getIndexes()) {
|
|
52
|
+
const newTableDataIndex = newTableData.getIndexes().find((newTableDataIndex) => newTableDataIndex.getName() == tableDataIndex.getName())
|
|
53
|
+
const actualTableIndex = newTableDataIndex || tableDataIndex
|
|
54
|
+
|
|
55
|
+
newTableData.addIndex(actualTableIndex)
|
|
56
|
+
|
|
57
|
+
console.log({actualTableIndex})
|
|
58
|
+
|
|
59
|
+
const createIndexArgs = {
|
|
60
|
+
columns: actualTableIndex.getColumns(),
|
|
61
|
+
driver: this.getDriver(),
|
|
62
|
+
name: actualTableIndex.getName(),
|
|
63
|
+
tableName,
|
|
64
|
+
unique: actualTableIndex.getUnique()
|
|
65
|
+
}
|
|
66
|
+
const sql = new CreateIndexBase(createIndexArgs).toSql()
|
|
67
|
+
|
|
68
|
+
sqls.push(sql)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log({sqls})
|
|
72
|
+
|
|
73
|
+
return sqls
|
|
74
|
+
}
|
|
4
75
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import BaseTable from "../base-table.js"
|
|
2
2
|
import Column from "./column.js"
|
|
3
|
+
import ColumnsIndex from "./columns-index.js"
|
|
3
4
|
import ForeignKey from "./foreign-key.js"
|
|
4
5
|
|
|
5
6
|
export default class VelociousDatabaseDriversSqliteTable extends BaseTable {
|
|
@@ -35,6 +36,43 @@ export default class VelociousDatabaseDriversSqliteTable extends BaseTable {
|
|
|
35
36
|
return foreignKeys
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
async getIndexes() {
|
|
40
|
+
const rows = await this.getDriver().query(`PRAGMA index_list(${this.getOptions().quoteTableName(this.getName())})`)
|
|
41
|
+
const indexes = []
|
|
42
|
+
|
|
43
|
+
for (const row of rows) {
|
|
44
|
+
const columnsIndex = new ColumnsIndex(this, row)
|
|
45
|
+
const indexMasterData = await this.getDriver().query(`SELECT * FROM sqlite_master WHERE type = 'index' AND name = ${this.getOptions().quote(columnsIndex.getName())}`)
|
|
46
|
+
|
|
47
|
+
columnsIndex.data.columnNames = this._parseColumnsFromSQL(indexMasterData[0].sql)
|
|
48
|
+
|
|
49
|
+
indexes.push(columnsIndex)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return indexes
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_parseColumnsFromSQL(sql) {
|
|
56
|
+
const columnsSQLMatch = sql.match(/\((.+?)\)/)
|
|
57
|
+
const columnsSQL = columnsSQLMatch[1].split(",")
|
|
58
|
+
const columnNames = []
|
|
59
|
+
|
|
60
|
+
for (const column of columnsSQL) {
|
|
61
|
+
const matchTicks = column.match(/`(.+)`/)
|
|
62
|
+
const matchQuotes = column.match(/"(.+)"/)
|
|
63
|
+
|
|
64
|
+
if (matchTicks) {
|
|
65
|
+
columnNames.push(matchTicks[1])
|
|
66
|
+
} else if (matchQuotes) {
|
|
67
|
+
columnNames.push(matchQuotes[1])
|
|
68
|
+
} else{
|
|
69
|
+
throw new Error(`Couldn't parse column part: ${column}`)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return columnNames
|
|
74
|
+
}
|
|
75
|
+
|
|
38
76
|
getName() {
|
|
39
77
|
if (!this.row.name) {
|
|
40
78
|
throw new Error("No name given for SQLite table")
|
|
@@ -30,11 +30,11 @@ export default class VelociousDatabaseMigration {
|
|
|
30
30
|
|
|
31
31
|
async addColumn(tableName, columnName, columnType, args) {
|
|
32
32
|
const tableColumnArgs = Object.assign({type: columnType}, args)
|
|
33
|
+
const tableData = new TableData(tableName)
|
|
34
|
+
|
|
35
|
+
tableData.addColumn(columnName, tableColumnArgs)
|
|
33
36
|
|
|
34
|
-
const sqls = this._db.alterTableSql(
|
|
35
|
-
columns: [new TableColumn(columnName, tableColumnArgs)],
|
|
36
|
-
tableName
|
|
37
|
-
})
|
|
37
|
+
const sqls = await this._db.alterTableSql(tableData)
|
|
38
38
|
|
|
39
39
|
for (const sql of sqls) {
|
|
40
40
|
await this._db.query(sql)
|
|
@@ -80,6 +80,13 @@ export default class VelociousDatabaseMigration {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
async changeColumnNull(tableName, columnName, nullable) {
|
|
84
|
+
const table = await this.getDriver().getTableByName(tableName)
|
|
85
|
+
const column = await table.getColumnByName(columnName)
|
|
86
|
+
|
|
87
|
+
await column.changeNullable(nullable)
|
|
88
|
+
}
|
|
89
|
+
|
|
83
90
|
async createTable(tableName, arg1, arg2) {
|
|
84
91
|
let args
|
|
85
92
|
let callback
|
|
@@ -1,26 +1,46 @@
|
|
|
1
|
+
import {digs} from "diggerize"
|
|
1
2
|
import QueryBase from "./base.js"
|
|
2
3
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
4
|
+
import TableData from "../table-data/index.js"
|
|
3
5
|
|
|
4
6
|
export default class VelociousDatabaseQueryAlterTableBase extends QueryBase {
|
|
5
|
-
constructor({
|
|
7
|
+
constructor({driver, tableData, ...restArgs}) {
|
|
6
8
|
restArgsError(restArgs)
|
|
7
9
|
|
|
10
|
+
if (!(tableData instanceof TableData)) throw new Error("Invalid table data was given")
|
|
11
|
+
|
|
8
12
|
super({driver})
|
|
9
|
-
this.
|
|
10
|
-
this.tableName = tableName
|
|
13
|
+
this.tableData = tableData
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
toSqls() {
|
|
17
|
+
const databaseType = this.getDriver().getType()
|
|
14
18
|
const sqls = []
|
|
19
|
+
const {tableData} = digs(this, "tableData")
|
|
20
|
+
const options = this.getOptions()
|
|
21
|
+
|
|
22
|
+
let sql = `ALTER TABLE ${options.quoteTableName(tableData.getName())} `
|
|
23
|
+
let columnsCount = 0
|
|
15
24
|
|
|
16
|
-
for (const column of
|
|
17
|
-
|
|
25
|
+
for (const column of tableData.getColumns()) {
|
|
26
|
+
if (columnsCount > 0) sql += ", "
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
if (column.isNewColumn()) {
|
|
29
|
+
sql += "ADD "
|
|
30
|
+
} else {
|
|
31
|
+
if (databaseType == "mssql" || databaseType == "pgsql") {
|
|
32
|
+
sql += "ALTER COLUMN "
|
|
33
|
+
} else {
|
|
34
|
+
sql += "MODIFY "
|
|
35
|
+
}
|
|
36
|
+
}
|
|
20
37
|
|
|
21
|
-
|
|
38
|
+
sql += column.getSQL({driver: this.getDriver(), forAlterTable: true})
|
|
39
|
+
columnsCount++
|
|
22
40
|
}
|
|
23
41
|
|
|
42
|
+
sqls.push(sql)
|
|
43
|
+
|
|
24
44
|
return sqls
|
|
25
45
|
}
|
|
26
46
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import CreateIndexBase from "./create-index-base.js"
|
|
2
|
-
import
|
|
2
|
+
import {digs} from "diggerize"
|
|
3
3
|
import QueryBase from "./base.js"
|
|
4
4
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
5
|
+
import TableData from "../table-data/index.js"
|
|
5
6
|
|
|
6
7
|
export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
7
8
|
constructor({driver, ifNotExists, indexInCreateTable = true, tableData}) {
|
|
9
|
+
if (!(tableData instanceof TableData)) throw new Error("Invalid table data was given")
|
|
10
|
+
|
|
8
11
|
super({driver})
|
|
9
12
|
this.ifNotExists = ifNotExists
|
|
10
13
|
this.indexInCreateTable = indexInCreateTable
|
|
@@ -15,7 +18,7 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
15
18
|
const databaseType = this.getDatabaseType()
|
|
16
19
|
const driver = this.getDriver()
|
|
17
20
|
const options = this.getOptions()
|
|
18
|
-
const {tableData} = this
|
|
21
|
+
const {tableData} = digs(this, "tableData")
|
|
19
22
|
const sqls = []
|
|
20
23
|
const ifNotExists = this.ifNotExists || tableData.getIfNotExists()
|
|
21
24
|
let sql = ""
|
|
@@ -35,86 +38,9 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
35
38
|
for (const column of tableData.getColumns()) {
|
|
36
39
|
columnCount++
|
|
37
40
|
|
|
38
|
-
let maxlength = column.getMaxLength()
|
|
39
|
-
let type = column.getType().toUpperCase()
|
|
40
|
-
|
|
41
|
-
if (type == "DATETIME" && databaseType == "pgsql") {
|
|
42
|
-
type = "TIMESTAMP"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (type == "STRING") {
|
|
46
|
-
type = "VARCHAR"
|
|
47
|
-
maxlength ||= 255
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (databaseType == "mssql" && type == "BOOLEAN") {
|
|
51
|
-
type = "BIT"
|
|
52
|
-
} else if (databaseType == "mssql" && type == "UUID") {
|
|
53
|
-
type = "VARCHAR"
|
|
54
|
-
maxlength ||= 36
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (databaseType == "sqlite" && column.getAutoIncrement() && column.getPrimaryKey()) {
|
|
58
|
-
type = "INTEGER"
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (databaseType == "pgsql" && column.getAutoIncrement() && column.getPrimaryKey()) {
|
|
62
|
-
type = "SERIAL"
|
|
63
|
-
}
|
|
64
|
-
|
|
65
41
|
if (columnCount > 1) sql += ", "
|
|
66
42
|
|
|
67
|
-
sql +=
|
|
68
|
-
|
|
69
|
-
if (maxlength !== undefined) sql += `(${maxlength})`
|
|
70
|
-
|
|
71
|
-
if (column.getAutoIncrement() && driver.shouldSetAutoIncrementWhenPrimaryKey()) {
|
|
72
|
-
if (databaseType == "mssql") {
|
|
73
|
-
sql += " IDENTITY"
|
|
74
|
-
} else if (databaseType == "pgsql") {
|
|
75
|
-
if (column.getAutoIncrement() && column.getPrimaryKey()) {
|
|
76
|
-
// Do nothing
|
|
77
|
-
} else {
|
|
78
|
-
throw new Error("pgsql auto increment must be primary key")
|
|
79
|
-
}
|
|
80
|
-
} else {
|
|
81
|
-
sql += " AUTO_INCREMENT"
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (typeof column.getDefault() == "function") {
|
|
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 += ")"
|
|
99
|
-
} else if (column.getDefault()) {
|
|
100
|
-
sql += ` DEFAULT ${options.quote(column.getDefault())}`
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (column.getPrimaryKey()) sql += " PRIMARY KEY"
|
|
104
|
-
if (column.getNull() === false) sql += " NOT NULL"
|
|
105
|
-
|
|
106
|
-
if (column.getForeignKey()) {
|
|
107
|
-
let foreignKeyTable, foreignKeyColumn
|
|
108
|
-
|
|
109
|
-
if (column.getForeignKey() === true) {
|
|
110
|
-
foreignKeyColumn = "id"
|
|
111
|
-
foreignKeyTable = inflection.pluralize(column.getName().replace(/_id$/, ""))
|
|
112
|
-
} else {
|
|
113
|
-
throw new Error(`Unknown foreign key type given: ${column.getForeignKey()} (${typeof column.getForeignKey()})`)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
sql += ` REFERENCES ${options.quoteTableName(foreignKeyTable)}(${options.quoteColumnName(foreignKeyColumn)})`
|
|
117
|
-
}
|
|
43
|
+
sql += column.getSQL({driver, forAlterTable: false})
|
|
118
44
|
}
|
|
119
45
|
|
|
120
46
|
if (this.indexInCreateTable) {
|
|
@@ -145,7 +71,7 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
145
71
|
for (const column of tableData.getColumns()) {
|
|
146
72
|
if (!column.getIndex()) continue
|
|
147
73
|
|
|
148
|
-
const indexName = `index_on_${column.getName()}`
|
|
74
|
+
const indexName = `index_on_${tableData.getName()}_${column.getName()}`
|
|
149
75
|
|
|
150
76
|
sql += ","
|
|
151
77
|
|
|
@@ -174,6 +100,7 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
174
100
|
const createIndexArgs = {
|
|
175
101
|
columns: index.getColumns(),
|
|
176
102
|
driver: this.getDriver(),
|
|
103
|
+
name: index.getName(),
|
|
177
104
|
tableName: tableData.getName(),
|
|
178
105
|
unique: index.getUnique()
|
|
179
106
|
}
|
|
@@ -185,7 +112,7 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
185
112
|
for (const column of tableData.getColumns()) {
|
|
186
113
|
if (!column.getIndex()) continue
|
|
187
114
|
|
|
188
|
-
const indexName = `index_on_${column.getName()}`
|
|
115
|
+
const indexName = `index_on_${tableData.getName()}_${column.getName()}`
|
|
189
116
|
const {unique, ...restIndexArgs} = column.getIndex()
|
|
190
117
|
|
|
191
118
|
restArgsError(restIndexArgs)
|
|
@@ -204,6 +204,8 @@ class VelociousDatabaseRecord {
|
|
|
204
204
|
this._table = await this.connection().getTableByName(this.tableName())
|
|
205
205
|
this._columns = await this._getTable().getColumns()
|
|
206
206
|
this._columnsAsHash = {}
|
|
207
|
+
this._columnNameToAttributeName = {}
|
|
208
|
+
this._attributeNameToColumnName = {}
|
|
207
209
|
|
|
208
210
|
for (const column of this._columns) {
|
|
209
211
|
this._columnsAsHash[column.getName()] = column
|
|
@@ -212,6 +214,9 @@ class VelociousDatabaseRecord {
|
|
|
212
214
|
const camelizedColumnNameBigFirst = inflection.camelize(column.getName())
|
|
213
215
|
const setterMethodName = `set${camelizedColumnNameBigFirst}`
|
|
214
216
|
|
|
217
|
+
this._attributeNameToColumnName[camelizedColumnName] = column.getName()
|
|
218
|
+
this._columnNameToAttributeName[column.getName()] = camelizedColumnName
|
|
219
|
+
|
|
215
220
|
this.prototype[camelizedColumnName] = function () {
|
|
216
221
|
return this.readAttribute(camelizedColumnName)
|
|
217
222
|
}
|
|
@@ -300,7 +305,11 @@ class VelociousDatabaseRecord {
|
|
|
300
305
|
}
|
|
301
306
|
|
|
302
307
|
_setColumnAttribute(name, newValue) {
|
|
303
|
-
|
|
308
|
+
if (!this.constructor._attributeNameToColumnName) throw new Error("No attribute-to-column mapping. Has record been initialized?")
|
|
309
|
+
|
|
310
|
+
const columnName = this.constructor._attributeNameToColumnName[name]
|
|
311
|
+
|
|
312
|
+
if (!columnName) throw new Error(`Couldn't figure out column name for attribute: ${attributeName}`)
|
|
304
313
|
|
|
305
314
|
if (this._attributes[columnName] != newValue) {
|
|
306
315
|
this._changes[columnName] = newValue
|
|
@@ -767,9 +776,11 @@ class VelociousDatabaseRecord {
|
|
|
767
776
|
}
|
|
768
777
|
|
|
769
778
|
readAttribute(attributeName) {
|
|
770
|
-
const
|
|
779
|
+
const columnName = this.constructor._attributeNameToColumnName[attributeName]
|
|
780
|
+
|
|
781
|
+
if (!columnName) throw new Error(`Couldn't figure out column name for attribute: ${attributeName}`)
|
|
771
782
|
|
|
772
|
-
return this.readColumn(
|
|
783
|
+
return this.readColumn(columnName)
|
|
773
784
|
}
|
|
774
785
|
|
|
775
786
|
readColumn(attributeName) {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import * as inflection from "inflection"
|
|
1
2
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
2
3
|
|
|
3
4
|
class TableColumn {
|
|
4
5
|
constructor(name, args) {
|
|
5
6
|
if (args) {
|
|
6
|
-
const {autoIncrement, default: columnDefault, foreignKey, index, maxLength, name, null: argsNull, primaryKey, type, ...restArgs} = args
|
|
7
|
+
const {autoIncrement, default: columnDefault, foreignKey, index, isNewColumn, maxLength, name, null: argsNull, primaryKey, type, ...restArgs} = args
|
|
8
|
+
|
|
9
|
+
if (Object.keys(args).length == 0) {
|
|
10
|
+
throw new Error("Empty args given")
|
|
11
|
+
}
|
|
7
12
|
|
|
8
13
|
restArgsError(restArgs)
|
|
9
14
|
}
|
|
@@ -12,15 +17,106 @@ class TableColumn {
|
|
|
12
17
|
this.name = name
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
getAutoIncrement
|
|
16
|
-
getDefault
|
|
17
|
-
getForeignKey
|
|
18
|
-
getIndex
|
|
19
|
-
getMaxLength
|
|
20
|
-
getName
|
|
21
|
-
getNull
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
getAutoIncrement() { return this.args?.autoIncrement }
|
|
21
|
+
getDefault() { return this.args?.default }
|
|
22
|
+
getForeignKey() { return this.args?.foreignKey }
|
|
23
|
+
getIndex() { return this.args?.index }
|
|
24
|
+
getMaxLength() { return this.args?.maxLength }
|
|
25
|
+
getName() { return this.name }
|
|
26
|
+
getNull() { return this.args?.null }
|
|
27
|
+
setNull(nullable) { this.args.null = nullable }
|
|
28
|
+
getPrimaryKey() { return this.args?.primaryKey }
|
|
29
|
+
getType() { return this.args?.type }
|
|
30
|
+
isNewColumn() { return this.args?.isNewColumn }
|
|
31
|
+
|
|
32
|
+
getSQL({forAlterTable, driver}) {
|
|
33
|
+
const databaseType = driver.getType()
|
|
34
|
+
const options = driver.options()
|
|
35
|
+
let maxlength = this.getMaxLength()
|
|
36
|
+
let type = this.getType().toUpperCase()
|
|
37
|
+
|
|
38
|
+
if (type == "DATETIME" && databaseType == "pgsql") {
|
|
39
|
+
type = "TIMESTAMP"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (type == "STRING") {
|
|
43
|
+
type = "VARCHAR"
|
|
44
|
+
maxlength ||= 255
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (databaseType == "mssql" && type == "BOOLEAN") {
|
|
48
|
+
type = "BIT"
|
|
49
|
+
} else if (databaseType == "mssql" && type == "UUID") {
|
|
50
|
+
type = "VARCHAR"
|
|
51
|
+
maxlength ||= 36
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (databaseType == "sqlite" && this.getAutoIncrement() && this.getPrimaryKey()) {
|
|
55
|
+
type = "INTEGER"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (databaseType == "pgsql" && this.getAutoIncrement() && this.getPrimaryKey()) {
|
|
59
|
+
type = "SERIAL"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let sql = `${options.quoteColumnName(this.getName())} `
|
|
63
|
+
|
|
64
|
+
if (databaseType == "pgsql" && forAlterTable) sql += "TYPE "
|
|
65
|
+
|
|
66
|
+
sql += type
|
|
67
|
+
|
|
68
|
+
if (maxlength !== undefined && maxlength !== null) sql += `(${maxlength})`
|
|
69
|
+
|
|
70
|
+
if (this.getAutoIncrement() && driver.shouldSetAutoIncrementWhenPrimaryKey()) {
|
|
71
|
+
if (databaseType == "mssql") {
|
|
72
|
+
sql += " IDENTITY"
|
|
73
|
+
} else if (databaseType == "pgsql") {
|
|
74
|
+
if (this.getAutoIncrement() && this.getPrimaryKey()) {
|
|
75
|
+
// Do nothing
|
|
76
|
+
} else {
|
|
77
|
+
throw new Error("pgsql auto increment must be primary key")
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
sql += " AUTO_INCREMENT"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (typeof this.getDefault() == "function") {
|
|
85
|
+
const defaultValue = this.getDefault()()
|
|
86
|
+
|
|
87
|
+
sql += ` DEFAULT (`
|
|
88
|
+
|
|
89
|
+
if (databaseType == "pgsql" && defaultValue == "UUID()") {
|
|
90
|
+
sql += "gen_random_uuid()"
|
|
91
|
+
} else if (databaseType == "mssql" && defaultValue == "UUID()") {
|
|
92
|
+
sql += "NEWID()"
|
|
93
|
+
} else {
|
|
94
|
+
sql += defaultValue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
sql += ")"
|
|
98
|
+
} else if (this.getDefault()) {
|
|
99
|
+
sql += ` DEFAULT ${options.quote(this.getDefault())}`
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (this.getPrimaryKey()) sql += " PRIMARY KEY"
|
|
103
|
+
if (this.getNull() === false) sql += " NOT NULL"
|
|
104
|
+
|
|
105
|
+
if (this.getForeignKey()) {
|
|
106
|
+
let foreignKeyTable, foreignKeyColumn
|
|
107
|
+
|
|
108
|
+
if (this.getForeignKey() === true) {
|
|
109
|
+
foreignKeyColumn = "id"
|
|
110
|
+
foreignKeyTable = inflection.pluralize(this.getName().replace(/_id$/, ""))
|
|
111
|
+
} else {
|
|
112
|
+
throw new Error(`Unknown foreign key type given: ${this.getForeignKey()} (${typeof this.getForeignKey()})`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
sql += ` REFERENCES ${options.quoteTableName(foreignKeyTable)}(${options.quoteColumnName(foreignKeyColumn)})`
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return sql
|
|
119
|
+
}
|
|
24
120
|
}
|
|
25
121
|
|
|
26
122
|
class TableIndex {
|
|
@@ -35,9 +131,9 @@ class TableIndex {
|
|
|
35
131
|
this.columns = columns
|
|
36
132
|
}
|
|
37
133
|
|
|
38
|
-
getColumns
|
|
39
|
-
getName
|
|
40
|
-
getUnique
|
|
134
|
+
getColumns() { return this.columns }
|
|
135
|
+
getName() { return this.args.name }
|
|
136
|
+
getUnique() { return Boolean(this.args.unique) }
|
|
41
137
|
}
|
|
42
138
|
|
|
43
139
|
class TableReference {
|
|
@@ -47,7 +143,7 @@ class TableReference {
|
|
|
47
143
|
}
|
|
48
144
|
}
|
|
49
145
|
|
|
50
|
-
export {TableColumn}
|
|
146
|
+
export {TableColumn, TableIndex}
|
|
51
147
|
|
|
52
148
|
export default class TableData {
|
|
53
149
|
_columns = []
|
|
@@ -55,34 +151,42 @@ export default class TableData {
|
|
|
55
151
|
_references = []
|
|
56
152
|
|
|
57
153
|
constructor(name, args = {}) {
|
|
154
|
+
if (!name) throw new Error(`Invalid table name: ${name}`)
|
|
155
|
+
|
|
58
156
|
this.args = args
|
|
59
157
|
this._name = name
|
|
60
158
|
}
|
|
61
159
|
|
|
62
|
-
|
|
63
|
-
|
|
160
|
+
addColumn(name, args = {}) {
|
|
161
|
+
if (name instanceof TableColumn) {
|
|
162
|
+
this._columns.push(name)
|
|
163
|
+
} else {
|
|
164
|
+
const column = new TableColumn(name, args)
|
|
64
165
|
|
|
65
|
-
|
|
166
|
+
this._columns.push(column)
|
|
167
|
+
}
|
|
66
168
|
}
|
|
67
169
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
170
|
+
addIndex(index) { this._indexes.push(index) }
|
|
171
|
+
getColumns() { return this._columns }
|
|
172
|
+
getName() { return this._name }
|
|
173
|
+
setName(newName) { this._name = newName }
|
|
174
|
+
getIfNotExists() { return this.args.ifNotExists }
|
|
175
|
+
getIndexes() { return this._indexes }
|
|
176
|
+
getReferences() { return this._references }
|
|
177
|
+
|
|
178
|
+
bigint(name, args = {}) { this.addColumn(name, Object.assign({isNewColumn: true, type: "bigint"}, args)) }
|
|
179
|
+
blob(name, args = {}) { this.addColumn(name, Object.assign({isNewColumn: true, type: "blob"}, args)) }
|
|
180
|
+
boolean(name, args) { this.addColumn(name, Object.assign({isNewColumn: true, type: "boolean"}, args)) }
|
|
181
|
+
datetime(name, args) { this.addColumn(name, Object.assign({isNewColumn: true, type: "datetime"}, args)) }
|
|
182
|
+
integer(name, args = {}) { this.addColumn(name, Object.assign({isNewColumn: true, type: "integer"}, args)) }
|
|
183
|
+
tinyint(name, args = {}) { this.addColumn(name, Object.assign({isNewColumn: true, type: "tinyint"}, args)) }
|
|
80
184
|
|
|
81
185
|
references(name, args = {}) {
|
|
82
186
|
const columnName = `${name}_id`
|
|
83
|
-
const indexName = `index_on_${columnName}`
|
|
187
|
+
const indexName = `index_on_${this.getName()}_${columnName}`
|
|
84
188
|
const reference = new TableReference(name, args)
|
|
85
|
-
const columnArgs = Object.assign({type: "bigint"}, args)
|
|
189
|
+
const columnArgs = Object.assign({isNewColumn: true, type: "bigint"}, args)
|
|
86
190
|
const column = new TableColumn(columnName, columnArgs)
|
|
87
191
|
const index = new TableIndex([column], {name: indexName})
|
|
88
192
|
|
|
@@ -91,13 +195,13 @@ export default class TableData {
|
|
|
91
195
|
this._references.push(reference)
|
|
92
196
|
}
|
|
93
197
|
|
|
94
|
-
string
|
|
95
|
-
text
|
|
198
|
+
string(name, args) { this.addColumn(name, Object.assign({isNewColumn: true, type: "string"}, args)) }
|
|
199
|
+
text(name, args) { this.addColumn(name, Object.assign({isNewColumn: true, type: "text"}, args)) }
|
|
96
200
|
|
|
97
201
|
timestamps(args = {}) {
|
|
98
202
|
this.datetime("created_at", args)
|
|
99
203
|
this.datetime("updated_at", args)
|
|
100
204
|
}
|
|
101
205
|
|
|
102
|
-
uuid
|
|
206
|
+
uuid(name, args) { this.addColumn(name, Object.assign({isNewColumn: true, type: "uuid"}, args)) }
|
|
103
207
|
}
|
|
@@ -25,11 +25,12 @@ export default class VelociousHttpServerWorkerHandlerWorkerThread {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
async initialize() {
|
|
28
|
-
const {debug, directory} = digs(this.workerData, "debug", "directory")
|
|
29
|
-
const configurationPath = `${
|
|
28
|
+
const {debug, directory, environment} = digs(this.workerData, "debug", "directory", "environment")
|
|
29
|
+
const configurationPath = `${directory}/src/config/configuration.js`
|
|
30
30
|
const configurationImport = await import(configurationPath)
|
|
31
31
|
|
|
32
32
|
this.configuration = configurationImport.default
|
|
33
|
+
this.configuration.setEnvironment(environment)
|
|
33
34
|
this.configuration.setCurrent()
|
|
34
35
|
|
|
35
36
|
this.application = new Application({configuration: this.configuration, debug, directory})
|