velocious 1.0.8 → 1.0.10
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/src/database/drivers/base.js +25 -0
- package/src/database/drivers/mysql/index.js +3 -2
- package/src/database/drivers/mysql/sql/insert.js +0 -25
- package/src/database/drivers/sqlite/base.js +61 -2
- package/src/database/drivers/sqlite/index.native.js +1 -0
- package/src/database/drivers/sqlite/index.web.js +1 -0
- package/src/database/drivers/sqlite/sql/insert.js +0 -25
- package/src/database/migrate-from-require-context.js +3 -4
- package/src/database/query/insert-base.js +59 -3
- package/src/database/record/index.js +36 -4
- package/src/database/record/instance-relationships/has-many.js +0 -4
package/package.json
CHANGED
|
@@ -69,6 +69,31 @@ export default class VelociousDatabaseDriversBase {
|
|
|
69
69
|
this.idSeq = id
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
async tableExists(tableName) {
|
|
73
|
+
const tables = await this.getTables()
|
|
74
|
+
const table = tables.find((table) => table.getName() == tableName)
|
|
75
|
+
|
|
76
|
+
if (table) return true
|
|
77
|
+
|
|
78
|
+
return false
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async transaction(callback) {
|
|
82
|
+
await this.query("BEGIN TRANSACTION")
|
|
83
|
+
|
|
84
|
+
let result
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
result = await callback()
|
|
88
|
+
await this.query("COMMIT")
|
|
89
|
+
} catch (error) {
|
|
90
|
+
this.query("ROLLBACK")
|
|
91
|
+
throw error
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result
|
|
95
|
+
}
|
|
96
|
+
|
|
72
97
|
async update(...args) {
|
|
73
98
|
const sql = this.updateSql(...args)
|
|
74
99
|
|
|
@@ -93,8 +93,9 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
93
93
|
return deleteInstruction.toSql()
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
insertSql(
|
|
97
|
-
const
|
|
96
|
+
insertSql(args) {
|
|
97
|
+
const insertArgs = Object.assign({driver: this}, args)
|
|
98
|
+
const insert = new Insert(insertArgs)
|
|
98
99
|
|
|
99
100
|
return insert.toSql()
|
|
100
101
|
}
|
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
import InsertBase from "../../../query/insert-base.js"
|
|
2
2
|
|
|
3
3
|
export default class VelociousDatabaseConnectionDriversMysqlSqlInsert extends InsertBase {
|
|
4
|
-
toSql() {
|
|
5
|
-
let sql = `INSERT INTO ${this.getOptions().quoteTableName(this.tableName)} (`
|
|
6
|
-
let count = 0
|
|
7
|
-
|
|
8
|
-
for (let columnName in this.data) {
|
|
9
|
-
if (count > 0) sql += ", "
|
|
10
|
-
|
|
11
|
-
sql += this.getOptions().quoteColumnName(columnName)
|
|
12
|
-
count++
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
sql += ") VALUES ("
|
|
16
|
-
count = 0
|
|
17
|
-
|
|
18
|
-
for (let columnName in this.data) {
|
|
19
|
-
if (count > 0) sql += ", "
|
|
20
|
-
|
|
21
|
-
sql += this.getOptions().quote(this.data[columnName])
|
|
22
|
-
count++
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
sql += ")"
|
|
26
|
-
|
|
27
|
-
return sql
|
|
28
|
-
}
|
|
29
4
|
}
|
|
@@ -34,8 +34,8 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
34
34
|
return createTable.toSql()
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
deleteSql = (
|
|
38
|
-
insertSql = (
|
|
37
|
+
deleteSql = (args) => new Delete(Object.assign({driver: this}, args)).toSql()
|
|
38
|
+
insertSql = (args) => new Insert(Object.assign({driver: this}, args)).toSql()
|
|
39
39
|
|
|
40
40
|
async getTableByName(tableName) {
|
|
41
41
|
const result = await this.query(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${this.quote(tableName)} LIMIT 1`)
|
|
@@ -64,6 +64,53 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
64
64
|
return tables
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
async insertMultiple(...args) {
|
|
68
|
+
if (this.supportsMultipleInsertValues()) {
|
|
69
|
+
return await this.insertMultipleWithSingleInsert(...args)
|
|
70
|
+
} else {
|
|
71
|
+
return await this.insertMultipleWithTransaction(...args)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
supportsMultipleInsertValues() {
|
|
76
|
+
if (this.versionMajor >= 4) return true
|
|
77
|
+
if (this.versionMajor == 3 && this.versionMinor >= 8) return true
|
|
78
|
+
if (this.versionMajor == 3 && this.versionMinor == 7 && this.versionPatch >= 11) return true
|
|
79
|
+
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async insertMultipleWithSingleInsert(tableName, columns, rows) {
|
|
84
|
+
const sql = new Insert({columns, driver: this, rows, tableName}).toSql()
|
|
85
|
+
|
|
86
|
+
return await this.query(sql)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async insertMultipleWithTransaction(tableName, columns, rows) {
|
|
90
|
+
const sqls = []
|
|
91
|
+
|
|
92
|
+
for (const row of rows) {
|
|
93
|
+
const data = []
|
|
94
|
+
|
|
95
|
+
for (const columnIndex in columns) {
|
|
96
|
+
const columnName = columns[columnIndex]
|
|
97
|
+
const value = row[columnIndex]
|
|
98
|
+
|
|
99
|
+
data[columnName] = value
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const insertSql = this.insertSql({tableName, data})
|
|
103
|
+
|
|
104
|
+
sqls.push(insertSql)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
await this.transaction(async () => {
|
|
108
|
+
for (const sql of sqls) {
|
|
109
|
+
await this.query(sql)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
67
114
|
async lastInsertID() {
|
|
68
115
|
const result = await this.query("SELECT LAST_INSERT_ROWID() AS last_insert_id")
|
|
69
116
|
|
|
@@ -80,6 +127,18 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
80
127
|
|
|
81
128
|
queryToSql = (query) => new QueryParser({query}).toSql()
|
|
82
129
|
|
|
130
|
+
async registerVersion() {
|
|
131
|
+
const versionResult = await this.query("SELECT sqlite_version() AS version")
|
|
132
|
+
|
|
133
|
+
this.version = versionResult[0].version
|
|
134
|
+
|
|
135
|
+
const versionParts = this.version.split(".")
|
|
136
|
+
|
|
137
|
+
this.versionMajor = versionParts[0]
|
|
138
|
+
this.versionMinor = versionParts[1]
|
|
139
|
+
this.versionPatch = versionParts[2]
|
|
140
|
+
}
|
|
141
|
+
|
|
83
142
|
escape(value) {
|
|
84
143
|
const type = typeof value
|
|
85
144
|
|
|
@@ -24,6 +24,7 @@ export default class VelociousDatabaseDriversSqliteWeb extends Base {
|
|
|
24
24
|
const databaseContent = await this.betterLocaleStorage.get(this.localStorageName())
|
|
25
25
|
|
|
26
26
|
this.connection = new SQL.Database(databaseContent)
|
|
27
|
+
await this.registerVersion()
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
localStorageName = () => `VelociousDatabaseDriversSqliteWeb---${digg(this.getArgs(), "name")}`
|
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
import InsertBase from "../../../query/insert-base.js"
|
|
2
2
|
|
|
3
3
|
export default class VelociousDatabaseConnectionDriversMysqlSqlInsert extends InsertBase {
|
|
4
|
-
toSql() {
|
|
5
|
-
let sql = `INSERT INTO ${this.getOptions().quoteTableName(this.tableName)} (`
|
|
6
|
-
let count = 0
|
|
7
|
-
|
|
8
|
-
for (let columnName in this.data) {
|
|
9
|
-
if (count > 0) sql += ", "
|
|
10
|
-
|
|
11
|
-
sql += this.getOptions().quoteColumnName(columnName)
|
|
12
|
-
count++
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
sql += ") VALUES ("
|
|
16
|
-
count = 0
|
|
17
|
-
|
|
18
|
-
for (let columnName in this.data) {
|
|
19
|
-
if (count > 0) sql += ", "
|
|
20
|
-
|
|
21
|
-
sql += this.getOptions().quote(this.data[columnName])
|
|
22
|
-
count++
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
sql += ")"
|
|
26
|
-
|
|
27
|
-
return sql
|
|
28
|
-
}
|
|
29
4
|
}
|
|
@@ -5,12 +5,11 @@ import Migrator from "./migrator"
|
|
|
5
5
|
export default class VelociousDatabaseMigrateFromRequireContext {
|
|
6
6
|
constructor(configuration) {
|
|
7
7
|
this.configuration = configuration || Configuration.current()
|
|
8
|
+
this.migrator = new Migrator({configuration: this.configuration})
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
async execute(requireContext) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
await migrator.prepare()
|
|
12
|
+
await this.migrator.prepare()
|
|
14
13
|
|
|
15
14
|
const files = requireContext.keys()
|
|
16
15
|
.map((file) => {
|
|
@@ -32,7 +31,7 @@ export default class VelociousDatabaseMigrateFromRequireContext {
|
|
|
32
31
|
.sort((migration1, migration2) => migration1.date - migration2.date)
|
|
33
32
|
|
|
34
33
|
for (const migration of files) {
|
|
35
|
-
if (!migrator.hasRunMigrationVersion(migration.date)) {
|
|
34
|
+
if (!this.migrator.hasRunMigrationVersion(migration.date)) {
|
|
36
35
|
await this.runMigrationFile(migration, requireContext)
|
|
37
36
|
}
|
|
38
37
|
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import restArgsError from "../../utils/rest-args-error.js"
|
|
2
|
+
|
|
1
3
|
export default class VelociousDatabaseQueryInsertBase {
|
|
2
|
-
constructor({driver, tableName,
|
|
4
|
+
constructor({columns, data, driver, multiple, tableName, rows, ...restArgs}) {
|
|
3
5
|
if (!driver) throw new Error("No driver given to insert base")
|
|
4
6
|
if (!tableName) throw new Error(`Invalid table name given to insert base: ${tableName}`)
|
|
5
|
-
if (!data) throw new Error("No data given to insert base")
|
|
6
7
|
|
|
8
|
+
restArgsError(restArgs)
|
|
9
|
+
|
|
10
|
+
this.columns = columns
|
|
7
11
|
this.data = data
|
|
8
12
|
this.driver = driver
|
|
13
|
+
this.multiple = multiple
|
|
14
|
+
this.rows = rows
|
|
9
15
|
this.tableName = tableName
|
|
10
16
|
}
|
|
11
17
|
|
|
@@ -14,6 +20,56 @@ export default class VelociousDatabaseQueryInsertBase {
|
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
toSql() {
|
|
17
|
-
|
|
23
|
+
let sql = `INSERT INTO ${this.getOptions().quoteTableName(this.tableName)} (`
|
|
24
|
+
let count = 0
|
|
25
|
+
let columns
|
|
26
|
+
|
|
27
|
+
if (this.columns && this.rows) {
|
|
28
|
+
columns = this.columns
|
|
29
|
+
} else if (this.data) {
|
|
30
|
+
columns = Object.keys(this.data)
|
|
31
|
+
} else {
|
|
32
|
+
throw new Error("Neither 'column' and 'rows' or data was given")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const columnName of columns) {
|
|
36
|
+
if (count > 0) sql += ", "
|
|
37
|
+
|
|
38
|
+
sql += this.getOptions().quoteColumnName(columnName)
|
|
39
|
+
count++
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
sql += ") VALUES "
|
|
43
|
+
|
|
44
|
+
if (this.columns && this.rows) {
|
|
45
|
+
let count = 0
|
|
46
|
+
|
|
47
|
+
for (const row of this.rows) {
|
|
48
|
+
if (count >= 1) sql += ", "
|
|
49
|
+
|
|
50
|
+
count++
|
|
51
|
+
sql += this._valuesSql(row)
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
sql += this._valuesSql(Object.values(this.data))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return sql
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_valuesSql(data) {
|
|
61
|
+
let count = 0
|
|
62
|
+
let sql = "("
|
|
63
|
+
|
|
64
|
+
for (const value of data) {
|
|
65
|
+
if (count > 0) sql += ", "
|
|
66
|
+
|
|
67
|
+
sql += this.getOptions().quote(value)
|
|
68
|
+
count++
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
sql += ")"
|
|
72
|
+
|
|
73
|
+
return sql
|
|
18
74
|
}
|
|
19
75
|
}
|
|
@@ -19,6 +19,7 @@ export default class VelociousDatabaseRecord {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
static _defineRelationship(relationshipName, data) {
|
|
22
|
+
if (!relationshipName) throw new Error(`Invalid relationship name given: ${relationshipName}`)
|
|
22
23
|
if (!this._relationships) this._relationships = {}
|
|
23
24
|
if (this._relationshipExists(relationshipName)) throw new Error(`Relationship ${relationshipName} already exists`)
|
|
24
25
|
|
|
@@ -77,6 +78,12 @@ export default class VelociousDatabaseRecord {
|
|
|
77
78
|
return relationship
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
static getRelationships() {
|
|
82
|
+
if (this._relationships) return Object.values(this._relationships)
|
|
83
|
+
|
|
84
|
+
return []
|
|
85
|
+
}
|
|
86
|
+
|
|
80
87
|
getRelationshipByName(relationshipName) {
|
|
81
88
|
if (!this._instanceRelationships) this._instanceRelationships = {}
|
|
82
89
|
|
|
@@ -269,6 +276,10 @@ export default class VelociousDatabaseRecord {
|
|
|
269
276
|
return this._table
|
|
270
277
|
}
|
|
271
278
|
|
|
279
|
+
static async insertMultiple(columns, rows) {
|
|
280
|
+
return await this.connection().insertMultiple(this.tableName(), columns, rows)
|
|
281
|
+
}
|
|
282
|
+
|
|
272
283
|
static async last() {
|
|
273
284
|
const query = this._newQuery().order(this.primaryKey())
|
|
274
285
|
const record = await query.last()
|
|
@@ -308,7 +319,7 @@ export default class VelociousDatabaseRecord {
|
|
|
308
319
|
|
|
309
320
|
const model = instanceRelationship.loaded()
|
|
310
321
|
|
|
311
|
-
if (model
|
|
322
|
+
if (model?.isChanged()) {
|
|
312
323
|
await model.save()
|
|
313
324
|
|
|
314
325
|
const foreignKey = instanceRelationship.getForeignKey()
|
|
@@ -409,9 +420,11 @@ export default class VelociousDatabaseRecord {
|
|
|
409
420
|
}
|
|
410
421
|
|
|
411
422
|
_setTranslatedAttribute(name, locale, newValue) {
|
|
412
|
-
let translation = this.translations().loaded()?.find((translation) =>translation.locale() == locale)
|
|
423
|
+
let translation = this.translations().loaded()?.find((translation) => translation.locale() == locale)
|
|
413
424
|
|
|
414
|
-
if (!translation)
|
|
425
|
+
if (!translation) {
|
|
426
|
+
translation = this.translations().build({locale})
|
|
427
|
+
}
|
|
415
428
|
|
|
416
429
|
const assignments = {}
|
|
417
430
|
|
|
@@ -513,7 +526,7 @@ export default class VelociousDatabaseRecord {
|
|
|
513
526
|
_hasChanges = () => Object.keys(this._changes).length > 0
|
|
514
527
|
|
|
515
528
|
isChanged() {
|
|
516
|
-
if (this.isNewRecord() || this._hasChanges())
|
|
529
|
+
if (this.isNewRecord() || this._hasChanges()){
|
|
517
530
|
return true
|
|
518
531
|
}
|
|
519
532
|
|
|
@@ -537,6 +550,18 @@ export default class VelociousDatabaseRecord {
|
|
|
537
550
|
return false
|
|
538
551
|
}
|
|
539
552
|
|
|
553
|
+
changes() {
|
|
554
|
+
const changes = {}
|
|
555
|
+
|
|
556
|
+
for (const changeKey in this._changes) {
|
|
557
|
+
const changeValue = this._changes[changeKey]
|
|
558
|
+
|
|
559
|
+
changes[changeKey] = [this._attributes[changeKey], changeValue]
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return changes
|
|
563
|
+
}
|
|
564
|
+
|
|
540
565
|
_tableName() {
|
|
541
566
|
if (this.__tableName) return this.__tableName
|
|
542
567
|
|
|
@@ -569,6 +594,13 @@ export default class VelociousDatabaseRecord {
|
|
|
569
594
|
|
|
570
595
|
await this._reloadWithId(id)
|
|
571
596
|
this.setIsNewRecord(false)
|
|
597
|
+
|
|
598
|
+
// Mark all relationships as preloaded, since we don't expect anything to have magically appeared since we created the record.
|
|
599
|
+
for (const relationship of this.constructor.getRelationships()) {
|
|
600
|
+
const instanceRelationship = this.getRelationshipByName(relationship.getRelationshipName())
|
|
601
|
+
|
|
602
|
+
instanceRelationship.setPreloaded(true)
|
|
603
|
+
}
|
|
572
604
|
}
|
|
573
605
|
|
|
574
606
|
async _updateRecordWithChanges() {
|
|
@@ -39,9 +39,5 @@ export default class VelociousDatabaseRecordHasManyInstanceRelationship extends
|
|
|
39
39
|
this._loaded = models
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
setPreloaded(preloadedValue) {
|
|
43
|
-
this._preloaded = preloadedValue
|
|
44
|
-
}
|
|
45
|
-
|
|
46
42
|
getTargetModelClass = () => this.relationship.getTargetModelClass()
|
|
47
43
|
}
|