@sap/cds 5.4.6 → 5.5.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/CHANGELOG.md +208 -2
- package/apis/ql.d.ts +17 -15
- package/app/index.js +1 -1
- package/bin/build/buildTaskEngine.js +26 -42
- package/bin/build/buildTaskFactory.js +6 -10
- package/bin/build/buildTaskHandler.js +2 -4
- package/bin/build/buildTaskProvider.js +3 -1
- package/bin/build/buildTaskProviderFactory.js +9 -15
- package/bin/build/constants.js +15 -3
- package/bin/build/index.js +5 -4
- package/bin/build/mtaUtil.js +8 -11
- package/bin/build/provider/buildTaskHandlerEdmx.js +63 -6
- package/bin/build/provider/buildTaskHandlerInternal.js +2 -34
- package/bin/build/provider/buildTaskProviderInternal.js +16 -42
- package/bin/build/provider/fiori/index.js +13 -24
- package/bin/build/provider/hana/2migration.js +17 -15
- package/bin/build/provider/hana/2tabledata.js +52 -48
- package/bin/build/provider/hana/index.js +27 -25
- package/bin/build/provider/hana/migrationtable.js +91 -67
- package/bin/build/provider/java-cf/index.js +14 -24
- package/bin/build/provider/mtx/index.js +12 -14
- package/bin/build/provider/node-cf/index.js +18 -32
- package/bin/cds.js +5 -5
- package/bin/serve.js +29 -23
- package/bin/version.js +0 -1
- package/lib/compile/etc/_localized.js +4 -9
- package/lib/compile/for/sql.js +5 -2
- package/lib/compile/parse.js +25 -17
- package/lib/compile/to/srvinfo.js +2 -1
- package/lib/connect/bindings.js +2 -1
- package/lib/connect/index.js +48 -49
- package/lib/core/classes.js +1 -1
- package/lib/core/reflect.js +10 -2
- package/lib/deploy.js +26 -23
- package/lib/env/defaults.js +13 -6
- package/lib/env/index.js +73 -78
- package/lib/env/requires.js +38 -19
- package/lib/index.js +9 -10
- package/lib/lazy.js +2 -2
- package/lib/log/index.js +33 -45
- package/lib/log/service/index.js +2 -2
- package/lib/ql/CREATE.js +14 -9
- package/lib/ql/DELETE.js +6 -5
- package/lib/ql/DROP.js +12 -9
- package/lib/ql/INSERT.js +40 -16
- package/lib/ql/Query.js +67 -40
- package/lib/ql/SELECT.js +162 -127
- package/lib/ql/UPDATE.js +74 -42
- package/lib/ql/Whereable.js +77 -87
- package/lib/ql/index.js +36 -24
- package/lib/ql/parse.js +35 -0
- package/lib/req/context.js +44 -8
- package/lib/req/locale.js +7 -7
- package/lib/serve/Service-api.js +21 -14
- package/lib/serve/Service-dispatch.js +28 -12
- package/lib/serve/Transaction.js +22 -10
- package/lib/serve/index.js +16 -11
- package/lib/utils/axios.js +23 -16
- package/lib/utils/data.js +35 -0
- package/lib/utils/tests.js +27 -18
- package/libx/_runtime/audit/generic/personal/access.js +81 -0
- package/libx/_runtime/audit/generic/personal/constants.js +4 -0
- package/libx/_runtime/audit/generic/personal/index.js +50 -0
- package/libx/_runtime/audit/generic/personal/modification.js +138 -0
- package/libx/_runtime/audit/generic/personal/utils.js +186 -0
- package/libx/_runtime/audit/utils/v2.js +10 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +5 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +5 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +2 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +4 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +7 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +59 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +11 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +6 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +3 -46
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +2 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/createToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/deleteToCQN.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectHelper.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +16 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityType.js +6 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/format/RepresentationKind.js +4 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/OdataRequest.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +15 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/OperationValidator.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +8 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +6 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +12 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +7 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +14 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +13 -13
- package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +2 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +2 -2
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +2 -4
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +4 -2
- package/libx/_runtime/cds-services/services/Service.js +40 -5
- package/libx/_runtime/cds-services/services/utils/columns.js +13 -7
- package/libx/_runtime/cds-services/services/utils/compareJson.js +88 -4
- package/libx/_runtime/cds-services/services/utils/differ.js +24 -6
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -2
- package/libx/_runtime/common/composition/data.js +44 -55
- package/libx/_runtime/common/composition/delete.js +97 -71
- package/libx/_runtime/common/composition/index.js +2 -1
- package/libx/_runtime/common/composition/insert.js +34 -11
- package/libx/_runtime/common/composition/tree.js +119 -92
- package/libx/_runtime/common/composition/update.js +4 -1
- package/libx/_runtime/common/composition/utils.js +1 -3
- package/libx/_runtime/common/constants/draft.js +12 -1
- package/libx/_runtime/common/generic/auth.js +6 -22
- package/libx/_runtime/common/generic/crud.js +14 -13
- package/libx/_runtime/common/generic/input.js +23 -26
- package/libx/_runtime/common/generic/put.js +1 -1
- package/libx/_runtime/common/generic/sorting.js +16 -16
- package/libx/_runtime/common/i18n/index.js +1 -1
- package/libx/_runtime/common/i18n/messages.properties +4 -0
- package/libx/_runtime/common/utils/backlinks.js +12 -5
- package/libx/_runtime/common/utils/cqn.js +6 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +102 -101
- package/libx/_runtime/common/utils/csn.js +47 -4
- package/libx/_runtime/common/utils/data.js +0 -37
- package/libx/_runtime/common/utils/enrichWithKeysFromWhere.js +1 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +7 -24
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +39 -7
- package/libx/_runtime/common/utils/generateOnCond.js +11 -12
- package/libx/_runtime/common/utils/onlyKeysRemain.js +10 -0
- package/libx/_runtime/common/utils/path.js +35 -0
- package/libx/_runtime/common/utils/postProcessing.js +86 -0
- package/libx/_runtime/common/utils/quotingStyles.js +37 -26
- package/libx/_runtime/common/utils/resolveView.js +223 -171
- package/libx/_runtime/common/utils/rewriteAsterisk.js +46 -26
- package/libx/_runtime/common/utils/structured.js +6 -12
- package/libx/_runtime/common/utils/template.js +10 -5
- package/libx/_runtime/common/utils/templateDelimiter.js +1 -0
- package/libx/_runtime/common/utils/templateProcessor.js +22 -30
- package/libx/_runtime/common/utils/union.js +31 -0
- package/libx/_runtime/common/utils/unionCqnTemplate.js +184 -0
- package/libx/_runtime/db/Service.js +1 -1
- package/libx/_runtime/db/data-conversion/timestamp.js +2 -9
- package/libx/_runtime/db/expand/expandCQNToJoin.js +204 -297
- package/libx/_runtime/db/expand/index.js +3 -3
- package/libx/_runtime/db/expand/rawToExpanded.js +36 -7
- package/libx/_runtime/db/generic/index.js +1 -1
- package/libx/_runtime/db/generic/input.js +5 -7
- package/libx/_runtime/db/generic/integrity.js +1 -1
- package/libx/_runtime/db/generic/rewrite.js +2 -10
- package/libx/_runtime/db/generic/update.js +13 -5
- package/libx/_runtime/db/generic/virtual.js +22 -58
- package/libx/_runtime/db/query/delete.js +7 -4
- package/libx/_runtime/db/query/insert.js +6 -4
- package/libx/_runtime/db/query/read.js +13 -20
- package/libx/_runtime/db/query/run.js +4 -1
- package/libx/_runtime/db/query/update.js +5 -4
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +35 -2
- package/libx/_runtime/db/sql-builder/FunctionBuilder.js +17 -2
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +6 -5
- package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +10 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +35 -24
- package/libx/_runtime/db/sql-builder/UpdateBuilder.js +14 -4
- package/libx/_runtime/db/sql-builder/arrayed.js +4 -0
- package/libx/_runtime/db/utils/deep.js +8 -0
- package/libx/_runtime/db/utils/generateAliases.js +2 -1
- package/libx/_runtime/fiori/generic/activate.js +19 -15
- package/libx/_runtime/fiori/generic/before.js +3 -11
- package/libx/_runtime/fiori/generic/cancel.js +1 -1
- package/libx/_runtime/fiori/generic/delete.js +3 -1
- package/libx/_runtime/fiori/generic/edit.js +12 -2
- package/libx/_runtime/fiori/generic/new.js +5 -5
- package/libx/_runtime/fiori/generic/patch.js +0 -18
- package/libx/_runtime/fiori/generic/read.js +241 -189
- package/libx/_runtime/fiori/utils/delete.js +36 -7
- package/libx/_runtime/fiori/utils/handler.js +43 -44
- package/libx/_runtime/fiori/utils/where.js +30 -15
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +4 -6
- package/libx/_runtime/hana/execute.js +2 -2
- package/libx/_runtime/hana/localized.js +4 -4
- package/libx/_runtime/hana/pool.js +29 -14
- package/libx/_runtime/hana/search2cqn4sql.js +2 -1
- package/libx/_runtime/hana/searchToContains.js +18 -14
- package/libx/_runtime/index.js +0 -5
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +13 -5
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +4 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +31 -19
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -2
- package/libx/_runtime/messaging/enterprise-messaging.js +6 -4
- package/libx/_runtime/messaging/service.js +7 -6
- package/libx/_runtime/odata/cqn2odata.js +110 -43
- package/libx/_runtime/odata/index.js +26 -48
- package/libx/_runtime/odata/odata2cqn.js +1 -6154
- package/libx/_runtime/odata/odata2cqn.pegjs +559 -0
- package/libx/_runtime/odata/readToCqn.js +94 -64
- package/libx/_runtime/remote/Service.js +74 -21
- package/libx/_runtime/remote/cqn2odata/index.js +1 -5
- package/libx/_runtime/remote/utils/client.js +24 -101
- package/libx/_runtime/remote/utils/dataConversion.js +27 -12
- package/libx/_runtime/sqlite/Service.js +3 -5
- package/libx/_runtime/sqlite/execute.js +23 -24
- package/libx/_runtime/sqlite/localized.js +12 -7
- package/libx/_runtime/types/api.js +10 -0
- package/package.json +1 -1
- package/server.js +16 -2
- package/lib/ql/grammar.pegjs +0 -208
- package/lib/ql/parser.js +0 -1
- package/lib/ql/rt/DELETE.js +0 -29
- package/lib/ql/rt/INSERT.js +0 -23
- package/lib/ql/rt/Query.js +0 -84
- package/lib/ql/rt/SELECT.js +0 -174
- package/lib/ql/rt/UPDATE.js +0 -119
- package/lib/ql/rt/_helpers.js +0 -91
- package/lib/ql/rt/index.js +0 -32
- package/libx/_runtime/audit/generic/personal.js +0 -260
- package/libx/_runtime/cds-services/statements/BaseStatement.js +0 -72
- package/libx/_runtime/cds-services/statements/Create.js +0 -57
- package/libx/_runtime/cds-services/statements/Delete.js +0 -33
- package/libx/_runtime/cds-services/statements/Drop.js +0 -42
- package/libx/_runtime/cds-services/statements/Insert.js +0 -201
- package/libx/_runtime/cds-services/statements/Select.js +0 -826
- package/libx/_runtime/cds-services/statements/Update.js +0 -181
- package/libx/_runtime/cds-services/statements/Where.js +0 -726
- package/libx/_runtime/cds-services/statements/index.js +0 -25
- package/libx/_runtime/common/generic/resolve-mock.js +0 -9
|
@@ -9,8 +9,7 @@ const { foreignKeyPropagations } = require('./foreignKeyPropagations')
|
|
|
9
9
|
const search2cqn4sql = require('./search2cqn4sql')
|
|
10
10
|
const { getEntityNameFromCQN } = require('./entityFromCqn')
|
|
11
11
|
const getError = require('../../common/error')
|
|
12
|
-
|
|
13
|
-
const SYMBOL_FROM_ANNOTATION = Symbol.for('sap.cds.FROM_ANNOTATION')
|
|
12
|
+
const { getPathFromRef, getEntityFromPath } = require('../../common/utils/path')
|
|
14
13
|
|
|
15
14
|
const PARENT_ALIAS = '_parent_'
|
|
16
15
|
const PARENT_ALIAS_REGEX = new RegExp('^' + PARENT_ALIAS + '\\d*$')
|
|
@@ -48,9 +47,7 @@ const _addParentAlias = (where, alias) => {
|
|
|
48
47
|
|
|
49
48
|
const _addAliasToElement = (e, alias) => {
|
|
50
49
|
if (e.ref) {
|
|
51
|
-
|
|
52
|
-
if (e[SYMBOL_FROM_ANNOTATION]) aliased[SYMBOL_FROM_ANNOTATION] = true
|
|
53
|
-
return aliased
|
|
50
|
+
return { ref: [alias, ...e.ref] }
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
if (e.list) {
|
|
@@ -95,10 +92,10 @@ const _getTargetFromRef = ref => {
|
|
|
95
92
|
|
|
96
93
|
const _getEntityName = (fromClause, entity, i) => {
|
|
97
94
|
const targetName = _getTargetFromRef(fromClause.ref[i])
|
|
98
|
-
return i === 0 ? targetName : entity.elements[targetName].target
|
|
95
|
+
return i === 0 ? targetName : entity && entity.elements[targetName] && entity.elements[targetName].target
|
|
99
96
|
}
|
|
100
97
|
|
|
101
|
-
const convertPathExpressionToWhere = (fromClause, model) => {
|
|
98
|
+
const convertPathExpressionToWhere = (fromClause, model, options) => {
|
|
102
99
|
if (fromClause.ref.length === 1) {
|
|
103
100
|
const target = _getTargetFromRef(fromClause.ref[0])
|
|
104
101
|
const alias = fromClause.as
|
|
@@ -108,6 +105,7 @@ const convertPathExpressionToWhere = (fromClause, model) => {
|
|
|
108
105
|
|
|
109
106
|
let previousSelect, previousEntityName, previousTableAlias, structParent
|
|
110
107
|
let prefix = []
|
|
108
|
+
let columns
|
|
111
109
|
for (let i = 0; i < fromClause.ref.length; i++) {
|
|
112
110
|
const entity = structParent || model.definitions[previousEntityName]
|
|
113
111
|
const element = _elementFromRef(fromClause.ref[i], entity)
|
|
@@ -116,14 +114,16 @@ const convertPathExpressionToWhere = (fromClause, model) => {
|
|
|
116
114
|
prefix.push(element.name)
|
|
117
115
|
structParent = element
|
|
118
116
|
continue
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (element &&
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
} else if (element && element.isAssociation) {
|
|
118
|
+
_modifyNavigationInWhere(fromClause.ref[i].where, element._target)
|
|
119
|
+
} else if (element && previousSelect && i === fromClause.ref.length - 1) {
|
|
120
|
+
columns = [{ ref: [...prefix, element.name] }]
|
|
121
|
+
fromClause.ref.splice(-1)
|
|
122
|
+
continue
|
|
124
123
|
}
|
|
125
124
|
|
|
126
125
|
const currentEntityName = _getEntityName(fromClause, entity, i)
|
|
126
|
+
if (!currentEntityName) continue
|
|
127
127
|
const tableAlias = `T${i}`
|
|
128
128
|
const currentSelect = SELECT.from(`${currentEntityName} as ${tableAlias}`)
|
|
129
129
|
|
|
@@ -145,7 +145,7 @@ const convertPathExpressionToWhere = (fromClause, model) => {
|
|
|
145
145
|
model,
|
|
146
146
|
prefix
|
|
147
147
|
)
|
|
148
|
-
|
|
148
|
+
_convertSelect(previousSelect, model, options)
|
|
149
149
|
currentSelect.where('exists', previousSelect)
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -159,7 +159,8 @@ const convertPathExpressionToWhere = (fromClause, model) => {
|
|
|
159
159
|
return {
|
|
160
160
|
target: previousEntityName,
|
|
161
161
|
alias: previousTableAlias,
|
|
162
|
-
where: previousSelect && previousSelect.SELECT && previousSelect.SELECT.where
|
|
162
|
+
where: previousSelect && previousSelect.SELECT && previousSelect.SELECT.where,
|
|
163
|
+
columns
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
|
|
@@ -272,21 +273,17 @@ const _getLambdaSubSelect = (cqn, index, lambdaOp, model, options) => {
|
|
|
272
273
|
const innerAlias = FOREIGN_ALIAS + options.lambdaIteration
|
|
273
274
|
cqn.SELECT.from.as = outerAlias
|
|
274
275
|
|
|
276
|
+
const queryTarget = getEntityFromPath(getPathFromRef(cqn.SELECT.from.ref), model)
|
|
277
|
+
|
|
275
278
|
const nav = cqn.SELECT.where[index].ref.map(el => (el.id ? el.id : el))
|
|
276
|
-
const navName = nav[0]
|
|
277
279
|
const last = cqn.SELECT.where[index].ref.slice(-1)[0]
|
|
278
|
-
|
|
279
|
-
const queryTarget =
|
|
280
|
-
typeof cqn._target.name === 'string'
|
|
281
|
-
? model.definitions[cqn._target.name.split('[')[0]]
|
|
282
|
-
: cqn._target.name.id
|
|
283
|
-
? model.definitions[cqn._target.name.id]
|
|
284
|
-
: cqn._target
|
|
280
|
+
const navName = queryTarget.elements[nav[0]] ? nav[0] : nav[nav.length - 1]
|
|
285
281
|
const navElement = queryTarget.elements[navName]
|
|
286
282
|
const lastElement = nav.reduce((csn, segment) => {
|
|
287
283
|
if (csn.items) return csn // arrayed not supported
|
|
288
284
|
if (csn.elements) {
|
|
289
285
|
const next = csn.elements[segment]
|
|
286
|
+
if (!next) return csn
|
|
290
287
|
if (next.target) return model.definitions[next.target]
|
|
291
288
|
return next
|
|
292
289
|
}
|
|
@@ -298,7 +295,7 @@ const _getLambdaSubSelect = (cqn, index, lambdaOp, model, options) => {
|
|
|
298
295
|
? nav.length > 1
|
|
299
296
|
? last.where.map(_unshiftRefsWithNavigation(nav.slice(1)))
|
|
300
297
|
: last.where
|
|
301
|
-
:
|
|
298
|
+
: undefined
|
|
302
299
|
const onConditionOptions = {
|
|
303
300
|
associationNames: navName,
|
|
304
301
|
csn: model,
|
|
@@ -310,7 +307,21 @@ const _getLambdaSubSelect = (cqn, index, lambdaOp, model, options) => {
|
|
|
310
307
|
const onCondition = getOnCond(navElement, onConditionOptions)
|
|
311
308
|
|
|
312
309
|
const subSelect = SELECT.from({ ref: [navElement.target], as: innerAlias })
|
|
313
|
-
if (condition)
|
|
310
|
+
if (condition) {
|
|
311
|
+
if (subSelect.SELECT.from.as) {
|
|
312
|
+
for (let i = 0; i < condition.length; i++) {
|
|
313
|
+
if (
|
|
314
|
+
condition[i].ref &&
|
|
315
|
+
condition[i].ref.length > 1 &&
|
|
316
|
+
condition[i].ref.every(r => typeof r === 'string') &&
|
|
317
|
+
condition[i].ref[0] === navName
|
|
318
|
+
) {
|
|
319
|
+
condition[i].ref[0] = subSelect.SELECT.from.as
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
subSelect.where(condition)
|
|
324
|
+
}
|
|
314
325
|
subSelect.where(onCondition)
|
|
315
326
|
if (cds.env.effective.odata.structs) {
|
|
316
327
|
flattenStructuredSelect(subSelect, model)
|
|
@@ -429,22 +440,24 @@ const _convertWhereIfSkip = (whereCQN, index) => {
|
|
|
429
440
|
OPERATIONS.includes(whereCQN[index + 1]) ? whereCQN.splice(index + 1, 2) : whereCQN.splice(index - 2, 2)
|
|
430
441
|
}
|
|
431
442
|
|
|
432
|
-
const _convertOrderByOrWhereCQN = (orderByOrWhereCQN,
|
|
433
|
-
const queryTarget = model.definitions[ensureNoDraftsSuffix(
|
|
443
|
+
const _convertOrderByOrWhereCQN = (orderByOrWhereCQN, target, model, processFn) => {
|
|
444
|
+
const queryTarget = model.definitions[ensureNoDraftsSuffix(target)]
|
|
445
|
+
|
|
434
446
|
orderByOrWhereCQN.forEach((el, index) => {
|
|
435
447
|
if (el.ref && _skip(queryTarget, el.ref, model)) processFn(orderByOrWhereCQN, index)
|
|
436
448
|
})
|
|
437
449
|
}
|
|
438
450
|
|
|
439
|
-
const _convertOrderByOrWhereIfSkip = (cqn, model) => {
|
|
451
|
+
const _convertOrderByOrWhereIfSkip = (cqn, target, model) => {
|
|
440
452
|
if (cqn.SELECT.orderBy && cqn.SELECT.orderBy.length > 1) {
|
|
441
|
-
_convertOrderByOrWhereCQN(cqn.SELECT.orderBy,
|
|
453
|
+
_convertOrderByOrWhereCQN(cqn.SELECT.orderBy, target, model, _convertOrderByIfSkip)
|
|
442
454
|
}
|
|
443
455
|
|
|
444
456
|
if (cqn.SELECT.where) {
|
|
445
|
-
_convertOrderByOrWhereCQN(cqn.SELECT.where,
|
|
457
|
+
_convertOrderByOrWhereCQN(cqn.SELECT.where, target, model, _convertWhereIfSkip)
|
|
446
458
|
}
|
|
447
459
|
}
|
|
460
|
+
|
|
448
461
|
const _convertExpand = expand => {
|
|
449
462
|
expand.forEach(expandElement => {
|
|
450
463
|
if (expandElement.ref && expandElement.ref[0]) {
|
|
@@ -470,9 +483,39 @@ const _convertRefWhereInExpand = columns => {
|
|
|
470
483
|
}
|
|
471
484
|
}
|
|
472
485
|
|
|
486
|
+
const _defaultColumns4 = entity => {
|
|
487
|
+
if (entity && entity.elements) {
|
|
488
|
+
const addAliasToColumns = []
|
|
489
|
+
for (const column in entity.elements) {
|
|
490
|
+
if (column === 'DraftAdministrativeData_DraftUUID') continue
|
|
491
|
+
const e = entity.elements[column]
|
|
492
|
+
if (e.isAssociation || e.virtual) continue
|
|
493
|
+
else if (entity._isDraftEnabled && column === 'IsActiveEntity') {
|
|
494
|
+
addAliasToColumns.push({ val: true, as: 'IsActiveEntity', cast: { type: 'cds.Boolean' } })
|
|
495
|
+
} else if (entity._isDraftEnabled && column === 'HasActiveEntity') {
|
|
496
|
+
addAliasToColumns.push({ val: false, as: 'HasActiveEntity', cast: { type: 'cds.Boolean' } })
|
|
497
|
+
} else if (entity._isDraftEnabled && column === 'HasDraftEntity') {
|
|
498
|
+
const draftName = `${entity.name}_drafts`
|
|
499
|
+
const subSelect = SELECT.from(draftName).columns([1])
|
|
500
|
+
for (const k in entity.keys) {
|
|
501
|
+
if (k !== 'IsActiveEntity') subSelect.where([{ ref: [entity.name, k] }, '=', { ref: [draftName, k] }])
|
|
502
|
+
}
|
|
503
|
+
addAliasToColumns.push({
|
|
504
|
+
xpr: ['case', 'when', 'exists', subSelect, 'then', 'true', 'else', 'false', 'end'],
|
|
505
|
+
as: 'HasDraftEntity',
|
|
506
|
+
cast: { type: 'cds.Boolean' }
|
|
507
|
+
})
|
|
508
|
+
} else addAliasToColumns.push({ ref: [column], as: column })
|
|
509
|
+
}
|
|
510
|
+
return addAliasToColumns
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// eslint-disable-next-line complexity
|
|
473
515
|
const _convertSelect = (cqn, model, options) => {
|
|
474
|
-
//
|
|
475
|
-
|
|
516
|
+
// REVISIT: still needed?
|
|
517
|
+
// Moved from old SELECT.from where this done much too eager, always for all queries
|
|
518
|
+
if (!cqn.SELECT.columns && cqn._target) cqn.SELECT.columns = _defaultColumns4(cqn._target)
|
|
476
519
|
|
|
477
520
|
// lambda functions
|
|
478
521
|
_convertLambda(cqn, model, options)
|
|
@@ -488,6 +531,9 @@ const _convertSelect = (cqn, model, options) => {
|
|
|
488
531
|
|
|
489
532
|
// no path expression
|
|
490
533
|
if (!cqnSelectFromRef || (cqnSelectFromRef.length === 1 && !cqnSelectFromRef[0].where)) {
|
|
534
|
+
// remove virtual and with skip annotated fields in orderby and where
|
|
535
|
+
_convertOrderByOrWhereIfSkip(cqn, getEntityNameFromCQN(cqn), model)
|
|
536
|
+
|
|
491
537
|
if (cqnSelectFromRef && cqn.SELECT.search && !options.suppressSearch) {
|
|
492
538
|
searchOptions = { ...searchOptions, ...{ targetName: cqnSelectFromRef[0] } }
|
|
493
539
|
search2cqn4sql(cqn, model, searchOptions)
|
|
@@ -506,8 +552,12 @@ const _convertSelect = (cqn, model, options) => {
|
|
|
506
552
|
}
|
|
507
553
|
|
|
508
554
|
// path expression handling
|
|
509
|
-
const { target, alias, where, cardinality } = convertPathExpressionToWhere(cqn.SELECT.from, model)
|
|
510
|
-
|
|
555
|
+
const { target, alias, where, cardinality, columns } = convertPathExpressionToWhere(cqn.SELECT.from, model, options)
|
|
556
|
+
|
|
557
|
+
// remove virtual and with skip annotated fields in orderby and where
|
|
558
|
+
_convertOrderByOrWhereIfSkip(cqn, target, model)
|
|
559
|
+
|
|
560
|
+
const select = SELECT.from(target, columns || cqn.SELECT.columns)
|
|
511
561
|
|
|
512
562
|
if (alias) {
|
|
513
563
|
select.SELECT.from.as = alias
|
|
@@ -533,7 +583,11 @@ const _convertSelect = (cqn, model, options) => {
|
|
|
533
583
|
|
|
534
584
|
// We add all previous properties ot the newly created query.
|
|
535
585
|
// Reason is to not lose the query API functionality
|
|
536
|
-
Object.assign(select.SELECT, cqn.SELECT, {
|
|
586
|
+
Object.assign(select.SELECT, cqn.SELECT, {
|
|
587
|
+
columns: select.SELECT.columns,
|
|
588
|
+
from: select.SELECT.from,
|
|
589
|
+
where: select.SELECT.where
|
|
590
|
+
})
|
|
537
591
|
|
|
538
592
|
if (select.SELECT.columns && cds.env.effective.odata.structs) {
|
|
539
593
|
flattenStructuredSelect(select, model)
|
|
@@ -542,35 +596,6 @@ const _convertSelect = (cqn, model, options) => {
|
|
|
542
596
|
return select
|
|
543
597
|
}
|
|
544
598
|
|
|
545
|
-
const _getElement = (column, columns, target) => {
|
|
546
|
-
if (!target) return
|
|
547
|
-
|
|
548
|
-
if (columns) {
|
|
549
|
-
// if columns is defined, column is index and row[column] should contain value that belongs to name in columns with same index
|
|
550
|
-
return target.elements[columns[column]]
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
return target.elements[column]
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
const _handleArrayedElements = (rows, target, columns) => {
|
|
557
|
-
for (const row of rows) {
|
|
558
|
-
for (const column in row) {
|
|
559
|
-
const element = _getElement(column, columns, target)
|
|
560
|
-
|
|
561
|
-
if (element && element.is2one) {
|
|
562
|
-
_handleArrayedElements([row[column]], element._target, columns)
|
|
563
|
-
} else if (element && element.is2many) {
|
|
564
|
-
_handleArrayedElements(row[column], element._target, columns)
|
|
565
|
-
} else if (element && element._isStructured) {
|
|
566
|
-
_handleArrayedElements([row[column]], element, columns)
|
|
567
|
-
} else if (Array.isArray(row[column])) {
|
|
568
|
-
row[column] = JSON.stringify(row[column])
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
599
|
const _convertInsert = (cqn, model) => {
|
|
575
600
|
// resolve path expression
|
|
576
601
|
const resolvedIntoClause = _convertPathExpressionForInsertOrDelete(cqn.INSERT.into, model)
|
|
@@ -585,22 +610,11 @@ const _convertInsert = (cqn, model) => {
|
|
|
585
610
|
Object.assign(insert.INSERT, cqn.INSERT, { into: resolvedIntoClause })
|
|
586
611
|
|
|
587
612
|
const targetName = insert.INSERT.into.name || insert.INSERT.into
|
|
588
|
-
const queryTarget = model.definitions[ensureNoDraftsSuffix(targetName)]
|
|
589
|
-
|
|
590
|
-
if (cds.env.effective.odata.version !== 'v2') {
|
|
591
|
-
if (cqn.INSERT.entries) {
|
|
592
|
-
_handleArrayedElements(cqn.INSERT.entries, queryTarget)
|
|
593
|
-
} else if (cqn.INSERT.rows) {
|
|
594
|
-
_handleArrayedElements(cqn.INSERT.rows, queryTarget, cqn.INSERT.columns)
|
|
595
|
-
} else if (cqn.INSERT.values) {
|
|
596
|
-
_handleArrayedElements([cqn.INSERT.values], queryTarget, cqn.INSERT.columns)
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
613
|
|
|
600
614
|
const target = model.definitions[targetName]
|
|
601
615
|
if (!target) return insert
|
|
602
616
|
|
|
603
|
-
const resolvedView = resolveView(insert, model,
|
|
617
|
+
const resolvedView = resolveView(insert, model, cds.db)
|
|
604
618
|
|
|
605
619
|
if (cqn.INSERT.into.ref && cqn.INSERT.into.ref.length > 1) {
|
|
606
620
|
const copyFrom = [...cqn.INSERT.into.ref]
|
|
@@ -612,6 +626,7 @@ const _convertInsert = (cqn, model) => {
|
|
|
612
626
|
}
|
|
613
627
|
|
|
614
628
|
function _modifyNavigationInWhere(whereClause, target) {
|
|
629
|
+
if (!whereClause) return
|
|
615
630
|
whereClause.forEach(e => {
|
|
616
631
|
if (e.ref && e.ref.length > 1 && target.elements[e.ref[0]]) {
|
|
617
632
|
const element = target.elements[e.ref[0]]
|
|
@@ -633,10 +648,10 @@ const _plainDelete = (cqn, model) => {
|
|
|
633
648
|
const target = model.definitions[name]
|
|
634
649
|
if (!target) return cqn
|
|
635
650
|
|
|
636
|
-
return resolveView(cqn, model,
|
|
651
|
+
return resolveView(cqn, model, cds.db)
|
|
637
652
|
}
|
|
638
653
|
|
|
639
|
-
const _convertDelete = (cqn, model) => {
|
|
654
|
+
const _convertDelete = (cqn, model, options) => {
|
|
640
655
|
// .from is plain string or csn entity
|
|
641
656
|
if (
|
|
642
657
|
typeof cqn.DELETE.from === 'string' ||
|
|
@@ -646,7 +661,7 @@ const _convertDelete = (cqn, model) => {
|
|
|
646
661
|
return _plainDelete(cqn, model)
|
|
647
662
|
}
|
|
648
663
|
|
|
649
|
-
const { target, alias, where } = convertPathExpressionToWhere(cqn.DELETE.from, model)
|
|
664
|
+
const { target, alias, where } = convertPathExpressionToWhere(cqn.DELETE.from, model, options)
|
|
650
665
|
const deleet = DELETE('x')
|
|
651
666
|
Object.assign(deleet.DELETE, cqn.DELETE, { from: target, where: undefined })
|
|
652
667
|
|
|
@@ -657,37 +672,30 @@ const _convertDelete = (cqn, model) => {
|
|
|
657
672
|
const targetEntity = model.definitions[target]
|
|
658
673
|
if (!targetEntity) return deleet
|
|
659
674
|
|
|
660
|
-
return resolveView(deleet, model,
|
|
675
|
+
return resolveView(deleet, model, cds.db)
|
|
661
676
|
}
|
|
662
677
|
|
|
663
678
|
function _plainUpdate(cqn, model) {
|
|
664
679
|
const name = cqn.UPDATE.entity.name || (cqn.UPDATE.entity.ref && cqn.UPDATE.entity.ref[0]) || cqn.UPDATE.entity
|
|
665
|
-
const queryTarget = model.definitions[ensureNoDraftsSuffix(name)]
|
|
666
|
-
|
|
667
|
-
if (cds.env.effective.odata.version !== 'v2') {
|
|
668
|
-
cqn.UPDATE.data && _handleArrayedElements([cqn.UPDATE.data], queryTarget)
|
|
669
|
-
cqn.UPDATE.with && _handleArrayedElements([cqn.UPDATE.with], queryTarget)
|
|
670
|
-
}
|
|
671
|
-
|
|
672
680
|
const target = model.definitions[name]
|
|
673
681
|
if (!target) return cqn
|
|
674
682
|
|
|
675
|
-
return resolveView(cqn, model,
|
|
683
|
+
return resolveView(cqn, model, cds.db)
|
|
676
684
|
}
|
|
677
685
|
|
|
678
|
-
const _convertUpdate = (cqn, model) => {
|
|
686
|
+
const _convertUpdate = (cqn, model, options) => {
|
|
679
687
|
// REVISIT flatten structured types, currently its done in SQL builder
|
|
680
688
|
|
|
681
689
|
// .into is plain string or csn entity
|
|
682
690
|
if (
|
|
683
691
|
typeof cqn.UPDATE.entity === 'string' ||
|
|
684
692
|
cqn.UPDATE.entity.name ||
|
|
685
|
-
(cqn.UPDATE.entity.ref && typeof cqn.UPDATE.entity.ref[0] === 'string')
|
|
693
|
+
(cqn.UPDATE.entity.ref && typeof cqn.UPDATE.entity.ref[0] === 'string' && cqn.UPDATE.entity.ref.length === 1)
|
|
686
694
|
) {
|
|
687
695
|
return _plainUpdate(cqn, model)
|
|
688
696
|
}
|
|
689
697
|
|
|
690
|
-
const { target, alias, where } = convertPathExpressionToWhere(cqn.UPDATE.entity, model)
|
|
698
|
+
const { target, alias, where } = convertPathExpressionToWhere(cqn.UPDATE.entity, model, options)
|
|
691
699
|
|
|
692
700
|
// link .with and .data and set query target and remove current where clause
|
|
693
701
|
// REVISIT: update statement does not accept cqn partial as input
|
|
@@ -698,17 +706,10 @@ const _convertUpdate = (cqn, model) => {
|
|
|
698
706
|
if (where) update.where(where)
|
|
699
707
|
if (cqn.UPDATE.where) update.where(_addAliasToExpression(cqn.UPDATE.where, alias))
|
|
700
708
|
|
|
701
|
-
const queryTarget = model.definitions[target]
|
|
702
|
-
|
|
703
|
-
if (cds.env.effective.odata.version !== 'v2') {
|
|
704
|
-
cqn.UPDATE.data && _handleArrayedElements([cqn.UPDATE.data], queryTarget)
|
|
705
|
-
cqn.UPDATE.with && _handleArrayedElements([cqn.UPDATE.with], queryTarget)
|
|
706
|
-
}
|
|
707
|
-
|
|
708
709
|
const targetEntity = model.definitions[target]
|
|
709
710
|
if (!targetEntity) return update
|
|
710
711
|
|
|
711
|
-
return resolveView(update, model,
|
|
712
|
+
return resolveView(update, model, cds.db)
|
|
712
713
|
}
|
|
713
714
|
|
|
714
715
|
/**
|
|
@@ -729,15 +730,15 @@ const cqn2cqn4sql = (cqn, model, options = { suppressSearch: false }) => {
|
|
|
729
730
|
}
|
|
730
731
|
|
|
731
732
|
if (cqn.UPDATE) {
|
|
732
|
-
return _convertUpdate(cqn, model)
|
|
733
|
+
return _convertUpdate(cqn, model, options)
|
|
733
734
|
}
|
|
734
735
|
|
|
735
736
|
if (cqn.INSERT) {
|
|
736
|
-
return _convertInsert(cqn, model)
|
|
737
|
+
return _convertInsert(cqn, model, options)
|
|
737
738
|
}
|
|
738
739
|
|
|
739
740
|
if (cqn.DELETE) {
|
|
740
|
-
return _convertDelete(cqn, model)
|
|
741
|
+
return _convertDelete(cqn, model, options)
|
|
741
742
|
}
|
|
742
743
|
|
|
743
744
|
return cqn
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
|
|
3
3
|
const { ensureNoDraftsSuffix } = require('./draft')
|
|
4
|
+
const { getFlatArray } = require('../../db/utils/deep')
|
|
4
5
|
|
|
5
6
|
const getEtagElement = entity => {
|
|
6
7
|
return Object.values(entity.elements).find(element => element['@odata.etag'])
|
|
@@ -41,7 +42,7 @@ const _isDependent = (assoc, parent, target) => {
|
|
|
41
42
|
* doing as aspect is difficult due to no global definitons per tenant
|
|
42
43
|
*/
|
|
43
44
|
const getDependents = (entity, model) => {
|
|
44
|
-
if (entity.
|
|
45
|
+
if (entity.own('__dependents')) return entity.__dependents
|
|
45
46
|
|
|
46
47
|
/** @type {Array|boolean} */
|
|
47
48
|
let dependents = []
|
|
@@ -61,8 +62,49 @@ const getDependents = (entity, model) => {
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
if (dependents.length === 0) dependents = false
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
return entity.set('__dependents', dependents)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const _getUps = (entity, model, previous = []) => {
|
|
69
|
+
const ups = []
|
|
70
|
+
for (const def of Object.values(model.definitions)) {
|
|
71
|
+
if (def.kind !== 'entity') continue
|
|
72
|
+
if (!def.associations) continue
|
|
73
|
+
for (const assoc of Object.values(def.associations)) {
|
|
74
|
+
if (assoc.target !== entity.name) continue
|
|
75
|
+
ups.push({
|
|
76
|
+
entity: assoc.parent,
|
|
77
|
+
assoc: assoc,
|
|
78
|
+
previous
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return ups
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const _ifDataSubject = (entity, role) => {
|
|
86
|
+
return entity['@PersonalData.EntitySemantics'] === 'DataSubject' && entity['@PersonalData.DataSubjectRole'] === role
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const getDataSubject = (entity, model, role) => {
|
|
90
|
+
const hash = '__dataSubject4' + role
|
|
91
|
+
if (entity.own(hash)) return entity[hash]
|
|
92
|
+
|
|
93
|
+
if (_ifDataSubject(entity, role)) return entity.set(hash, { entity: entity, assoc: [], previous: [] })
|
|
94
|
+
|
|
95
|
+
let dataSubject
|
|
96
|
+
let ups = _getUps(entity, model)
|
|
97
|
+
while (!dataSubject) {
|
|
98
|
+
for (const { entity, assoc, previous } of ups) {
|
|
99
|
+
if (_ifDataSubject(entity, role)) dataSubject = { entity, assoc, previous }
|
|
100
|
+
}
|
|
101
|
+
if (dataSubject) break
|
|
102
|
+
ups = getFlatArray([
|
|
103
|
+
...ups.map(up => [..._getUps(up.entity, model, up.previous.concat({ entity: up.entity, assoc: up.assoc }))])
|
|
104
|
+
])
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return entity.set(hash, dataSubject)
|
|
66
108
|
}
|
|
67
109
|
|
|
68
110
|
const _findRootEntity = (entities, edmName) => {
|
|
@@ -166,5 +208,6 @@ module.exports = {
|
|
|
166
208
|
findCsnTargetFor,
|
|
167
209
|
getElementDeep,
|
|
168
210
|
getDependents,
|
|
169
|
-
isRootEntity
|
|
211
|
+
isRootEntity,
|
|
212
|
+
getDataSubject
|
|
170
213
|
}
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
// REVISIT: use follow projection
|
|
2
|
-
|
|
3
|
-
const getError = require('../error')
|
|
4
|
-
|
|
5
|
-
const _renameData = (query, data) => {
|
|
6
|
-
if (query.SELECT && query.SELECT.columns) {
|
|
7
|
-
for (const col of query.SELECT.columns) {
|
|
8
|
-
if (typeof col === 'object' && col.ref && col.as && col.ref[0] !== col.as) {
|
|
9
|
-
if (data[col.as]) {
|
|
10
|
-
data[col.ref[0]] = data[col.as]
|
|
11
|
-
delete data[col.as]
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const getTargetData = (target, data = {}) => {
|
|
19
|
-
if (target.query) {
|
|
20
|
-
_renameData(target.query, data)
|
|
21
|
-
|
|
22
|
-
if (target.query._target) {
|
|
23
|
-
return getTargetData(target.query._target, data)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!target.query.from || target.query.from.length > 1 || target.query.where) {
|
|
27
|
-
// REVISIT: when is this the case?! getTargetData only used in deleteDraftUtils...
|
|
28
|
-
throw getError(501, 'Insert, Update or Delete on views with join|union|where is not supported')
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return { target: target.query.from[0].absolute, data }
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return { target, data }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
1
|
// REVISIT: remove once not needed anymore
|
|
38
2
|
const getDataFromCQN = query => (query.INSERT && query.INSERT.entries) || (query.UPDATE && query.UPDATE.data)
|
|
39
3
|
|
|
@@ -47,7 +11,6 @@ const setDataFromCQN = req => {
|
|
|
47
11
|
}
|
|
48
12
|
|
|
49
13
|
module.exports = {
|
|
50
|
-
getTargetData,
|
|
51
14
|
getDataFromCQN,
|
|
52
15
|
setDataFromCQN
|
|
53
16
|
}
|
|
@@ -85,7 +85,7 @@ module.exports = (data, { query, target }, { model }) => {
|
|
|
85
85
|
} else if (query.UPDATE) {
|
|
86
86
|
const where = _getWhereFromUpdate(query, target, model)
|
|
87
87
|
if (!where || !where.length) return
|
|
88
|
-
|
|
88
|
+
if (!data) data = query.UPDATE.data = {} // REVISIT: We should not expect data to be present always!
|
|
89
89
|
_addKeysFromWhereToData(where, target, data)
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -1,38 +1,21 @@
|
|
|
1
1
|
const { ensureNoDraftsSuffix } = require('../../common/utils/draft')
|
|
2
2
|
|
|
3
|
-
const _entityFromRef = ref => {
|
|
4
|
-
if (ref) return ref[0].id || ref[0]
|
|
5
|
-
}
|
|
6
|
-
|
|
7
3
|
const getEntityNameFromCQN = cqn => {
|
|
8
|
-
while (cqn.SELECT)
|
|
9
|
-
cqn = cqn.SELECT.from
|
|
10
|
-
}
|
|
4
|
+
while (cqn.SELECT) cqn = cqn.SELECT.from
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
// Do the most likely first -> {ref}
|
|
7
|
+
if (cqn.ref) {
|
|
8
|
+
return cqn.ref[0].id || cqn.ref[0]
|
|
9
|
+
}
|
|
14
10
|
|
|
15
|
-
const _getEntityNameFromUnionCQN = cqn => {
|
|
16
11
|
// TODO cleanup
|
|
17
12
|
// REVISIT infer should do this for req.target
|
|
18
13
|
// REVISIT2 No, req.target doesn't make sense for joins
|
|
19
14
|
if (cqn.SET) {
|
|
20
|
-
return cqn.SET.args
|
|
21
|
-
.map(arg => {
|
|
22
|
-
return getEntityNameFromCQN(arg)
|
|
23
|
-
})
|
|
24
|
-
.filter(name => {
|
|
25
|
-
return name !== 'DRAFT.DraftAdministrativeData'
|
|
26
|
-
})[0]
|
|
15
|
+
return cqn.SET.args.map(getEntityNameFromCQN).find(n => n !== 'DRAFT.DraftAdministrativeData')
|
|
27
16
|
}
|
|
28
17
|
if (cqn.join) {
|
|
29
|
-
return cqn.args
|
|
30
|
-
.map(arg => {
|
|
31
|
-
return getEntityNameFromCQN(arg)
|
|
32
|
-
})
|
|
33
|
-
.filter(name => {
|
|
34
|
-
return name !== 'DRAFT.DraftAdministrativeData'
|
|
35
|
-
})[0]
|
|
18
|
+
return cqn.args.map(getEntityNameFromCQN).find(n => n !== 'DRAFT.DraftAdministrativeData')
|
|
36
19
|
}
|
|
37
20
|
}
|
|
38
21
|
|