velocious 1.0.47 → 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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/spec/cli/commands/db/migrate-spec.js +44 -6
  3. package/spec/database/drivers/columns-spec.js +27 -0
  4. package/spec/dummy/src/database/migrations/20250916111330-rename_authentication_tokens_token_to_user_token.js +11 -0
  5. package/src/database/drivers/base-column.js +4 -3
  6. package/src/database/drivers/base-foreign-key.js +31 -0
  7. package/src/database/drivers/base-table.js +15 -1
  8. package/src/database/drivers/base.js +44 -1
  9. package/src/database/drivers/mssql/column.js +7 -14
  10. package/src/database/drivers/mssql/columns-index.js +1 -1
  11. package/src/database/drivers/mssql/foreign-key.js +2 -5
  12. package/src/database/drivers/mssql/index.js +7 -5
  13. package/src/database/drivers/mssql/table.js +43 -1
  14. package/src/database/drivers/mysql/column.js +8 -3
  15. package/src/database/drivers/mysql/foreign-key.js +2 -5
  16. package/src/database/drivers/mysql/table.js +41 -0
  17. package/src/database/drivers/pgsql/column.js +8 -0
  18. package/src/database/drivers/pgsql/foreign-key.js +2 -5
  19. package/src/database/drivers/pgsql/table.js +56 -3
  20. package/src/database/drivers/sqlite/column.js +5 -3
  21. package/src/database/drivers/sqlite/columns-index.js +2 -2
  22. package/src/database/drivers/sqlite/foreign-key.js +8 -7
  23. package/src/database/drivers/sqlite/index.js +2 -0
  24. package/src/database/drivers/sqlite/index.native.js +3 -1
  25. package/src/database/drivers/sqlite/index.web.js +3 -1
  26. package/src/database/drivers/sqlite/sql/alter-table.js +79 -6
  27. package/src/database/migration/index.js +30 -18
  28. package/src/database/query/alter-table-base.js +6 -1
  29. package/src/database/query/create-index-base.js +28 -4
  30. package/src/database/query/create-table-base.js +14 -2
  31. package/src/database/table-data/index.js +12 -150
  32. package/src/database/table-data/table-column.js +145 -0
  33. package/src/database/table-data/table-foreign-key.js +23 -0
  34. package/src/database/table-data/table-index.js +18 -0
  35. package/src/database/table-data/table-reference.js +6 -0
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "velocious": "bin/velocious.js"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.47",
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",
@@ -40,15 +40,43 @@ describe("Cli - Commands - db:migrate", () => {
40
40
  }
41
41
  }
42
42
 
43
- // It creates unique indexes
43
+ // It creates the correct index
44
44
  const authenticationTokensTable = await dbs.default.getTableByName("authentication_tokens")
45
- const tokenColumn = await authenticationTokensTable.getColumnByName("token")
46
- const tokenIndex = await tokenColumn.getIndexByName("index_on_authentication_tokens_token")
45
+ const indexes = await authenticationTokensTable.getIndexes()
46
+ const indexesNames = indexes
47
+ .map((index) => index.getName())
48
+ .filter((indexName) => indexName != "authentication_tokens_pkey" && indexName != "PRIMARY" && !indexName.startsWith("PK__"))
49
+ .sort()
50
+
51
+ if (defaultDatabaseType == "mysql") {
52
+ expect(indexesNames).toEqual(["index_on_token","user_id"])
53
+ } else if (defaultDatabaseType == "sqlite") {
54
+ expect(indexesNames).toEqual(["index_on_authentication_tokens_token", "index_on_authentication_tokens_user_id"])
55
+ } else {
56
+ expect(indexesNames).toEqual(["index_on_token", "index_on_user_id"])
57
+ }
47
58
 
48
- expect(tokenIndex.getName()).toEqual("index_on_authentication_tokens_token")
59
+ // It creates unique indexes
60
+ let tokenIndexName
61
+
62
+ if (defaultDatabaseType == "sqlite") {
63
+ tokenIndexName = "index_on_authentication_tokens_token"
64
+ } else {
65
+ tokenIndexName = "index_on_token"
66
+ }
67
+
68
+ const tokenColumn = await authenticationTokensTable.getColumnByName("user_token")
69
+ const tokenIndex = await tokenColumn.getIndexByName(tokenIndexName)
70
+
71
+ expect(tokenIndex.getName()).toEqual(tokenIndexName)
49
72
  expect(tokenIndex.isPrimaryKey()).toBeFalse()
50
73
  expect(tokenIndex.isUnique()).toBeTrue()
51
74
 
75
+ // It creates foreign keys
76
+ const authTokensTableForeignKeys = await authenticationTokensTable.getForeignKeys()
77
+
78
+ expect(authTokensTableForeignKeys.length).toEqual(1)
79
+
52
80
  for (const db of Object.values(dbs)) {
53
81
  const schemaMigrations = await db.query("SELECT * FROM schema_migrations ORDER BY version")
54
82
 
@@ -89,7 +117,8 @@ describe("Cli - Commands - db:migrate", () => {
89
117
  "20250903112845",
90
118
  "20250912183605",
91
119
  "20250912183606",
92
- "20250915085450"
120
+ "20250915085450",
121
+ "20250916111330"
93
122
  ])
94
123
  } else {
95
124
  expect(tablesResult.sort()).toEqual(
@@ -105,7 +134,16 @@ describe("Cli - Commands - db:migrate", () => {
105
134
  ]
106
135
  )
107
136
 
108
- expect(defaultSchemaMigrations.sort()).toEqual(["20230728075328", "20230728075329", "20250605133926", "20250903112845", "20250912183605", "20250912183606", "20250915085450"])
137
+ expect(defaultSchemaMigrations.sort()).toEqual([
138
+ "20230728075328",
139
+ "20230728075329",
140
+ "20250605133926",
141
+ "20250903112845",
142
+ "20250912183605",
143
+ "20250912183606",
144
+ "20250915085450",
145
+ "20250916111330"
146
+ ])
109
147
  }
110
148
  })
111
149
  })
@@ -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
+ })
@@ -0,0 +1,11 @@
1
+ import Migration from "../../../../../src/database/migration/index.js"
2
+
3
+ export default class RenameAuthenticationTokensTokenToUserToken extends Migration {
4
+ async up() {
5
+ await this.renameColumn("authentication_tokens", "token", "user_token")
6
+ }
7
+
8
+ async down() {
9
+ await this.renameColumn("authentication_tokens", "user_token", "token")
10
+ }
11
+ }
@@ -1,4 +1,5 @@
1
- import TableData, {TableColumn} from "../table-data/index.js"
1
+ import TableColumn from "../table-data/table-column.js"
2
+ import TableData from "../table-data/index.js"
2
3
 
3
4
  export default class VelociousDatabaseDriversBaseColumn {
4
5
  async getIndexByName(indexName) {
@@ -18,8 +19,6 @@ export default class VelociousDatabaseDriversBaseColumn {
18
19
 
19
20
  const sqls = await this.getDriver().alterTableSql(tableData)
20
21
 
21
- console.log({sqls})
22
-
23
22
  for (const sql of sqls) {
24
23
  await this.getDriver().query(sql)
25
24
  }
@@ -41,10 +40,12 @@ export default class VelociousDatabaseDriversBaseColumn {
41
40
 
42
41
  getTableDataColumn() {
43
42
  return new TableColumn(this.getName(), {
43
+ autoIncrement: this.getAutoIncrement(),
44
44
  default: this.getDefault(),
45
45
  isNewColumn: false,
46
46
  maxLength: this.getMaxLength(),
47
47
  null: this.getNull(),
48
+ primaryKey: this.getPrimaryKey(),
48
49
  type: this.getType()
49
50
  })
50
51
  }
@@ -0,0 +1,31 @@
1
+ import TableForeignKey from "../table-data/table-foreign-key.js"
2
+
3
+ export default class VelociousDatabaseDriversBaseForeignKey {
4
+ constructor(data) {
5
+ this.data = data
6
+ }
7
+
8
+ getDriver() {
9
+ return this.getTable().getDriver()
10
+ }
11
+
12
+ getOptions() {
13
+ return this.getDriver().options()
14
+ }
15
+
16
+ getTable() {
17
+ if (!this.table) throw new Error("No table set on column")
18
+
19
+ return this.table
20
+ }
21
+
22
+ getTableDataForeignKey() {
23
+ return new TableForeignKey({
24
+ columnName: this.getColumnName(),
25
+ name: this.getName(),
26
+ tableName: this.getTableName(),
27
+ referencedColumnName: this.getReferencedColumnName(),
28
+ referencedTableName: this.getReferencedTableName()
29
+ })
30
+ }
31
+ }
@@ -21,9 +21,23 @@ export default class VelociousDatabaseDriversBaseTable {
21
21
 
22
22
  async getTableData() {
23
23
  const tableData = new TableData(this.getName())
24
+ const tableDataColumns = []
24
25
 
25
26
  for (const column of await this.getColumns()) {
26
- tableData.addColumn(column.getTableDataColumn())
27
+ const tableDataColumn = column.getTableDataColumn()
28
+
29
+ tableData.addColumn(tableDataColumn)
30
+ tableDataColumns.push(tableDataColumn)
31
+ }
32
+
33
+ for (const foreignKey of await this.getForeignKeys()) {
34
+ tableData.addForeignKey(foreignKey.getTableDataForeignKey())
35
+
36
+ const tableDataColumn = tableDataColumns.find((tableDataColumn) => tableDataColumn.getName() == foreignKey.getColumnName())
37
+
38
+ if (!tableDataColumn) throw new Error(`Couldn't find table data column for foreign key: ${foreignKey.getColumnName()}`)
39
+
40
+ tableDataColumn.setForeignKey(foreignKey)
27
41
  }
28
42
 
29
43
  for (const index of await this.getIndexes()) {
@@ -3,6 +3,9 @@ import Query from "../query/index.js"
3
3
  import Handler from "../handler.js"
4
4
  import strftime from "strftime"
5
5
  import UUID from "pure-uuid"
6
+ import TableData from "../table-data/index.js"
7
+ import TableColumn from "../table-data/table-column.js"
8
+ import TableForeignKey from "../table-data/table-foreign-key.js"
6
9
 
7
10
  export default class VelociousDatabaseDriversBase {
8
11
  constructor(config, configuration) {
@@ -12,6 +15,30 @@ export default class VelociousDatabaseDriversBase {
12
15
  this._transactionsCount = 0
13
16
  }
14
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
+
15
42
  async createTable(...args) {
16
43
  const sqls = this.createTableSql(...args)
17
44
 
@@ -42,7 +69,7 @@ export default class VelociousDatabaseDriversBase {
42
69
  if (!this.configuration) throw new Error("No configuration set")
43
70
 
44
71
  return this.configuration
45
- }
72
+ }
46
73
 
47
74
  getIdSeq() {
48
75
  return this.idSeq
@@ -203,6 +230,22 @@ export default class VelociousDatabaseDriversBase {
203
230
  await this.query(`SAVEPOINT ${savePointName}`)
204
231
  }
205
232
 
233
+ async renameColumn(tableName, oldColumnName, newColumnName) {
234
+ const tableColumn = new TableColumn(oldColumnName)
235
+
236
+ tableColumn.setNewName(newColumnName)
237
+
238
+ const tableData = new TableData(tableName)
239
+
240
+ tableData.addColumn(tableColumn)
241
+
242
+ const alterTableSQLs = await this.alterTableSql(tableData)
243
+
244
+ for (const alterTableSQL of alterTableSQLs) {
245
+ await this.query(alterTableSQL)
246
+ }
247
+ }
248
+
206
249
  async releaseSavePoint(savePointName) {
207
250
  await this.query(`RELEASE SAVEPOINT ${savePointName}`)
208
251
  }
@@ -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
  }
@@ -1,6 +1,6 @@
1
1
  import BaseColumnsIndex from "../base-columns-index.js"
2
2
 
3
- export default class VelociousDatabaseDriversMssqlColumn extends BaseColumnsIndex {
3
+ export default class VelociousDatabaseDriversMssqlColumnsIndex extends BaseColumnsIndex {
4
4
  constructor(table, data) {
5
5
  super()
6
6
  this.data = data
@@ -1,10 +1,7 @@
1
+ import BaseForeignKey from "../base-foreign-key.js"
1
2
  import {digg} from "diggerize"
2
3
 
3
- export default class VelociousDatabaseDriversMssqlForeignKey {
4
- constructor(data) {
5
- this.data = data
6
- }
7
-
4
+ export default class VelociousDatabaseDriversMssqlForeignKey extends BaseForeignKey {
8
5
  getColumnName = () => digg(this, "data", "ParentColumn")
9
6
  getName = () => digg(this, "data", "CONSTRAINT_NAME")
10
7
  getTableName = () => digg(this, "data", "TableName")
@@ -119,9 +119,7 @@ export default class VelociousDatabaseDriversMssql extends Base{
119
119
  return new QueryParser({query}).toSql()
120
120
  }
121
121
 
122
- shouldSetAutoIncrementWhenPrimaryKey = () => true
123
-
124
-
122
+ shouldSetAutoIncrementWhenPrimaryKey() { return true }
125
123
 
126
124
  escape(value) {
127
125
  value = this._convertValue(value)
@@ -147,8 +145,12 @@ export default class VelociousDatabaseDriversMssql extends Base{
147
145
  return escapeString(value)
148
146
  }
149
147
 
150
- quoteColumn = (string) => this.options().quoteColumnName(string)
151
- quoteTable = (string) => this.options().quoteTableName(string)
148
+ quoteColumn(string) { return this.options().quoteColumnName(string) }
149
+ quoteTable(string) { return this.options().quoteTableName(string) }
150
+
151
+ async renameColumn(tableName, oldColumnName, newColumnName) {
152
+ await this.query(`EXEC sp_rename ${this.quote(`${tableName}.${oldColumnName}`)}, ${this.quote(newColumnName)}, 'COLUMN'`)
153
+ }
152
154
 
153
155
  deleteSql({tableName, conditions}) {
154
156
  const deleteInstruction = new Delete({conditions, driver: this, tableName})
@@ -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 {digg} from "diggerize"
4
5
  import ForeignKey from "./foreign-key.js"
5
6
 
@@ -11,7 +12,13 @@ export default class VelociousDatabaseDriversMssqlTable extends BaseTable {
11
12
  }
12
13
 
13
14
  async getColumns() {
14
- 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
+ `)
15
22
  const columns = []
16
23
 
17
24
  for (const data of result) {
@@ -61,6 +68,41 @@ export default class VelociousDatabaseDriversMssqlTable extends BaseTable {
61
68
  return foreignKeys
62
69
  }
63
70
 
71
+ async getIndexes() {
72
+ const options = this.getOptions()
73
+ const sql = `
74
+ SELECT
75
+ sys.tables.name AS TableName,
76
+ sys.columns.name AS ColumnName,
77
+ sys.indexes.name AS index_name,
78
+ sys.indexes.type_desc AS IndexType,
79
+ sys.index_columns.is_included_column AS IsIncludedColumn,
80
+ sys.indexes.is_unique,
81
+ sys.indexes.is_primary_key,
82
+ sys.indexes.is_unique_constraint
83
+ FROM sys.indexes
84
+ INNER JOIN sys.index_columns ON sys.indexes.object_id = sys.index_columns.object_id AND sys.indexes.index_id = sys.index_columns.index_id
85
+ INNER JOIN sys.columns ON sys.index_columns.object_id = sys.columns.object_id AND sys.index_columns.column_id = sys.columns.column_id
86
+ INNER JOIN sys.tables ON sys.indexes.object_id = sys.tables.object_id
87
+ WHERE
88
+ sys.tables.name = ${options.quote(this.getName())}
89
+ ORDER BY
90
+ sys.indexes.name,
91
+ sys.index_columns.key_ordinal
92
+ `
93
+
94
+ const rows = await this.getDriver().query(sql)
95
+ const indexes = []
96
+
97
+ for (const row of rows) {
98
+ const index = new ColumnsIndex(this, row)
99
+
100
+ indexes.push(index)
101
+ }
102
+
103
+ return indexes
104
+ }
105
+
64
106
  getName() {
65
107
  return digg(this.data, "TABLE_NAME")
66
108
  }
@@ -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 = `
@@ -21,9 +23,10 @@ export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
21
23
  NON_UNIQUE,
22
24
  INDEX_TYPE
23
25
  FROM INFORMATION_SCHEMA.STATISTICS
24
- WHERE TABLE_SCHEMA = DATABASE()
25
- AND TABLE_NAME = ${options.quote(this.table.getName())}
26
- AND COLUMN_NAME = ${options.quote(this.getName())}
26
+ WHERE
27
+ TABLE_SCHEMA = DATABASE() AND
28
+ TABLE_NAME = ${options.quote(this.table.getName())} AND
29
+ COLUMN_NAME = ${options.quote(this.getName())}
27
30
  `
28
31
  const indexesRows = await this.getDriver().query(sql)
29
32
  const indexes = []
@@ -76,6 +79,8 @@ export default class VelociousDatabaseDriversMysqlColumn extends BaseColumn {
76
79
  }
77
80
  }
78
81
 
82
+ getPrimaryKey() { return digg(this, "data", "Key") == "PRI" }
83
+
79
84
  getType() {
80
85
  const type = digg(this, "data", "Type")
81
86
  const match = type.match(/^(.+)\((\d+)\)$/)
@@ -1,10 +1,7 @@
1
+ import BaseForeignKey from "../base-foreign-key.js"
1
2
  import {digg} from "diggerize"
2
3
 
3
- export default class VelociousDatabaseDriversMysqlForeignKey {
4
- constructor(data) {
5
- this.data = data
6
- }
7
-
4
+ export default class VelociousDatabaseDriversMysqlForeignKey extends BaseForeignKey {
8
5
  getColumnName = () => digg(this, "data", "COLUMN_NAME")
9
6
  getName = () => digg(this, "data", "CONSTRAINT_NAME")
10
7
  getTableName = () => digg(this, "data", "TABLE_NAME")
@@ -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 VelociousDatabaseDriversMysqlTable extends BaseTable {
@@ -43,6 +44,46 @@ export default class VelociousDatabaseDriversMysqlTable extends BaseTable {
43
44
  return foreignKeys
44
45
  }
45
46
 
47
+ async getIndexes() {
48
+ const options = this.getOptions()
49
+ const sql = `
50
+ SELECT
51
+ TABLE_SCHEMA,
52
+ TABLE_NAME,
53
+ INDEX_NAME AS index_name,
54
+ COLUMN_NAME,
55
+ SEQ_IN_INDEX,
56
+ NON_UNIQUE,
57
+ INDEX_TYPE
58
+ FROM INFORMATION_SCHEMA.STATISTICS
59
+ WHERE
60
+ TABLE_SCHEMA = DATABASE() AND
61
+ TABLE_NAME = ${options.quote(this.getName())}
62
+ `
63
+ const indexesRows = await this.getDriver().query(sql)
64
+ const indexes = []
65
+
66
+ for (const indexRow of indexesRows) {
67
+ if (indexRow.NON_UNIQUE == 1) {
68
+ indexRow.is_unique = false
69
+ } else {
70
+ indexRow.is_unique = true
71
+ }
72
+
73
+ if (indexRow.index_name == "PRIMARY") {
74
+ indexRow.is_primary_key = true
75
+ } else {
76
+ indexRow.is_primary_key = false
77
+ }
78
+
79
+ const index = new ColumnsIndex(this, indexRow)
80
+
81
+ indexes.push(index)
82
+ }
83
+
84
+ return indexes
85
+ }
86
+
46
87
  getName() {
47
88
  return Object.values(this.data)[0]
48
89
  }
@@ -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
 
@@ -1,10 +1,7 @@
1
+ import BaseForeignKey from "../base-foreign-key.js"
1
2
  import {digg} from "diggerize"
2
3
 
3
- export default class VelociousDatabaseDriversPgsqlForeignKey {
4
- constructor(data) {
5
- this.data = data
6
- }
7
-
4
+ export default class VelociousDatabaseDriversPgsqlForeignKey extends BaseForeignKey {
8
5
  getColumnName = () => digg(this, "data", "column_name")
9
6
  getName = () => digg(this, "data", "constraint_name")
10
7
  getTableName = () => digg(this, "data", "table_name")
@@ -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 {
@@ -10,7 +11,30 @@ export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
10
11
  }
11
12
 
12
13
  async getColumns() {
13
- 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
+ `)
14
38
  const columns = []
15
39
 
16
40
  for (const data of result) {
@@ -43,10 +67,10 @@ export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
43
67
  WHERE
44
68
  constraint_type = 'FOREIGN KEY' AND
45
69
  tc.table_catalog = CURRENT_DATABASE() AND
46
- tc.table_name = ${this.driver.quote(this.getName())}
70
+ tc.table_name = ${this.getDriver().quote(this.getName())}
47
71
  `
48
72
 
49
- const foreignKeyRows = await this.driver.query(sql)
73
+ const foreignKeyRows = await this.getDriver().query(sql)
50
74
  const foreignKeys = []
51
75
 
52
76
  for (const foreignKeyRow of foreignKeyRows) {
@@ -58,6 +82,35 @@ export default class VelociousDatabaseDriversPgsqlTable extends BaseTable {
58
82
  return foreignKeys
59
83
  }
60
84
 
85
+ async getIndexes() {
86
+ const options = this.getOptions()
87
+
88
+ const indexesRows = await this.getDriver().query(`
89
+ SELECT
90
+ pg_attribute.attname AS column_name,
91
+ pg_index.indexrelid::regclass as index_name,
92
+ pg_class.relnamespace::regnamespace as schema_name,
93
+ pg_class.relname as table_name,
94
+ pg_index.indisprimary as is_primary_key,
95
+ pg_index.indisunique as is_unique
96
+ FROM pg_index
97
+ JOIN pg_class ON pg_class.oid = pg_index.indrelid
98
+ JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid AND pg_attribute.attnum = ANY(pg_index.indkey)
99
+ WHERE
100
+ pg_class.relname = ${options.quote(this.getName())}
101
+ `)
102
+
103
+ const indexes = []
104
+
105
+ for (const indexRow of indexesRows) {
106
+ const columnsIndex = new ColumnsIndex(this, indexRow)
107
+
108
+ indexes.push(columnsIndex)
109
+ }
110
+
111
+ return indexes
112
+ }
113
+
61
114
  getName() {
62
115
  return this.data.table_name
63
116
  }