@sap/cds 5.5.3 → 5.6.1
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/CHANGELOG.md +134 -1
- package/apis/services.d.ts +27 -1
- package/app/index.js +22 -11
- package/bin/build/buildTaskFactory.js +1 -1
- package/bin/build/provider/buildTaskProviderInternal.js +1 -1
- package/bin/build/provider/fiori/index.js +1 -1
- package/bin/build/provider/hana/2migration.js +8 -7
- package/bin/build/provider/java-cf/index.js +1 -1
- package/bin/deploy/to-hana/hana.js +1 -17
- package/common.cds +8 -0
- package/lib/compile/index.js +1 -1
- package/lib/compile/to/sql.js +22 -2
- package/lib/connect/bindings.js +2 -1
- package/lib/connect/index.js +1 -1
- package/lib/core/infer.js +1 -1
- package/lib/core/reflect.js +3 -1
- package/lib/env/index.js +175 -41
- package/lib/env/requires.js +24 -3
- package/lib/i18n/localize.js +33 -5
- package/lib/index.js +7 -6
- package/lib/log/format/kibana.js +6 -2
- package/lib/ql/DELETE.js +1 -1
- package/lib/ql/INSERT.js +1 -1
- package/lib/ql/Query.js +13 -10
- package/lib/ql/SELECT.js +15 -8
- package/lib/ql/UPDATE.js +1 -1
- package/lib/ql/Whereable.js +5 -0
- package/lib/req/context.js +87 -37
- package/lib/req/{impl.js → request.js} +1 -1
- package/lib/req/{res.js → response.js} +0 -0
- package/lib/serve/Service-api.js +1 -1
- package/lib/serve/Service-dispatch.js +12 -2
- package/lib/serve/Service-handlers.js +21 -7
- package/lib/serve/Service-methods.js +1 -1
- package/lib/serve/Transaction.js +7 -6
- package/lib/serve/index.js +1 -1
- package/lib/utils/axios.js +7 -0
- package/lib/utils/data.js +1 -1
- package/libx/_runtime/audit/Service.js +18 -18
- package/libx/_runtime/audit/generic/personal/access.js +1 -1
- package/libx/_runtime/audit/generic/personal/modification.js +3 -2
- package/libx/_runtime/audit/generic/personal/utils.js +23 -63
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +6 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +37 -35
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +3 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +5 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +13 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +84 -34
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +10 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +9 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +8 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +1 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +13 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectHelper.js +11 -95
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ResourcePathParser.js +17 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +2 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +6 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +3 -34
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +3 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +48 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +10 -5
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/update.js +1 -1
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +1 -3
- package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +9 -2
- package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +20 -21
- package/libx/_runtime/cds-services/services/utils/columns.js +6 -1
- package/libx/_runtime/cds-services/services/utils/compareJson.js +1 -8
- package/libx/_runtime/cds-services/services/utils/differ.js +7 -26
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -4
- package/libx/_runtime/cds-services/util/assert.js +29 -13
- package/libx/_runtime/cds.js +2 -1
- package/libx/_runtime/common/aspects/Association.js +72 -0
- package/libx/_runtime/common/aspects/any.js +8 -45
- package/libx/_runtime/common/aspects/entity.js +0 -1
- package/libx/_runtime/common/aspects/relation.js +40 -0
- package/libx/_runtime/common/aspects/utils.js +73 -1
- package/libx/_runtime/common/auth/strategies/utils/uaa.js +10 -14
- package/libx/_runtime/common/composition/data.js +3 -2
- package/libx/_runtime/common/composition/delete.js +3 -1
- package/libx/_runtime/common/composition/tree.js +23 -18
- package/libx/_runtime/common/composition/utils.js +34 -8
- package/libx/_runtime/common/error/frontend.js +6 -1
- package/libx/_runtime/common/generic/auth.js +15 -13
- package/libx/_runtime/common/generic/crud.js +2 -2
- package/libx/_runtime/common/generic/etag.js +11 -8
- package/libx/_runtime/common/generic/input.js +3 -3
- package/libx/_runtime/common/generic/paging.js +9 -5
- package/libx/_runtime/common/generic/put.js +3 -2
- package/libx/_runtime/common/generic/sorting.js +3 -3
- package/libx/_runtime/common/generic/temporal.js +3 -3
- package/libx/_runtime/common/toggles/alpha.js +1 -1
- package/libx/_runtime/common/utils/cqn.js +20 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +125 -139
- package/libx/_runtime/common/utils/csn.js +50 -52
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +41 -176
- package/libx/_runtime/common/utils/generateOnCond.js +40 -70
- package/libx/_runtime/common/utils/{enrichWithKeysFromWhere.js → keys.js} +29 -28
- package/libx/_runtime/common/utils/postProcessing.js +3 -0
- package/libx/_runtime/common/utils/propagateForeignKeys.js +84 -0
- package/libx/_runtime/common/utils/resolveStructured.js +1 -1
- package/libx/_runtime/common/utils/resolveView.js +19 -9
- package/libx/_runtime/common/utils/rewriteAsterisks.js +94 -0
- package/libx/_runtime/common/utils/search2cqn4sql.js +9 -8
- package/libx/_runtime/common/utils/template.js +54 -46
- package/libx/_runtime/db/Service.js +9 -2
- package/libx/_runtime/db/expand/expandCQNToJoin.js +10 -24
- package/libx/_runtime/db/expand/rawToExpanded.js +2 -1
- package/libx/_runtime/db/generic/create.js +1 -0
- package/libx/_runtime/db/generic/input.js +7 -11
- package/libx/_runtime/db/generic/integrity.js +2 -2
- package/libx/_runtime/db/generic/rewrite.js +2 -5
- package/libx/_runtime/db/generic/update.js +1 -0
- package/libx/_runtime/db/query/read.js +10 -5
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +6 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +7 -2
- package/libx/_runtime/db/sql-builder/annotations.js +1 -0
- package/libx/_runtime/db/utils/columns.js +14 -43
- package/libx/_runtime/db/utils/deep.js +5 -7
- package/libx/_runtime/fiori/generic/activate.js +3 -2
- package/libx/_runtime/fiori/generic/before.js +2 -2
- package/libx/_runtime/fiori/generic/cancel.js +3 -2
- package/libx/_runtime/fiori/generic/delete.js +3 -2
- package/libx/_runtime/fiori/generic/edit.js +2 -2
- package/libx/_runtime/fiori/generic/new.js +2 -2
- package/libx/_runtime/fiori/generic/patch.js +2 -2
- package/libx/_runtime/fiori/generic/prepare.js +2 -2
- package/libx/_runtime/fiori/generic/read.js +17 -63
- package/libx/_runtime/fiori/generic/readOverDraft.js +4 -4
- package/libx/_runtime/fiori/uiflex/extensibility/index.cds +15 -0
- package/libx/_runtime/fiori/uiflex/extensibility/index.js +148 -0
- package/libx/_runtime/fiori/uiflex/handler/transformREAD.js +119 -0
- package/libx/_runtime/fiori/uiflex/handler/transformRESULT.js +43 -0
- package/libx/_runtime/fiori/uiflex/handler/transformWRITE.js +62 -0
- package/libx/_runtime/fiori/uiflex/index.js +35 -0
- package/libx/_runtime/fiori/uiflex/utils.js +78 -0
- package/libx/_runtime/fiori/utils/handler.js +3 -13
- package/libx/_runtime/fiori/utils/where.js +6 -1
- package/libx/_runtime/hana/Service.js +5 -2
- package/libx/_runtime/hana/execute.js +1 -1
- package/libx/_runtime/hana/pool.js +12 -11
- package/libx/_runtime/hana/search2cqn4sql.js +34 -43
- package/libx/_runtime/hana/searchToContains.js +3 -3
- package/libx/_runtime/index.js +5 -2
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +1 -1
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +16 -3
- package/libx/_runtime/messaging/common-utils/connections.js +11 -14
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -1
- package/libx/_runtime/messaging/enterprise-messaging.js +1 -1
- package/libx/_runtime/messaging/message-queuing.js +18 -0
- package/libx/_runtime/remote/Service.js +14 -2
- package/libx/_runtime/remote/utils/client-types.d.ts +7 -0
- package/libx/_runtime/remote/utils/client.js +117 -23
- package/libx/_runtime/sqlite/Service.js +4 -3
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +1 -3
- package/libx/_runtime/sqlite/execute.js +1 -1
- package/libx/gql/GraphQLAdapter.js +33 -0
- package/libx/gql/constants/adapter.js +69 -0
- package/libx/gql/constants/cds.js +18 -0
- package/libx/gql/constants/graphql.js +33 -0
- package/libx/gql/resolvers/crud/create.js +15 -0
- package/libx/gql/resolvers/crud/delete.js +24 -0
- package/libx/gql/resolvers/crud/index.js +6 -0
- package/libx/gql/resolvers/crud/read.js +25 -0
- package/libx/gql/resolvers/crud/update.js +31 -0
- package/libx/gql/resolvers/crud/utils/index.js +36 -0
- package/libx/gql/resolvers/field.js +5 -0
- package/libx/gql/resolvers/index.js +7 -0
- package/libx/gql/resolvers/mutation.js +23 -0
- package/libx/gql/resolvers/parse/ast/enrich.js +51 -0
- package/libx/gql/resolvers/parse/ast/fragment.js +11 -0
- package/libx/gql/resolvers/parse/ast/fromObject.js +39 -0
- package/libx/gql/resolvers/parse/ast/index.js +3 -0
- package/libx/gql/resolvers/parse/ast/meta.js +4 -0
- package/libx/gql/resolvers/parse/ast/variable.js +7 -0
- package/libx/gql/resolvers/parse/ast2cqn/columns.js +42 -0
- package/libx/gql/resolvers/parse/ast2cqn/entries.js +31 -0
- package/libx/gql/resolvers/parse/ast2cqn/index.js +8 -0
- package/libx/gql/resolvers/parse/ast2cqn/limit.js +6 -0
- package/libx/gql/resolvers/parse/ast2cqn/orderBy.js +24 -0
- package/libx/gql/resolvers/parse/ast2cqn/utils/index.js +3 -0
- package/libx/gql/resolvers/parse/ast2cqn/where.js +70 -0
- package/libx/gql/resolvers/parse/utils/index.js +8 -0
- package/libx/gql/resolvers/query.js +13 -0
- package/libx/gql/resolvers/root.js +34 -0
- package/libx/gql/schema/generate.js +18 -0
- package/libx/gql/schema/index.js +5 -0
- package/libx/gql/schema/mutation.js +76 -0
- package/libx/gql/schema/query.js +108 -0
- package/libx/gql/schema/typeDefMap.js +45 -0
- package/libx/gql/schema/utils/index.js +54 -0
- package/libx/gql/utils/index.js +12 -0
- package/libx/{_runtime/odata/cqn2odata.js → odata/cqn2odata/index.js} +39 -100
- package/libx/odata/index.js +80 -0
- package/libx/odata/odata2cqn/afterburner.js +170 -0
- package/libx/{_runtime/odata/odata2cqn.pegjs → odata/odata2cqn/grammar.pegjs} +102 -123
- package/libx/odata/odata2cqn/index.js +3 -0
- package/libx/odata/odata2cqn/parser.js +1 -0
- package/libx/odata/utils/index.js +64 -0
- package/libx/rest/RestAdapter.js +101 -0
- package/libx/rest/RestRequest.js +30 -0
- package/libx/rest/index.js +3 -0
- package/libx/rest/middleware/auth.js +22 -0
- package/libx/rest/middleware/content.js +15 -0
- package/libx/rest/middleware/create.js +40 -0
- package/libx/rest/middleware/delete.js +20 -0
- package/libx/rest/middleware/error.js +56 -0
- package/libx/rest/middleware/operation.js +39 -0
- package/libx/rest/middleware/parse.js +90 -0
- package/libx/rest/middleware/read.js +29 -0
- package/libx/rest/middleware/update.js +42 -0
- package/libx/rest/utils/data.js +65 -0
- package/package.json +4 -1
- package/server.js +42 -29
- package/lib/req/cls.js +0 -39
- package/libx/_runtime/cds-services/services/utils/diff.js +0 -53
- package/libx/_runtime/cds-services/util/auditlog.js +0 -247
- package/libx/_runtime/cds-services/util/xsenv.js +0 -51
- package/libx/_runtime/common/utils/backlinks.js +0 -83
- package/libx/_runtime/common/utils/rewriteAsterisk.js +0 -72
- package/libx/_runtime/odata/index.js +0 -55
- package/libx/_runtime/odata/odata2cqn.js +0 -1
- package/libx/_runtime/odata/readToCqn.js +0 -129
- package/libx/_runtime/remote/cqn2odata/index.js +0 -2
|
@@ -1,93 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
const _generateParentField = (foreignKeyPropagations, row) => {
|
|
4
|
-
if (
|
|
5
|
-
foreignKeyPropagations.parentFieldName &&
|
|
6
|
-
!row[foreignKeyPropagations.parentFieldName] &&
|
|
7
|
-
foreignKeyPropagations.autoGenerate
|
|
8
|
-
) {
|
|
9
|
-
row[foreignKeyPropagations.parentFieldName] = cds.utils.uuid()
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const _generateChildField = (foreignKeyPropagations, childRow) => {
|
|
14
|
-
if (foreignKeyPropagations.deep) {
|
|
15
|
-
const deep = foreignKeyPropagations.deep
|
|
16
|
-
_generateChildField(deep.propagation, childRow[deep.targetName])
|
|
17
|
-
} else if (childRow && !childRow[foreignKeyPropagations.childFieldName] && foreignKeyPropagations.autoGenerate) {
|
|
18
|
-
childRow[foreignKeyPropagations.childFieldName] = cds.utils.uuid()
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const _getNestedVal = (row, prefix) => {
|
|
23
|
-
let val = row
|
|
24
|
-
const splitted = prefix.split('_')
|
|
25
|
-
let k = ''
|
|
26
|
-
|
|
27
|
-
while (splitted.length > 0) {
|
|
28
|
-
k += splitted.shift()
|
|
29
|
-
if (k in val) {
|
|
30
|
-
val = val[k]
|
|
31
|
-
k = ''
|
|
32
|
-
} else {
|
|
33
|
-
k += '_'
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return val
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const _propagateToChid = (foreignKeyPropagation, row, childRow) => {
|
|
41
|
-
const { parentFieldName, childFieldName, prefix, parentFieldValue } = foreignKeyPropagation
|
|
42
|
-
|
|
43
|
-
if (parentFieldName) {
|
|
44
|
-
if (prefix) {
|
|
45
|
-
const nested = _getNestedVal(row, prefix)
|
|
46
|
-
childRow[childFieldName] = nested[parentFieldName]
|
|
47
|
-
} else {
|
|
48
|
-
childRow[childFieldName] = row[parentFieldName]
|
|
49
|
-
}
|
|
50
|
-
} else if (parentFieldValue !== undefined) {
|
|
51
|
-
childRow[childFieldName] = parentFieldValue
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const _propagateToParent = (foreignKeyPropagations, childRow, row) => {
|
|
56
|
-
if (foreignKeyPropagations.deep) {
|
|
57
|
-
const deep = foreignKeyPropagations.deep
|
|
58
|
-
_propagateToParent(deep.propagation, childRow[deep.targetName], childRow)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (childRow && Object.prototype.hasOwnProperty.call(childRow, foreignKeyPropagations.childFieldName)) {
|
|
62
|
-
row[foreignKeyPropagations.parentFieldName] = childRow[foreignKeyPropagations.childFieldName]
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const propagateForeignKeys = (tKey, row, foreignKeyPropagations, opts = {}) => {
|
|
67
|
-
const childRows = Array.isArray(row[tKey]) ? row[tKey] : [row[tKey]]
|
|
68
|
-
|
|
69
|
-
for (const childRow of childRows) {
|
|
70
|
-
if (!childRow) return
|
|
71
|
-
|
|
72
|
-
for (const foreignKeyPropagation of foreignKeyPropagations) {
|
|
73
|
-
if (foreignKeyPropagation.fillChild) {
|
|
74
|
-
_generateParentField(foreignKeyPropagation, row)
|
|
75
|
-
if (opts.onlyWriteCompositionEffective && !foreignKeyPropagations._element._isCompositionEffective) {
|
|
76
|
-
delete row[tKey]
|
|
77
|
-
} else {
|
|
78
|
-
_propagateToChid(foreignKeyPropagation, row, childRow)
|
|
79
|
-
}
|
|
80
|
-
} else {
|
|
81
|
-
_generateChildField(foreignKeyPropagation, childRow)
|
|
82
|
-
_propagateToParent(foreignKeyPropagation, childRow, row)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const _getSubOns = on => {
|
|
1
|
+
const _getSubOns = element => {
|
|
89
2
|
// this only works for on conds with `and`, once we support `or` this needs to be adjusted
|
|
90
|
-
const newOn = on.filter(e => e !== '(' && e !== ')')
|
|
3
|
+
const newOn = element.on ? element.on.filter(e => e !== '(' && e !== ')') : []
|
|
91
4
|
const subOns = []
|
|
92
5
|
let currArr = []
|
|
93
6
|
|
|
@@ -108,8 +21,6 @@ const _getSubOns = on => {
|
|
|
108
21
|
return subOns
|
|
109
22
|
}
|
|
110
23
|
|
|
111
|
-
const _autoGenerate = el => el && el.type === 'cds.UUID' && el.key
|
|
112
|
-
|
|
113
24
|
const _parentFieldsFromSimpleOnCond = (element, subOn) => {
|
|
114
25
|
const idxChildField = subOn.findIndex(o => o.ref && o.ref[0] === element.name)
|
|
115
26
|
if (idxChildField === -1 || subOn[1] !== '=') return
|
|
@@ -124,26 +35,20 @@ const _parentFieldsFromSimpleOnCond = (element, subOn) => {
|
|
|
124
35
|
if (idxChildInParent > -1) parentRef.splice(idxChildInParent, 1)
|
|
125
36
|
parentRef = [parentRef.join('_')]
|
|
126
37
|
}
|
|
38
|
+
const parentElement = parentRef && element.parent.elements[parentRef[0]]
|
|
127
39
|
|
|
128
40
|
if (!childElement) {
|
|
129
41
|
// update on view with key in parent
|
|
130
|
-
|
|
131
|
-
return [
|
|
132
|
-
{
|
|
133
|
-
fillChild: false,
|
|
134
|
-
childFieldName,
|
|
135
|
-
parentFieldName: parentRef[0],
|
|
136
|
-
autoGenerate: _autoGenerate(element.parent.elements[parentRef[0]])
|
|
137
|
-
}
|
|
138
|
-
]
|
|
42
|
+
return [{ fillChild: false, parentElement, childElement }]
|
|
139
43
|
}
|
|
140
44
|
|
|
141
|
-
if (!childElement.on
|
|
142
|
-
return _foreignKeyPropagationsFromToManyOn(element,
|
|
45
|
+
if (!childElement.on) {
|
|
46
|
+
if (element._isSelfManaged) return _foreignKeyPropagationsFromToManyOn(element, childFieldName)
|
|
47
|
+
if (parentElement) return [{ fillChild: true, parentElement, childElement }]
|
|
143
48
|
}
|
|
144
49
|
|
|
145
50
|
if ('val' in subOn[idxParentField]) {
|
|
146
|
-
return
|
|
51
|
+
return [{ fillChild: true, parentFieldValue: subOn[idxParentField].val, childElement }]
|
|
147
52
|
}
|
|
148
53
|
|
|
149
54
|
if (childElement._isAssociationStrict && childElement.on) {
|
|
@@ -151,40 +56,19 @@ const _parentFieldsFromSimpleOnCond = (element, subOn) => {
|
|
|
151
56
|
}
|
|
152
57
|
}
|
|
153
58
|
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const _foreignKeyPropagationsFromToManyOn = (element, parentRef, childFieldName) => {
|
|
161
|
-
const parentFieldName = parentRef[0]
|
|
162
|
-
if (parentFieldName === '$self') {
|
|
163
|
-
const foreignKeys = _foreignKeysForTarget(element, childFieldName)
|
|
164
|
-
|
|
165
|
-
// REVISIT foreignKeys is empty if we have deep operations where a sub element is annotated with persistence skip
|
|
166
|
-
if (foreignKeys && foreignKeys.length) {
|
|
167
|
-
const parentKeys = _parentKeys(element)
|
|
168
|
-
|
|
169
|
-
return resolvedKeys(parentKeys, foreignKeys, true)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return []
|
|
59
|
+
const _foreignKeyPropagationsFromToManyOn = (element, childFieldName) => {
|
|
60
|
+
const foreignKeys = _foreignKeysForTarget(element, childFieldName)
|
|
61
|
+
// REVISIT foreignKeys is empty if we have deep operations where a sub element is annotated with persistence skip
|
|
62
|
+
if (foreignKeys && foreignKeys.length) {
|
|
63
|
+
const parentKeys = _parentKeys(element)
|
|
64
|
+
return _resolvedKeys(parentKeys, foreignKeys, true)
|
|
173
65
|
}
|
|
174
|
-
|
|
175
|
-
return [
|
|
176
|
-
{
|
|
177
|
-
fillChild: true,
|
|
178
|
-
childFieldName,
|
|
179
|
-
parentFieldName,
|
|
180
|
-
autoGenerate: _autoGenerate(element.parent.elements[parentFieldName])
|
|
181
|
-
}
|
|
182
|
-
]
|
|
66
|
+
return []
|
|
183
67
|
}
|
|
184
68
|
|
|
185
69
|
const _foreignKeyPropagationsFromCustomBacklink = (element, childElement) => {
|
|
186
70
|
const foreignKeyPropagations = []
|
|
187
|
-
const subOns = _getSubOns(childElement
|
|
71
|
+
const subOns = _getSubOns(childElement)
|
|
188
72
|
|
|
189
73
|
for (const subOn of subOns) {
|
|
190
74
|
if (subOn[1] === '=') {
|
|
@@ -192,20 +76,26 @@ const _foreignKeyPropagationsFromCustomBacklink = (element, childElement) => {
|
|
|
192
76
|
const otherFieldIdx = parentFieldIdx === 0 ? 2 : 0
|
|
193
77
|
const otherField = subOn[otherFieldIdx]
|
|
194
78
|
|
|
195
|
-
if (
|
|
79
|
+
if (parentFieldIdx === -1 && subOn[otherFieldIdx === 0 ? 2 : 0].val !== undefined) {
|
|
80
|
+
const parentField = subOn[otherFieldIdx === 0 ? 2 : 0]
|
|
81
|
+
foreignKeyPropagations.push({
|
|
82
|
+
fillChild: false,
|
|
83
|
+
parentFieldValue: parentField.val,
|
|
84
|
+
childElement: element._target.elements[otherField.ref[0]]
|
|
85
|
+
})
|
|
86
|
+
} else if (otherField.ref && otherField.ref.length === 1) {
|
|
196
87
|
const parentFieldName = subOn[parentFieldIdx].ref[1]
|
|
197
88
|
foreignKeyPropagations.push({
|
|
198
89
|
fillChild: true,
|
|
199
|
-
parentFieldName,
|
|
200
|
-
|
|
201
|
-
autoGenerate: _autoGenerate(element.parent.elements[parentFieldName])
|
|
90
|
+
parentElement: element.parent.elements[parentFieldName],
|
|
91
|
+
childElement: element._target.elements[otherField.ref[0]]
|
|
202
92
|
})
|
|
203
93
|
} else if (otherField.val !== undefined) {
|
|
204
94
|
const parentFieldName = subOn[parentFieldIdx] && subOn[parentFieldIdx].ref[1]
|
|
205
95
|
const parentField = subOn[otherFieldIdx === 2 ? 0 : 2]
|
|
206
96
|
foreignKeyPropagations.push({
|
|
207
97
|
fillChild: true,
|
|
208
|
-
parentFieldName,
|
|
98
|
+
parentElement: element.parent.elements[parentFieldName],
|
|
209
99
|
parentFieldValue: parentField.val,
|
|
210
100
|
childFieldValue: otherField.val
|
|
211
101
|
})
|
|
@@ -216,8 +106,8 @@ const _foreignKeyPropagationsFromCustomBacklink = (element, childElement) => {
|
|
|
216
106
|
return foreignKeyPropagations
|
|
217
107
|
}
|
|
218
108
|
|
|
219
|
-
const _foreignKeyPropagationsFromOn =
|
|
220
|
-
const subOns = _getSubOns(
|
|
109
|
+
const _foreignKeyPropagationsFromOn = element => {
|
|
110
|
+
const subOns = _getSubOns(element)
|
|
221
111
|
const foreignKeyPropagations = []
|
|
222
112
|
|
|
223
113
|
for (const subOn of subOns) {
|
|
@@ -265,10 +155,9 @@ const _resolve4struct = (others, struct, fkps, fillChild, childIsStruct, i) => {
|
|
|
265
155
|
|
|
266
156
|
// push propagation
|
|
267
157
|
fkps.push({
|
|
268
|
-
|
|
269
|
-
|
|
158
|
+
childElement: childIsStruct ? current : other,
|
|
159
|
+
parentElement: childIsStruct ? other : current,
|
|
270
160
|
fillChild,
|
|
271
|
-
autoGenerate: _autoGenerate(other),
|
|
272
161
|
prefix,
|
|
273
162
|
deep: !fillChild && _resolveTargetForeignKey(childIsStruct ? current : other)
|
|
274
163
|
})
|
|
@@ -285,11 +174,11 @@ const _resolveTargetForeignKey = targetKey => {
|
|
|
285
174
|
const targetName = targetKey['@odata.foreignKey4']
|
|
286
175
|
if (!targetName) return
|
|
287
176
|
const _foreignKeyProps = foreignKeyPropagations(targetKey.parent.elements[targetName])
|
|
288
|
-
const propagation = _foreignKeyProps.find(_fkp => targetKey.name === _fkp.
|
|
177
|
+
const propagation = _foreignKeyProps.find(_fkp => _fkp.parentElement && targetKey.name === _fkp.parentElement.name)
|
|
289
178
|
return { targetName, propagation }
|
|
290
179
|
}
|
|
291
180
|
|
|
292
|
-
const
|
|
181
|
+
const _resolvedKeys = (foreignKeys, targetKeys, fillChild) => {
|
|
293
182
|
const foreignKeyPropagations = []
|
|
294
183
|
|
|
295
184
|
for (let i = 0; i < foreignKeys.length; i++) {
|
|
@@ -302,9 +191,8 @@ const resolvedKeys = (foreignKeys, targetKeys, fillChild) => {
|
|
|
302
191
|
} else {
|
|
303
192
|
foreignKeyPropagations.push({
|
|
304
193
|
fillChild,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
parentFieldName: fk.name,
|
|
194
|
+
parentElement: fk,
|
|
195
|
+
childElement: tk,
|
|
308
196
|
// needed only for child -> parent propagation since template loops in other direction
|
|
309
197
|
deep: !fillChild && _resolveTargetForeignKey(tk)
|
|
310
198
|
})
|
|
@@ -314,32 +202,23 @@ const resolvedKeys = (foreignKeys, targetKeys, fillChild) => {
|
|
|
314
202
|
return foreignKeyPropagations
|
|
315
203
|
}
|
|
316
204
|
|
|
317
|
-
const
|
|
205
|
+
const foreignKeyPropagations = element => {
|
|
318
206
|
if (element.is2many && element.on) {
|
|
319
|
-
return _foreignKeyPropagationsFromOn(element
|
|
207
|
+
return _foreignKeyPropagationsFromOn(element)
|
|
320
208
|
}
|
|
321
|
-
|
|
322
209
|
if (element.is2one) {
|
|
323
210
|
if (!element.on) {
|
|
324
211
|
const foreignKeys = _foreignKeys(element)
|
|
325
|
-
|
|
326
212
|
if (foreignKeys) {
|
|
327
213
|
const targetKeys = _targetKeys(element)
|
|
328
|
-
return
|
|
214
|
+
return _resolvedKeys(foreignKeys, targetKeys)
|
|
329
215
|
}
|
|
330
|
-
|
|
331
|
-
return []
|
|
332
216
|
} else {
|
|
333
217
|
// It's a link through a backlink
|
|
334
|
-
return _foreignKeyPropagationsFromOn(element
|
|
218
|
+
return _foreignKeyPropagationsFromOn(element)
|
|
335
219
|
}
|
|
336
220
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const foreignKeyPropagations = element => {
|
|
340
|
-
const foreignKeyProps = _foreignKeyPropagations(element)
|
|
341
|
-
if (foreignKeyProps) foreignKeyProps._element = element
|
|
342
|
-
return foreignKeyProps
|
|
221
|
+
return []
|
|
343
222
|
}
|
|
344
223
|
|
|
345
224
|
const _foreignKeys = csnElement => {
|
|
@@ -365,20 +244,6 @@ const _parentKeys = csnElement => {
|
|
|
365
244
|
)
|
|
366
245
|
}
|
|
367
246
|
|
|
368
|
-
const _structPrefix = csnElement => {
|
|
369
|
-
if (csnElement.parent && csnElement.parent._isStructured) {
|
|
370
|
-
const prefix = _structPrefix(csnElement.parent)
|
|
371
|
-
if (!prefix) return csnElement.parent.name + '_'
|
|
372
|
-
return prefix + csnElement.parent.name + '_'
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return ''
|
|
376
|
-
}
|
|
377
|
-
|
|
378
247
|
module.exports = {
|
|
379
|
-
foreignKeyPropagations
|
|
380
|
-
propagateForeignKeys,
|
|
381
|
-
_foreignKeys,
|
|
382
|
-
_targetKeys,
|
|
383
|
-
_structPrefix
|
|
248
|
+
foreignKeyPropagations
|
|
384
249
|
}
|
|
@@ -1,26 +1,23 @@
|
|
|
1
|
-
const { foreignKeyPropagations } = require('./foreignKeyPropagations')
|
|
2
|
-
const { _structPrefix } = require('./foreignKeyPropagations')
|
|
3
|
-
|
|
4
1
|
const _toRef = (alias, column) => {
|
|
5
2
|
if (Array.isArray(column)) column = column.join('_')
|
|
6
3
|
return { ref: alias ? [alias, column] : [column] }
|
|
7
4
|
}
|
|
8
5
|
|
|
9
|
-
const
|
|
6
|
+
const _adaptRefs = (onCond, path, { select, join }) => {
|
|
10
7
|
const adaptedOnCondition = onCond.map(el => {
|
|
11
8
|
const ref = el.ref
|
|
12
9
|
|
|
13
10
|
if (ref) {
|
|
14
|
-
if (ref[0] ===
|
|
15
|
-
return _toRef(
|
|
11
|
+
if (ref[0] === path.join('_') && ref[1]) {
|
|
12
|
+
return _toRef(select, ref.slice(1))
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
// no alias for special $user of canonical localized association
|
|
19
|
-
if (ref[0] === '$user' &&
|
|
16
|
+
if (ref[0] === '$user' && path[0] === 'localized') {
|
|
20
17
|
return _toRef(undefined, ref.slice(0))
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
return _toRef(
|
|
20
|
+
return _toRef(join, ref.slice(0))
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
return el
|
|
@@ -29,8 +26,7 @@ const _adaptOnConditionElements = (onCond, associationName, selectAlias, joinAli
|
|
|
29
26
|
return adaptedOnCondition
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
const _args = (csnElement,
|
|
33
|
-
const { associationNames, csn, aliases } = options
|
|
29
|
+
const _args = (csnElement, path, aliases) => {
|
|
34
30
|
const onCond = csnElement.on
|
|
35
31
|
|
|
36
32
|
if (!onCond || !onCond.length) {
|
|
@@ -41,86 +37,60 @@ const _args = (csnElement, options) => {
|
|
|
41
37
|
return onCond
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// revert join and select aliases because of backlink
|
|
52
|
-
aliases: { select: aliases.join, join: aliases.select }
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
if (onCond.some(ele => ele === 'and')) {
|
|
56
|
-
const and = _adaptOnConditionElements(
|
|
57
|
-
onCond.slice(onCond.findIndex(ele => ele === 'and') + 1),
|
|
58
|
-
associationNames,
|
|
59
|
-
aliases.select,
|
|
60
|
-
aliases.join
|
|
61
|
-
)
|
|
62
|
-
oc.push('and', ...and)
|
|
63
|
-
}
|
|
40
|
+
if (!csnElement._isSelfManaged) return _adaptRefs(onCond, path, aliases)
|
|
41
|
+
|
|
42
|
+
// revert join and select aliases because of backlink
|
|
43
|
+
const oc = _newOnConditions(csnElement._backlink, [csnElement._backlink.name], {
|
|
44
|
+
select: aliases.join,
|
|
45
|
+
join: aliases.select
|
|
46
|
+
})
|
|
64
47
|
|
|
65
|
-
|
|
48
|
+
if (onCond.some(e => e === 'and')) {
|
|
49
|
+
// managed with ON-conditions must contain `$self`, which we replace with `oc`
|
|
50
|
+
const onCondWithouSelf = _adaptRefs(_onCondWithout$self(onCond), path, aliases)
|
|
51
|
+
oc.push('and', ...onCondWithouSelf)
|
|
66
52
|
}
|
|
67
53
|
|
|
68
|
-
return
|
|
54
|
+
return oc
|
|
69
55
|
}
|
|
70
56
|
|
|
71
|
-
const
|
|
72
|
-
const { aliases } = options
|
|
73
|
-
const on = []
|
|
74
|
-
const foreignKeys = foreignKeyPropagations(csnElement)
|
|
57
|
+
const _isSelfRef = e => e && e.ref && e.ref[0] === '$self'
|
|
75
58
|
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
const _onCondWithout$self = onCond => {
|
|
60
|
+
const onCondWithoutSelf = [...onCond]
|
|
61
|
+
const selfIndex = onCondWithoutSelf.findIndex((e, i, on) => {
|
|
62
|
+
if (e === 'and') return _isSelfRef(on[i + 1]) || _isSelfRef(on[i + 3])
|
|
63
|
+
return on[i + 1] === '=' && (_isSelfRef(e) || _isSelfRef(on[i + 2]))
|
|
64
|
+
})
|
|
65
|
+
onCondWithoutSelf.splice(selfIndex, 4)
|
|
66
|
+
return onCondWithoutSelf
|
|
67
|
+
}
|
|
78
68
|
|
|
79
|
-
|
|
69
|
+
const _foreignToOn = (csnElement, path, { select, join }) => {
|
|
70
|
+
// this is only for 2one managed w/o ON-conditions i.e. no static values are possible
|
|
71
|
+
const on = []
|
|
72
|
+
for (const key of csnElement._foreignKeys) {
|
|
80
73
|
if (on.length !== 0) {
|
|
81
74
|
on.push('and')
|
|
82
75
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const ref1 = _toRef(aliases.select, key.prefix ? `${key.prefix}_${key.childFieldName}` : key.childFieldName)
|
|
87
|
-
const structPrefix = _structPrefix(csnElement)
|
|
88
|
-
const ref2 = _toRef(aliases.join, `${structPrefix}${key.parentFieldName}`)
|
|
76
|
+
const ref1 = _toRef(select, key.prefix ? `${key.prefix}_${key.childElement.name}` : key.childElement.name)
|
|
77
|
+
const structPrefix = path.length > 1 ? path.slice(0, -1) : []
|
|
78
|
+
const ref2 = _toRef(join, [...structPrefix, key.parentElement.name])
|
|
89
79
|
on.push(ref1, '=', ref2)
|
|
90
80
|
}
|
|
91
|
-
|
|
92
81
|
return on
|
|
93
82
|
}
|
|
94
83
|
|
|
95
|
-
|
|
96
|
-
* Gets the `ON` conditions in CQN format based on the CSN.
|
|
97
|
-
*
|
|
98
|
-
* @param {object} csnElement
|
|
99
|
-
* @param {import('../../types/api').ONConditionOptions} [options]
|
|
100
|
-
* @returns {Array}
|
|
101
|
-
* @private
|
|
102
|
-
*/
|
|
103
|
-
function getOnCondNew(csnElement, options) {
|
|
104
|
-
const defaultOptions = {
|
|
105
|
-
aliases: {},
|
|
106
|
-
resolveView: true
|
|
107
|
-
}
|
|
108
|
-
options = { ...defaultOptions, ...options }
|
|
109
|
-
const { associationNames } = options
|
|
110
|
-
|
|
111
|
-
if (!Array.isArray(associationNames)) {
|
|
112
|
-
options.associationNames = [associationNames]
|
|
113
|
-
}
|
|
114
|
-
|
|
84
|
+
const _newOnConditions = (csnElement, path, aliases) => {
|
|
115
85
|
if (csnElement.keys) {
|
|
116
|
-
return _foreignToOn(csnElement,
|
|
86
|
+
return _foreignToOn(csnElement, path, aliases)
|
|
117
87
|
}
|
|
118
88
|
|
|
119
|
-
return _args(csnElement,
|
|
89
|
+
return _args(csnElement, path, aliases)
|
|
120
90
|
}
|
|
121
91
|
|
|
122
|
-
const getOnCond = (
|
|
123
|
-
return ['(', ...
|
|
92
|
+
const getOnCond = (csnElement, path = [], aliases = { select: '', join: '' }) => {
|
|
93
|
+
return ['(', ..._newOnConditions(csnElement, path, aliases), ')']
|
|
124
94
|
}
|
|
125
95
|
|
|
126
96
|
module.exports = {
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { where2obj } = require('./cqn')
|
|
2
|
+
|
|
3
|
+
function _getOnCondElements(onCond, onCondElements = []) {
|
|
4
|
+
const andIndex = onCond.indexOf('and')
|
|
5
|
+
const entityKey = onCond[2].ref && onCond[2].ref.join('.')
|
|
6
|
+
const entityVal = onCond[2].val
|
|
7
|
+
const targetKey = onCond[0].ref && onCond[0].ref.join('.')
|
|
8
|
+
const targetVal = onCond[0].val
|
|
9
|
+
onCondElements.push({ entityKey, targetKey, entityVal, targetVal })
|
|
10
|
+
|
|
11
|
+
if (andIndex !== -1) {
|
|
12
|
+
_getOnCondElements(onCond.slice(andIndex + 1), onCondElements)
|
|
13
|
+
}
|
|
14
|
+
return onCondElements
|
|
15
|
+
}
|
|
2
16
|
|
|
3
17
|
function _modifyWhereWithNavigations(where, newWhere, targetKeyElement, keyName) {
|
|
4
18
|
if (where) {
|
|
5
|
-
|
|
19
|
+
// copy where else query will be modified
|
|
20
|
+
const whereCopy = JSON.parse(JSON.stringify(where))
|
|
6
21
|
if (newWhere.length > 0) newWhere.push('and')
|
|
7
22
|
newWhere.push(...whereCopy)
|
|
8
23
|
}
|
|
@@ -14,7 +29,7 @@ function _modifyWhereWithNavigations(where, newWhere, targetKeyElement, keyName)
|
|
|
14
29
|
})
|
|
15
30
|
}
|
|
16
31
|
|
|
17
|
-
|
|
32
|
+
function _buildWhereForNavigations(ref, newWhere, model, target) {
|
|
18
33
|
const currentRef = ref[0]
|
|
19
34
|
const nextRef = ref[1]
|
|
20
35
|
|
|
@@ -24,7 +39,7 @@ const _buildWhereForNavigations = (ref, newWhere, model, target) => {
|
|
|
24
39
|
|
|
25
40
|
if (!navigationElement || !navigationElement.on) return
|
|
26
41
|
|
|
27
|
-
const nextKeys =
|
|
42
|
+
const nextKeys = _getOnCondElements(navigationElement.on)
|
|
28
43
|
for (const key of nextKeys) {
|
|
29
44
|
const keyName = key.targetKey.replace(navigationElement.name + '.', '')
|
|
30
45
|
const targetKeyElement = navigationElement._target.elements[keyName]
|
|
@@ -55,37 +70,23 @@ function _getWhereFromUpdate(query, target, model) {
|
|
|
55
70
|
return query.UPDATE.where
|
|
56
71
|
}
|
|
57
72
|
|
|
58
|
-
function _addKeysFromWhereToData(where, target, data) {
|
|
59
|
-
const whereLength = where.length
|
|
60
|
-
for (let i = 0; i < whereLength; i++) {
|
|
61
|
-
const whereEl = where[i]
|
|
62
|
-
const colName = whereEl.ref && whereEl.ref[whereEl.ref.length - 1]
|
|
63
|
-
const colEl = colName && target.elements[colName]
|
|
64
|
-
if (colEl && colEl.key) {
|
|
65
|
-
const opWhere = where[i + 1]
|
|
66
|
-
const valWhere = where[i + 2]
|
|
67
|
-
if (opWhere === '=' && valWhere && 'val' in valWhere) {
|
|
68
|
-
data[colName] = valWhere.val
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
73
|
// params: data, req, service/tx
|
|
75
|
-
|
|
74
|
+
function enrichDataWithKeysFromWhere(data, { query, target }, { model }) {
|
|
76
75
|
if (query.INSERT) {
|
|
77
76
|
const where = _getWhereFromInsert(query, target, model)
|
|
78
77
|
if (!where || !where.length) return
|
|
79
|
-
|
|
80
78
|
if (!Array.isArray(data)) data = [data]
|
|
81
|
-
|
|
82
|
-
for (const d of data) {
|
|
83
|
-
_addKeysFromWhereToData(where, target, d)
|
|
84
|
-
}
|
|
79
|
+
for (const d of data) Object.assign(d, where2obj(where, target))
|
|
85
80
|
} else if (query.UPDATE) {
|
|
86
81
|
const where = _getWhereFromUpdate(query, target, model)
|
|
87
82
|
if (!where || !where.length) return
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
// REVISIT: We should not expect data to be present always!
|
|
84
|
+
if (!data) data = query.UPDATE.data = {}
|
|
85
|
+
Object.assign(data, where2obj(where, target))
|
|
90
86
|
}
|
|
91
87
|
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
where2obj,
|
|
91
|
+
enrichDataWithKeysFromWhere
|
|
92
|
+
}
|
|
@@ -64,6 +64,9 @@ const handleAliasInResult = (columns, result) => {
|
|
|
64
64
|
// REVISIT: todo renaming for deep operations
|
|
65
65
|
const postProcess = (query, result, service, onlySelectAliases = false) => {
|
|
66
66
|
if (query.SELECT) {
|
|
67
|
+
if (query.SELECT.columns && query.SELECT.columns.find(col => col.func === 'count' && col.as === '$count')) {
|
|
68
|
+
return [{ $count: result }]
|
|
69
|
+
}
|
|
67
70
|
handleAliasInResult(query.SELECT.columns, result)
|
|
68
71
|
|
|
69
72
|
if (!onlySelectAliases) {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const cds = require('../../cds')
|
|
2
|
+
|
|
3
|
+
const _generateParentField = ({ parentElement }, row) => {
|
|
4
|
+
if (_autoGenerate(parentElement) && !row[parentElement.name]) {
|
|
5
|
+
row[parentElement.name] = cds.utils.uuid()
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const _generateChildField = ({ deep, childElement }, childRow) => {
|
|
10
|
+
if (deep) {
|
|
11
|
+
_generateChildField(deep.propagation, childRow[deep.targetName])
|
|
12
|
+
} else if (_autoGenerate(childElement) && childRow && !childRow[childElement.name]) {
|
|
13
|
+
childRow[childElement.name] = cds.utils.uuid()
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const _autoGenerate = e => e && e.type === 'cds.UUID' && e.key
|
|
18
|
+
|
|
19
|
+
const _getNestedVal = (row, prefix) => {
|
|
20
|
+
let val = row
|
|
21
|
+
const splitted = prefix.split('_')
|
|
22
|
+
let k = ''
|
|
23
|
+
|
|
24
|
+
while (splitted.length > 0) {
|
|
25
|
+
k += splitted.shift()
|
|
26
|
+
if (k in val) {
|
|
27
|
+
val = val[k]
|
|
28
|
+
k = ''
|
|
29
|
+
} else {
|
|
30
|
+
k += '_'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return val
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const _propagateToChid = ({ parentElement, childElement, prefix, parentFieldValue }, row, childRow) => {
|
|
38
|
+
if (!childElement) return
|
|
39
|
+
if (parentElement) {
|
|
40
|
+
if (prefix) {
|
|
41
|
+
const nested = _getNestedVal(row, prefix)
|
|
42
|
+
childRow[childElement.name] = nested[parentElement.name]
|
|
43
|
+
} else {
|
|
44
|
+
childRow[childElement.name] = row[parentElement.name]
|
|
45
|
+
}
|
|
46
|
+
} else if (parentFieldValue !== undefined) {
|
|
47
|
+
childRow[childElement.name] = parentFieldValue
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const _propagateToParent = ({ parentElement, childElement, deep }, childRow, row) => {
|
|
52
|
+
if (deep) {
|
|
53
|
+
_propagateToParent(deep.propagation, childRow[deep.targetName], childRow)
|
|
54
|
+
}
|
|
55
|
+
if (parentElement && childElement && childRow && Object.prototype.hasOwnProperty.call(childRow, childElement.name)) {
|
|
56
|
+
row[parentElement.name] = childRow[childElement.name]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const propagateForeignKeys = (tKey, row, foreignKeyPropagations, isCompositionEffective) => {
|
|
61
|
+
const childRows = Array.isArray(row[tKey]) ? row[tKey] : [row[tKey]]
|
|
62
|
+
|
|
63
|
+
for (const childRow of childRows) {
|
|
64
|
+
if (!childRow) return
|
|
65
|
+
|
|
66
|
+
for (const foreignKeyPropagation of foreignKeyPropagations) {
|
|
67
|
+
if (foreignKeyPropagation.fillChild) {
|
|
68
|
+
_generateParentField(foreignKeyPropagation, row)
|
|
69
|
+
if (!isCompositionEffective) {
|
|
70
|
+
delete row[tKey]
|
|
71
|
+
} else {
|
|
72
|
+
_propagateToChid(foreignKeyPropagation, row, childRow)
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
_generateChildField(foreignKeyPropagation, childRow)
|
|
76
|
+
_propagateToParent(foreignKeyPropagation, childRow, row)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
propagateForeignKeys
|
|
84
|
+
}
|
|
@@ -22,7 +22,7 @@ const _flattenProps = (subElement, structName, structProperties, structElement,
|
|
|
22
22
|
|
|
23
23
|
const _resolveStructured = ({ structName, structProperties }, subElements, asRef = true) => {
|
|
24
24
|
if (!subElements) {
|
|
25
|
-
return
|
|
25
|
+
return []
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// only add from structProperties
|