velocious 1.0.48 → 1.0.49
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/database/drivers/columns-spec.js +27 -0
- package/src/database/drivers/base-column.js +2 -0
- package/src/database/drivers/base.js +25 -0
- package/src/database/drivers/mssql/column.js +7 -14
- package/src/database/drivers/mssql/table.js +7 -1
- package/src/database/drivers/mysql/column.js +4 -0
- package/src/database/drivers/pgsql/column.js +8 -0
- package/src/database/drivers/pgsql/table.js +24 -1
- package/src/database/drivers/sqlite/column.js +5 -3
- package/src/database/drivers/sqlite/index.js +2 -0
- package/src/database/drivers/sqlite/index.native.js +3 -1
- package/src/database/drivers/sqlite/sql/alter-table.js +3 -1
- package/src/database/migration/index.js +10 -7
- package/src/database/table-data/table-column.js +1 -1
- package/src/database/table-data/table-foreign-key.js +3 -1
package/package.json
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import dummyConfiguration from "../../dummy/src/config/configuration.js"
|
|
2
|
+
|
|
3
|
+
describe("database - drivers - columns", () => {
|
|
4
|
+
it("runs migrations", {databaseCleaning: {transaction: false}}, async () => {
|
|
5
|
+
await dummyConfiguration.ensureConnections(async (dbs) => {
|
|
6
|
+
// Authentication tokens table is important because it will be totally re-created in SQLite because the renaming of the token column to user-column
|
|
7
|
+
const authenticationTokensTable = await dbs.default.getTableByName("authentication_tokens")
|
|
8
|
+
const authenticationTokensIDColumn = await authenticationTokensTable.getColumnByName("id")
|
|
9
|
+
|
|
10
|
+
expect(authenticationTokensIDColumn.getAutoIncrement()).toBeTrue()
|
|
11
|
+
expect(authenticationTokensIDColumn.getPrimaryKey()).toBeTrue()
|
|
12
|
+
expect(authenticationTokensIDColumn.getNull()).toBeFalse()
|
|
13
|
+
|
|
14
|
+
const projectsTable = await dbs.default.getTableByName("projects")
|
|
15
|
+
const projectsCreatedAtColumn = await projectsTable.getColumnByName("created_at")
|
|
16
|
+
const projectsIDColumn = await projectsTable.getColumnByName("id")
|
|
17
|
+
|
|
18
|
+
expect(projectsIDColumn.getAutoIncrement()).toBeTrue()
|
|
19
|
+
expect(projectsIDColumn.getPrimaryKey()).toBeTrue()
|
|
20
|
+
expect(projectsIDColumn.getNull()).toBeFalse()
|
|
21
|
+
|
|
22
|
+
expect(projectsCreatedAtColumn.getAutoIncrement()).toBeFalse()
|
|
23
|
+
expect(projectsCreatedAtColumn.getPrimaryKey()).toBeFalse()
|
|
24
|
+
expect(projectsCreatedAtColumn.getNull()).toBeTrue()
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
})
|
|
@@ -40,10 +40,12 @@ export default class VelociousDatabaseDriversBaseColumn {
|
|
|
40
40
|
|
|
41
41
|
getTableDataColumn() {
|
|
42
42
|
return new TableColumn(this.getName(), {
|
|
43
|
+
autoIncrement: this.getAutoIncrement(),
|
|
43
44
|
default: this.getDefault(),
|
|
44
45
|
isNewColumn: false,
|
|
45
46
|
maxLength: this.getMaxLength(),
|
|
46
47
|
null: this.getNull(),
|
|
48
|
+
primaryKey: this.getPrimaryKey(),
|
|
47
49
|
type: this.getType()
|
|
48
50
|
})
|
|
49
51
|
}
|
|
@@ -5,6 +5,7 @@ import strftime from "strftime"
|
|
|
5
5
|
import UUID from "pure-uuid"
|
|
6
6
|
import TableData from "../table-data/index.js"
|
|
7
7
|
import TableColumn from "../table-data/table-column.js"
|
|
8
|
+
import TableForeignKey from "../table-data/table-foreign-key.js"
|
|
8
9
|
|
|
9
10
|
export default class VelociousDatabaseDriversBase {
|
|
10
11
|
constructor(config, configuration) {
|
|
@@ -14,6 +15,30 @@ export default class VelociousDatabaseDriversBase {
|
|
|
14
15
|
this._transactionsCount = 0
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
async addForeignKey(tableName, columnName, referencedTableName, referencedColumnName, args) {
|
|
19
|
+
console.log("ADD FOREIGN KEY")
|
|
20
|
+
|
|
21
|
+
const tableForeignKeyArgs = Object.assign(
|
|
22
|
+
{
|
|
23
|
+
columnName,
|
|
24
|
+
tableName,
|
|
25
|
+
referencedColumnName,
|
|
26
|
+
referencedTableName
|
|
27
|
+
},
|
|
28
|
+
args
|
|
29
|
+
)
|
|
30
|
+
const tableForeignKey = new TableForeignKey(tableForeignKeyArgs)
|
|
31
|
+
const tableData = new TableData(tableName)
|
|
32
|
+
|
|
33
|
+
tableData.addForeignKey(tableForeignKey)
|
|
34
|
+
|
|
35
|
+
const alterTableSQLs = await this.alterTableSql(tableData)
|
|
36
|
+
|
|
37
|
+
for (const alterTableSQL of alterTableSQLs) {
|
|
38
|
+
await this.query(alterTableSQL)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
17
42
|
async createTable(...args) {
|
|
18
43
|
const sqls = this.createTableSql(...args)
|
|
19
44
|
|
|
@@ -9,6 +9,8 @@ export default class VelociousDatabaseDriversMssqlColumn extends BaseColumn {
|
|
|
9
9
|
this.table = table
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
getAutoIncrement() { return digg(this, "data", "isIdentity") === 1 }
|
|
13
|
+
|
|
12
14
|
async getIndexes() {
|
|
13
15
|
const options = this.getOptions()
|
|
14
16
|
const sql = `
|
|
@@ -45,17 +47,9 @@ export default class VelociousDatabaseDriversMssqlColumn extends BaseColumn {
|
|
|
45
47
|
return indexes
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
getDefault() {
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getMaxLength() {
|
|
53
|
-
return digg(this, "data", "CHARACTER_MAXIMUM_LENGTH")
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
getName() {
|
|
57
|
-
return digg(this, "data", "COLUMN_NAME")
|
|
58
|
-
}
|
|
50
|
+
getDefault() { return digg(this, "data", "COLUMN_DEFAULT") }
|
|
51
|
+
getMaxLength() { return digg(this, "data", "CHARACTER_MAXIMUM_LENGTH") }
|
|
52
|
+
getName() { return digg(this, "data", "COLUMN_NAME") }
|
|
59
53
|
|
|
60
54
|
getNull() {
|
|
61
55
|
const nullValue = digg(this, "data", "IS_NULLABLE")
|
|
@@ -67,7 +61,6 @@ export default class VelociousDatabaseDriversMssqlColumn extends BaseColumn {
|
|
|
67
61
|
}
|
|
68
62
|
}
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
64
|
+
getPrimaryKey() { return digg(this, "data", "isIdentity") === 1 }
|
|
65
|
+
getType() { return digg(this, "data", "DATA_TYPE") }
|
|
73
66
|
}
|
|
@@ -12,7 +12,13 @@ export default class VelociousDatabaseDriversMssqlTable extends BaseTable {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
async getColumns() {
|
|
15
|
-
const result = await this.driver.query(`
|
|
15
|
+
const result = await this.driver.query(`
|
|
16
|
+
SELECT
|
|
17
|
+
*,
|
|
18
|
+
COLUMNPROPERTY(object_id(TABLE_SCHEMA + '.' + TABLE_NAME), COLUMN_NAME, 'IsIdentity') AS isIdentity
|
|
19
|
+
FROM [INFORMATION_SCHEMA].[COLUMNS]
|
|
20
|
+
WHERE [TABLE_NAME] = ${this.driver.quote(this.getName())}
|
|
21
|
+
`)
|
|
16
22
|
const columns = []
|
|
17
23
|
|
|
18
24
|
for (const data of result) {
|
|
@@ -9,6 +9,8 @@ export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
|
|
|
9
9
|
this.table = table
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
getAutoIncrement() { return digg(this, "data", "Extra").includes("auto_increment") }
|
|
13
|
+
|
|
12
14
|
async getIndexes() {
|
|
13
15
|
const options = this.getOptions()
|
|
14
16
|
const sql = `
|
|
@@ -77,6 +79,8 @@ export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
|
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
getPrimaryKey() { return digg(this, "data", "Key") == "PRI" }
|
|
83
|
+
|
|
80
84
|
getType() {
|
|
81
85
|
const type = digg(this, "data", "Type")
|
|
82
86
|
const match = type.match(/^(.+)\((\d+)\)$/)
|
|
@@ -9,6 +9,14 @@ export default class VelociousDatabaseDriversPgsqlColumn extends BaseColumn {
|
|
|
9
9
|
this.table = table
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
getAutoIncrement() {
|
|
13
|
+
return this.getDefault() == `nextval('${this.getTable().getName()}_${this.getName()}_seq'::regclass)`
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getPrimaryKey() {
|
|
17
|
+
return digg(this, "data", "is_primary_key") === 1
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
async getIndexes() {
|
|
13
21
|
const options = this.getOptions()
|
|
14
22
|
|
|
@@ -11,7 +11,30 @@ export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async getColumns() {
|
|
14
|
-
const result = await this.driver.query(`
|
|
14
|
+
const result = await this.driver.query(`
|
|
15
|
+
SELECT
|
|
16
|
+
columns.*,
|
|
17
|
+
CASE WHEN key_column_usage.column_name IS NOT NULL THEN 1 ELSE 0 END AS is_primary_key
|
|
18
|
+
|
|
19
|
+
FROM
|
|
20
|
+
information_schema.columns AS columns
|
|
21
|
+
|
|
22
|
+
LEFT JOIN information_schema.table_constraints AS table_constraints ON
|
|
23
|
+
table_constraints.table_name = columns.table_name AND
|
|
24
|
+
table_constraints.table_schema = columns.table_schema AND
|
|
25
|
+
table_constraints.constraint_type = 'PRIMARY KEY'
|
|
26
|
+
|
|
27
|
+
LEFT JOIN information_schema.key_column_usage AS key_column_usage ON
|
|
28
|
+
key_column_usage.constraint_name = table_constraints.constraint_name AND
|
|
29
|
+
key_column_usage.table_schema = table_constraints.table_schema AND
|
|
30
|
+
key_column_usage.table_name = columns.table_name AND
|
|
31
|
+
key_column_usage.column_name = columns.column_name
|
|
32
|
+
|
|
33
|
+
WHERE
|
|
34
|
+
columns.table_catalog = CURRENT_DATABASE() AND
|
|
35
|
+
columns.table_schema = 'public' AND
|
|
36
|
+
columns.table_name = '${this.getName()}'
|
|
37
|
+
`)
|
|
15
38
|
const columns = []
|
|
16
39
|
|
|
17
40
|
for (const data of result) {
|
|
@@ -9,6 +9,8 @@ export default class VelociousDatabaseDriversSqliteColumn extends BaseColumn {
|
|
|
9
9
|
this.table = table
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
getAutoIncrement() { return this.getPrimaryKey() }
|
|
13
|
+
|
|
12
14
|
async getIndexes() {
|
|
13
15
|
const indexes = await this.getTable().getIndexes()
|
|
14
16
|
const indexesForColumn = indexes.filter((index) => index.getColumnNames().includes(this.getName()))
|
|
@@ -16,9 +18,7 @@ export default class VelociousDatabaseDriversSqliteColumn extends BaseColumn {
|
|
|
16
18
|
return indexesForColumn
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
getDefault() {
|
|
20
|
-
return digg(this, "column", "dflt_value")
|
|
21
|
-
}
|
|
21
|
+
getDefault() { return digg(this, "column", "dflt_value") }
|
|
22
22
|
|
|
23
23
|
getName() {
|
|
24
24
|
const name = digg(this, "column", "name")
|
|
@@ -47,6 +47,8 @@ export default class VelociousDatabaseDriversSqliteColumn extends BaseColumn {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
getPrimaryKey() { return digg(this, "column", "pk") == 1 }
|
|
51
|
+
|
|
50
52
|
getType() {
|
|
51
53
|
const columnType = digg(this, "column", "type")
|
|
52
54
|
const match = columnType.match(/(.*)\((\d+)\)$/)
|
|
@@ -56,7 +56,9 @@ export default class VelociousDatabaseDriversSqliteNative extends Base {
|
|
|
56
56
|
this.connection = undefined
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
async query(sql) {
|
|
60
|
+
console.error("Native SQL: ", sql)
|
|
61
|
+
|
|
60
62
|
if (!this.connection) throw new Error("Not connected yet")
|
|
61
63
|
|
|
62
64
|
return await query(this.connection, sql)
|
|
@@ -89,6 +89,8 @@ export default class VelociousDatabaseConnectionDriversSqliteSqlAlterTable exten
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
for (const foreignKey of tableData.getForeignKeys()) {
|
|
92
|
+
console.log(`Foreign key`, {foreignKey})
|
|
93
|
+
|
|
92
94
|
if (foundForeignKeys.includes(foreignKey.getName())) continue
|
|
93
95
|
|
|
94
96
|
// Register foreign key on the table
|
|
@@ -100,7 +102,7 @@ export default class VelociousDatabaseConnectionDriversSqliteSqlAlterTable exten
|
|
|
100
102
|
if (!tableDataColumn) throw new Error(`Couldn't find column for foreign key: ${actualTableDataForeignKey.getName()}`)
|
|
101
103
|
|
|
102
104
|
this.logger.debug(() => [`Setting foreign key on column ${tableDataColumn.getName()}`])
|
|
103
|
-
tableDataColumn.setForeignKey(
|
|
105
|
+
tableDataColumn.setForeignKey(foreignKey)
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
const createNewTableSQL = this.getDriver().createTableSql(newTableData)
|
|
@@ -61,14 +61,17 @@ export default class VelociousDatabaseMigration {
|
|
|
61
61
|
const tableNameUnderscore = inflection.underscore(tableName)
|
|
62
62
|
const columnName = `${referenceNameUnderscore}_id`
|
|
63
63
|
const foreignKeyName = `fk_${tableName}_${referenceName}`
|
|
64
|
-
let sql = ""
|
|
65
64
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
await this.getDriver().addForeignKey(
|
|
66
|
+
tableName,
|
|
67
|
+
columnName,
|
|
68
|
+
tableNameUnderscore,
|
|
69
|
+
"id",
|
|
70
|
+
{
|
|
71
|
+
isNewForeignKey: true,
|
|
72
|
+
name: foreignKeyName
|
|
73
|
+
}
|
|
74
|
+
)
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
async addReference(tableName, referenceName, args) {
|
|
@@ -134,7 +134,7 @@ export default class TableColumn {
|
|
|
134
134
|
foreignKeyColumn = foreignKey.getReferencedColumnName()
|
|
135
135
|
foreignKeyTable = foreignKey.getReferencedTableName()
|
|
136
136
|
} else {
|
|
137
|
-
throw new Error(`Unknown foreign key type given: ${
|
|
137
|
+
throw new Error(`Unknown foreign key type given: ${foreignKey} (${typeof foreignKey})`)
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
sql += ` REFERENCES ${options.quoteTableName(foreignKeyTable)}(${options.quoteColumnName(foreignKeyColumn)})`
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import restArgsError from "../../utils/rest-args-error.js"
|
|
2
2
|
|
|
3
3
|
export default class TableForeignKey {
|
|
4
|
-
constructor({columnName, name, tableName, referencedColumnName, referencedTableName, ...restArgs}) {
|
|
4
|
+
constructor({columnName, isNewForeignKey, name, tableName, referencedColumnName, referencedTableName, ...restArgs}) {
|
|
5
5
|
restArgsError(restArgs)
|
|
6
6
|
|
|
7
7
|
this._columnName = columnName
|
|
8
|
+
this._isNewForeignKey = isNewForeignKey
|
|
8
9
|
this._name = name
|
|
9
10
|
this._tableName = tableName
|
|
10
11
|
this._referencedColumnName = referencedColumnName
|
|
@@ -12,6 +13,7 @@ export default class TableForeignKey {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
getColumnName() { return this._columnName }
|
|
16
|
+
getIsNewForeignKey() { return this._isNewForeignKey }
|
|
15
17
|
getTableName() { return this._tableName }
|
|
16
18
|
getReferencedColumnName() { return this._referencedColumnName }
|
|
17
19
|
getReferencedTableName() { return this._referencedTableName }
|