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.
Files changed (69) hide show
  1. package/package.json +5 -3
  2. package/spec/cli/commands/db/create-spec.mjs +1 -1
  3. package/spec/cli/commands/db/migrate-spec.mjs +2 -0
  4. package/spec/database/record/create-spec.mjs +9 -0
  5. package/spec/database/record/find-spec.mjs +0 -1
  6. package/spec/database/record/query-spec.mjs +37 -0
  7. package/spec/dummy/index.mjs +14 -2
  8. package/spec/dummy/src/config/configuration.example.mjs +16 -1
  9. package/spec/dummy/src/config/configuration.peakflow.mjs +16 -1
  10. package/spec/dummy/src/database/migrations/20230728075328-create-projects.mjs +0 -1
  11. package/spec/dummy/src/database/migrations/20230728075329-create-tasks.mjs +0 -1
  12. package/spec/dummy/src/database/migrations/20250605133926-create-project-translations.mjs +16 -0
  13. package/spec/dummy/src/models/project.mjs +9 -0
  14. package/spec/dummy/src/models/task.mjs +5 -1
  15. package/src/big-brother.mjs +37 -0
  16. package/src/cli/commands/db/create.mjs +8 -6
  17. package/src/cli/commands/db/migrate.mjs +1 -2
  18. package/src/cli/commands/generate/migration.mjs +1 -1
  19. package/src/cli/commands/generate/model.mjs +1 -1
  20. package/src/configuration.mjs +39 -3
  21. package/src/database/drivers/base.mjs +21 -2
  22. package/src/database/drivers/mysql/column.mjs +8 -0
  23. package/src/database/drivers/mysql/index.mjs +34 -2
  24. package/src/database/drivers/mysql/options.mjs +1 -0
  25. package/src/database/drivers/mysql/query-parser.mjs +2 -23
  26. package/src/database/drivers/mysql/table.mjs +25 -0
  27. package/src/database/drivers/sqlite/base.mjs +76 -4
  28. package/src/database/drivers/sqlite/column.mjs +10 -0
  29. package/src/database/drivers/sqlite/index.native.mjs +19 -22
  30. package/src/database/drivers/sqlite/index.web.mjs +27 -17
  31. package/src/database/drivers/sqlite/options.mjs +2 -1
  32. package/src/database/drivers/sqlite/query-parser.mjs +2 -23
  33. package/src/database/drivers/sqlite/query.native.mjs +16 -1
  34. package/src/database/drivers/sqlite/query.web.mjs +27 -2
  35. package/src/database/drivers/sqlite/sql/create-index.mjs +4 -0
  36. package/src/database/drivers/sqlite/table.mjs +16 -1
  37. package/src/database/initializer-from-require-context.mjs +21 -0
  38. package/src/database/migration/index.mjs +34 -2
  39. package/src/database/migrator.mjs +4 -2
  40. package/src/database/pool/base.mjs +5 -0
  41. package/src/database/query/base.mjs +2 -1
  42. package/src/database/query/create-index-base.mjs +50 -0
  43. package/src/database/query/create-table-base.mjs +40 -17
  44. package/src/database/query/index.mjs +83 -21
  45. package/src/database/query/preloader/belongs-to.mjs +52 -0
  46. package/src/database/query/preloader/has-many.mjs +55 -0
  47. package/src/database/query/preloader.mjs +41 -0
  48. package/src/database/query/where-base.mjs +9 -0
  49. package/src/database/query/where-hash.mjs +35 -0
  50. package/src/database/query/where-plain.mjs +13 -0
  51. package/src/database/query-parser/base-query-parser.mjs +33 -0
  52. package/src/database/query-parser/group-parser.mjs +40 -0
  53. package/src/database/query-parser/joins-parser.mjs +48 -7
  54. package/src/database/query-parser/limit-parser.mjs +40 -0
  55. package/src/database/query-parser/options.mjs +2 -1
  56. package/src/database/query-parser/order-parser.mjs +39 -0
  57. package/src/database/query-parser/select-parser.mjs +5 -1
  58. package/src/database/query-parser/where-parser.mjs +39 -0
  59. package/src/database/record/index.mjs +464 -29
  60. package/src/database/record/instance-relationships/base.mjs +28 -0
  61. package/src/database/record/instance-relationships/belongs-to.mjs +20 -0
  62. package/src/database/record/instance-relationships/has-many.mjs +47 -0
  63. package/src/database/record/relationships/base.mjs +32 -0
  64. package/src/database/record/relationships/belongs-to.mjs +12 -0
  65. package/src/database/record/relationships/has-many.mjs +12 -0
  66. package/src/database/table-data/index.mjs +15 -25
  67. package/src/http-server/worker-handler/worker-thread.mjs +7 -4
  68. package/src/templates/generate-model.mjs +3 -1
  69. 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
- quoteColumn = (string) => `\`${string}\``
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
  }
@@ -0,0 +1,10 @@
1
+ import {digg} from "diggerize"
2
+
3
+ export default class VelociousDatabaseDriversSqliteColumn {
4
+ constructor({column, driver}) {
5
+ this.column = column
6
+ this.driver = driver
7
+ }
8
+
9
+ getName = () => digg(this, "column", "name")
10
+ }
@@ -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 connection = await SQLite.openDatabaseAsync(digg(this.getArgs(), "name"))
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 = connection
24
+ this.connection = await SQLite.openDatabaseAsync(databaseName)
13
25
  }
14
26
 
15
- disconnect() {
16
- this.connection.end()
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 Base from "./base.mjs"
1
+ import BetterLocalStorage from "better-localstorage"
2
+ import debounce from "debounce"
2
3
  import {digg} from "diggerize"
3
- import Options from "../sqlite/options.mjs"
4
+ import initSqlJs from "sql.js"
4
5
  import query from "./query"
5
6
 
6
- import initSqlJs from "sql.js"
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 = localStorage.getItem(this.localStorageName())
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 = () => localStorage.setItem(this.localStorageName(), this.connection.export())
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) => await query(this.connection, sql)
31
-
32
- quote(string) {
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
- options() {
39
- if (!this._options) {
40
- this._options = new Options({driver: 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 this._options
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 VelociousDatabaseDriversMysqlOptions extends QueryParserOptions {
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 {digs} from "diggerize"
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 VelociousDatabaseConnectionDriversMysqlQueryParser {
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
- for await (const entry of connection.getEachAsync(sql)) {
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
- for await (const entry of connection.exec(sql)) {
5
- rows.push(entry)
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
@@ -0,0 +1,4 @@
1
+ import CreateIndexBase from "../../../query/create-index-base.mjs"
2
+
3
+ export default class VelociousDatabaseConnectionDriversMysqlSqlCreateIndex extends CreateIndexBase {
4
+ }
@@ -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 sql = databasePool.createTableSql(tableData)
30
+ const sqls = databasePool.createTableSql(tableData)
15
31
 
16
- await databasePool.query(sql)
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 createSchemaMigrationsTableSql = db.createTableSql(schemaMigrationsTable)
23
+ const createSchemaMigrationsTableSqls = db.createTableSql(schemaMigrationsTable)
24
24
 
25
- await db.query(createSchemaMigrationsTableSql)
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
- getOptions = () => this.driver?.options()
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
- for (const index of tableData.getIndexes()) {
42
- sql += ","
46
+ if (this.indexInCreateTable) {
47
+ for (const index of tableData.getIndexes()) {
48
+ sql += ","
43
49
 
44
- if (index.getUnique()) {
45
- sql += " UNIQUE"
46
- }
50
+ if (index.getUnique()) {
51
+ sql += " UNIQUE"
52
+ }
47
53
 
48
- sql += " INDEX"
54
+ sql += " INDEX"
49
55
 
50
- if (index.getName()) {
51
- sql += ` ${index.getName()}`
52
- }
56
+ if (index.getName()) {
57
+ sql += ` ${index.getName()}`
58
+ }
53
59
 
54
- sql += " ("
60
+ sql += " ("
55
61
 
56
- index.getColumns().forEach((column, columnIndex) => {
57
- if (columnIndex > 0) sql += ", "
62
+ index.getColumns().forEach((column, columnIndex) => {
63
+ if (columnIndex > 0) sql += ", "
58
64
 
59
- sql += this.driver.quoteColumn(column.name)
60
- })
65
+ sql += this.driver.quoteColumn(column.name)
66
+ })
61
67
 
62
- sql += ")"
68
+ sql += ")"
69
+ }
63
70
  }
64
71
 
65
72
  sql += ")"
66
73
 
67
- return sql
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
  }