velocious 1.0.46 → 1.0.48
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 +1 -1
- package/spec/cli/commands/db/migrate-spec.js +52 -8
- package/spec/dummy/src/database/migrations/20250915085450-change-authentication-tokens-user-id-nullable.js +11 -0
- package/spec/dummy/src/database/migrations/20250916111330-rename_authentication_tokens_token_to_user_token.js +11 -0
- package/src/database/drivers/base-column.js +28 -0
- package/src/database/drivers/base-foreign-key.js +31 -0
- package/src/database/drivers/base-table.js +29 -0
- package/src/database/drivers/base.js +19 -1
- package/src/database/drivers/mssql/column.js +22 -0
- package/src/database/drivers/mssql/columns-index.js +1 -1
- package/src/database/drivers/mssql/foreign-key.js +2 -5
- package/src/database/drivers/mssql/index.js +16 -6
- package/src/database/drivers/mssql/sql/alter-table.js +4 -0
- package/src/database/drivers/mssql/table.js +37 -1
- package/src/database/drivers/mysql/column.js +38 -4
- package/src/database/drivers/mysql/foreign-key.js +2 -5
- package/src/database/drivers/mysql/index.js +9 -1
- package/src/database/drivers/mysql/sql/alter-table.js +4 -0
- package/src/database/drivers/mysql/table.js +41 -0
- package/src/database/drivers/pgsql/column.js +22 -0
- package/src/database/drivers/pgsql/foreign-key.js +2 -5
- package/src/database/drivers/pgsql/index.js +10 -2
- package/src/database/drivers/pgsql/sql/alter-table.js +4 -0
- package/src/database/drivers/pgsql/table.js +32 -2
- 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 +13 -1
- package/src/database/drivers/sqlite/foreign-key.js +8 -7
- package/src/database/drivers/sqlite/index.js +1 -1
- package/src/database/drivers/sqlite/index.web.js +3 -1
- package/src/database/drivers/sqlite/query.js +1 -2
- package/src/database/drivers/sqlite/sql/alter-table.js +143 -1
- package/src/database/drivers/sqlite/table.js +38 -0
- package/src/database/migration/index.js +31 -15
- package/src/database/query/alter-table-base.js +32 -7
- package/src/database/query/create-index-base.js +28 -4
- package/src/database/query/create-table-base.js +21 -82
- package/src/database/table-data/index.js +36 -70
- package/src/database/table-data/table-column.js +145 -0
- package/src/database/table-data/table-foreign-key.js +21 -0
- package/src/database/table-data/table-index.js +18 -0
- package/src/database/table-data/table-reference.js +6 -0
|
@@ -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()
|
|
@@ -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 VelociousDatabaseDriversPgsqlTable extends BaseTable {
|
|
@@ -43,10 +44,10 @@ export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
|
|
|
43
44
|
WHERE
|
|
44
45
|
constraint_type = 'FOREIGN KEY' AND
|
|
45
46
|
tc.table_catalog = CURRENT_DATABASE() AND
|
|
46
|
-
tc.table_name = ${this.
|
|
47
|
+
tc.table_name = ${this.getDriver().quote(this.getName())}
|
|
47
48
|
`
|
|
48
49
|
|
|
49
|
-
const foreignKeyRows = await this.
|
|
50
|
+
const foreignKeyRows = await this.getDriver().query(sql)
|
|
50
51
|
const foreignKeys = []
|
|
51
52
|
|
|
52
53
|
for (const foreignKeyRow of foreignKeyRows) {
|
|
@@ -58,6 +59,35 @@ export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
|
|
|
58
59
|
return foreignKeys
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
async getIndexes() {
|
|
63
|
+
const options = this.getOptions()
|
|
64
|
+
|
|
65
|
+
const indexesRows = await this.getDriver().query(`
|
|
66
|
+
SELECT
|
|
67
|
+
pg_attribute.attname AS column_name,
|
|
68
|
+
pg_index.indexrelid::regclass as index_name,
|
|
69
|
+
pg_class.relnamespace::regnamespace as schema_name,
|
|
70
|
+
pg_class.relname as table_name,
|
|
71
|
+
pg_index.indisprimary as is_primary_key,
|
|
72
|
+
pg_index.indisunique as is_unique
|
|
73
|
+
FROM pg_index
|
|
74
|
+
JOIN pg_class ON pg_class.oid = pg_index.indrelid
|
|
75
|
+
JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid AND pg_attribute.attnum = ANY(pg_index.indkey)
|
|
76
|
+
WHERE
|
|
77
|
+
pg_class.relname = ${options.quote(this.getName())}
|
|
78
|
+
`)
|
|
79
|
+
|
|
80
|
+
const indexes = []
|
|
81
|
+
|
|
82
|
+
for (const indexRow of indexesRows) {
|
|
83
|
+
const columnsIndex = new ColumnsIndex(this, indexRow)
|
|
84
|
+
|
|
85
|
+
indexes.push(columnsIndex)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return indexes
|
|
89
|
+
}
|
|
90
|
+
|
|
61
91
|
getName() {
|
|
62
92
|
return this.data.table_name
|
|
63
93
|
}
|
|
@@ -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,17 +1,29 @@
|
|
|
1
1
|
import BaseColumnsIndex from "../base-columns-index.js"
|
|
2
2
|
import {digg} from "diggerize"
|
|
3
|
+
import TableIndex from "../../table-data/table-index.js"
|
|
3
4
|
|
|
4
|
-
export default class
|
|
5
|
+
export default class VelociousDatabaseDriversSqliteColumnsIndex extends BaseColumnsIndex {
|
|
5
6
|
constructor(table, data) {
|
|
6
7
|
super()
|
|
7
8
|
this.data = data
|
|
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,14 +1,15 @@
|
|
|
1
|
+
import BaseForeignKey from "../base-foreign-key.js"
|
|
1
2
|
import {digg} from "diggerize"
|
|
2
3
|
|
|
3
|
-
export default class VelociousDatabaseDriversSqliteForeignKey {
|
|
4
|
+
export default class VelociousDatabaseDriversSqliteForeignKey extends BaseForeignKey {
|
|
4
5
|
constructor(data, {tableName}) {
|
|
5
|
-
|
|
6
|
+
super(data)
|
|
6
7
|
this.tableName = tableName
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
getColumnName
|
|
10
|
-
getName
|
|
11
|
-
getTableName
|
|
12
|
-
getReferencedColumnName
|
|
13
|
-
getReferencedTableName
|
|
10
|
+
getColumnName() { return digg(this, "data", "from") }
|
|
11
|
+
getName() { return `${this.getTableName()}_${this.getColumnName()}_${this.data.id}` }
|
|
12
|
+
getTableName() { return digg(this, "tableName") }
|
|
13
|
+
getReferencedColumnName() { return digg(this, "data", "to") }
|
|
14
|
+
getReferencedTableName() { return digg(this, "data", "table") }
|
|
14
15
|
}
|
|
@@ -45,5 +45,7 @@ export default class VelociousDatabaseDriversSqliteWeb extends Base {
|
|
|
45
45
|
return `VelociousDatabaseDriversSqliteWeb---${this.args.name}`
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
query = async (sql) =>
|
|
48
|
+
query = async (sql) => {
|
|
49
|
+
return await this.getConnection().query(sql)
|
|
50
|
+
}
|
|
49
51
|
}
|
|
@@ -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,146 @@
|
|
|
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 * as inflection from "inflection"
|
|
5
|
+
import {Logger} from "../../../../logger.js"
|
|
6
|
+
import restArgsError from "../../../../utils/rest-args-error.js"
|
|
7
|
+
import TableData from "../../../table-data/index.js"
|
|
2
8
|
|
|
3
|
-
export default class
|
|
9
|
+
export default class VelociousDatabaseConnectionDriversSqliteSqlAlterTable extends AlterTableBase {
|
|
10
|
+
constructor({driver, tableData, ...restArgs}) {
|
|
11
|
+
restArgsError(restArgs)
|
|
12
|
+
|
|
13
|
+
if (!(tableData instanceof TableData)) throw new Error("Invalid table data was given")
|
|
14
|
+
|
|
15
|
+
super({driver, tableData})
|
|
16
|
+
this.logger = new Logger(this)
|
|
17
|
+
this.tableData = tableData
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async toSqls() {
|
|
21
|
+
const {tableData} = digs(this, "tableData")
|
|
22
|
+
const table = await this.getDriver().getTableByName(tableData.getName())
|
|
23
|
+
const currentTableData = await table.getTableData()
|
|
24
|
+
const options = this.getOptions()
|
|
25
|
+
const tableName = tableData.getName()
|
|
26
|
+
const tempTableName = `${tableData.getName()}AlterTableTemp`
|
|
27
|
+
const newColumnNames = currentTableData.getColumns()
|
|
28
|
+
.filter((column) => !column.isNewColumn())
|
|
29
|
+
.map((column) => {
|
|
30
|
+
const newTableColumn = tableData.getColumns().find((tableColumn) => tableColumn.getName() == column.getName())
|
|
31
|
+
|
|
32
|
+
return newTableColumn?.getNewName() || newTableColumn?.getName() || column.getNewName() || column.getName()
|
|
33
|
+
})
|
|
34
|
+
const oldColumnNames = currentTableData.getColumns().filter((column) => !column.isNewColumn()).map((column) => column.getName())
|
|
35
|
+
const newColumnsSQL = newColumnNames.map((name) => options.quoteColumnName(name)).join(", ")
|
|
36
|
+
const oldColumnsSQL = oldColumnNames.map((name) => options.quoteColumnName(name)).join(", ")
|
|
37
|
+
|
|
38
|
+
tableData.setName(tempTableName)
|
|
39
|
+
|
|
40
|
+
const newTableData = new TableData(tempTableName)
|
|
41
|
+
|
|
42
|
+
for (const tableDataColumn of currentTableData.getColumns()) {
|
|
43
|
+
const newTableDataColumn = tableData.getColumns().find((newTableDataColumn) => newTableDataColumn.getName() == tableDataColumn.getName())
|
|
44
|
+
|
|
45
|
+
if (newTableDataColumn) {
|
|
46
|
+
const settingsToClone = ["autoIncrement", "default", "index", "foreignKey", "maxLength", "primaryKey", "type"]
|
|
47
|
+
|
|
48
|
+
for (const settingToClone of settingsToClone) {
|
|
49
|
+
const camelizedSettingToClone = inflection.camelize(settingToClone)
|
|
50
|
+
|
|
51
|
+
if (!newTableDataColumn[`get${camelizedSettingToClone}`]) {
|
|
52
|
+
throw new Error(`No such method on column: get${camelizedSettingToClone}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!newTableDataColumn[`get${camelizedSettingToClone}`]()) {
|
|
56
|
+
newTableDataColumn[`set${camelizedSettingToClone}`](tableDataColumn[`get${camelizedSettingToClone}`]())
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
newTableData.addColumn(newTableDataColumn || tableDataColumn)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (const tableDataColumn of tableData.getColumns()) {
|
|
65
|
+
if (!tableDataColumn.isNewColumn()) continue
|
|
66
|
+
|
|
67
|
+
newTableData.addColumn(tableDataColumn)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const foundForeignKeys = []
|
|
71
|
+
|
|
72
|
+
for (const tableDataForeignKey of currentTableData.getForeignKeys()) {
|
|
73
|
+
const newTableDataForeignKey = newTableData.getForeignKeys().find((newTableDataForeignKey) => newTableDataForeignKey.getName() == tableDataForeignKey.getName())
|
|
74
|
+
|
|
75
|
+
if (newTableDataForeignKey) foundForeignKeys.push(newTableDataForeignKey.getName())
|
|
76
|
+
|
|
77
|
+
const actualTableDataForeignKey = newTableDataForeignKey || tableDataForeignKey
|
|
78
|
+
|
|
79
|
+
// Register foreign key on the table
|
|
80
|
+
newTableData.addForeignKey(actualTableDataForeignKey)
|
|
81
|
+
|
|
82
|
+
// Register foreign key on the column
|
|
83
|
+
const tableDataColumn = newTableData.getColumns().find((newTableDataColumn) => newTableDataColumn.getName() == actualTableDataForeignKey.getColumnName())
|
|
84
|
+
|
|
85
|
+
if (!tableDataColumn) throw new Error(`Couldn't find column for foreign key: ${actualTableDataForeignKey.getName()}`)
|
|
86
|
+
|
|
87
|
+
this.logger.debug(() => [`Setting foreign key on column ${tableDataColumn.getName()}`])
|
|
88
|
+
tableDataColumn.setForeignKey(actualTableDataForeignKey)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for (const foreignKey of tableData.getForeignKeys()) {
|
|
92
|
+
if (foundForeignKeys.includes(foreignKey.getName())) continue
|
|
93
|
+
|
|
94
|
+
// Register foreign key on the table
|
|
95
|
+
newTableData.addForeignKey(foreignKey)
|
|
96
|
+
|
|
97
|
+
// Register foreign key on the column
|
|
98
|
+
const tableDataColumn = newTableData.getColumns().find((newTableDataColumn) => newTableDataColumn.getName() == foreignKey.getColumnName())
|
|
99
|
+
|
|
100
|
+
if (!tableDataColumn) throw new Error(`Couldn't find column for foreign key: ${actualTableDataForeignKey.getName()}`)
|
|
101
|
+
|
|
102
|
+
this.logger.debug(() => [`Setting foreign key on column ${tableDataColumn.getName()}`])
|
|
103
|
+
tableDataColumn.setForeignKey(actualTableDataForeignKey)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const createNewTableSQL = this.getDriver().createTableSql(newTableData)
|
|
107
|
+
const insertSQL = `INSERT INTO ${options.quoteTableName(tempTableName)} (${newColumnsSQL}) SELECT ${oldColumnsSQL} FROM ${options.quoteTableName(tableName)}`
|
|
108
|
+
const dropTableSQL = `DROP TABLE ${options.quoteTableName(tableName)}`
|
|
109
|
+
const renameTableSQL = `ALTER TABLE ${options.quoteTableName(tempTableName)} RENAME TO ${options.quoteTableName(tableName)}`
|
|
110
|
+
const sqls = []
|
|
111
|
+
|
|
112
|
+
for (const sql of createNewTableSQL) {
|
|
113
|
+
sqls.push(sql)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
sqls.push(insertSQL)
|
|
117
|
+
sqls.push(dropTableSQL)
|
|
118
|
+
sqls.push(renameTableSQL)
|
|
119
|
+
|
|
120
|
+
for (const tableDataIndex of currentTableData.getIndexes()) {
|
|
121
|
+
const newTableDataIndex = newTableData.getIndexes().find((newTableDataIndex) => newTableDataIndex.getName() == tableDataIndex.getName())
|
|
122
|
+
const actualTableIndex = newTableDataIndex || tableDataIndex
|
|
123
|
+
|
|
124
|
+
newTableData.addIndex(actualTableIndex)
|
|
125
|
+
|
|
126
|
+
const columnNames = actualTableIndex.getColumns().map((columnName) => {
|
|
127
|
+
const newTableColumn = tableData.getColumns().find((tableColumn) => tableColumn.getName() == columnName)
|
|
128
|
+
|
|
129
|
+
return newTableColumn?.getNewName() || newTableColumn?.getName() || columnName
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const createIndexArgs = {
|
|
133
|
+
columns: columnNames,
|
|
134
|
+
driver: this.getDriver(),
|
|
135
|
+
name: actualTableIndex.getName(),
|
|
136
|
+
tableName,
|
|
137
|
+
unique: actualTableIndex.getUnique()
|
|
138
|
+
}
|
|
139
|
+
const sql = new CreateIndexBase(createIndexArgs).toSql()
|
|
140
|
+
|
|
141
|
+
sqls.push(sql)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return sqls
|
|
145
|
+
}
|
|
4
146
|
}
|
|
@@ -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")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as inflection from "inflection"
|
|
2
2
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
3
|
-
import TableData
|
|
3
|
+
import TableData from "../table-data/index.js"
|
|
4
4
|
|
|
5
5
|
export default class VelociousDatabaseMigration {
|
|
6
6
|
static onDatabases(databaseIdentifiers) {
|
|
@@ -29,15 +29,17 @@ export default class VelociousDatabaseMigration {
|
|
|
29
29
|
getDriver() { return this._db }
|
|
30
30
|
|
|
31
31
|
async addColumn(tableName, columnName, columnType, args) {
|
|
32
|
-
|
|
32
|
+
if (!columnType) throw new Error("No column type given")
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
const tableColumnArgs = Object.assign({isNewColumn: true, type: columnType}, args)
|
|
35
|
+
const tableData = new TableData(tableName)
|
|
36
|
+
|
|
37
|
+
tableData.addColumn(columnName, tableColumnArgs)
|
|
38
|
+
|
|
39
|
+
const sqls = await this.getDriver().alterTableSql(tableData)
|
|
38
40
|
|
|
39
41
|
for (const sql of sqls) {
|
|
40
|
-
await this.
|
|
42
|
+
await this.getDriver().query(sql)
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -49,9 +51,9 @@ export default class VelociousDatabaseMigration {
|
|
|
49
51
|
},
|
|
50
52
|
args
|
|
51
53
|
)
|
|
52
|
-
const sql = this.
|
|
54
|
+
const sql = this.getDriver().createIndexSql(createIndexArgs)
|
|
53
55
|
|
|
54
|
-
await this.
|
|
56
|
+
await this.getDriver().query(sql)
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
async addForeignKey(tableName, referenceName) {
|
|
@@ -66,20 +68,30 @@ export default class VelociousDatabaseMigration {
|
|
|
66
68
|
sql += ` FOREIGN KEY (${this._db.quoteColumn(columnName)})`
|
|
67
69
|
sql += ` REFERENCES ${tableNameUnderscore}(id)`
|
|
68
70
|
|
|
69
|
-
await this.
|
|
71
|
+
await this.getDriver().query(sql)
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
async addReference(tableName, referenceName, args) {
|
|
75
|
+
const {foreignKey, type, unique, ...restArgs} = args
|
|
73
76
|
const columnName = `${inflection.underscore(referenceName)}_id`
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
restArgsError(restArgs)
|
|
79
|
+
|
|
80
|
+
await this.addColumn(tableName, columnName, type || "integer")
|
|
81
|
+
await this.addIndex(tableName, [columnName], {unique: unique})
|
|
77
82
|
|
|
78
|
-
if (
|
|
83
|
+
if (foreignKey) {
|
|
79
84
|
await this.addForeignKey(tableName, referenceName)
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
|
|
88
|
+
async changeColumnNull(tableName, columnName, nullable) {
|
|
89
|
+
const table = await this.getDriver().getTableByName(tableName)
|
|
90
|
+
const column = await table.getColumnByName(columnName)
|
|
91
|
+
|
|
92
|
+
await column.changeNullable(nullable)
|
|
93
|
+
}
|
|
94
|
+
|
|
83
95
|
async createTable(tableName, arg1, arg2) {
|
|
84
96
|
let args
|
|
85
97
|
let callback
|
|
@@ -111,15 +123,19 @@ export default class VelociousDatabaseMigration {
|
|
|
111
123
|
callback(tableData)
|
|
112
124
|
}
|
|
113
125
|
|
|
114
|
-
const sqls = this.
|
|
126
|
+
const sqls = this.getDriver().createTableSql(tableData)
|
|
115
127
|
|
|
116
128
|
for (const sql of sqls) {
|
|
117
129
|
await this._db.query(sql)
|
|
118
130
|
}
|
|
119
131
|
}
|
|
120
132
|
|
|
133
|
+
async renameColumn(tableName, oldColumnName, newColumnName) {
|
|
134
|
+
await this.getDriver().renameColumn(tableName, oldColumnName, newColumnName)
|
|
135
|
+
}
|
|
136
|
+
|
|
121
137
|
async tableExists(tableName) {
|
|
122
|
-
const exists = await this.
|
|
138
|
+
const exists = await this.getDriver().tableExists(tableName)
|
|
123
139
|
|
|
124
140
|
return exists
|
|
125
141
|
}
|
|
@@ -1,26 +1,51 @@
|
|
|
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
|
|
24
|
+
|
|
25
|
+
for (const column of tableData.getColumns()) {
|
|
26
|
+
if (columnsCount > 0) sql += ", "
|
|
15
27
|
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
if (column.isNewColumn()) {
|
|
29
|
+
sql += "ADD "
|
|
30
|
+
sql += column.getSQL({driver: this.getDriver(), forAlterTable: true})
|
|
31
|
+
} else if (column.getNewName()) {
|
|
32
|
+
sql += `RENAME COLUMN ${options.quoteColumnName(column.getName())} TO ${options.quoteColumnName(column.getNewName())}`
|
|
33
|
+
} else {
|
|
34
|
+
if (databaseType == "mssql" || databaseType == "pgsql") {
|
|
35
|
+
sql += "ALTER COLUMN "
|
|
36
|
+
} else {
|
|
37
|
+
sql += "MODIFY "
|
|
38
|
+
}
|
|
18
39
|
|
|
19
|
-
|
|
40
|
+
sql += column.getSQL({driver: this.getDriver(), forAlterTable: true})
|
|
41
|
+
}
|
|
20
42
|
|
|
21
|
-
|
|
43
|
+
|
|
44
|
+
columnsCount++
|
|
22
45
|
}
|
|
23
46
|
|
|
47
|
+
sqls.push(sql)
|
|
48
|
+
|
|
24
49
|
return sqls
|
|
25
50
|
}
|
|
26
51
|
}
|