@sqb/connect 4.20.7 → 4.21.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/{types/client → client}/cursor-stream.d.ts +1 -1
- package/{types/client → client}/cursor.d.ts +4 -4
- package/{types/client → client}/sqb-connection.d.ts +4 -4
- package/{esm/orm → orm}/commands/command.helper.js +2 -3
- package/{types/orm → orm}/commands/count.command.d.ts +2 -2
- package/{types/orm → orm}/commands/create.command.d.ts +1 -1
- package/{esm/orm → orm}/commands/create.command.js +3 -5
- package/{types/orm → orm}/commands/delete.command.d.ts +2 -2
- package/{types/orm → orm}/commands/find.command.d.ts +2 -2
- package/{esm/orm → orm}/commands/find.command.js +3 -4
- package/{types/orm → orm}/commands/row-converter.d.ts +1 -1
- package/{types/orm → orm}/commands/update.command.d.ts +2 -2
- package/{esm/orm → orm}/commands/update.command.js +3 -5
- package/{types/orm → orm}/model/association-field-metadata.d.ts +0 -5
- package/{types/orm → orm}/model/association.d.ts +3 -3
- package/{esm/orm → orm}/model/association.js +1 -1
- package/{types/orm → orm}/model/column-field-metadata.d.ts +2 -8
- package/{types/orm → orm}/model/embedded-field-metadata.d.ts +0 -1
- package/{esm/orm → orm}/model/embedded-field-metadata.js +0 -14
- package/{types/orm → orm}/model/entity-metadata.d.ts +3 -3
- package/{esm/orm → orm}/model/entity-metadata.js +21 -6
- package/orm/model/index-metadata.js +1 -0
- package/orm/orm.type.js +1 -0
- package/{types/orm → orm}/repository.class.d.ts +2 -2
- package/{esm/orm → orm}/repository.class.js +1 -1
- package/{types/orm → orm}/util/orm.helper.d.ts +5 -3
- package/{esm/orm → orm}/util/orm.helper.js +14 -0
- package/package.json +10 -26
- package/cjs/client/adapter.js +0 -2
- package/cjs/client/cursor-stream.js +0 -104
- package/cjs/client/cursor.js +0 -261
- package/cjs/client/extensions.js +0 -41
- package/cjs/client/field-info-map.js +0 -54
- package/cjs/client/helpers.js +0 -140
- package/cjs/client/sqb-client.js +0 -175
- package/cjs/client/sqb-connection.js +0 -293
- package/cjs/client/sqb-error.js +0 -15
- package/cjs/client/types.js +0 -5
- package/cjs/index.js +0 -41
- package/cjs/orm/backward.js +0 -24
- package/cjs/orm/base-entity.js +0 -29
- package/cjs/orm/commands/command.helper.js +0 -170
- package/cjs/orm/commands/count.command.js +0 -30
- package/cjs/orm/commands/create.command.js +0 -92
- package/cjs/orm/commands/delete.command.js +0 -30
- package/cjs/orm/commands/find.command.js +0 -301
- package/cjs/orm/commands/row-converter.js +0 -190
- package/cjs/orm/commands/update.command.js +0 -83
- package/cjs/orm/decorators/column.decorator.js +0 -32
- package/cjs/orm/decorators/embedded.decorator.js +0 -15
- package/cjs/orm/decorators/entity.decorator.js +0 -180
- package/cjs/orm/decorators/events.decorator.js +0 -63
- package/cjs/orm/decorators/foreignkey.decorator.js +0 -12
- package/cjs/orm/decorators/index.decorator.js +0 -20
- package/cjs/orm/decorators/link.decorator.js +0 -72
- package/cjs/orm/decorators/primarykey.decorator.js +0 -24
- package/cjs/orm/decorators/transform.decorator.js +0 -21
- package/cjs/orm/model/association-field-metadata.js +0 -24
- package/cjs/orm/model/association-node.js +0 -28
- package/cjs/orm/model/association.js +0 -141
- package/cjs/orm/model/column-field-metadata.js +0 -32
- package/cjs/orm/model/embedded-field-metadata.js +0 -28
- package/cjs/orm/model/entity-metadata.js +0 -327
- package/cjs/orm/model/field-metadata.js +0 -2
- package/cjs/orm/model/index-metadata.js +0 -2
- package/cjs/orm/model/link-chain.js +0 -47
- package/cjs/orm/orm.const.js +0 -6
- package/cjs/orm/orm.type.js +0 -2
- package/cjs/orm/repository.class.js +0 -293
- package/cjs/orm/util/apply-mixins.js +0 -16
- package/cjs/orm/util/extract-keyvalues.js +0 -63
- package/cjs/orm/util/orm.helper.js +0 -34
- package/cjs/orm/util/parse-fields-projection.js +0 -68
- package/cjs/orm/util/serialize-field.js +0 -49
- package/cjs/package.json +0 -3
- package/esm/orm/model/association-field-metadata.js +0 -20
- package/esm/orm/model/column-field-metadata.js +0 -28
- package/esm/package.json +0 -3
- package/types/index.d.cts +0 -33
- /package/{types/client → client}/adapter.d.ts +0 -0
- /package/{esm/client → client}/adapter.js +0 -0
- /package/{esm/client → client}/cursor-stream.js +0 -0
- /package/{esm/client → client}/cursor.js +0 -0
- /package/{types/client → client}/extensions.d.ts +0 -0
- /package/{esm/client → client}/extensions.js +0 -0
- /package/{types/client → client}/field-info-map.d.ts +0 -0
- /package/{esm/client → client}/field-info-map.js +0 -0
- /package/{types/client → client}/helpers.d.ts +0 -0
- /package/{esm/client → client}/helpers.js +0 -0
- /package/{types/client → client}/sqb-client.d.ts +0 -0
- /package/{esm/client → client}/sqb-client.js +0 -0
- /package/{esm/client → client}/sqb-connection.js +0 -0
- /package/{types/client → client}/sqb-error.d.ts +0 -0
- /package/{esm/client → client}/sqb-error.js +0 -0
- /package/{types/client → client}/types.d.ts +0 -0
- /package/{esm/client → client}/types.js +0 -0
- /package/{types/index.d.ts → index.d.ts} +0 -0
- /package/{esm/index.js → index.js} +0 -0
- /package/{types/orm → orm}/backward.d.ts +0 -0
- /package/{esm/orm → orm}/backward.js +0 -0
- /package/{types/orm → orm}/base-entity.d.ts +0 -0
- /package/{esm/orm → orm}/base-entity.js +0 -0
- /package/{types/orm → orm}/commands/command.helper.d.ts +0 -0
- /package/{esm/orm → orm}/commands/count.command.js +0 -0
- /package/{esm/orm → orm}/commands/delete.command.js +0 -0
- /package/{esm/orm → orm}/commands/row-converter.js +0 -0
- /package/{types/orm → orm}/decorators/column.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/column.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/embedded.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/embedded.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/entity.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/entity.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/events.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/events.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/foreignkey.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/foreignkey.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/index.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/index.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/link.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/link.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/primarykey.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/primarykey.decorator.js +0 -0
- /package/{types/orm → orm}/decorators/transform.decorator.d.ts +0 -0
- /package/{esm/orm → orm}/decorators/transform.decorator.js +0 -0
- /package/{esm/orm/model/field-metadata.js → orm/model/association-field-metadata.js} +0 -0
- /package/{types/orm → orm}/model/association-node.d.ts +0 -0
- /package/{esm/orm → orm}/model/association-node.js +0 -0
- /package/{esm/orm/model/index-metadata.js → orm/model/column-field-metadata.js} +0 -0
- /package/{types/orm → orm}/model/field-metadata.d.ts +0 -0
- /package/{esm/orm/orm.type.js → orm/model/field-metadata.js} +0 -0
- /package/{types/orm → orm}/model/index-metadata.d.ts +0 -0
- /package/{types/orm → orm}/model/link-chain.d.ts +0 -0
- /package/{esm/orm → orm}/model/link-chain.js +0 -0
- /package/{types/orm → orm}/orm.const.d.ts +0 -0
- /package/{esm/orm → orm}/orm.const.js +0 -0
- /package/{types/orm → orm}/orm.type.d.ts +0 -0
- /package/{types/orm → orm}/util/apply-mixins.d.ts +0 -0
- /package/{esm/orm → orm}/util/apply-mixins.js +0 -0
- /package/{types/orm → orm}/util/extract-keyvalues.d.ts +0 -0
- /package/{esm/orm → orm}/util/extract-keyvalues.js +0 -0
- /package/{types/orm → orm}/util/parse-fields-projection.d.ts +0 -0
- /package/{esm/orm → orm}/util/parse-fields-projection.js +0 -0
- /package/{types/orm → orm}/util/serialize-field.d.ts +0 -0
- /package/{esm/orm → orm}/util/serialize-field.js +0 -0
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CreateCommand = void 0;
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
5
|
-
const column_field_metadata_js_1 = require("../model/column-field-metadata.js");
|
|
6
|
-
const embedded_field_metadata_js_1 = require("../model/embedded-field-metadata.js");
|
|
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 {
|
|
10
|
-
// istanbul ignore next
|
|
11
|
-
constructor() {
|
|
12
|
-
throw new Error('This class is abstract');
|
|
13
|
-
}
|
|
14
|
-
static async execute(args) {
|
|
15
|
-
const { entity } = args;
|
|
16
|
-
const tableName = entity.tableName;
|
|
17
|
-
if (!tableName)
|
|
18
|
-
throw new Error(`${entity.ctor.name} is not decorated with @Entity decorator`);
|
|
19
|
-
// Create a context
|
|
20
|
-
const ctx = {
|
|
21
|
-
entity,
|
|
22
|
-
queryParams: {},
|
|
23
|
-
queryValues: {},
|
|
24
|
-
colCount: 0,
|
|
25
|
-
};
|
|
26
|
-
// Prepare
|
|
27
|
-
await this._prepareParams(ctx, entity, args.values);
|
|
28
|
-
if (!ctx.colCount)
|
|
29
|
-
throw new Error('No field given to create new entity instance');
|
|
30
|
-
const query = (0, builder_1.Insert)(tableName, ctx.queryValues);
|
|
31
|
-
if (args.returning) {
|
|
32
|
-
const primaryIndexColumns = entity_metadata_js_1.EntityMetadata.getPrimaryIndexColumns(entity);
|
|
33
|
-
if (primaryIndexColumns.length)
|
|
34
|
-
query.returning(...primaryIndexColumns.map(col => col.fieldName));
|
|
35
|
-
}
|
|
36
|
-
const qr = await args.connection.execute(query, {
|
|
37
|
-
params: ctx.queryParams,
|
|
38
|
-
objectRows: false,
|
|
39
|
-
cursor: false,
|
|
40
|
-
});
|
|
41
|
-
if (args.returning && qr.fields && qr.rows?.length) {
|
|
42
|
-
const keyValues = {};
|
|
43
|
-
for (const f of qr.fields.values()) {
|
|
44
|
-
const el = entity_metadata_js_1.EntityMetadata.getColumnFieldByFieldName(entity, f.fieldName);
|
|
45
|
-
if (el)
|
|
46
|
-
keyValues[el.name] = qr.rows[0][f.index];
|
|
47
|
-
}
|
|
48
|
-
return keyValues;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
static async _prepareParams(ctx, entity, values, prefix, suffix) {
|
|
52
|
-
let v;
|
|
53
|
-
prefix = prefix || '';
|
|
54
|
-
suffix = suffix || '';
|
|
55
|
-
for (const col of Object.values(entity.fields)) {
|
|
56
|
-
v = values[col.name];
|
|
57
|
-
if ((0, orm_helper_js_1.isColumnField)(col)) {
|
|
58
|
-
if (col.noInsert)
|
|
59
|
-
continue;
|
|
60
|
-
if (v == null && col.default !== undefined) {
|
|
61
|
-
v =
|
|
62
|
-
typeof col.default === 'function'
|
|
63
|
-
? col.default(values)
|
|
64
|
-
: col.default;
|
|
65
|
-
}
|
|
66
|
-
if (typeof col.serialize === 'function')
|
|
67
|
-
v = col.serialize(v, col.name);
|
|
68
|
-
if (v == null) {
|
|
69
|
-
if (col.notNull && !col.autoGenerated) {
|
|
70
|
-
throw new Error(`${entity.name}.${col.name} is required and can't be null`);
|
|
71
|
-
}
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
column_field_metadata_js_1.ColumnFieldMetadata.checkEnumValue(col, v);
|
|
75
|
-
const fieldName = prefix + col.fieldName + suffix;
|
|
76
|
-
const k = ('I$_' + fieldName).substring(0, 30);
|
|
77
|
-
ctx.queryValues[fieldName] = (0, builder_1.Param)({
|
|
78
|
-
name: k,
|
|
79
|
-
dataType: col.dataType,
|
|
80
|
-
isArray: col.isArray,
|
|
81
|
-
});
|
|
82
|
-
ctx.queryParams[k] = v;
|
|
83
|
-
ctx.colCount++;
|
|
84
|
-
}
|
|
85
|
-
else if (v != null && (0, orm_helper_js_1.isEmbeddedField)(col)) {
|
|
86
|
-
const type = await embedded_field_metadata_js_1.EmbeddedFieldMetadata.resolveType(col);
|
|
87
|
-
await this._prepareParams(ctx, type, v, col.fieldNamePrefix, col.fieldNameSuffix);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
exports.CreateCommand = CreateCommand;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DeleteCommand = void 0;
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
5
|
-
const command_helper_js_1 = require("./command.helper.js");
|
|
6
|
-
class DeleteCommand {
|
|
7
|
-
// istanbul ignore next
|
|
8
|
-
constructor() {
|
|
9
|
-
throw new Error('This class is abstract');
|
|
10
|
-
}
|
|
11
|
-
static async execute(args) {
|
|
12
|
-
const { connection, entity, filter, params } = args;
|
|
13
|
-
let where;
|
|
14
|
-
if (filter) {
|
|
15
|
-
where = (0, builder_1.And)();
|
|
16
|
-
await (0, command_helper_js_1.prepareFilter)(entity, filter, where);
|
|
17
|
-
}
|
|
18
|
-
const query = (0, builder_1.Delete)(entity.tableName + ' T');
|
|
19
|
-
if (where)
|
|
20
|
-
query.where(...where._items);
|
|
21
|
-
// Execute query
|
|
22
|
-
const resp = await connection.execute(query, {
|
|
23
|
-
params,
|
|
24
|
-
objectRows: false,
|
|
25
|
-
cursor: false,
|
|
26
|
-
});
|
|
27
|
-
return (resp && resp.rowsAffected) || 0;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
exports.DeleteCommand = DeleteCommand;
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FindCommand = void 0;
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
5
|
-
const association_node_js_1 = require("../model/association-node.js");
|
|
6
|
-
const embedded_field_metadata_js_1 = require("../model/embedded-field-metadata.js");
|
|
7
|
-
const entity_metadata_js_1 = require("../model/entity-metadata.js");
|
|
8
|
-
const orm_helper_js_1 = require("../util/orm.helper.js");
|
|
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");
|
|
12
|
-
const SORT_ORDER_PATTERN = /^([-+])?(.*)$/;
|
|
13
|
-
class FindCommand {
|
|
14
|
-
maxEagerFetch = 100000;
|
|
15
|
-
maxSubQueries = 5;
|
|
16
|
-
mainEntity;
|
|
17
|
-
resultEntity;
|
|
18
|
-
converter;
|
|
19
|
-
mainAlias = 'T';
|
|
20
|
-
resultAlias = 'T';
|
|
21
|
-
_joins = [];
|
|
22
|
-
_selectColumns = {};
|
|
23
|
-
_filter = (0, builder_1.And)();
|
|
24
|
-
_sort;
|
|
25
|
-
constructor(selectEntity, outputEntity) {
|
|
26
|
-
this.mainEntity = selectEntity;
|
|
27
|
-
this.resultEntity = outputEntity;
|
|
28
|
-
this.converter = new row_converter_js_1.RowConverter(outputEntity.ctor);
|
|
29
|
-
}
|
|
30
|
-
static async create(source, opts = {}) {
|
|
31
|
-
let command;
|
|
32
|
-
let listingEntity;
|
|
33
|
-
if (source instanceof association_node_js_1.AssociationNode) {
|
|
34
|
-
const node = source;
|
|
35
|
-
listingEntity = await node.resolveTarget();
|
|
36
|
-
const resultEntity = await node.getLast().resolveTarget();
|
|
37
|
-
command = new FindCommand(listingEntity, resultEntity);
|
|
38
|
-
if (node.conditions)
|
|
39
|
-
await command.filter(node.conditions);
|
|
40
|
-
if (node.next) {
|
|
41
|
-
const join = await (0, command_helper_js_1.joinAssociationGetLast)(command._joins, node.next, command.mainAlias);
|
|
42
|
-
command.resultAlias = join.joinAlias;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
listingEntity = source;
|
|
47
|
-
command = new FindCommand(listingEntity, listingEntity);
|
|
48
|
-
}
|
|
49
|
-
if (!listingEntity.tableName)
|
|
50
|
-
throw new Error(`${listingEntity.ctor.name} is not decorated with @Entity decorator`);
|
|
51
|
-
if (typeof opts.maxSubQueries === 'number')
|
|
52
|
-
command.maxSubQueries = opts.maxSubQueries;
|
|
53
|
-
if (typeof opts.maxEagerFetch === 'number')
|
|
54
|
-
command.maxEagerFetch = opts.maxEagerFetch;
|
|
55
|
-
return command;
|
|
56
|
-
}
|
|
57
|
-
static async execute(args) {
|
|
58
|
-
const command = await FindCommand.create(args.entity, {
|
|
59
|
-
maxSubQueries: args.maxSubQueries,
|
|
60
|
-
maxEagerFetch: args.maxEagerFetch,
|
|
61
|
-
});
|
|
62
|
-
await command.addFields({
|
|
63
|
-
projection: args.projection,
|
|
64
|
-
sort: args.sort,
|
|
65
|
-
});
|
|
66
|
-
if (args.filter)
|
|
67
|
-
await command.filter(args.filter);
|
|
68
|
-
if (args.sort)
|
|
69
|
-
await command.sort(args.sort);
|
|
70
|
-
return await command.execute(args);
|
|
71
|
-
}
|
|
72
|
-
async addFields(opts = {}) {
|
|
73
|
-
const tableAlias = opts.tableAlias || this.resultAlias;
|
|
74
|
-
const entity = opts.entity || this._getEntityFromAlias(tableAlias);
|
|
75
|
-
const converter = opts.converter || this.converter;
|
|
76
|
-
const projection = typeof opts.projection === 'string' || Array.isArray(opts.projection)
|
|
77
|
-
? (0, parse_fields_projection_js_1.parseFieldsProjection)(opts.projection)
|
|
78
|
-
: opts.projection;
|
|
79
|
-
const defaultFields = !projection || !Object.values(projection).find(p => !p.sign);
|
|
80
|
-
const sortFields = opts.sort && opts.sort.length
|
|
81
|
-
? opts.sort.map(x => x.toLowerCase())
|
|
82
|
-
: undefined;
|
|
83
|
-
const prefix = opts.prefix || '';
|
|
84
|
-
const suffix = opts.suffix || '';
|
|
85
|
-
for (const key of Object.keys(entity.fields)) {
|
|
86
|
-
const col = entity_metadata_js_1.EntityMetadata.getField(entity, key);
|
|
87
|
-
if (!col || col.hidden)
|
|
88
|
-
continue;
|
|
89
|
-
const colNameLower = col.name.toLowerCase();
|
|
90
|
-
const p = projection?.[colNameLower];
|
|
91
|
-
if (
|
|
92
|
-
/** Ignore if field is omitted */
|
|
93
|
-
p?.sign === '-' ||
|
|
94
|
-
/** Ignore if default fields and field is not in projection */
|
|
95
|
-
(!defaultFields && !p) ||
|
|
96
|
-
/** Ignore if default fields enabled and fields is exclusive */
|
|
97
|
-
(defaultFields && col.exclusive && !p)) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
// Add field to select list if field is a column
|
|
101
|
-
if ((0, orm_helper_js_1.isColumnField)(col)) {
|
|
102
|
-
const fieldAlias = this._selectColumn(tableAlias, col, prefix, suffix);
|
|
103
|
-
// Add column to converter
|
|
104
|
-
converter.addValueProperty({
|
|
105
|
-
name: col.name,
|
|
106
|
-
fieldAlias,
|
|
107
|
-
dataType: col.dataType,
|
|
108
|
-
parse: col.parse,
|
|
109
|
-
});
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
if ((0, orm_helper_js_1.isEmbeddedField)(col)) {
|
|
113
|
-
const typ = await embedded_field_metadata_js_1.EmbeddedFieldMetadata.resolveType(col);
|
|
114
|
-
const subConverter = converter.addObjectProperty({
|
|
115
|
-
name: col.name,
|
|
116
|
-
type: typ.ctor,
|
|
117
|
-
}).converter;
|
|
118
|
-
await this.addFields({
|
|
119
|
-
tableAlias,
|
|
120
|
-
converter: subConverter,
|
|
121
|
-
entity: typ,
|
|
122
|
-
prefix: col.fieldNamePrefix,
|
|
123
|
-
suffix: col.fieldNameSuffix,
|
|
124
|
-
projection: p?.projection,
|
|
125
|
-
sort: extractSubFields(colNameLower, sortFields),
|
|
126
|
-
});
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if ((0, orm_helper_js_1.isAssociationField)(col)) {
|
|
130
|
-
// OtO relation
|
|
131
|
-
if (!col.association.returnsMany()) {
|
|
132
|
-
const joinInfo = await (0, command_helper_js_1.joinAssociationGetLast)(this._joins, col.association, tableAlias);
|
|
133
|
-
const subConverter = converter.addObjectProperty({
|
|
134
|
-
name: col.name,
|
|
135
|
-
type: joinInfo.targetEntity.ctor,
|
|
136
|
-
}).converter;
|
|
137
|
-
// Add join fields to select columns list
|
|
138
|
-
await this.addFields({
|
|
139
|
-
tableAlias: joinInfo.joinAlias,
|
|
140
|
-
converter: subConverter,
|
|
141
|
-
entity: joinInfo.targetEntity,
|
|
142
|
-
projection: p?.projection,
|
|
143
|
-
sort: extractSubFields(colNameLower, sortFields),
|
|
144
|
-
});
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
// One-2-Many Eager relation
|
|
148
|
-
if (this.maxSubQueries > 0) {
|
|
149
|
-
const targetCol = await col.association.resolveTargetProperty();
|
|
150
|
-
const sourceCol = await col.association.resolveSourceProperty();
|
|
151
|
-
// We need to know key value to filter sub query.
|
|
152
|
-
// So add key field into select columns
|
|
153
|
-
const parentField = this._selectColumn(tableAlias, sourceCol);
|
|
154
|
-
const findCommand = await FindCommand.create(col.association, {
|
|
155
|
-
maxSubQueries: this.maxSubQueries - 1,
|
|
156
|
-
maxEagerFetch: this.maxEagerFetch,
|
|
157
|
-
});
|
|
158
|
-
findCommand.converter.parent = this.converter;
|
|
159
|
-
await findCommand.filter((0, builder_1.In)(targetCol.name, (0, builder_1.Param)(parentField)));
|
|
160
|
-
const sort = sortFields && extractSubFields(colNameLower, sortFields);
|
|
161
|
-
await findCommand.addFields({
|
|
162
|
-
projection: p?.projection,
|
|
163
|
-
sort,
|
|
164
|
-
});
|
|
165
|
-
if (sort)
|
|
166
|
-
await findCommand.sort(sort);
|
|
167
|
-
const keyField = findCommand._selectColumn(findCommand.mainAlias, targetCol);
|
|
168
|
-
const resultType = await col.association.getLast().resolveTarget();
|
|
169
|
-
converter.addNestedProperty({
|
|
170
|
-
name: col.name,
|
|
171
|
-
type: resultType.ctor,
|
|
172
|
-
findCommand,
|
|
173
|
-
parentField,
|
|
174
|
-
keyField,
|
|
175
|
-
sort: extractSubFields(colNameLower, sortFields),
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
_selectColumn(tableAlias, el, prefix, suffix) {
|
|
182
|
-
const fieldName = (prefix || '').toLowerCase() +
|
|
183
|
-
el.fieldName.toUpperCase() +
|
|
184
|
-
(suffix || '').toLowerCase();
|
|
185
|
-
const fieldAlias = (tableAlias + '_' + fieldName).substring(0, 30);
|
|
186
|
-
this._selectColumns[fieldAlias] = {
|
|
187
|
-
field: el,
|
|
188
|
-
statement: tableAlias + '.' + fieldName + ' as ' + fieldAlias,
|
|
189
|
-
};
|
|
190
|
-
return fieldAlias;
|
|
191
|
-
}
|
|
192
|
-
async filter(filter) {
|
|
193
|
-
await (0, command_helper_js_1.prepareFilter)(this.mainEntity, filter, this._filter);
|
|
194
|
-
}
|
|
195
|
-
async sort(sortFields) {
|
|
196
|
-
const out = [];
|
|
197
|
-
for (const item of sortFields) {
|
|
198
|
-
const m = item.match(SORT_ORDER_PATTERN);
|
|
199
|
-
if (!m)
|
|
200
|
-
throw new Error(`"${item}" is not a valid order expression`);
|
|
201
|
-
let elName = m[2];
|
|
202
|
-
let prefix = '';
|
|
203
|
-
let suffix = '';
|
|
204
|
-
let _entityDef = this.resultEntity;
|
|
205
|
-
let tableAlias = this.resultAlias;
|
|
206
|
-
if (elName.includes('.')) {
|
|
207
|
-
const a = elName.split('.');
|
|
208
|
-
while (a.length > 1) {
|
|
209
|
-
const col = entity_metadata_js_1.EntityMetadata.getField(_entityDef, a.shift() || '');
|
|
210
|
-
if ((0, orm_helper_js_1.isEmbeddedField)(col)) {
|
|
211
|
-
_entityDef = await embedded_field_metadata_js_1.EmbeddedFieldMetadata.resolveType(col);
|
|
212
|
-
if (col.fieldNamePrefix)
|
|
213
|
-
prefix += col.fieldNamePrefix;
|
|
214
|
-
if (col.fieldNameSuffix)
|
|
215
|
-
suffix = col.fieldNameSuffix + suffix;
|
|
216
|
-
}
|
|
217
|
-
else if ((0, orm_helper_js_1.isAssociationField)(col)) {
|
|
218
|
-
if (col.association.returnsMany()) {
|
|
219
|
-
elName = '';
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
const joinInfo = await (0, command_helper_js_1.joinAssociationGetLast)(this._joins, col.association, tableAlias);
|
|
223
|
-
tableAlias = joinInfo.joinAlias;
|
|
224
|
-
_entityDef = joinInfo.targetEntity;
|
|
225
|
-
}
|
|
226
|
-
else
|
|
227
|
-
throw new Error(`Invalid column (${elName}) declared in sort property`);
|
|
228
|
-
}
|
|
229
|
-
if (!elName)
|
|
230
|
-
continue;
|
|
231
|
-
elName = a.shift() || '';
|
|
232
|
-
}
|
|
233
|
-
const col = entity_metadata_js_1.EntityMetadata.getField(_entityDef, elName);
|
|
234
|
-
if (!col)
|
|
235
|
-
throw new Error(`Unknown field (${elName}) declared in sort property`);
|
|
236
|
-
if (!(0, orm_helper_js_1.isColumnField)(col))
|
|
237
|
-
throw new Error(`Can not sort by "${elName}", because it is not a data column`);
|
|
238
|
-
const dir = m[1] || '+';
|
|
239
|
-
out.push((dir || '') + tableAlias + '.' + prefix + col.fieldName + suffix);
|
|
240
|
-
}
|
|
241
|
-
this._sort = out;
|
|
242
|
-
}
|
|
243
|
-
async execute(args) {
|
|
244
|
-
// Generate select query
|
|
245
|
-
const columnSqls = Object.keys(this._selectColumns).map(x => this._selectColumns[x].statement);
|
|
246
|
-
if (!columnSqls.length)
|
|
247
|
-
columnSqls.push('1');
|
|
248
|
-
const query = (0, builder_1.Select)(...columnSqls).from(this.mainEntity.tableName + ' as ' + this.mainAlias);
|
|
249
|
-
if (args.distinct)
|
|
250
|
-
query.distinct();
|
|
251
|
-
query.where(...this._filter._items);
|
|
252
|
-
if (this._sort) {
|
|
253
|
-
query.orderBy(...this._sort);
|
|
254
|
-
}
|
|
255
|
-
if (args.offset)
|
|
256
|
-
query.offset(args.offset);
|
|
257
|
-
// joins must be added last
|
|
258
|
-
if (this._joins) {
|
|
259
|
-
for (const j of this._joins) {
|
|
260
|
-
query.join(j.join);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
// Execute query
|
|
264
|
-
const resp = await args.connection.execute(query, {
|
|
265
|
-
params: args?.params,
|
|
266
|
-
fetchRows: args?.limit,
|
|
267
|
-
objectRows: false,
|
|
268
|
-
cursor: false,
|
|
269
|
-
prettyPrint: args.prettyPrint,
|
|
270
|
-
});
|
|
271
|
-
// Create objects
|
|
272
|
-
if (resp.rows && resp.fields) {
|
|
273
|
-
return this.converter.transform(args.connection, resp.fields, resp.rows, args.onTransformRow);
|
|
274
|
-
}
|
|
275
|
-
return [];
|
|
276
|
-
}
|
|
277
|
-
_getEntityFromAlias(tableAlias) {
|
|
278
|
-
if (tableAlias === this.mainAlias)
|
|
279
|
-
return this.mainEntity;
|
|
280
|
-
if (tableAlias === this.resultAlias)
|
|
281
|
-
return this.resultEntity;
|
|
282
|
-
if (this._joins) {
|
|
283
|
-
const join = this._joins.find(j => j.joinAlias === tableAlias);
|
|
284
|
-
if (join)
|
|
285
|
-
return join.targetEntity;
|
|
286
|
-
}
|
|
287
|
-
throw new Error(`Unknown table alias "${tableAlias}"`);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
exports.FindCommand = FindCommand;
|
|
291
|
-
function extractSubFields(colNameLower, fields) {
|
|
292
|
-
if (!(fields && fields.length))
|
|
293
|
-
return;
|
|
294
|
-
if (fields) {
|
|
295
|
-
return fields.reduce((trg, v) => {
|
|
296
|
-
if (v.startsWith(colNameLower + '.'))
|
|
297
|
-
trg.push(v.substring(colNameLower.length + 1).toLowerCase());
|
|
298
|
-
return trg;
|
|
299
|
-
}, []);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RowConverter = void 0;
|
|
4
|
-
const builder_1 = require("@sqb/builder");
|
|
5
|
-
const isValueProperty = (prop) => prop.fieldAlias && !prop.converter;
|
|
6
|
-
const isObjectProperty = (prop) => prop.converter && !prop.findCommand;
|
|
7
|
-
const isNestedProperty = (prop) => prop.converter && prop.findCommand;
|
|
8
|
-
class RowConverter {
|
|
9
|
-
resultType;
|
|
10
|
-
parent;
|
|
11
|
-
_properties = {};
|
|
12
|
-
_propertyKeys;
|
|
13
|
-
constructor(resultType, parent) {
|
|
14
|
-
this.resultType = resultType;
|
|
15
|
-
this.parent = parent;
|
|
16
|
-
}
|
|
17
|
-
addValueProperty(args) {
|
|
18
|
-
this._propertyKeys = undefined;
|
|
19
|
-
const item = {
|
|
20
|
-
fieldAlias: args.fieldAlias,
|
|
21
|
-
dataType: args.dataType,
|
|
22
|
-
parse: args.parse,
|
|
23
|
-
};
|
|
24
|
-
this._properties[args.name] = item;
|
|
25
|
-
return item;
|
|
26
|
-
}
|
|
27
|
-
addObjectProperty(args) {
|
|
28
|
-
this._checkCircularDep(args.type);
|
|
29
|
-
this._propertyKeys = undefined;
|
|
30
|
-
const converter = new RowConverter(args.type, this);
|
|
31
|
-
const item = {
|
|
32
|
-
converter,
|
|
33
|
-
type: args.type,
|
|
34
|
-
};
|
|
35
|
-
this._properties[args.name] = item;
|
|
36
|
-
return item;
|
|
37
|
-
}
|
|
38
|
-
addNestedProperty(args) {
|
|
39
|
-
this._checkCircularDep(args.type);
|
|
40
|
-
const converter = new RowConverter(args.type, this);
|
|
41
|
-
const item = {
|
|
42
|
-
converter,
|
|
43
|
-
type: args.type,
|
|
44
|
-
parentField: args.parentField,
|
|
45
|
-
keyField: args.keyField,
|
|
46
|
-
findCommand: args.findCommand,
|
|
47
|
-
sort: args.sort,
|
|
48
|
-
paramValues: [],
|
|
49
|
-
};
|
|
50
|
-
this._properties[args.name] = item;
|
|
51
|
-
return item;
|
|
52
|
-
}
|
|
53
|
-
get keys() {
|
|
54
|
-
if (!this._propertyKeys)
|
|
55
|
-
this._propertyKeys = Object.keys(this._properties);
|
|
56
|
-
return this._propertyKeys;
|
|
57
|
-
}
|
|
58
|
-
async transform(connection, fields, rows, onTransform) {
|
|
59
|
-
const rowLen = rows.length;
|
|
60
|
-
const result = [];
|
|
61
|
-
for (let rowIdx = 0; rowIdx < rowLen; rowIdx++) {
|
|
62
|
-
const row = rows[rowIdx];
|
|
63
|
-
const o = (await this._rowToObject(connection, fields, row)) || {};
|
|
64
|
-
if (onTransform)
|
|
65
|
-
onTransform(fields, row, o);
|
|
66
|
-
result.push(o);
|
|
67
|
-
}
|
|
68
|
-
if (!this.keys)
|
|
69
|
-
return result;
|
|
70
|
-
await this._iterateForNested(this, connection, fields, rows, result);
|
|
71
|
-
// Return only non empty objects
|
|
72
|
-
return result.filter(x => !!x);
|
|
73
|
-
}
|
|
74
|
-
_rowToObject(executor, fields, row) {
|
|
75
|
-
// Cache keys for better performance
|
|
76
|
-
const fieldKeys = this.keys;
|
|
77
|
-
const fieldsLen = fieldKeys.length;
|
|
78
|
-
let result;
|
|
79
|
-
for (let elIdx = 0; elIdx < fieldsLen; elIdx++) {
|
|
80
|
-
const elKey = fieldKeys[elIdx];
|
|
81
|
-
const prop = this._properties[elKey];
|
|
82
|
-
if (isValueProperty(prop)) {
|
|
83
|
-
const field = fields.get(prop.fieldAlias);
|
|
84
|
-
if (field) {
|
|
85
|
-
let v = row[field.index];
|
|
86
|
-
if (typeof prop.parse === 'function')
|
|
87
|
-
v = prop.parse(v, elKey);
|
|
88
|
-
if (v != null) {
|
|
89
|
-
result = result || {};
|
|
90
|
-
if (prop.dataType === builder_1.DataType.JSON && typeof v === 'string')
|
|
91
|
-
v = JSON.parse(v);
|
|
92
|
-
result[elKey] = v;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
else if (isNestedProperty(prop)) {
|
|
97
|
-
// One2Many Eager field
|
|
98
|
-
// Keep a list of key field/value pairs to fetch rows for eager relation
|
|
99
|
-
const _params = prop.paramValues;
|
|
100
|
-
const f = fields.get(prop.parentField);
|
|
101
|
-
const v = f && row[f.index];
|
|
102
|
-
if (v != null && !_params.includes(v))
|
|
103
|
-
_params.push(v);
|
|
104
|
-
}
|
|
105
|
-
else if (isObjectProperty(prop)) {
|
|
106
|
-
const v = prop.converter._rowToObject(executor, fields, row);
|
|
107
|
-
if (v != null) {
|
|
108
|
-
result = result || {};
|
|
109
|
-
result[elKey] = v;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (result)
|
|
114
|
-
Object.setPrototypeOf(result, this.resultType.prototype);
|
|
115
|
-
return result;
|
|
116
|
-
}
|
|
117
|
-
async _iterateForNested(node, connection, fields, rows, result) {
|
|
118
|
-
// Fetch one-2-many related rows and merge with result rows
|
|
119
|
-
const keys = node.keys;
|
|
120
|
-
const propertyLen = keys.length;
|
|
121
|
-
const promises = [];
|
|
122
|
-
for (let propIdx = 0; propIdx < propertyLen; propIdx++) {
|
|
123
|
-
const propKey = keys[propIdx];
|
|
124
|
-
const prop = node._properties[propKey];
|
|
125
|
-
if (isNestedProperty(prop)) {
|
|
126
|
-
if (!(prop.paramValues && prop.paramValues.length))
|
|
127
|
-
continue;
|
|
128
|
-
const resultType = this.resultType;
|
|
129
|
-
const promise = (async function (p) {
|
|
130
|
-
const findCommand = p.findCommand;
|
|
131
|
-
let fld;
|
|
132
|
-
const map = new Map();
|
|
133
|
-
const r = await findCommand.execute({
|
|
134
|
-
connection,
|
|
135
|
-
limit: findCommand.maxEagerFetch + 1,
|
|
136
|
-
params: { [p.parentField]: p.paramValues },
|
|
137
|
-
onTransformRow: (_fields, row, obj) => {
|
|
138
|
-
fld = fld || _fields.get('' + p.keyField);
|
|
139
|
-
const keyValue = fld && row[fld.index];
|
|
140
|
-
if (keyValue != null) {
|
|
141
|
-
const keyValues = Array.isArray(keyValue)
|
|
142
|
-
? keyValue
|
|
143
|
-
: [keyValue];
|
|
144
|
-
keyValues.forEach(k => {
|
|
145
|
-
let arr = map.get(k);
|
|
146
|
-
if (!arr) {
|
|
147
|
-
arr = [];
|
|
148
|
-
map.set(k, arr);
|
|
149
|
-
}
|
|
150
|
-
arr.push(obj);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
if (r.length > findCommand.maxEagerFetch) {
|
|
156
|
-
throw new Error(`Number of returning rows for "${propKey}" exceeds maxEagerFetch limit`);
|
|
157
|
-
}
|
|
158
|
-
for (let i = 0; i < result.length; i++) {
|
|
159
|
-
const row = rows[i];
|
|
160
|
-
let obj = result[i];
|
|
161
|
-
if (!obj) {
|
|
162
|
-
obj = {};
|
|
163
|
-
Object.setPrototypeOf(result, resultType.prototype);
|
|
164
|
-
}
|
|
165
|
-
const f = fields.get('' + p.parentField);
|
|
166
|
-
const keyValue = f && row[f.index];
|
|
167
|
-
if (keyValue != null) {
|
|
168
|
-
const arr = map.get(keyValue);
|
|
169
|
-
if (arr) {
|
|
170
|
-
obj[propKey] = arr;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
})(prop);
|
|
175
|
-
promises.push(promise);
|
|
176
|
-
}
|
|
177
|
-
else if (isObjectProperty(prop)) {
|
|
178
|
-
promises.push(this._iterateForNested(prop.converter, connection, fields, rows, result));
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
await Promise.all(promises);
|
|
182
|
-
}
|
|
183
|
-
_checkCircularDep(t) {
|
|
184
|
-
if (this.resultType === t)
|
|
185
|
-
throw new Error('Circular fields requested');
|
|
186
|
-
if (this.parent)
|
|
187
|
-
this.parent._checkCircularDep(t);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
exports.RowConverter = RowConverter;
|