velocious 1.0.5 → 1.0.6
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 +5 -3
- package/spec/cli/commands/db/create-spec.mjs +1 -1
- package/spec/cli/commands/db/migrate-spec.mjs +2 -0
- package/spec/database/record/create-spec.mjs +9 -0
- package/spec/database/record/find-spec.mjs +0 -1
- package/spec/database/record/query-spec.mjs +37 -0
- package/spec/dummy/index.mjs +14 -2
- package/spec/dummy/src/config/configuration.example.mjs +16 -1
- package/spec/dummy/src/config/configuration.peakflow.mjs +16 -1
- package/spec/dummy/src/database/migrations/20230728075328-create-projects.mjs +0 -1
- package/spec/dummy/src/database/migrations/20230728075329-create-tasks.mjs +0 -1
- package/spec/dummy/src/database/migrations/20250605133926-create-project-translations.mjs +16 -0
- package/spec/dummy/src/models/project.mjs +9 -0
- package/spec/dummy/src/models/task.mjs +5 -1
- package/src/big-brother.mjs +37 -0
- package/src/cli/commands/db/create.mjs +8 -6
- package/src/cli/commands/db/migrate.mjs +1 -2
- package/src/cli/commands/generate/migration.mjs +1 -1
- package/src/cli/commands/generate/model.mjs +1 -1
- package/src/configuration.mjs +39 -3
- package/src/database/drivers/base.mjs +21 -2
- package/src/database/drivers/mysql/column.mjs +8 -0
- package/src/database/drivers/mysql/index.mjs +34 -2
- package/src/database/drivers/mysql/options.mjs +1 -0
- package/src/database/drivers/mysql/query-parser.mjs +2 -23
- package/src/database/drivers/mysql/table.mjs +25 -0
- package/src/database/drivers/sqlite/base.mjs +76 -4
- package/src/database/drivers/sqlite/column.mjs +10 -0
- package/src/database/drivers/sqlite/index.native.mjs +19 -22
- package/src/database/drivers/sqlite/index.web.mjs +27 -17
- package/src/database/drivers/sqlite/options.mjs +2 -1
- package/src/database/drivers/sqlite/query-parser.mjs +2 -23
- package/src/database/drivers/sqlite/query.native.mjs +16 -1
- package/src/database/drivers/sqlite/query.web.mjs +27 -2
- package/src/database/drivers/sqlite/sql/create-index.mjs +4 -0
- package/src/database/drivers/sqlite/table.mjs +16 -1
- package/src/database/initializer-from-require-context.mjs +21 -0
- package/src/database/migration/index.mjs +34 -2
- package/src/database/migrator.mjs +4 -2
- package/src/database/pool/base.mjs +5 -0
- package/src/database/query/base.mjs +2 -1
- package/src/database/query/create-index-base.mjs +50 -0
- package/src/database/query/create-table-base.mjs +40 -17
- package/src/database/query/index.mjs +83 -21
- package/src/database/query/preloader/belongs-to.mjs +52 -0
- package/src/database/query/preloader/has-many.mjs +55 -0
- package/src/database/query/preloader.mjs +41 -0
- package/src/database/query/where-base.mjs +9 -0
- package/src/database/query/where-hash.mjs +35 -0
- package/src/database/query/where-plain.mjs +13 -0
- package/src/database/query-parser/base-query-parser.mjs +33 -0
- package/src/database/query-parser/group-parser.mjs +40 -0
- package/src/database/query-parser/joins-parser.mjs +48 -7
- package/src/database/query-parser/limit-parser.mjs +40 -0
- package/src/database/query-parser/options.mjs +2 -1
- package/src/database/query-parser/order-parser.mjs +39 -0
- package/src/database/query-parser/select-parser.mjs +5 -1
- package/src/database/query-parser/where-parser.mjs +39 -0
- package/src/database/record/index.mjs +464 -29
- package/src/database/record/instance-relationships/base.mjs +28 -0
- package/src/database/record/instance-relationships/belongs-to.mjs +20 -0
- package/src/database/record/instance-relationships/has-many.mjs +47 -0
- package/src/database/record/relationships/base.mjs +32 -0
- package/src/database/record/relationships/belongs-to.mjs +12 -0
- package/src/database/record/relationships/has-many.mjs +12 -0
- package/src/database/table-data/index.mjs +15 -25
- package/src/http-server/worker-handler/worker-thread.mjs +7 -4
- package/src/templates/generate-model.mjs +3 -1
- package/src/utils/rest-args-error.mjs +9 -0
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import {digg} from "diggerize"
|
|
2
|
+
|
|
1
3
|
import Base from "../base.mjs"
|
|
4
|
+
import CreateIndex from "../sqlite/sql/create-index.mjs"
|
|
2
5
|
import CreateTable from "../sqlite/sql/create-table.mjs"
|
|
3
6
|
import Delete from "../sqlite/sql/delete.mjs"
|
|
7
|
+
import escapeString from "sql-string-escape"
|
|
4
8
|
import Insert from "../sqlite/sql/insert.mjs"
|
|
9
|
+
import Options from "../sqlite/options.mjs"
|
|
5
10
|
import QueryParser from "../sqlite/query-parser.mjs"
|
|
6
11
|
import Table from "./table"
|
|
7
12
|
import Update from "../sqlite/sql/update.mjs"
|
|
8
13
|
|
|
9
14
|
export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
15
|
+
createIndexSql(indexData) {
|
|
16
|
+
const createArgs = Object.assign({driver: this}, indexData)
|
|
17
|
+
const createIndex = new CreateIndex(createArgs)
|
|
18
|
+
|
|
19
|
+
return createIndex.toSql()
|
|
20
|
+
}
|
|
21
|
+
|
|
10
22
|
createTableSql(tableData) {
|
|
11
|
-
const createArgs = Object.assign({tableData, driver: this})
|
|
23
|
+
const createArgs = Object.assign({tableData, driver: this, indexInCreateTable: false})
|
|
12
24
|
const createTable = new CreateTable(createArgs)
|
|
13
25
|
|
|
14
26
|
return createTable.toSql()
|
|
@@ -17,12 +29,26 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
17
29
|
deleteSql = ({tableName, conditions}) => new Delete({conditions, driver: this, tableName}).toSql()
|
|
18
30
|
insertSql = ({tableName, data}) => new Insert({driver: this, tableName, data}).toSql()
|
|
19
31
|
|
|
32
|
+
async getTableByName(tableName) {
|
|
33
|
+
const result = await this.query(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${this.quote(tableName)} LIMIT 1`)
|
|
34
|
+
const row = result[0]
|
|
35
|
+
|
|
36
|
+
if (!row) {
|
|
37
|
+
const tables = await this.getTables()
|
|
38
|
+
const tableNames = tables.map((table) => table.getName())
|
|
39
|
+
|
|
40
|
+
throw new Error(`No table by that name: ${tableName} in ${tableNames.join(", ")}`)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return new Table({driver: this, row})
|
|
44
|
+
}
|
|
45
|
+
|
|
20
46
|
async getTables() {
|
|
21
|
-
const result = await this.query("SELECT name FROM sqlite_master WHERE type = 'table'")
|
|
47
|
+
const result = await this.query("SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name")
|
|
22
48
|
const tables = []
|
|
23
49
|
|
|
24
50
|
for (const row of result) {
|
|
25
|
-
const table = new Table(row)
|
|
51
|
+
const table = new Table({driver: this, row})
|
|
26
52
|
|
|
27
53
|
tables.push(table)
|
|
28
54
|
}
|
|
@@ -30,7 +56,53 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
30
56
|
return tables
|
|
31
57
|
}
|
|
32
58
|
|
|
59
|
+
async lastInsertID() {
|
|
60
|
+
const result = await this.query("SELECT LAST_INSERT_ROWID() AS last_insert_id")
|
|
61
|
+
|
|
62
|
+
return digg(result, 0, "last_insert_id")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
options() {
|
|
66
|
+
if (!this._options) {
|
|
67
|
+
this._options = new Options({driver: this})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return this._options
|
|
71
|
+
}
|
|
72
|
+
|
|
33
73
|
queryToSql = (query) => new QueryParser({query}).toSql()
|
|
34
|
-
|
|
74
|
+
|
|
75
|
+
escape(value) {
|
|
76
|
+
const type = typeof value
|
|
77
|
+
|
|
78
|
+
if (type != "string") value = `${value}`
|
|
79
|
+
|
|
80
|
+
const resultWithQuotes = escapeString(value)
|
|
81
|
+
const result = resultWithQuotes.substring(1, resultWithQuotes.length - 1)
|
|
82
|
+
|
|
83
|
+
return result
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
quote(value) {
|
|
87
|
+
const type = typeof value
|
|
88
|
+
|
|
89
|
+
if (type == "number") return value
|
|
90
|
+
if (type != "string") value = `${value}`
|
|
91
|
+
|
|
92
|
+
return escapeString(value)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
quoteColumn = (string) => {
|
|
96
|
+
if (string.includes("`")) throw new Error(`Possible SQL injection in column name: ${string}`)
|
|
97
|
+
|
|
98
|
+
return `\`${string}\``
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
quoteTable = (string) => {
|
|
102
|
+
if (string.includes("`")) throw new Error(`Possible SQL injection in table name: ${string}`)
|
|
103
|
+
|
|
104
|
+
return `\`${string}\``
|
|
105
|
+
}
|
|
106
|
+
|
|
35
107
|
updateSql = ({conditions, data, tableName}) => new Update({conditions, data, driver: this, tableName}).toSql()
|
|
36
108
|
}
|
|
@@ -1,19 +1,31 @@
|
|
|
1
|
-
import Base from "./base"
|
|
2
1
|
import {digg} from "diggerize"
|
|
3
|
-
import escapeString from "sql-string-escape"
|
|
4
|
-
import Options from "../sqlite/options.mjs"
|
|
5
2
|
import query from "./query"
|
|
6
3
|
import * as SQLite from "expo-sqlite"
|
|
7
4
|
|
|
5
|
+
import Base from "./base"
|
|
6
|
+
|
|
8
7
|
export default class VelociousDatabaseDriversSqliteNative extends Base {
|
|
9
8
|
async connect() {
|
|
10
|
-
const
|
|
9
|
+
const args = this.getArgs()
|
|
10
|
+
const databaseName = digg(args, "name")
|
|
11
|
+
|
|
12
|
+
if (args.reset) {
|
|
13
|
+
try {
|
|
14
|
+
await SQLite.deleteDatabaseAsync(databaseName)
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error.message.match(/Database '(.+)' not found/)) {
|
|
17
|
+
// Ignore not found
|
|
18
|
+
} else {
|
|
19
|
+
throw error
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
11
23
|
|
|
12
|
-
this.connection =
|
|
24
|
+
this.connection = await SQLite.openDatabaseAsync(databaseName)
|
|
13
25
|
}
|
|
14
26
|
|
|
15
|
-
disconnect() {
|
|
16
|
-
this.connection.
|
|
27
|
+
async disconnect() {
|
|
28
|
+
await this.connection.closeAsync()
|
|
17
29
|
}
|
|
18
30
|
|
|
19
31
|
connectArgs() {
|
|
@@ -36,19 +48,4 @@ export default class VelociousDatabaseDriversSqliteNative extends Base {
|
|
|
36
48
|
}
|
|
37
49
|
|
|
38
50
|
query = async (sql) => await query(this.connection, sql)
|
|
39
|
-
|
|
40
|
-
quote(string) {
|
|
41
|
-
const type = typeof string
|
|
42
|
-
|
|
43
|
-
if (type == "number") return string
|
|
44
|
-
if (type != "string") string = `${string}`
|
|
45
|
-
|
|
46
|
-
return escapeString(string)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
options() {
|
|
50
|
-
if (!this._options) this._options = new Options({driver: this})
|
|
51
|
-
|
|
52
|
-
return this._options
|
|
53
|
-
}
|
|
54
51
|
}
|
|
@@ -1,45 +1,55 @@
|
|
|
1
|
-
import
|
|
1
|
+
import BetterLocalStorage from "better-localstorage"
|
|
2
|
+
import debounce from "debounce"
|
|
2
3
|
import {digg} from "diggerize"
|
|
3
|
-
import
|
|
4
|
+
import initSqlJs from "sql.js"
|
|
4
5
|
import query from "./query"
|
|
5
6
|
|
|
6
|
-
import
|
|
7
|
+
import Base from "./base.mjs"
|
|
7
8
|
|
|
8
9
|
export default class VelociousDatabaseDriversSqliteWeb extends Base {
|
|
9
10
|
async connect() {
|
|
11
|
+
this.betterLocaleStorage ||= new BetterLocalStorage()
|
|
12
|
+
|
|
13
|
+
const args = this.getArgs()
|
|
14
|
+
|
|
15
|
+
if (args.reset) {
|
|
16
|
+
await this.betterLocaleStorage.delete(this.localStorageName())
|
|
17
|
+
}
|
|
18
|
+
|
|
10
19
|
const SQL = await initSqlJs({
|
|
11
20
|
// Required to load the wasm binary asynchronously. Of course, you can host it wherever you want you can omit locateFile completely when running in Node.
|
|
12
21
|
locateFile: (file) => `https://sql.js.org/dist/${file}`
|
|
13
22
|
})
|
|
14
23
|
|
|
15
|
-
const databaseContent =
|
|
24
|
+
const databaseContent = await this.betterLocaleStorage.get(this.localStorageName())
|
|
16
25
|
|
|
17
26
|
this.connection = new SQL.Database(databaseContent)
|
|
18
27
|
}
|
|
19
28
|
|
|
20
29
|
localStorageName = () => `VelociousDatabaseDriversSqliteWeb---${digg(this.getArgs(), "name")}`
|
|
21
30
|
disconnect = () => this.saveDatabase()
|
|
22
|
-
saveDatabase = () =>
|
|
31
|
+
saveDatabase = async () => {
|
|
32
|
+
const localStorageContent = this.connection.export()
|
|
33
|
+
await this.betterLocaleStorage.set(this.localStorageName(), localStorageContent)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
saveDatabaseDebounce = debounce(this.saveDatabase, 500)
|
|
23
37
|
|
|
24
38
|
async close() {
|
|
25
|
-
this.saveDatabase()
|
|
39
|
+
await this.saveDatabase()
|
|
26
40
|
await this.connection.end()
|
|
27
41
|
this.connection = undefined
|
|
28
42
|
}
|
|
29
43
|
|
|
30
|
-
query = async (sql) =>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (!this.connection) throw new Error("Can't escape before connected")
|
|
34
|
-
|
|
35
|
-
return this.connection.escape(string)
|
|
36
|
-
}
|
|
44
|
+
query = async (sql) => {
|
|
45
|
+
const result = await query(this.connection, sql)
|
|
46
|
+
const downcasedSQL = sql.toLowerCase().trim()
|
|
37
47
|
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
this.
|
|
48
|
+
// Auto-save database in local storage in case we can find manipulating instructions in the SQL
|
|
49
|
+
if (downcasedSQL.startsWith("delete ") || downcasedSQL.startsWith("insert into ") || downcasedSQL.startsWith("update ")) {
|
|
50
|
+
this.saveDatabaseDebounce()
|
|
41
51
|
}
|
|
42
52
|
|
|
43
|
-
return
|
|
53
|
+
return result
|
|
44
54
|
}
|
|
45
55
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import QueryParserOptions from "../../query-parser/options.mjs"
|
|
2
2
|
|
|
3
|
-
export default class
|
|
3
|
+
export default class VelociousDatabaseDriversSqliteOptions extends QueryParserOptions {
|
|
4
4
|
constructor(options) {
|
|
5
5
|
options.columnQuote = "`"
|
|
6
|
+
options.indexQuote = "`"
|
|
6
7
|
options.stringQuote = "'"
|
|
7
8
|
options.tableQuote = "`"
|
|
8
9
|
|
|
@@ -1,25 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import FromParser from "../../query-parser/from-parser.mjs"
|
|
3
|
-
import JoinsParser from "../../query-parser/joins-parser.mjs"
|
|
4
|
-
import SelectParser from "../../query-parser/select-parser.mjs"
|
|
1
|
+
import BaseQueryParser from "../../query-parser/base-query-parser.mjs"
|
|
5
2
|
|
|
6
|
-
export default class
|
|
7
|
-
constructor({pretty, query}) {
|
|
8
|
-
if (!query) throw new Error("No query given")
|
|
9
|
-
|
|
10
|
-
this.pretty = pretty
|
|
11
|
-
this.query = query
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
toSql() {
|
|
15
|
-
const {pretty, query} = digs(this, "pretty", "query")
|
|
16
|
-
|
|
17
|
-
let sql = ""
|
|
18
|
-
|
|
19
|
-
sql += new SelectParser({pretty, query}).toSql()
|
|
20
|
-
sql += new FromParser({pretty, query}).toSql()
|
|
21
|
-
sql += new JoinsParser({pretty, query}).toSql()
|
|
22
|
-
|
|
23
|
-
return sql
|
|
24
|
-
}
|
|
3
|
+
export default class VelociousDatabaseConnectionDriversSqliteQueryParser extends BaseQueryParser {
|
|
25
4
|
}
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
export default async function query(connection, sql) {
|
|
2
2
|
const rows = []
|
|
3
|
+
let result
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
try {
|
|
6
|
+
result = await connection.getAllAsync(sql)
|
|
7
|
+
} catch (error) {
|
|
8
|
+
let sqlInErrorMessage = `${sql}`
|
|
9
|
+
|
|
10
|
+
if (sqlInErrorMessage.length >= 4096) {
|
|
11
|
+
sqlInErrorMessage = `${sqlInErrorMessage.substring(0, 4096)}...`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
error.message += `\n\n${sqlInErrorMessage}`
|
|
15
|
+
|
|
16
|
+
throw error
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
for await (const entry of result) {
|
|
5
20
|
rows.push(entry)
|
|
6
21
|
}
|
|
7
22
|
|
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
export default async function query(connection, sql) {
|
|
2
2
|
const rows = []
|
|
3
|
+
let result
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
try {
|
|
6
|
+
result = connection.exec(sql)
|
|
7
|
+
} catch (error) {
|
|
8
|
+
let sqlInErrorMessage = `${sql}`
|
|
9
|
+
|
|
10
|
+
if (sqlInErrorMessage.length >= 4096) {
|
|
11
|
+
sqlInErrorMessage = `${sqlInErrorMessage.substring(0, 4096)}...`
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
error.message += `\n\n${sqlInErrorMessage}`
|
|
15
|
+
|
|
16
|
+
throw error
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (result[0]) {
|
|
20
|
+
const columns = result[0].columns
|
|
21
|
+
|
|
22
|
+
for (const rowValues of result[0].values) {
|
|
23
|
+
const row = {}
|
|
24
|
+
|
|
25
|
+
for (const columnIndex in columns) {
|
|
26
|
+
row[columns[columnIndex]] = rowValues[columnIndex]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
rows.push(row)
|
|
30
|
+
}
|
|
6
31
|
}
|
|
7
32
|
|
|
8
33
|
return rows
|
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
import Column from "./column.mjs"
|
|
1
2
|
import {digg} from "diggerize"
|
|
2
3
|
|
|
3
4
|
export default class VelociousDatabaseDriversSqliteTable {
|
|
4
|
-
constructor(row) {
|
|
5
|
+
constructor({driver, row}) {
|
|
6
|
+
this.driver = driver
|
|
5
7
|
this.row = row
|
|
6
8
|
}
|
|
7
9
|
|
|
10
|
+
getColumns = async () => {
|
|
11
|
+
const result = await this.driver.query(`PRAGMA table_info('${this.getName()}')`)
|
|
12
|
+
const columns = []
|
|
13
|
+
|
|
14
|
+
for (const columnData of result) {
|
|
15
|
+
const column = new Column({column: columnData, driver: this.driver, table: this})
|
|
16
|
+
|
|
17
|
+
columns.push(column)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return columns
|
|
21
|
+
}
|
|
22
|
+
|
|
8
23
|
getName = () => digg(this, "row", "name")
|
|
9
24
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default class VelociousDatabaseInitializerFromRequireContext {
|
|
2
|
+
constructor({requireContext, ...restProps}) {
|
|
3
|
+
const restPropsKeys = Object.keys(restProps)
|
|
4
|
+
|
|
5
|
+
if (restPropsKeys.length > 0) throw new Error(`Unknown arguments: ${restPropsKeys.join(", ")}`)
|
|
6
|
+
|
|
7
|
+
this.requireContext = requireContext
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async initialize({configuration}) {
|
|
11
|
+
for (const fileName of this.requireContext.keys()) {
|
|
12
|
+
const modelClass = this.requireContext(fileName).default
|
|
13
|
+
|
|
14
|
+
await modelClass.initializeRecord({configuration})
|
|
15
|
+
|
|
16
|
+
if (await modelClass.hasTranslationsTable()) {
|
|
17
|
+
await modelClass.getTranslationClass().initializeRecord({configuration})
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -5,14 +5,46 @@ export default class VelociousDatabaseMigration {
|
|
|
5
5
|
this.configuration = configuration
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
async addIndex(tableName, columns, args) {
|
|
9
|
+
const databasePool = this.configuration.getDatabasePool()
|
|
10
|
+
const createIndexArgs = Object.assign(
|
|
11
|
+
{
|
|
12
|
+
columns,
|
|
13
|
+
tableName
|
|
14
|
+
},
|
|
15
|
+
args
|
|
16
|
+
)
|
|
17
|
+
const sql = databasePool.createIndexSql(createIndexArgs)
|
|
18
|
+
|
|
19
|
+
await databasePool.query(sql)
|
|
20
|
+
}
|
|
21
|
+
|
|
8
22
|
async createTable(tableName, callback) {
|
|
9
23
|
const tableData = new TableData(tableName)
|
|
10
24
|
|
|
25
|
+
tableData.integer("id", {null: false, primaryKey: true})
|
|
26
|
+
|
|
11
27
|
callback(tableData)
|
|
12
28
|
|
|
13
29
|
const databasePool = this.configuration.getDatabasePool()
|
|
14
|
-
const
|
|
30
|
+
const sqls = databasePool.createTableSql(tableData)
|
|
15
31
|
|
|
16
|
-
|
|
32
|
+
for (const sql of sqls) {
|
|
33
|
+
await databasePool.query(sql)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getConnection() {
|
|
38
|
+
const connection = this.configuration.getDatabasePool().getCurrentConnection()
|
|
39
|
+
|
|
40
|
+
if (!connection) throw new Error("Couldn't get current connection")
|
|
41
|
+
|
|
42
|
+
return connection
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async tableExists(tableName) {
|
|
46
|
+
const exists = await this.getConnection().tableExists(tableName)
|
|
47
|
+
|
|
48
|
+
return exists
|
|
17
49
|
}
|
|
18
50
|
}
|
|
@@ -20,9 +20,11 @@ export default class VelociousDatabaseMigrator {
|
|
|
20
20
|
schemaMigrationsTable.string("version", {null: false, primaryKey: true})
|
|
21
21
|
|
|
22
22
|
await this.configuration.getDatabasePool().withConnection(async (db) => {
|
|
23
|
-
const
|
|
23
|
+
const createSchemaMigrationsTableSqls = db.createTableSql(schemaMigrationsTable)
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
for (const createSchemaMigrationsTableSql of createSchemaMigrationsTableSqls) {
|
|
26
|
+
await db.query(createSchemaMigrationsTableSql)
|
|
27
|
+
}
|
|
26
28
|
})
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -35,6 +35,8 @@ class VelociousDatabasePoolBase {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const forwardMethods = [
|
|
38
|
+
"createIndex",
|
|
39
|
+
"createIndexSql",
|
|
38
40
|
"createTable",
|
|
39
41
|
"createTableSql",
|
|
40
42
|
"delete",
|
|
@@ -52,6 +54,9 @@ const forwardMethods = [
|
|
|
52
54
|
for (const forwardMethod of forwardMethods) {
|
|
53
55
|
VelociousDatabasePoolBase.prototype[forwardMethod] = function(...args) {
|
|
54
56
|
const connection = this.getCurrentConnection()
|
|
57
|
+
const connectionMethod = connection[forwardMethod]
|
|
58
|
+
|
|
59
|
+
if (!connectionMethod) throw new Error(`${forwardMethod} isn't defined on driver`)
|
|
55
60
|
|
|
56
61
|
return connection[forwardMethod](...args)
|
|
57
62
|
}
|
|
@@ -3,7 +3,8 @@ export default class VelociousDatabaseQueryBase {
|
|
|
3
3
|
this.driver = driver
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
getDriver = () => this.driver
|
|
7
|
+
getOptions = () => this.getDriver()?.options()
|
|
7
8
|
|
|
8
9
|
toSql() {
|
|
9
10
|
throw new Error("'toSql' wasn't implemented")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {digs} from "diggerize"
|
|
2
|
+
import QueryBase from "./base.mjs"
|
|
3
|
+
|
|
4
|
+
export default class VelociousDatabaseQueryCreateIndexBase extends QueryBase {
|
|
5
|
+
constructor({columns, driver, ifNotExists, name, unique, tableName}) {
|
|
6
|
+
super({driver})
|
|
7
|
+
this.columns = columns
|
|
8
|
+
this.name = name
|
|
9
|
+
this.tableName = tableName
|
|
10
|
+
this.ifNotExists = ifNotExists
|
|
11
|
+
this.unique = unique
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
generateIndexName() {
|
|
15
|
+
let indexName = `index_on_${this.tableName}_`
|
|
16
|
+
|
|
17
|
+
for (const columnIndex in this.columns) {
|
|
18
|
+
if (columnIndex > 0) indexName += "_"
|
|
19
|
+
|
|
20
|
+
indexName += this.columns[columnIndex]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return indexName
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
toSql() {
|
|
27
|
+
const {tableName} = this
|
|
28
|
+
const {columnQuote, indexQuote, tableQuote} = digs(this.getOptions(), "columnQuote", "indexQuote", "tableQuote")
|
|
29
|
+
let sql = "CREATE"
|
|
30
|
+
|
|
31
|
+
if (this.unique) sql += " UNIQUE"
|
|
32
|
+
|
|
33
|
+
sql += " INDEX"
|
|
34
|
+
|
|
35
|
+
if (this.ifNotExists) sql += " IF NOT EXISTS"
|
|
36
|
+
|
|
37
|
+
sql += ` ${indexQuote}${this.name || this.generateIndexName()}${indexQuote}`
|
|
38
|
+
sql += ` ON ${tableQuote}${tableName}${tableQuote} (`
|
|
39
|
+
|
|
40
|
+
for (const columnIndex in this.columns) {
|
|
41
|
+
if (columnIndex > 0) sql += ", "
|
|
42
|
+
|
|
43
|
+
sql += `${columnQuote}${this.columns[columnIndex]}${columnQuote}`
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
sql += ")"
|
|
47
|
+
|
|
48
|
+
return sql
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import CreateIndexBase from "./create-index-base.mjs"
|
|
1
2
|
import QueryBase from "./base.mjs"
|
|
2
3
|
|
|
3
4
|
export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
4
|
-
constructor({driver, ifNotExists, tableData}) {
|
|
5
|
+
constructor({driver, ifNotExists, indexInCreateTable = true, tableData}) {
|
|
5
6
|
super({driver})
|
|
6
7
|
this.ifNotExists = ifNotExists
|
|
8
|
+
this.indexInCreateTable = indexInCreateTable
|
|
7
9
|
this.tableData = tableData
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
toSql() {
|
|
11
13
|
const {tableData} = this
|
|
14
|
+
const sqls = []
|
|
15
|
+
|
|
12
16
|
let sql = "CREATE TABLE"
|
|
13
17
|
|
|
14
18
|
if (this.ifNotExists || tableData.getIfNotExists()) sql += " IF NOT EXISTS"
|
|
@@ -36,34 +40,53 @@ export default class VelociousDatabaseQueryCreateTableBase extends QueryBase {
|
|
|
36
40
|
|
|
37
41
|
if (column.args.autoIncrement) sql += " AUTO_INCREMENT"
|
|
38
42
|
if (column.args.primaryKey) sql += " PRIMARY KEY"
|
|
43
|
+
if (column.args.null === false) sql += " NOT NULL"
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
if (this.indexInCreateTable) {
|
|
47
|
+
for (const index of tableData.getIndexes()) {
|
|
48
|
+
sql += ","
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
if (index.getUnique()) {
|
|
51
|
+
sql += " UNIQUE"
|
|
52
|
+
}
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
sql += " INDEX"
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
if (index.getName()) {
|
|
57
|
+
sql += ` ${index.getName()}`
|
|
58
|
+
}
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
sql += " ("
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
index.getColumns().forEach((column, columnIndex) => {
|
|
63
|
+
if (columnIndex > 0) sql += ", "
|
|
58
64
|
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
sql += this.driver.quoteColumn(column.name)
|
|
66
|
+
})
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
sql += ")"
|
|
69
|
+
}
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
sql += ")"
|
|
66
73
|
|
|
67
|
-
|
|
74
|
+
sqls.push(sql)
|
|
75
|
+
|
|
76
|
+
if (!this.indexInCreateTable) {
|
|
77
|
+
for (const index of tableData.getIndexes()) {
|
|
78
|
+
const createIndexArgs = {
|
|
79
|
+
columns: index.getColumns(),
|
|
80
|
+
driver: this.getDriver(),
|
|
81
|
+
tableName: tableData.getName(),
|
|
82
|
+
unique: index.getUnique()
|
|
83
|
+
}
|
|
84
|
+
const sql = new CreateIndexBase(createIndexArgs).toSql()
|
|
85
|
+
|
|
86
|
+
sqls.push(sql)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return [sql]
|
|
68
91
|
}
|
|
69
92
|
}
|