objection 4.0.0-rc.2 → 4.0.0-rc.4
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/lib/queryBuilder/InternalOptions.js +4 -0
- package/lib/queryBuilder/graph/GraphLoader.js +201 -126
- package/lib/queryBuilder/graph/GraphNode.js +18 -3
- package/lib/queryBuilder/graph/GraphOptions.js +24 -49
- package/lib/queryBuilder/graph/GraphPlan.js +105 -108
- package/lib/queryBuilder/graph/GraphSchedule.js +102 -55
- package/lib/queryBuilder/graph/GraphUpsert.js +48 -548
- package/lib/queryBuilder/graph/GraphWriter.js +355 -28
- package/lib/queryBuilder/graph/graphChecks.js +534 -0
- package/lib/queryBuilder/graph/graphKeys.js +189 -418
- package/lib/queryBuilder/jsonDialects/JsonDialect.js +6 -0
- package/lib/queryBuilder/operations/UpdateOperation.js +5 -2
- package/lib/queryBuilder/operations/fieldExpressions.js +10 -7
- package/lib/relations/RelationProperty.js +6 -0
- package/package.json +3 -2
- package/typings/objection/index.d.ts +516 -163
|
@@ -17,6 +17,12 @@ export class JsonDialect {
|
|
|
17
17
|
return sql;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// The value that the path updates of a column start from, an empty one where
|
|
21
|
+
// the column is NULL, as `set()` leaves NULL as it is.
|
|
22
|
+
setBase(sql, access) {
|
|
23
|
+
return `COALESCE(${sql}, '${access[0].type === 'array' ? '[]' : '{}'}')`;
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
// Reference the bare column if there is no path, so that the database can use
|
|
21
27
|
// its indexes.
|
|
22
28
|
field(sql, access) {
|
|
@@ -70,8 +70,11 @@ export class UpdateOperation extends QueryBuilderOperation {
|
|
|
70
70
|
if (this.modelOptions.patch) {
|
|
71
71
|
return knexBuilder.update(convertFieldExpressionsToRaw(builder, json));
|
|
72
72
|
} else {
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const { fieldExpressionKeys } = builder.internalOptions();
|
|
74
|
+
checkFieldExpressions(builder.modelClass(), this.model, 'update', fieldExpressionKeys);
|
|
75
|
+
return knexBuilder.update(
|
|
76
|
+
fieldExpressionKeys.length > 0 ? convertFieldExpressionsToRaw(builder, json) : json,
|
|
77
|
+
);
|
|
75
78
|
}
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -7,13 +7,14 @@ import { ValidationErrorType } from '../../model/ValidationError.js';
|
|
|
7
7
|
import { getQueryPropKeys } from '../../model/modelQueryProps.js';
|
|
8
8
|
|
|
9
9
|
// Inserts and updates write whole values, so they can't write into json
|
|
10
|
-
// columns with field expressions like `'meta:color'
|
|
11
|
-
//
|
|
12
|
-
|
|
10
|
+
// columns with field expressions like `'meta:color'`, except for the
|
|
11
|
+
// `allowedKeys` of internal writes. Keys with a ':' that don't parse as field
|
|
12
|
+
// expressions are columns, as in the query properties.
|
|
13
|
+
export function checkFieldExpressions(modelClass, model, operation, allowedKeys = []) {
|
|
13
14
|
const keys = getFieldExpressionKeys(modelClass, [
|
|
14
15
|
...Object.keys(model),
|
|
15
16
|
...getQueryPropKeys(model),
|
|
16
|
-
]);
|
|
17
|
+
]).filter((key) => !allowedKeys.includes(key));
|
|
17
18
|
|
|
18
19
|
if (keys.length > 0) {
|
|
19
20
|
throw modelClass.createValidationError({
|
|
@@ -48,7 +49,7 @@ export function convertFieldExpressionsToRaw(builder, json) {
|
|
|
48
49
|
|
|
49
50
|
if (getFieldExpressionColumn(key, declaredColumns) !== null) {
|
|
50
51
|
// 'col:attr' : ref('other:lol') is transformed to
|
|
51
|
-
// "col" : raw(`jsonb_set("table"."col", '{attr}', to_jsonb("other"#>'{lol}'), true)`)
|
|
52
|
+
// "col" : raw(`jsonb_set(COALESCE("table"."col", '{}'), '{attr}', to_jsonb("other"#>'{lol}'), true)`)
|
|
52
53
|
// on Postgres, with the column qualified, as it is ambiguous with
|
|
53
54
|
// `excluded` in merge().
|
|
54
55
|
dialect.checkSupport();
|
|
@@ -82,9 +83,11 @@ export function convertFieldExpressionsToRaw(builder, json) {
|
|
|
82
83
|
val = JSON.stringify(val);
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
const { access } = parsed.parsedExpr;
|
|
87
|
+
const previous = convertedJson[parsed.column];
|
|
85
88
|
convertedJson[parsed.column] = knex.raw(
|
|
86
|
-
dialect.set('??',
|
|
87
|
-
[
|
|
89
|
+
dialect.set(previous ? '??' : dialect.setBase('??', access), access, valuePlaceholder),
|
|
90
|
+
[previous || `${builder.tableRef()}.${parsed.column}`, val],
|
|
88
91
|
);
|
|
89
92
|
} else {
|
|
90
93
|
convertedJson[key] = val;
|
|
@@ -126,6 +126,12 @@ export class RelationProperty {
|
|
|
126
126
|
return this._propSetters[index](obj, value);
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
// Returns true if the index:th column is a key at the top level of a json
|
|
130
|
+
// column.
|
|
131
|
+
isJsonKey(index) {
|
|
132
|
+
return this._refs[index].parsedExpr.access.length === 1;
|
|
133
|
+
}
|
|
134
|
+
|
|
129
135
|
// Returns an instance of ReferenceBuilder that points to the index:th
|
|
130
136
|
// value of a row.
|
|
131
137
|
ref(builder, index) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "objection",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
3
|
+
"version": "4.0.0-rc.4",
|
|
4
4
|
"description": "An SQL-friendly ORM for Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/objection.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"test": "pnpm eslint && vitest run && pnpm test:typings",
|
|
18
18
|
"test:fast": "vitest run --bail 1",
|
|
19
19
|
"test:watch": "vitest",
|
|
20
|
-
"test:typings": "tsc && tsc -p tests/ts/strict && tsc -p tests/bench/typings && prettier --check \"typings/**/*.ts\" \"tests/ts/**/*.ts\" \"tests/bench/typings/app/*.ts\"",
|
|
20
|
+
"test:typings": "tsc && tsc -p tests/ts/strict && tsc -p tests/bench/typings && node tests/ts/completions.js && prettier --check \"typings/**/*.ts\" \"tests/ts/**/*.ts\" \"tests/bench/typings/*.ts\" \"tests/bench/typings/app/*.ts\"",
|
|
21
21
|
"bench:typings": "node tests/bench/typings/bench.js",
|
|
22
22
|
"db:up": "docker compose up -d --wait",
|
|
23
23
|
"db:down": "docker compose --profile mssql down -v",
|
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
"sqlite3": "^6.0.1",
|
|
92
92
|
"tedious": "^20.3.7",
|
|
93
93
|
"typescript": "^7.0.0",
|
|
94
|
+
"typescript-5": "npm:typescript@5.8.3",
|
|
94
95
|
"vitepress": "1.6.4",
|
|
95
96
|
"vitest": "^4.1.11"
|
|
96
97
|
}
|