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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "velocious": "bin/velocious.js"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.48",
6
+ "version": "1.0.49",
7
7
  "main": "index.js",
8
8
  "scripts": {
9
9
  "test": "VELOCIOUS_TEST_DIR=../ cd spec/dummy && npx velocious test",
@@ -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
- return digg(this, "data", "COLUMN_DEFAULT")
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
- getType() {
71
- return digg(this, "data", "DATA_TYPE")
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(`SELECT * FROM [INFORMATION_SCHEMA].[COLUMNS] WHERE [TABLE_NAME] = ${this.driver.quote(this.getName())}`)
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(`SELECT * FROM information_schema.columns WHERE table_catalog = CURRENT_DATABASE() AND table_schema = 'public' AND table_name = '${this.getName()}'`)
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+)\)$/)
@@ -35,6 +35,8 @@ export default class VelociousDatabaseDriversSqliteNode extends Base {
35
35
  }
36
36
 
37
37
  async query(sql) {
38
+ console.error("SQL: ", sql)
39
+
38
40
  return await query(this.connection, sql)
39
41
  }
40
42
  }
@@ -56,7 +56,9 @@ export default class VelociousDatabaseDriversSqliteNative extends Base {
56
56
  this.connection = undefined
57
57
  }
58
58
 
59
- query = async (sql) => {
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(actualTableDataForeignKey)
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
- sql += `ALTER TABLE ${this._db.quoteTable(tableName)}`
67
- sql += ` ADD CONSTRAINT ${foreignKeyName} `
68
- sql += ` FOREIGN KEY (${this._db.quoteColumn(columnName)})`
69
- sql += ` REFERENCES ${tableNameUnderscore}(id)`
70
-
71
- await this.getDriver().query(sql)
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: ${this.getForeignKey()} (${typeof this.getForeignKey()})`)
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 }