@sqb/connect 4.15.0 → 4.16.0
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/esm/client/adapter.js +1 -2
- package/esm/client/cursor-stream.js +4 -9
- package/esm/client/cursor.js +17 -22
- package/esm/client/extensions.js +1 -5
- package/esm/client/field-info-map.js +1 -5
- package/esm/client/helpers.js +12 -19
- package/esm/client/sqb-client.js +27 -32
- package/esm/client/sqb-connection.js +36 -41
- package/esm/client/types.js +1 -5
- package/esm/index.js +32 -40
- package/esm/orm/backward.js +12 -19
- package/esm/orm/base-entity.js +6 -10
- package/esm/orm/commands/command.helper.js +28 -34
- package/esm/orm/commands/count.command.js +6 -10
- package/esm/orm/commands/create.command.js +14 -18
- package/esm/orm/commands/delete.command.js +6 -10
- package/esm/orm/commands/find.command.js +30 -34
- package/esm/orm/commands/row-converter.js +3 -7
- package/esm/orm/commands/update.command.js +14 -18
- package/esm/orm/decorators/column.decorator.js +7 -10
- package/esm/orm/decorators/embedded.decorator.js +4 -7
- package/esm/orm/decorators/entity.decorator.js +53 -56
- package/esm/orm/decorators/events.decorator.js +19 -27
- package/esm/orm/decorators/foreignkey.decorator.js +4 -7
- package/esm/orm/decorators/index.decorator.js +6 -9
- package/esm/orm/decorators/link.decorator.js +8 -11
- package/esm/orm/decorators/primarykey.decorator.js +8 -11
- package/esm/orm/decorators/transform.decorator.js +7 -11
- package/esm/orm/model/association-field-metadata.js +4 -8
- package/esm/orm/model/association-node.js +2 -6
- package/esm/orm/model/association.js +16 -20
- package/esm/orm/model/column-field-metadata.js +4 -8
- package/esm/orm/model/embedded-field-metadata.js +4 -7
- package/esm/orm/model/entity-metadata.js +47 -50
- package/esm/orm/model/field-metadata.js +1 -2
- package/esm/orm/model/index-metadata.js +1 -2
- package/esm/orm/model/link-chain.js +4 -8
- package/esm/orm/orm.const.js +3 -6
- package/esm/orm/orm.type.js +1 -2
- package/esm/orm/repository.class.js +22 -26
- package/esm/orm/util/apply-mixins.js +1 -4
- package/esm/orm/util/extract-keyvalues.js +6 -9
- package/esm/orm/util/orm.helper.js +10 -20
- package/esm/orm/util/parse-fields-projection.js +6 -11
- package/esm/orm/util/serialize-field.js +10 -13
- package/package.json +5 -5
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
exports.prepareFilter = prepareFilter;
|
|
7
|
-
const builder_1 = require("@sqb/builder");
|
|
8
|
-
const embedded_field_metadata_js_1 = require("../model/embedded-field-metadata.js");
|
|
9
|
-
const entity_metadata_js_1 = require("../model/entity-metadata.js");
|
|
10
|
-
const orm_helper_js_1 = require("../util/orm.helper.js");
|
|
11
|
-
async function joinAssociationGetFirst(joinInfos, association, parentAlias, innerJoin) {
|
|
1
|
+
import { And, Eq, Exists, Field, InnerJoin, isCompOperator, isLogicalOperator, LeftOuterJoin, op, OperatorType, Raw, Select, } from '@sqb/builder';
|
|
2
|
+
import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js';
|
|
3
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
4
|
+
import { isAssociationField, isColumnField, isEmbeddedField } from '../util/orm.helper.js';
|
|
5
|
+
export async function joinAssociationGetFirst(joinInfos, association, parentAlias, innerJoin) {
|
|
12
6
|
const joins = await joinAssociation(joinInfos, association, parentAlias, innerJoin);
|
|
13
7
|
return joins[0];
|
|
14
8
|
}
|
|
15
|
-
async function joinAssociationGetLast(joinInfos, association, parentAlias, innerJoin) {
|
|
9
|
+
export async function joinAssociationGetLast(joinInfos, association, parentAlias, innerJoin) {
|
|
16
10
|
const joins = await joinAssociation(joinInfos, association, parentAlias, innerJoin);
|
|
17
11
|
return joins[joins.length - 1];
|
|
18
12
|
}
|
|
19
|
-
async function joinAssociation(joinInfos, association, parentAlias, innerJoin) {
|
|
13
|
+
export async function joinAssociation(joinInfos, association, parentAlias, innerJoin) {
|
|
20
14
|
let joinInfo;
|
|
21
15
|
let node = association;
|
|
22
16
|
const result = [];
|
|
@@ -29,9 +23,9 @@ async function joinAssociation(joinInfos, association, parentAlias, innerJoin) {
|
|
|
29
23
|
const targetCol = await node.resolveTargetProperty();
|
|
30
24
|
const joinAlias = 'J' + (joinInfos.length + 1);
|
|
31
25
|
const join = innerJoin
|
|
32
|
-
?
|
|
33
|
-
:
|
|
34
|
-
join.on(
|
|
26
|
+
? InnerJoin(targetEntity.tableName + ' as ' + joinAlias)
|
|
27
|
+
: LeftOuterJoin(targetEntity.tableName + ' as ' + joinAlias);
|
|
28
|
+
join.on(Eq(Field(joinAlias + '.' + targetCol.fieldName, targetCol.dataType, targetCol.isArray), Field(parentAlias + '.' + keyCol.fieldName, keyCol.dataType, keyCol.isArray)));
|
|
35
29
|
if (node.conditions)
|
|
36
30
|
await prepareFilter(targetEntity, node.conditions, join._conditions, joinAlias);
|
|
37
31
|
joinInfo = {
|
|
@@ -51,12 +45,12 @@ async function joinAssociation(joinInfos, association, parentAlias, innerJoin) {
|
|
|
51
45
|
}
|
|
52
46
|
return result;
|
|
53
47
|
}
|
|
54
|
-
async function prepareFilter(entityDef, filter, trgOp, tableAlias = 'T') {
|
|
48
|
+
export async function prepareFilter(entityDef, filter, trgOp, tableAlias = 'T') {
|
|
55
49
|
let srcOp;
|
|
56
|
-
if (
|
|
50
|
+
if (isLogicalOperator(filter) && filter._operatorType === trgOp._operatorType)
|
|
57
51
|
srcOp = filter;
|
|
58
52
|
else {
|
|
59
|
-
srcOp =
|
|
53
|
+
srcOp = And();
|
|
60
54
|
if (Array.isArray(filter))
|
|
61
55
|
srcOp.add(...filter);
|
|
62
56
|
else
|
|
@@ -64,14 +58,14 @@ async function prepareFilter(entityDef, filter, trgOp, tableAlias = 'T') {
|
|
|
64
58
|
}
|
|
65
59
|
const associationPathCache = {};
|
|
66
60
|
for (const item of srcOp._items) {
|
|
67
|
-
if (
|
|
61
|
+
if (isLogicalOperator(item)) {
|
|
68
62
|
const ctor = Object.getPrototypeOf(item).constructor;
|
|
69
63
|
const logOp = new ctor();
|
|
70
64
|
await prepareFilter(entityDef, item, logOp, tableAlias);
|
|
71
65
|
trgOp.add(logOp);
|
|
72
66
|
continue;
|
|
73
67
|
}
|
|
74
|
-
if (
|
|
68
|
+
if (isCompOperator(item)) {
|
|
75
69
|
if (typeof item._left === 'string') {
|
|
76
70
|
const itemPath = item._left.split('.');
|
|
77
71
|
const l = itemPath.length;
|
|
@@ -97,38 +91,38 @@ async function prepareFilter(entityDef, filter, trgOp, tableAlias = 'T') {
|
|
|
97
91
|
}
|
|
98
92
|
for (i; i < l; i++) {
|
|
99
93
|
pt = itemPath[i];
|
|
100
|
-
const col =
|
|
94
|
+
const col = EntityMetadata.getField(_curEntity, pt);
|
|
101
95
|
if (!col)
|
|
102
96
|
throw new Error(`Unknown property (${item._left}) defined in filter`);
|
|
103
97
|
/** if last item on path */
|
|
104
98
|
if (i === l - 1) {
|
|
105
|
-
if (!
|
|
99
|
+
if (!isColumnField(col))
|
|
106
100
|
throw new Error(`Invalid column expression (${item._left}) defined in filter`);
|
|
107
101
|
const ctor = Object.getPrototypeOf(item).constructor;
|
|
108
|
-
currentOp.add(new ctor(
|
|
102
|
+
currentOp.add(new ctor(Field(_curAlias + '.' + _curPrefix + col.fieldName + _curSuffix, col.dataType, col.isArray), item._right));
|
|
109
103
|
}
|
|
110
104
|
else {
|
|
111
105
|
/** if not last item on path */
|
|
112
|
-
if (
|
|
106
|
+
if (isColumnField(col))
|
|
113
107
|
throw new Error(`Invalid column (${item._left}) defined in filter`);
|
|
114
|
-
if (
|
|
115
|
-
_curEntity = await
|
|
108
|
+
if (isEmbeddedField(col)) {
|
|
109
|
+
_curEntity = await EmbeddedFieldMetadata.resolveType(col);
|
|
116
110
|
_curPrefix = _curPrefix + (col.fieldNamePrefix || '');
|
|
117
111
|
_curSuffix = (col.fieldNameSuffix || '') + _curSuffix;
|
|
118
112
|
continue;
|
|
119
113
|
}
|
|
120
|
-
if (!
|
|
114
|
+
if (!isAssociationField(col))
|
|
121
115
|
throw new Error(`Invalid column (${item._left}) defined in filter`);
|
|
122
116
|
let node;
|
|
123
117
|
_curEntity = await col.association.resolveTarget();
|
|
124
118
|
if (!subSelect) {
|
|
125
119
|
const keyCol = await col.association.resolveSourceProperty();
|
|
126
120
|
const targetCol = await col.association.resolveTargetProperty();
|
|
127
|
-
subSelect =
|
|
128
|
-
subSelect.where(
|
|
129
|
-
currentOp.add(
|
|
130
|
-
if (currentOp._operatorType !==
|
|
131
|
-
currentOp =
|
|
121
|
+
subSelect = Select(Raw('1')).from(_curEntity.tableName + ' K');
|
|
122
|
+
subSelect.where(Eq(Field('K.' + targetCol.fieldName, targetCol.dataType, targetCol.isArray), Field(tableAlias + '.' + keyCol.fieldName, keyCol.dataType, keyCol.isArray)));
|
|
123
|
+
currentOp.add(Exists(subSelect));
|
|
124
|
+
if (currentOp._operatorType !== OperatorType.and) {
|
|
125
|
+
currentOp = op.or();
|
|
132
126
|
subSelect.where(currentOp);
|
|
133
127
|
}
|
|
134
128
|
else
|
|
@@ -146,7 +140,7 @@ async function prepareFilter(entityDef, filter, trgOp, tableAlias = 'T') {
|
|
|
146
140
|
const sourceColumn = await node.resolveSourceProperty();
|
|
147
141
|
const targetColumn = await node.resolveTargetProperty();
|
|
148
142
|
const joinAlias = 'J' + ((subSelect?._joins?.length || 0) + 1);
|
|
149
|
-
subSelect.join(
|
|
143
|
+
subSelect.join(InnerJoin(targetEntity.tableName + ' ' + joinAlias).on(Eq(Field(joinAlias + '.' + targetColumn.fieldName, targetColumn.dataType, targetColumn.isArray), Field(_curAlias + '.' + sourceColumn.fieldName, sourceColumn.dataType, sourceColumn.isArray))));
|
|
150
144
|
_curEntity = targetEntity;
|
|
151
145
|
_curAlias = joinAlias;
|
|
152
146
|
node = node.next;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
5
|
-
const command_helper_js_1 = require("./command.helper.js");
|
|
6
|
-
class CountCommand {
|
|
1
|
+
import { And, Count, Select } from '@sqb/builder';
|
|
2
|
+
import { prepareFilter } from './command.helper.js';
|
|
3
|
+
export class CountCommand {
|
|
7
4
|
// istanbul ignore next
|
|
8
5
|
constructor() {
|
|
9
6
|
throw new Error('This class is abstract');
|
|
@@ -12,10 +9,10 @@ class CountCommand {
|
|
|
12
9
|
const { connection, entity, filter, params } = args;
|
|
13
10
|
let where;
|
|
14
11
|
if (filter) {
|
|
15
|
-
where =
|
|
16
|
-
await
|
|
12
|
+
where = And();
|
|
13
|
+
await prepareFilter(entity, filter, where, 'T');
|
|
17
14
|
}
|
|
18
|
-
const query =
|
|
15
|
+
const query = Select(Count()).from(entity.tableName + ' T');
|
|
19
16
|
if (where)
|
|
20
17
|
query.where(where);
|
|
21
18
|
// Execute query
|
|
@@ -27,4 +24,3 @@ class CountCommand {
|
|
|
27
24
|
return (resp && resp.rows && resp.rows[0][0]) || 0;
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
|
-
exports.CountCommand = CountCommand;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const entity_metadata_js_1 = require("../model/entity-metadata.js");
|
|
8
|
-
const orm_helper_js_1 = require("../util/orm.helper.js");
|
|
9
|
-
class CreateCommand {
|
|
1
|
+
import { Insert, Param } from '@sqb/builder';
|
|
2
|
+
import { ColumnFieldMetadata } from '../model/column-field-metadata.js';
|
|
3
|
+
import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js';
|
|
4
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
5
|
+
import { isColumnField, isEmbeddedField } from '../util/orm.helper.js';
|
|
6
|
+
export class CreateCommand {
|
|
10
7
|
// istanbul ignore next
|
|
11
8
|
constructor() {
|
|
12
9
|
throw new Error('This class is abstract');
|
|
@@ -27,9 +24,9 @@ class CreateCommand {
|
|
|
27
24
|
await this._prepareParams(ctx, entity, args.values);
|
|
28
25
|
if (!ctx.colCount)
|
|
29
26
|
throw new Error('No field given to create new entity instance');
|
|
30
|
-
const query =
|
|
27
|
+
const query = Insert(tableName, ctx.queryValues);
|
|
31
28
|
if (args.returning) {
|
|
32
|
-
const primaryIndexColumns =
|
|
29
|
+
const primaryIndexColumns = EntityMetadata.getPrimaryIndexColumns(entity);
|
|
33
30
|
if (primaryIndexColumns.length)
|
|
34
31
|
query.returning(...primaryIndexColumns.map(col => col.fieldName));
|
|
35
32
|
}
|
|
@@ -41,7 +38,7 @@ class CreateCommand {
|
|
|
41
38
|
if (args.returning && qr.fields && qr.rows?.length) {
|
|
42
39
|
const keyValues = {};
|
|
43
40
|
for (const f of qr.fields.values()) {
|
|
44
|
-
const el =
|
|
41
|
+
const el = EntityMetadata.getColumnFieldByFieldName(entity, f.fieldName);
|
|
45
42
|
if (el)
|
|
46
43
|
keyValues[el.name] = qr.rows[0][f.index];
|
|
47
44
|
}
|
|
@@ -54,7 +51,7 @@ class CreateCommand {
|
|
|
54
51
|
suffix = suffix || '';
|
|
55
52
|
for (const col of Object.values(entity.fields)) {
|
|
56
53
|
v = values[col.name];
|
|
57
|
-
if (
|
|
54
|
+
if (isColumnField(col)) {
|
|
58
55
|
if (col.noInsert)
|
|
59
56
|
continue;
|
|
60
57
|
if (v == null && col.default !== undefined) {
|
|
@@ -68,10 +65,10 @@ class CreateCommand {
|
|
|
68
65
|
}
|
|
69
66
|
continue;
|
|
70
67
|
}
|
|
71
|
-
|
|
68
|
+
ColumnFieldMetadata.checkEnumValue(col, v);
|
|
72
69
|
const fieldName = prefix + col.fieldName + suffix;
|
|
73
70
|
const k = ('I$_' + fieldName).substring(0, 30);
|
|
74
|
-
ctx.queryValues[fieldName] =
|
|
71
|
+
ctx.queryValues[fieldName] = Param({
|
|
75
72
|
name: k,
|
|
76
73
|
dataType: col.dataType,
|
|
77
74
|
isArray: col.isArray,
|
|
@@ -79,11 +76,10 @@ class CreateCommand {
|
|
|
79
76
|
ctx.queryParams[k] = v;
|
|
80
77
|
ctx.colCount++;
|
|
81
78
|
}
|
|
82
|
-
else if (v != null &&
|
|
83
|
-
const type = await
|
|
79
|
+
else if (v != null && isEmbeddedField(col)) {
|
|
80
|
+
const type = await EmbeddedFieldMetadata.resolveType(col);
|
|
84
81
|
await this._prepareParams(ctx, type, v, col.fieldNamePrefix, col.fieldNameSuffix);
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
}
|
|
88
85
|
}
|
|
89
|
-
exports.CreateCommand = CreateCommand;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
5
|
-
const command_helper_js_1 = require("./command.helper.js");
|
|
6
|
-
class DeleteCommand {
|
|
1
|
+
import { And, Delete } from '@sqb/builder';
|
|
2
|
+
import { prepareFilter } from './command.helper.js';
|
|
3
|
+
export class DeleteCommand {
|
|
7
4
|
// istanbul ignore next
|
|
8
5
|
constructor() {
|
|
9
6
|
throw new Error('This class is abstract');
|
|
@@ -12,10 +9,10 @@ class DeleteCommand {
|
|
|
12
9
|
const { connection, entity, filter, params } = args;
|
|
13
10
|
let where;
|
|
14
11
|
if (filter) {
|
|
15
|
-
where =
|
|
16
|
-
await
|
|
12
|
+
where = And();
|
|
13
|
+
await prepareFilter(entity, filter, where);
|
|
17
14
|
}
|
|
18
|
-
const query =
|
|
15
|
+
const query = Delete(entity.tableName + ' T');
|
|
19
16
|
if (where)
|
|
20
17
|
query.where(...where._items);
|
|
21
18
|
// Execute query
|
|
@@ -27,4 +24,3 @@ class DeleteCommand {
|
|
|
27
24
|
return (resp && resp.rowsAffected) || 0;
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
|
-
exports.DeleteCommand = DeleteCommand;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const parse_fields_projection_js_1 = require("../util/parse-fields-projection.js");
|
|
10
|
-
const command_helper_js_1 = require("./command.helper.js");
|
|
11
|
-
const row_converter_js_1 = require("./row-converter.js");
|
|
1
|
+
import { And, In, Param, Select } from '@sqb/builder';
|
|
2
|
+
import { AssociationNode } from '../model/association-node.js';
|
|
3
|
+
import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js';
|
|
4
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
5
|
+
import { isAssociationField, isColumnField, isEmbeddedField } from '../util/orm.helper.js';
|
|
6
|
+
import { parseFieldsProjection } from '../util/parse-fields-projection.js';
|
|
7
|
+
import { joinAssociationGetLast, prepareFilter } from './command.helper.js';
|
|
8
|
+
import { RowConverter } from './row-converter.js';
|
|
12
9
|
const SORT_ORDER_PATTERN = /^([-+])?(.*)$/;
|
|
13
|
-
class FindCommand {
|
|
10
|
+
export class FindCommand {
|
|
14
11
|
constructor(selectEntity, outputEntity) {
|
|
15
12
|
this.maxEagerFetch = 100000;
|
|
16
13
|
this.maxSubQueries = 5;
|
|
@@ -18,15 +15,15 @@ class FindCommand {
|
|
|
18
15
|
this.resultAlias = 'T';
|
|
19
16
|
this._joins = [];
|
|
20
17
|
this._selectColumns = {};
|
|
21
|
-
this._filter =
|
|
18
|
+
this._filter = And();
|
|
22
19
|
this.mainEntity = selectEntity;
|
|
23
20
|
this.resultEntity = outputEntity;
|
|
24
|
-
this.converter = new
|
|
21
|
+
this.converter = new RowConverter(outputEntity.ctor);
|
|
25
22
|
}
|
|
26
23
|
static async create(source, opts = {}) {
|
|
27
24
|
let command;
|
|
28
25
|
let listingEntity;
|
|
29
|
-
if (source instanceof
|
|
26
|
+
if (source instanceof AssociationNode) {
|
|
30
27
|
const node = source;
|
|
31
28
|
listingEntity = await node.resolveTarget();
|
|
32
29
|
const resultEntity = await node.getLast().resolveTarget();
|
|
@@ -34,7 +31,7 @@ class FindCommand {
|
|
|
34
31
|
if (node.conditions)
|
|
35
32
|
await command.filter(node.conditions);
|
|
36
33
|
if (node.next) {
|
|
37
|
-
const join = await
|
|
34
|
+
const join = await joinAssociationGetLast(command._joins, node.next, command.mainAlias);
|
|
38
35
|
command.resultAlias = join.joinAlias;
|
|
39
36
|
}
|
|
40
37
|
}
|
|
@@ -70,14 +67,14 @@ class FindCommand {
|
|
|
70
67
|
const entity = opts.entity || this._getEntityFromAlias(tableAlias);
|
|
71
68
|
const converter = opts.converter || this.converter;
|
|
72
69
|
const projection = typeof opts.projection === 'string' || Array.isArray(opts.projection)
|
|
73
|
-
?
|
|
70
|
+
? parseFieldsProjection(opts.projection)
|
|
74
71
|
: opts.projection;
|
|
75
72
|
const defaultFields = !projection || !Object.values(projection).find(p => !p.sign);
|
|
76
73
|
const sortFields = opts.sort && opts.sort.length ? opts.sort.map(x => x.toLowerCase()) : undefined;
|
|
77
74
|
const prefix = opts.prefix || '';
|
|
78
75
|
const suffix = opts.suffix || '';
|
|
79
76
|
for (const key of Object.keys(entity.fields)) {
|
|
80
|
-
const col =
|
|
77
|
+
const col = EntityMetadata.getField(entity, key);
|
|
81
78
|
if (!col || col.hidden)
|
|
82
79
|
continue;
|
|
83
80
|
const colNameLower = col.name.toLowerCase();
|
|
@@ -92,7 +89,7 @@ class FindCommand {
|
|
|
92
89
|
continue;
|
|
93
90
|
}
|
|
94
91
|
// Add field to select list if field is a column
|
|
95
|
-
if (
|
|
92
|
+
if (isColumnField(col)) {
|
|
96
93
|
const fieldAlias = this._selectColumn(tableAlias, col, prefix, suffix);
|
|
97
94
|
// Add column to converter
|
|
98
95
|
converter.addValueProperty({
|
|
@@ -103,8 +100,8 @@ class FindCommand {
|
|
|
103
100
|
});
|
|
104
101
|
continue;
|
|
105
102
|
}
|
|
106
|
-
if (
|
|
107
|
-
const typ = await
|
|
103
|
+
if (isEmbeddedField(col)) {
|
|
104
|
+
const typ = await EmbeddedFieldMetadata.resolveType(col);
|
|
108
105
|
const subConverter = converter.addObjectProperty({
|
|
109
106
|
name: col.name,
|
|
110
107
|
type: typ.ctor,
|
|
@@ -120,10 +117,10 @@ class FindCommand {
|
|
|
120
117
|
});
|
|
121
118
|
continue;
|
|
122
119
|
}
|
|
123
|
-
if (
|
|
120
|
+
if (isAssociationField(col)) {
|
|
124
121
|
// OtO relation
|
|
125
122
|
if (!col.association.returnsMany()) {
|
|
126
|
-
const joinInfo = await
|
|
123
|
+
const joinInfo = await joinAssociationGetLast(this._joins, col.association, tableAlias);
|
|
127
124
|
const subConverter = converter.addObjectProperty({
|
|
128
125
|
name: col.name,
|
|
129
126
|
type: joinInfo.targetEntity.ctor,
|
|
@@ -150,7 +147,7 @@ class FindCommand {
|
|
|
150
147
|
maxEagerFetch: this.maxEagerFetch,
|
|
151
148
|
});
|
|
152
149
|
findCommand.converter.parent = this.converter;
|
|
153
|
-
await findCommand.filter(
|
|
150
|
+
await findCommand.filter(In(targetCol.name, Param(parentField)));
|
|
154
151
|
const sort = sortFields && extractSubFields(colNameLower, sortFields);
|
|
155
152
|
await findCommand.addFields({
|
|
156
153
|
projection: p?.projection,
|
|
@@ -182,7 +179,7 @@ class FindCommand {
|
|
|
182
179
|
return fieldAlias;
|
|
183
180
|
}
|
|
184
181
|
async filter(filter) {
|
|
185
|
-
await
|
|
182
|
+
await prepareFilter(this.mainEntity, filter, this._filter);
|
|
186
183
|
}
|
|
187
184
|
async sort(sortFields) {
|
|
188
185
|
const out = [];
|
|
@@ -198,20 +195,20 @@ class FindCommand {
|
|
|
198
195
|
if (elName.includes('.')) {
|
|
199
196
|
const a = elName.split('.');
|
|
200
197
|
while (a.length > 1) {
|
|
201
|
-
const col =
|
|
202
|
-
if (
|
|
203
|
-
_entityDef = await
|
|
198
|
+
const col = EntityMetadata.getField(_entityDef, a.shift() || '');
|
|
199
|
+
if (isEmbeddedField(col)) {
|
|
200
|
+
_entityDef = await EmbeddedFieldMetadata.resolveType(col);
|
|
204
201
|
if (col.fieldNamePrefix)
|
|
205
202
|
prefix += col.fieldNamePrefix;
|
|
206
203
|
if (col.fieldNameSuffix)
|
|
207
204
|
suffix = col.fieldNameSuffix + suffix;
|
|
208
205
|
}
|
|
209
|
-
else if (
|
|
206
|
+
else if (isAssociationField(col)) {
|
|
210
207
|
if (col.association.returnsMany()) {
|
|
211
208
|
elName = '';
|
|
212
209
|
break;
|
|
213
210
|
}
|
|
214
|
-
const joinInfo = await
|
|
211
|
+
const joinInfo = await joinAssociationGetLast(this._joins, col.association, tableAlias);
|
|
215
212
|
tableAlias = joinInfo.joinAlias;
|
|
216
213
|
_entityDef = joinInfo.targetEntity;
|
|
217
214
|
}
|
|
@@ -222,10 +219,10 @@ class FindCommand {
|
|
|
222
219
|
continue;
|
|
223
220
|
elName = a.shift() || '';
|
|
224
221
|
}
|
|
225
|
-
const col =
|
|
222
|
+
const col = EntityMetadata.getField(_entityDef, elName);
|
|
226
223
|
if (!col)
|
|
227
224
|
throw new Error(`Unknown field (${elName}) declared in sort property`);
|
|
228
|
-
if (!
|
|
225
|
+
if (!isColumnField(col))
|
|
229
226
|
throw new Error(`Can not sort by "${elName}", because it is not a data column`);
|
|
230
227
|
const dir = m[1] || '+';
|
|
231
228
|
out.push((dir || '') + tableAlias + '.' + prefix + col.fieldName + suffix);
|
|
@@ -237,7 +234,7 @@ class FindCommand {
|
|
|
237
234
|
const columnSqls = Object.keys(this._selectColumns).map(x => this._selectColumns[x].statement);
|
|
238
235
|
if (!columnSqls.length)
|
|
239
236
|
columnSqls.push('1');
|
|
240
|
-
const query =
|
|
237
|
+
const query = Select(...columnSqls).from(this.mainEntity.tableName + ' as ' + this.mainAlias);
|
|
241
238
|
if (args.distinct)
|
|
242
239
|
query.distinct();
|
|
243
240
|
query.where(...this._filter._items);
|
|
@@ -279,7 +276,6 @@ class FindCommand {
|
|
|
279
276
|
throw new Error(`Unknown table alias "${tableAlias}"`);
|
|
280
277
|
}
|
|
281
278
|
}
|
|
282
|
-
exports.FindCommand = FindCommand;
|
|
283
279
|
function extractSubFields(colNameLower, fields) {
|
|
284
280
|
if (!(fields && fields.length))
|
|
285
281
|
return;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RowConverter = void 0;
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
1
|
+
import { DataType } from '@sqb/builder';
|
|
5
2
|
const isValueProperty = (prop) => prop.fieldAlias && !prop.converter;
|
|
6
3
|
const isObjectProperty = (prop) => prop.converter && !prop.findCommand;
|
|
7
4
|
const isNestedProperty = (prop) => prop.converter && prop.findCommand;
|
|
8
|
-
class RowConverter {
|
|
5
|
+
export class RowConverter {
|
|
9
6
|
constructor(resultType, parent) {
|
|
10
7
|
this.resultType = resultType;
|
|
11
8
|
this.parent = parent;
|
|
@@ -84,7 +81,7 @@ class RowConverter {
|
|
|
84
81
|
v = prop.parse(v, elKey);
|
|
85
82
|
if (v != null) {
|
|
86
83
|
result = result || {};
|
|
87
|
-
if (prop.dataType ===
|
|
84
|
+
if (prop.dataType === DataType.JSON && typeof v === 'string')
|
|
88
85
|
v = JSON.parse(v);
|
|
89
86
|
result[elKey] = v;
|
|
90
87
|
}
|
|
@@ -182,4 +179,3 @@ class RowConverter {
|
|
|
182
179
|
this.parent._checkCircularDep(t);
|
|
183
180
|
}
|
|
184
181
|
}
|
|
185
|
-
exports.RowConverter = RowConverter;
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const orm_helper_js_1 = require("../util/orm.helper.js");
|
|
8
|
-
const command_helper_js_1 = require("./command.helper.js");
|
|
9
|
-
class UpdateCommand {
|
|
1
|
+
import { And, Param, Update } from '@sqb/builder';
|
|
2
|
+
import { ColumnFieldMetadata } from '../model/column-field-metadata.js';
|
|
3
|
+
import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js';
|
|
4
|
+
import { isColumnField, isEmbeddedField } from '../util/orm.helper.js';
|
|
5
|
+
import { prepareFilter } from './command.helper.js';
|
|
6
|
+
export class UpdateCommand {
|
|
10
7
|
// istanbul ignore next
|
|
11
8
|
constructor() {
|
|
12
9
|
throw new Error('This class is abstract');
|
|
@@ -30,7 +27,7 @@ class UpdateCommand {
|
|
|
30
27
|
return 0;
|
|
31
28
|
if (args.filter)
|
|
32
29
|
await this._prepareFilter(ctx, args.filter);
|
|
33
|
-
const query =
|
|
30
|
+
const query = Update(tableName + ' as T', ctx.queryValues).where(...ctx.queryFilter);
|
|
34
31
|
const qr = await args.connection.execute(query, {
|
|
35
32
|
params: args.params ? [...args.params, ctx.queryParams] : ctx.queryParams,
|
|
36
33
|
objectRows: false,
|
|
@@ -40,8 +37,8 @@ class UpdateCommand {
|
|
|
40
37
|
}
|
|
41
38
|
static async _prepareFilter(ctx, filter) {
|
|
42
39
|
if (filter) {
|
|
43
|
-
const where =
|
|
44
|
-
await
|
|
40
|
+
const where = And();
|
|
41
|
+
await prepareFilter(ctx.entity, filter, where);
|
|
45
42
|
ctx.queryFilter.push(...where._items);
|
|
46
43
|
}
|
|
47
44
|
}
|
|
@@ -53,7 +50,7 @@ class UpdateCommand {
|
|
|
53
50
|
v = values[col.name];
|
|
54
51
|
if (v === undefined)
|
|
55
52
|
continue;
|
|
56
|
-
if (
|
|
53
|
+
if (isColumnField(col)) {
|
|
57
54
|
if (col.noUpdate)
|
|
58
55
|
continue;
|
|
59
56
|
if (typeof col.serialize === 'function')
|
|
@@ -62,10 +59,10 @@ class UpdateCommand {
|
|
|
62
59
|
throw new Error(`${entity.name}.${col.name} is required and can't be null`);
|
|
63
60
|
if (v === undefined)
|
|
64
61
|
continue;
|
|
65
|
-
|
|
62
|
+
ColumnFieldMetadata.checkEnumValue(col, v);
|
|
66
63
|
const fieldName = prefix + col.fieldName + suffix;
|
|
67
64
|
const k = ('I$_' + fieldName).substring(0, 30);
|
|
68
|
-
ctx.queryValues[fieldName] =
|
|
65
|
+
ctx.queryValues[fieldName] = Param({
|
|
69
66
|
name: k,
|
|
70
67
|
dataType: col.dataType,
|
|
71
68
|
isArray: col.isArray,
|
|
@@ -73,11 +70,10 @@ class UpdateCommand {
|
|
|
73
70
|
ctx.queryParams[k] = v;
|
|
74
71
|
ctx.colCount++;
|
|
75
72
|
}
|
|
76
|
-
else if (v != null &&
|
|
77
|
-
const type = await
|
|
73
|
+
else if (v != null && isEmbeddedField(col)) {
|
|
74
|
+
const type = await EmbeddedFieldMetadata.resolveType(col);
|
|
78
75
|
await this._prepareParams(ctx, type, v, col.fieldNamePrefix, col.fieldNameSuffix);
|
|
79
76
|
}
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
79
|
}
|
|
83
|
-
exports.UpdateCommand = UpdateCommand;
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const orm_const_js_1 = require("../orm.const.js");
|
|
6
|
-
function Column(arg0) {
|
|
7
|
-
return Column[orm_const_js_1.DECORATOR_FACTORY](arg0);
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
import { DECORATOR_FACTORY } from '../orm.const.js';
|
|
3
|
+
export function Column(arg0) {
|
|
4
|
+
return Column[DECORATOR_FACTORY](arg0);
|
|
8
5
|
}
|
|
9
|
-
Column[
|
|
6
|
+
Column[DECORATOR_FACTORY] = function (arg0) {
|
|
10
7
|
return (target, propertyKey) => {
|
|
11
8
|
if (typeof propertyKey !== 'string')
|
|
12
9
|
throw new Error('Symbol properties are not accepted');
|
|
13
10
|
const options = (typeof arg0 === 'string' ? { dataType: arg0 } : arg0) || {};
|
|
14
|
-
const entity =
|
|
11
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
15
12
|
if (!options.type) {
|
|
16
13
|
const typ = Reflect.getMetadata('design:type', entity.ctor.prototype, propertyKey);
|
|
17
14
|
if (typ === Array) {
|
|
@@ -21,6 +18,6 @@ Column[orm_const_js_1.DECORATOR_FACTORY] = function (arg0) {
|
|
|
21
18
|
else
|
|
22
19
|
options.type = typ;
|
|
23
20
|
}
|
|
24
|
-
|
|
21
|
+
EntityMetadata.defineColumnField(entity, propertyKey, options);
|
|
25
22
|
};
|
|
26
23
|
};
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.Embedded = Embedded;
|
|
4
|
-
const entity_metadata_js_1 = require("../model/entity-metadata.js");
|
|
5
|
-
function Embedded(type, options) {
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function Embedded(type, options) {
|
|
6
3
|
return (target, propertyKey) => {
|
|
7
4
|
if (typeof propertyKey !== 'string')
|
|
8
5
|
throw new Error('Symbol properties are not accepted');
|
|
9
6
|
type = type || Reflect.getMetadata('design:type', target, propertyKey);
|
|
10
7
|
if (typeof type !== 'function')
|
|
11
8
|
throw new Error('"type" must be defined');
|
|
12
|
-
const entity =
|
|
13
|
-
|
|
9
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
10
|
+
EntityMetadata.defineEmbeddedField(entity, propertyKey, type, options);
|
|
14
11
|
};
|
|
15
12
|
}
|