@sap/cds 5.4.3 → 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 +239 -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 +66 -63
- 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 +12 -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 +53 -31
- 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 +123 -108
- package/libx/_runtime/common/utils/csn.js +56 -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 +227 -173
- package/libx/_runtime/common/utils/rewriteAsterisk.js +46 -26
- package/libx/_runtime/common/utils/structured.js +13 -13
- 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 +28 -72
- 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 +21 -8
- 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 +261 -205
- 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 +3 -3
- 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 +33 -27
- package/libx/_runtime/sqlite/localized.js +12 -7
- package/libx/_runtime/types/api.js +10 -0
- package/package.json +2 -2
- 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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const { SELECT } = cds.ql
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const cqn2cqn4sql = require('../../common/utils/cqn2cqn4sql')
|
|
5
|
+
const { getElementDeep } = require('../../common/utils/csn')
|
|
6
|
+
|
|
7
|
+
const { DRAFT_COLUMNS, DRAFT_COLUMNS_MAP, SCENARIO } = require('../../common/constants/draft')
|
|
5
8
|
const {
|
|
6
9
|
adaptStreamCQN,
|
|
7
10
|
addColumnAlias,
|
|
@@ -10,20 +13,39 @@ const {
|
|
|
10
13
|
ensureNoDraftsSuffix,
|
|
11
14
|
ensureUnlocalized,
|
|
12
15
|
getEnrichedCQN,
|
|
13
|
-
removeAnnotationWhere,
|
|
14
16
|
removeDraftUUIDIfNecessary,
|
|
15
17
|
replaceRefWithDraft,
|
|
16
18
|
hasKeyInWhere,
|
|
17
|
-
filterKeys
|
|
18
|
-
getKeyProperty
|
|
19
|
+
filterKeys
|
|
19
20
|
} = require('../utils/handler')
|
|
20
21
|
const { deleteCondition, readAndDeleteKeywords, removeIsActiveEntityRecursively } = require('../utils/where')
|
|
22
|
+
|
|
21
23
|
const { getColumns } = require('../../cds-services/services/utils/columns')
|
|
22
|
-
const cqn2cqn4sql = require('../../common/utils/cqn2cqn4sql')
|
|
23
|
-
const { removeVirtuals, postProcessVirtuals } = require('../../db/generic/virtual')
|
|
24
24
|
|
|
25
|
-
//
|
|
26
|
-
const
|
|
25
|
+
// append where with clauses from @restrict
|
|
26
|
+
const _getWhereWithAppendedDraftRestrictions = (where = [], req, scenarioAlias, model) => {
|
|
27
|
+
if (req.query._draftRestrictions) {
|
|
28
|
+
for (const each of req.query._draftRestrictions) {
|
|
29
|
+
if (where.length) where.push('and')
|
|
30
|
+
|
|
31
|
+
// REVISIT: remove with cds^6
|
|
32
|
+
// adjust alias of @restrict where "exists (select ...)"
|
|
33
|
+
if (scenarioAlias && model)
|
|
34
|
+
each
|
|
35
|
+
.filter(e => e.SELECT && e.SELECT.from && e.SELECT.where)
|
|
36
|
+
.forEach(e => {
|
|
37
|
+
const entity = model.definitions[e.SELECT.from.ref[0]]
|
|
38
|
+
e.SELECT.where = e.SELECT.where.map(w => {
|
|
39
|
+
if (w.ref && w.ref.length === 1 && !entity.elements[w.ref[0]]) w.ref.unshift(scenarioAlias)
|
|
40
|
+
return w
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
where.push(...each)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return where
|
|
48
|
+
}
|
|
27
49
|
|
|
28
50
|
const _isTrue = val => val === true || val === 'true'
|
|
29
51
|
|
|
@@ -113,7 +135,8 @@ const _getDraftPropertiesDetermineDraft = (req, where, tableName, calcDraftUUID
|
|
|
113
135
|
|
|
114
136
|
const hasDraftQuery = SELECT.from(tableName, [{ val: 1 }])
|
|
115
137
|
if (where && where.length > 0) {
|
|
116
|
-
|
|
138
|
+
// clone where to protect from later modification
|
|
139
|
+
hasDraftQuery.where([...where])
|
|
117
140
|
}
|
|
118
141
|
|
|
119
142
|
let draftUUIDColumn
|
|
@@ -158,13 +181,9 @@ function _copyCQNPartial(partial) {
|
|
|
158
181
|
}
|
|
159
182
|
|
|
160
183
|
function _copyArray(array) {
|
|
161
|
-
|
|
184
|
+
return array.map(entry => {
|
|
162
185
|
return typeof entry === 'object' && !(entry instanceof String) ? _copyCQNPartial(entry) : entry
|
|
163
186
|
})
|
|
164
|
-
if (array[SYMBOL_FROM_ANNOTATION] === true) {
|
|
165
|
-
copy[SYMBOL_FROM_ANNOTATION] = true
|
|
166
|
-
}
|
|
167
|
-
return copy
|
|
168
187
|
}
|
|
169
188
|
|
|
170
189
|
const _whereContainsKeys = (req, whereDraft) => {
|
|
@@ -276,12 +295,12 @@ const _draftAdminTable = req => {
|
|
|
276
295
|
}
|
|
277
296
|
|
|
278
297
|
return {
|
|
279
|
-
cqn: getEnrichedCQN(cqn, req.query.SELECT,
|
|
280
|
-
scenario:
|
|
298
|
+
cqn: getEnrichedCQN(cqn, req.query.SELECT, req.query.SELECT.where),
|
|
299
|
+
scenario: SCENARIO.DRAFT_ADMIN
|
|
281
300
|
}
|
|
282
301
|
}
|
|
283
302
|
|
|
284
|
-
const _allInactive = (req, columns
|
|
303
|
+
const _allInactive = (req, columns) => {
|
|
285
304
|
const table = {
|
|
286
305
|
ref: [ensureDraftsSuffix(req.query.SELECT.from.ref[0])],
|
|
287
306
|
as: req.query.SELECT.from.as || 'drafts'
|
|
@@ -292,17 +311,6 @@ const _allInactive = (req, columns, model) => {
|
|
|
292
311
|
_getDefaultDraftProperties({ hasDraft: false, isActive: false, withDraftUUID: false })
|
|
293
312
|
)
|
|
294
313
|
|
|
295
|
-
// determine name of primary key to use in HasActiveEntity expression
|
|
296
|
-
const pk = req.target['@assert.unique.locale']
|
|
297
|
-
? req.target['@assert.unique.locale'].map(o => o['=']).find(k => k !== 'locale')
|
|
298
|
-
: getKeyProperty(req.target.keys)
|
|
299
|
-
|
|
300
|
-
const xpr = {
|
|
301
|
-
xpr: ['case', 'when', `active.${pk}`, 'IS NOT NULL', 'then', 'true', 'else', 'false', 'end'],
|
|
302
|
-
as: 'HasActiveEntity',
|
|
303
|
-
cast: { type: 'cds.Boolean' }
|
|
304
|
-
}
|
|
305
|
-
|
|
306
314
|
const ids = filterKeys(req.target.keys)
|
|
307
315
|
const isCount = columns.some(element => element.func === 'count')
|
|
308
316
|
|
|
@@ -311,7 +319,7 @@ const _allInactive = (req, columns, model) => {
|
|
|
311
319
|
if (isCount) {
|
|
312
320
|
cqn.columns(...outerMostColumns)
|
|
313
321
|
} else {
|
|
314
|
-
cqn.columns(...outerMostColumns.filter(o => o.as !== 'HasActiveEntity'),
|
|
322
|
+
cqn.columns(...outerMostColumns.filter(o => o.as !== 'HasActiveEntity'), { ref: ['HasActiveEntity'] })
|
|
315
323
|
cqn.leftJoin(ensureNoDraftsSuffix(table.ref[0]) + ' as active').on(`${table.as}.${ids[0]} = active.${ids[0]}`)
|
|
316
324
|
|
|
317
325
|
for (let i = 1; i < ids.length; i++) {
|
|
@@ -321,9 +329,8 @@ const _allInactive = (req, columns, model) => {
|
|
|
321
329
|
}
|
|
322
330
|
|
|
323
331
|
cqn.where(req.query.SELECT.where)
|
|
324
|
-
removeAnnotationWhere(cqn.SELECT.where)
|
|
325
332
|
|
|
326
|
-
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, []), scenario:
|
|
333
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, []), scenario: SCENARIO.ALL_INACTIVE }
|
|
327
334
|
}
|
|
328
335
|
|
|
329
336
|
const _setRefAlias = (ref, as) => {
|
|
@@ -361,7 +368,7 @@ const _buildOrderBy = (query, columns, table) => {
|
|
|
361
368
|
}
|
|
362
369
|
}
|
|
363
370
|
|
|
364
|
-
const _allActive = (req, columns) => {
|
|
371
|
+
const _allActive = (req, columns, model) => {
|
|
365
372
|
const { table } = _getTableName(req)
|
|
366
373
|
if (!table.as) {
|
|
367
374
|
table.as = 'active'
|
|
@@ -405,12 +412,20 @@ const _allActive = (req, columns) => {
|
|
|
405
412
|
}
|
|
406
413
|
}
|
|
407
414
|
|
|
415
|
+
const scenarioAlias = 'active'
|
|
416
|
+
|
|
417
|
+
req.query.SELECT.where = _getWhereWithAppendedDraftRestrictions(req.query.SELECT.where, req, scenarioAlias, model)
|
|
418
|
+
|
|
408
419
|
if (req.query.SELECT.where) {
|
|
409
420
|
_buildWhere(req.query.SELECT.where, table)
|
|
410
421
|
}
|
|
422
|
+
|
|
411
423
|
_buildOrderBy(req.query, cqn.SELECT.columns, table)
|
|
412
424
|
|
|
413
|
-
return {
|
|
425
|
+
return {
|
|
426
|
+
cqn: getEnrichedCQN(cqn, req.query.SELECT, req.query.SELECT.where, scenarioAlias),
|
|
427
|
+
scenario: SCENARIO.ALL_ACTIVE
|
|
428
|
+
}
|
|
414
429
|
}
|
|
415
430
|
|
|
416
431
|
const _active = (req, draftWhere, columns) => {
|
|
@@ -420,7 +435,9 @@ const _active = (req, draftWhere, columns) => {
|
|
|
420
435
|
|
|
421
436
|
const cqn = SELECT.from(table).columns(...outerMostColumns)
|
|
422
437
|
|
|
423
|
-
|
|
438
|
+
draftWhere = _getWhereWithAppendedDraftRestrictions(draftWhere, req)
|
|
439
|
+
|
|
440
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.ACTIVE }
|
|
424
441
|
}
|
|
425
442
|
|
|
426
443
|
const _activeWithoutDraft = (req, draftWhere, columns) => {
|
|
@@ -448,7 +465,9 @@ const _activeWithoutDraft = (req, draftWhere, columns) => {
|
|
|
448
465
|
.columns(...outerMostColumns)
|
|
449
466
|
.where(['not exists', subSelect])
|
|
450
467
|
|
|
451
|
-
|
|
468
|
+
draftWhere = _getWhereWithAppendedDraftRestrictions(draftWhere, req)
|
|
469
|
+
|
|
470
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.ACTIVE_WITHOUT_DRAFT }
|
|
452
471
|
}
|
|
453
472
|
|
|
454
473
|
const _draftOfWhichIAmOwner = (req, draftWhere, columns) => {
|
|
@@ -468,9 +487,7 @@ const _draftOfWhichIAmOwner = (req, draftWhere, columns) => {
|
|
|
468
487
|
])
|
|
469
488
|
.where(_inProcessByUserWhere(req.user.id))
|
|
470
489
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: 'DRAFT_WHICH_OWNER' }
|
|
490
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.DRAFT_WHICH_OWNER }
|
|
474
491
|
}
|
|
475
492
|
|
|
476
493
|
const _activeWithDraftInProcess = (req, draftWhere, columns, isLocked) => {
|
|
@@ -503,7 +520,7 @@ const _activeWithDraftInProcess = (req, draftWhere, columns, isLocked) => {
|
|
|
503
520
|
'and',
|
|
504
521
|
{
|
|
505
522
|
func: 'seconds_between',
|
|
506
|
-
args: [{ ref: ['filterAdmin', 'LastChangeDateTime'] },
|
|
523
|
+
args: [{ ref: ['filterAdmin', 'LastChangeDateTime'] }, 'CURRENT_TIMESTAMP']
|
|
507
524
|
},
|
|
508
525
|
isLocked ? '<' : '>',
|
|
509
526
|
{ val: DRAFT_CANCEL_TIMEOUT_IN_SEC }
|
|
@@ -514,11 +531,13 @@ const _activeWithDraftInProcess = (req, draftWhere, columns, isLocked) => {
|
|
|
514
531
|
subSelect
|
|
515
532
|
)
|
|
516
533
|
|
|
534
|
+
subSelect.SELECT.where = _getWhereWithAppendedDraftRestrictions(subSelect.SELECT.where, req)
|
|
535
|
+
|
|
517
536
|
const outerMostColumns = _getOuterMostColumns(columns, draftColumns)
|
|
518
537
|
|
|
519
538
|
const cqn = SELECT.from(active.table).columns(outerMostColumns).where(['exists', subSelect])
|
|
520
539
|
|
|
521
|
-
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario:
|
|
540
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.DRAFT_IN_PROCESS }
|
|
522
541
|
}
|
|
523
542
|
|
|
524
543
|
const _alignAliasForUnion = (table, as, select) => {
|
|
@@ -535,37 +554,27 @@ const _alignAliasForUnion = (table, as, select) => {
|
|
|
535
554
|
return select
|
|
536
555
|
}
|
|
537
556
|
|
|
538
|
-
const
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
return _findKeysInQuery(query.SELECT.where[indexExists + 1], keys)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
_findKeysInWhereAndAddToResult(query.SELECT.where, keys, result)
|
|
560
|
-
}
|
|
561
|
-
return result
|
|
557
|
+
const _findJoinInQuery = (query, parentAlias) => {
|
|
558
|
+
const targetAlias = query.SELECT.from.as
|
|
559
|
+
const isTargetRef = el => targetAlias && el.ref && el.ref.length > 1 && el.ref[0] === targetAlias
|
|
560
|
+
if (query.SELECT && query.SELECT.where)
|
|
561
|
+
return query.SELECT.where.reduce((links, el, idx, where) => {
|
|
562
|
+
if (el.ref && el.ref[0] === parentAlias && el.ref[el.ref.length - 1] !== 'IsActiveEntity') {
|
|
563
|
+
if (where[idx - 1] && where[idx - 1] === '=' && isTargetRef(where[idx - 2])) {
|
|
564
|
+
if (links.length) links.push('and')
|
|
565
|
+
links.push(el, '=', where[idx - 2])
|
|
566
|
+
}
|
|
567
|
+
if (where[idx + 1] && where[idx + 1] === '=' && isTargetRef(where[idx + 2])) {
|
|
568
|
+
if (links.length) links.push('and')
|
|
569
|
+
links.push(el, '=', where[idx + 2])
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
return links
|
|
573
|
+
}, [])
|
|
574
|
+
return []
|
|
562
575
|
}
|
|
563
576
|
|
|
564
|
-
const _isFiltered = where =>
|
|
565
|
-
return where.some(element => {
|
|
566
|
-
return !(element in ['(', ')']) && element[SYMBOL_FROM_ANNOTATION] !== true
|
|
567
|
-
})
|
|
568
|
-
}
|
|
577
|
+
const _isFiltered = where => where.some(element => !(element in ['(', ')']))
|
|
569
578
|
|
|
570
579
|
const _isDraftField = element => element.ref && element.ref.length > 1 && element.ref[0] === 'DraftAdministrativeData'
|
|
571
580
|
|
|
@@ -613,40 +622,112 @@ const _getWhereForActive = where => {
|
|
|
613
622
|
return activeWhere
|
|
614
623
|
}
|
|
615
624
|
|
|
616
|
-
const _siblingEntity = (
|
|
617
|
-
const
|
|
618
|
-
const keys =
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
const
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const cqn = SELECT.from(
|
|
625
|
+
const _siblingEntity = ({ query, target, nav, params }, columns, model, draftAdminAlias, parentQuery, siblingIndex) => {
|
|
626
|
+
const parentLinks = parentQuery ? _findJoinInQuery(query, parentQuery.SELECT.from.as) : []
|
|
627
|
+
const keys = (nav[siblingIndex + 1].where && (params[siblingIndex] || params[0])) || {}
|
|
628
|
+
const siblingQuery = query.SELECT.where[query.SELECT.where.indexOf('exists') + 1]
|
|
629
|
+
const onCond = _findJoinInQuery(siblingQuery, target.as)
|
|
630
|
+
const siblingAlias = siblingQuery.SELECT.from.as
|
|
631
|
+
const subScenario = _siblingSubScenario(nav, siblingIndex, siblingQuery, target, params, model, onCond)
|
|
632
|
+
const isSiblingDraft = subScenario
|
|
633
|
+
? subScenario.isSiblingActive || subScenario.scenario === 'ACTIVE' || subScenario.scenario === 'ALL_ACTIVE'
|
|
634
|
+
: keys.IsActiveEntity && keys.IsActiveEntity !== 'false'
|
|
635
|
+
const { table } = _getTableName({ query, target }, isSiblingDraft)
|
|
636
|
+
const cqn = SELECT.from(table)
|
|
637
|
+
if (siblingIndex === 0) {
|
|
638
|
+
const columnCqnPartial = columns.map(col => {
|
|
639
|
+
const colName = col.ref ? col.ref[col.ref.length - 1] : col
|
|
640
|
+
const ref = col.ref ? [table.as, ...col.ref] : [table.as, colName]
|
|
641
|
+
return Object.assign({}, col, { ref })
|
|
642
|
+
})
|
|
643
|
+
columnCqnPartial.push({ ref: ['draftAdmin', 'InProcessByUser'], as: 'draftAdmin_inProcessByUser' })
|
|
644
|
+
cqn.columns(...columnCqnPartial)
|
|
645
|
+
} else {
|
|
646
|
+
cqn.columns([{ val: 1 }])
|
|
647
|
+
}
|
|
628
648
|
|
|
629
|
-
if (
|
|
649
|
+
if (isSiblingDraft) {
|
|
630
650
|
cqn
|
|
631
|
-
.join(
|
|
632
|
-
.on(
|
|
633
|
-
Object.keys(keys)
|
|
634
|
-
.map(k => `target.${k} = target_draft.${k}`)
|
|
635
|
-
.join(' AND ')
|
|
636
|
-
)
|
|
651
|
+
.join(ensureNoDraftsSuffix(target.name), siblingAlias)
|
|
652
|
+
.on(onCond)
|
|
637
653
|
.join('DRAFT.DraftAdministrativeData', 'draftAdmin')
|
|
638
|
-
.on(
|
|
654
|
+
.on(`${table.as}.DraftAdministrativeData_DraftUUID = draftAdmin.DraftUUID`)
|
|
639
655
|
} else {
|
|
640
656
|
cqn
|
|
657
|
+
.join(ensureDraftsSuffix(target.name), siblingAlias)
|
|
658
|
+
.on(onCond)
|
|
641
659
|
.join('DRAFT.DraftAdministrativeData', 'draftAdmin')
|
|
642
|
-
.on(
|
|
660
|
+
.on(`${siblingAlias}.DraftAdministrativeData_DraftUUID = draftAdmin.DraftUUID`)
|
|
643
661
|
}
|
|
644
662
|
|
|
645
663
|
for (const key in keys) {
|
|
646
|
-
if (key !== 'IsActiveEntity') cqn.where([{ ref: [
|
|
664
|
+
if (key !== 'IsActiveEntity') cqn.where([{ ref: [table.as, key] }, '=', { val: keys[key] }])
|
|
665
|
+
}
|
|
666
|
+
if (subScenario) {
|
|
667
|
+
cqn.where(['exists', subScenario.cqn])
|
|
668
|
+
}
|
|
669
|
+
// in DraftAdminData scenario parent is linked via join
|
|
670
|
+
if (draftAdminAlias) {
|
|
671
|
+
cqn.where([{ ref: [draftAdminAlias, 'DraftUUID'] }, '=', { ref: ['draftAdmin', 'DraftUUID'] }])
|
|
672
|
+
} else if (parentLinks.length) {
|
|
673
|
+
cqn.where('(', ...parentLinks, ')')
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return { cqn, scenario: SCENARIO.SIBLING_ENTITY, isSiblingActive: !isSiblingDraft }
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function _siblingSubScenario(nav, siblingIndex, siblingQuery, target, params, model, onCond) {
|
|
680
|
+
if (nav[siblingIndex + 1].where) return
|
|
681
|
+
let subScenario
|
|
682
|
+
const subNav = nav.slice(siblingIndex + 1)
|
|
683
|
+
const subSiblingIndex = subNav.indexOf('SiblingEntity')
|
|
684
|
+
const subReq = { query: siblingQuery, target: model.definitions[target.name], params: [...params].reverse() }
|
|
685
|
+
if (subSiblingIndex > -1) {
|
|
686
|
+
subScenario = _getSiblingScenario(subReq, [{ val: 1 }], model, subSiblingIndex, subNav, params)
|
|
687
|
+
if (subSiblingIndex > 0) {
|
|
688
|
+
const subQuery = SELECT.from(siblingQuery.SELECT.from).columns([{ val: 1 }])
|
|
689
|
+
_mergeSiblingIntoCQN(subQuery, subScenario, subSiblingIndex - 1)
|
|
690
|
+
subQuery.where(onCond)
|
|
691
|
+
subScenario.cqn = subQuery
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
subReq.query = SELECT.from(siblingQuery.SELECT.from).columns([{ val: 1 }])
|
|
695
|
+
const existsIdx = siblingQuery.SELECT.where.indexOf('exists')
|
|
696
|
+
if (existsIdx > -1) subReq.query.where(siblingQuery.SELECT.where.slice(existsIdx, existsIdx + 2))
|
|
697
|
+
const subReqOrig = { query: { SELECT: { from: { ref: [...subNav].reverse() } } } }
|
|
698
|
+
subScenario = _generateCQN(subReqOrig, subReq, [{ val: 1 }], model)
|
|
699
|
+
subScenario.cqn.where(onCond)
|
|
700
|
+
}
|
|
701
|
+
return subScenario
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const _getSiblingScenario = (req, columns, model, siblingIndex, nav) => {
|
|
705
|
+
const draftAdminAlias = _isDraftAdminScenario(req) && req.query.SELECT.from.as
|
|
706
|
+
const params = [...req.params].reverse()
|
|
707
|
+
const _getSiblingQueryFromWhere = (query, queryIndex, parentQuery) => {
|
|
708
|
+
if (query.SELECT && query.SELECT.where) {
|
|
709
|
+
const indexExists = query.SELECT.where.indexOf('exists')
|
|
710
|
+
if (indexExists > -1 && queryIndex > 0) {
|
|
711
|
+
return _getSiblingQueryFromWhere(query.SELECT.where[indexExists + 1], queryIndex - 1, query)
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
const target = { name: query.SELECT.from.ref[0].id || query.SELECT.from.ref[0], as: query.SELECT.from.as }
|
|
715
|
+
return _siblingEntity({ query, target, params, nav }, columns, model, draftAdminAlias, parentQuery, siblingIndex)
|
|
647
716
|
}
|
|
717
|
+
return _getSiblingQueryFromWhere(req.query, siblingIndex)
|
|
718
|
+
}
|
|
648
719
|
|
|
649
|
-
|
|
720
|
+
const _mergeSiblingIntoCQN = (cqn, { cqn: siblingCQN }, siblingIndex) => {
|
|
721
|
+
const _replaceWhereExists = (query, _siblingIndex) => {
|
|
722
|
+
if (query.SELECT && query.SELECT.where) {
|
|
723
|
+
const indexExists = query.SELECT.where.indexOf('exists')
|
|
724
|
+
if (indexExists > -1) {
|
|
725
|
+
if (_siblingIndex > 0) return _replaceWhereExists(query.SELECT.where[indexExists + 1], _siblingIndex - 1)
|
|
726
|
+
query.SELECT.where.splice(indexExists + 1, 1, siblingCQN)
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
return _replaceWhereExists(cqn, siblingIndex)
|
|
650
731
|
}
|
|
651
732
|
|
|
652
733
|
const _getDraftDoc = (req, draftName, draftWhere) => {
|
|
@@ -705,7 +786,7 @@ const _getUnionCQN = (req, draftName, columns, subSelect, draftWhere) => {
|
|
|
705
786
|
const activeDocs = getEnrichedCQN(SELECT.from(req.target), req.query.SELECT, draftActiveWhere, undefined, false)
|
|
706
787
|
|
|
707
788
|
_replaceDraftAlias(draftWhere)
|
|
708
|
-
const draftDocs = _getDraftDoc(req, draftName,
|
|
789
|
+
const draftDocs = _getDraftDoc(req, draftName, draftWhere)
|
|
709
790
|
|
|
710
791
|
const union = SELECT.from({ SET: { op: 'union', all: true, args: [draftDocs, activeDocs] } })
|
|
711
792
|
if (req.query.SELECT.count) union.SELECT.count = true
|
|
@@ -730,17 +811,22 @@ const _getUnionCQN = (req, draftName, columns, subSelect, draftWhere) => {
|
|
|
730
811
|
const enrichedColumns = _getOrderByEnrichedColumns(req.query.SELECT.orderBy, columns)
|
|
731
812
|
|
|
732
813
|
for (const col of enrichedColumns) {
|
|
814
|
+
// if we have columns for outer order by that may also be needed for joins, we need to duplicate them
|
|
815
|
+
const element = getElementDeep(req.target, col.ref)
|
|
816
|
+
if (element && element['@odata.foreignKey4']) columns.push({ ref: [...col.ref] })
|
|
817
|
+
|
|
733
818
|
col.as = _poorMansAlias4(col)
|
|
734
819
|
// add alias to outer order by
|
|
735
820
|
const ob = req.query.SELECT.orderBy.find(ele => _poorMansAlias4(ele) === col.as)
|
|
736
821
|
ob.ref = [col.as]
|
|
737
822
|
}
|
|
738
823
|
|
|
739
|
-
|
|
824
|
+
const draftColumns = [
|
|
740
825
|
...addColumnAlias([...columns, ...enrichedColumns], req.query.SELECT.from.as || draftName),
|
|
741
826
|
..._filterDraftColumnsBySelected(DRAFT_COLUMNS_CASTED, req.query.SELECT.columns),
|
|
742
827
|
'DraftAdministrativeData_DraftUUID'
|
|
743
|
-
|
|
828
|
+
]
|
|
829
|
+
draftDocs.columns(draftColumns)
|
|
744
830
|
|
|
745
831
|
const activeName = activeDocs.SELECT.from.as || (activeDocs.SELECT.from.ref && activeDocs.SELECT.from.ref[0])
|
|
746
832
|
|
|
@@ -751,19 +837,20 @@ const _getUnionCQN = (req, draftName, columns, subSelect, draftWhere) => {
|
|
|
751
837
|
hasDraftWhere.push({ ref: [activeName, key] }, '=', { ref: [draftName, key] })
|
|
752
838
|
}
|
|
753
839
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
req.query.SELECT.columns
|
|
761
|
-
)
|
|
840
|
+
const activeColumns = [
|
|
841
|
+
...columns,
|
|
842
|
+
...enrichedColumns,
|
|
843
|
+
..._filterDraftColumnsBySelected(
|
|
844
|
+
_getDraftPropertiesDetermineDraft(req, hasDraftWhere, ensureDraftsSuffix(req.target.name), true),
|
|
845
|
+
req.query.SELECT.columns
|
|
762
846
|
)
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
847
|
+
]
|
|
848
|
+
activeDocs.columns(activeColumns)
|
|
849
|
+
|
|
850
|
+
activeDocs.where([
|
|
851
|
+
'not exists',
|
|
852
|
+
_alignAliasForUnion(ensureNoDraftsSuffix(req.target.name), req.query.SELECT.from.as, subSelect)
|
|
853
|
+
])
|
|
767
854
|
|
|
768
855
|
// groupBy, orderBy and limit do not support partial CQNs
|
|
769
856
|
if (req.query.SELECT.groupBy) {
|
|
@@ -802,6 +889,8 @@ const _excludeActiveDraftExists = (req, draftWhere, columns) => {
|
|
|
802
889
|
subSelect.where([{ ref: [ensureNoDraftsSuffix(req.target.name), key] }, '=', { ref: [draftName, key] }])
|
|
803
890
|
}
|
|
804
891
|
|
|
892
|
+
draftWhere = _getWhereWithAppendedDraftRestrictions(draftWhere, req)
|
|
893
|
+
|
|
805
894
|
draftWhere = removeIsActiveEntityRecursively(draftWhere)
|
|
806
895
|
const cqn = _getUnionCQN(req, draftName, columns, subSelect, draftWhere)
|
|
807
896
|
cqn.SELECT.from.as = name
|
|
@@ -814,7 +903,7 @@ const _excludeActiveDraftExists = (req, draftWhere, columns) => {
|
|
|
814
903
|
}
|
|
815
904
|
}
|
|
816
905
|
|
|
817
|
-
return { cqn: cqn, scenario:
|
|
906
|
+
return { cqn: cqn, scenario: SCENARIO.UNION }
|
|
818
907
|
}
|
|
819
908
|
|
|
820
909
|
const _readDraftParameters = where => {
|
|
@@ -858,37 +947,46 @@ const _validatedActive = (req, draftWhere, draftParameters, columns) =>
|
|
|
858
947
|
const _validatedDraftOfWhichIAmOwner = (req, draftWhere, draftParameters, columns) =>
|
|
859
948
|
_isValidDraftOfWhichIAmOwner(draftParameters.isActiveEntity) && _draftOfWhichIAmOwner(req, draftWhere, columns)
|
|
860
949
|
|
|
861
|
-
const _draftInSubSelect = where => {
|
|
950
|
+
const _draftInSubSelect = (where, req) => {
|
|
862
951
|
return where.some(({ SELECT }) => {
|
|
863
952
|
if (SELECT && SELECT.where) {
|
|
864
953
|
const isActiveEntity = readAndDeleteKeywords(['IsActiveEntity'], SELECT.where, false)
|
|
865
954
|
if (isActiveEntity) {
|
|
866
|
-
|
|
955
|
+
const isFalse = _isFalse(isActiveEntity.value.val)
|
|
956
|
+
if (isFalse) SELECT.where = _getWhereWithAppendedDraftRestrictions(SELECT.where, req)
|
|
957
|
+
return isFalse
|
|
867
958
|
}
|
|
868
959
|
|
|
869
|
-
return _draftInSubSelect(SELECT.where)
|
|
960
|
+
return _draftInSubSelect(SELECT.where, req)
|
|
870
961
|
}
|
|
871
962
|
|
|
872
963
|
return false
|
|
873
964
|
})
|
|
874
965
|
}
|
|
875
966
|
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
967
|
+
const _isDraftAdminScenario = req =>
|
|
968
|
+
req.target.query && req.target.query._target && req.target.query._target.name === 'DRAFT.DraftAdministrativeData'
|
|
969
|
+
|
|
970
|
+
// eslint-disable-next-line complexity
|
|
971
|
+
const _generateCQN = (reqOriginal, req, columns, model) => {
|
|
972
|
+
const nav = [...reqOriginal.query.SELECT.from.ref].reverse() || []
|
|
973
|
+
const siblingIndex = nav.indexOf('SiblingEntity')
|
|
974
|
+
let siblingScenario
|
|
975
|
+
if (siblingIndex > -1) {
|
|
976
|
+
siblingScenario = _getSiblingScenario(req, columns, model, siblingIndex, nav)
|
|
977
|
+
if (siblingIndex === 0) {
|
|
978
|
+
return siblingScenario
|
|
979
|
+
} else {
|
|
980
|
+
_mergeSiblingIntoCQN(req.query, siblingScenario, siblingIndex - 1)
|
|
981
|
+
}
|
|
880
982
|
}
|
|
881
983
|
|
|
882
|
-
if (
|
|
883
|
-
req.target.query &&
|
|
884
|
-
req.target.query._target &&
|
|
885
|
-
req.target.query._target.name === 'DRAFT.DraftAdministrativeData'
|
|
886
|
-
) {
|
|
984
|
+
if (_isDraftAdminScenario(req)) {
|
|
887
985
|
return _draftAdminTable(req)
|
|
888
986
|
}
|
|
889
987
|
|
|
890
988
|
if (!req.query.SELECT.where || !_isFiltered(req.query.SELECT.where)) {
|
|
891
|
-
return _allActive(req, columns)
|
|
989
|
+
return _allActive(req, columns, model)
|
|
892
990
|
}
|
|
893
991
|
|
|
894
992
|
if (req.query.SELECT.where.length === 1 && req.query.SELECT.where[0].xpr) {
|
|
@@ -908,8 +1006,11 @@ const _generateCQN = (reqOriginal, req, columns, serviceName, model) => {
|
|
|
908
1006
|
}
|
|
909
1007
|
|
|
910
1008
|
if (!draftParameters.isActiveEntity) {
|
|
911
|
-
|
|
912
|
-
|
|
1009
|
+
// _draftInSubSelect adds draft restrictions in case check is truthy
|
|
1010
|
+
// -> not nice but works for now and we don't need to go in recursively again
|
|
1011
|
+
if (_draftInSubSelect(req.query.SELECT.where, req) || (siblingScenario && !siblingScenario.isSiblingActive)) {
|
|
1012
|
+
// this is only the case when navigating into tree
|
|
1013
|
+
return _allInactive(req, columns)
|
|
913
1014
|
}
|
|
914
1015
|
return _allActive(req, columns)
|
|
915
1016
|
}
|
|
@@ -936,52 +1037,39 @@ const _getColumns = ({ query: { SELECT } }, model) => {
|
|
|
936
1037
|
)
|
|
937
1038
|
: getColumns(model.definitions[ensureNoDraftsSuffix(SELECT.from.ref[0])], {
|
|
938
1039
|
onlyNames: true,
|
|
939
|
-
removeIgnore: true
|
|
940
|
-
filterVirtual: true
|
|
1040
|
+
removeIgnore: true
|
|
941
1041
|
})
|
|
942
1042
|
}
|
|
943
1043
|
|
|
944
|
-
const _isIsActiveEntity = element =>
|
|
945
|
-
element.ref &&
|
|
946
|
-
(element.ref[0] === 'IsActiveEntity' || (element.ref.length > 1 && element.ref[1] === 'IsActiveEntity'))
|
|
1044
|
+
const _isIsActiveEntity = element => element.ref && element.ref[element.ref.length - 1] === 'IsActiveEntity'
|
|
947
1045
|
|
|
948
1046
|
const _adaptSubSelects = ({ SELECT: { from, where } }, scenario) => {
|
|
949
|
-
if (!where)
|
|
950
|
-
return
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
let indexDel = -1
|
|
1047
|
+
if (!where) return
|
|
954
1048
|
|
|
955
1049
|
if (scenario === 'ALL_INACTIVE') {
|
|
956
1050
|
replaceRefWithDraft(from.ref)
|
|
957
1051
|
}
|
|
958
|
-
let _removeAnnotationWhere = false
|
|
959
1052
|
|
|
960
|
-
for (let i = 0
|
|
1053
|
+
for (let i = 0; i < where.length; i++) {
|
|
961
1054
|
const element = where[i]
|
|
962
1055
|
|
|
963
|
-
if (_isIsActiveEntity(element) &&
|
|
964
|
-
if (
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
} else if (scenario === 'DRAFT_ADMIN' && !_isFalse(where[i + 2].val)) {
|
|
1056
|
+
if (_isIsActiveEntity(element) && where.length > i + 2) {
|
|
1057
|
+
if (
|
|
1058
|
+
(scenario !== 'ALL_INACTIVE' && _isFalse(where[i + 2].val)) ||
|
|
1059
|
+
(scenario === SCENARIO.DRAFT_ADMIN && !_isFalse(where[i + 2].val))
|
|
1060
|
+
) {
|
|
969
1061
|
replaceRefWithDraft(from.ref)
|
|
970
|
-
_removeAnnotationWhere = true
|
|
971
1062
|
}
|
|
972
1063
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1064
|
+
if (!_isIsActiveEntity(where[i + 2])) {
|
|
1065
|
+
i = deleteCondition(i, where) - 1
|
|
1066
|
+
} else {
|
|
1067
|
+
i = i + 3 < where.length ? i + 2 : i + 3
|
|
1068
|
+
}
|
|
1069
|
+
} else if (element.SELECT) {
|
|
977
1070
|
_adaptSubSelects(element, scenario)
|
|
978
1071
|
}
|
|
979
1072
|
}
|
|
980
|
-
|
|
981
|
-
if (indexDel !== -1) {
|
|
982
|
-
deleteCondition(indexDel, where)
|
|
983
|
-
}
|
|
984
|
-
if (_removeAnnotationWhere) removeAnnotationWhere(where)
|
|
985
1073
|
}
|
|
986
1074
|
|
|
987
1075
|
const _calculateDraftAdminColumns = (result, user) => {
|
|
@@ -1006,16 +1094,6 @@ const _adaptDraftColumnsForSiblingEntity = (result, isSiblingActive) => {
|
|
|
1006
1094
|
result.HasActiveEntity = !isSiblingActive
|
|
1007
1095
|
}
|
|
1008
1096
|
|
|
1009
|
-
const _addAlias = (whereElement, aliases) => {
|
|
1010
|
-
if (whereElement.ref) {
|
|
1011
|
-
const table = whereElement.ref[0].replace(/\./g, '_')
|
|
1012
|
-
const alias = aliases.get(table)
|
|
1013
|
-
if (alias) {
|
|
1014
|
-
whereElement.ref.splice(0, 1, aliases.get(table))
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
1097
|
const _collectAliases = (from, aliases) => {
|
|
1020
1098
|
if (from) {
|
|
1021
1099
|
if (from.ref && from.as) {
|
|
@@ -1034,39 +1112,13 @@ const _collectAliases = (from, aliases) => {
|
|
|
1034
1112
|
}
|
|
1035
1113
|
}
|
|
1036
1114
|
|
|
1037
|
-
const _adaptAliasForSubSelect = (subselect, aliases) => {
|
|
1038
|
-
if (subselect.where) {
|
|
1039
|
-
for (const whereElement of subselect.where) {
|
|
1040
|
-
if (whereElement.ref) {
|
|
1041
|
-
_addAlias(whereElement, aliases)
|
|
1042
|
-
}
|
|
1043
|
-
|
|
1044
|
-
if (whereElement.SELECT) {
|
|
1045
|
-
_adaptAliasForSubSelect(whereElement.SELECT, aliases)
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
1115
|
const _adaptAnnotationAliases = cqn => {
|
|
1052
1116
|
const aliases = new Map()
|
|
1053
1117
|
_collectAliases(cqn.SELECT.from, aliases)
|
|
1054
|
-
|
|
1055
|
-
if (cqn.SELECT.where) {
|
|
1056
|
-
for (const whereElement of cqn.SELECT.where) {
|
|
1057
|
-
if (
|
|
1058
|
-
whereElement.SELECT &&
|
|
1059
|
-
whereElement.SELECT.from.ref &&
|
|
1060
|
-
whereElement.SELECT.from.ref[SYMBOL_FROM_ANNOTATION] === true
|
|
1061
|
-
) {
|
|
1062
|
-
_adaptAliasForSubSelect(whereElement.SELECT, aliases)
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
1118
|
}
|
|
1067
1119
|
|
|
1068
1120
|
const calculateDraftTimeout = (scenario, result, deleteLastChangeDateTime) => {
|
|
1069
|
-
if (scenario ===
|
|
1121
|
+
if (scenario === SCENARIO.DRAFT_ADMIN) {
|
|
1070
1122
|
if (!draftIsLocked(result[0].LastChangeDateTime)) {
|
|
1071
1123
|
result[0].InProcessByUser = ''
|
|
1072
1124
|
}
|
|
@@ -1090,12 +1142,12 @@ const calculateDraftTimeout = (scenario, result, deleteLastChangeDateTime) => {
|
|
|
1090
1142
|
}
|
|
1091
1143
|
|
|
1092
1144
|
const enhanceQueryForTimeoutIfNeeded = (scenario, columns = []) => {
|
|
1093
|
-
if (scenario !==
|
|
1145
|
+
if (scenario !== SCENARIO.DRAFT_ADMIN) {
|
|
1094
1146
|
const draftAdmin = columns.find(col => col.ref && col.ref[col.ref.length - 1] === 'DraftAdministrativeData')
|
|
1095
1147
|
columns = (draftAdmin && draftAdmin.expand) || []
|
|
1096
1148
|
}
|
|
1097
|
-
const inProcessByUser = columns.find(col => col.ref[col.ref.length - 1] === 'InProcessByUser')
|
|
1098
|
-
const lastChangeDateTime = columns.find(col => col.ref[col.ref.length - 1] === 'LastChangeDateTime')
|
|
1149
|
+
const inProcessByUser = columns.find(col => col.ref && col.ref[col.ref.length - 1] === 'InProcessByUser')
|
|
1150
|
+
const lastChangeDateTime = columns.find(col => col.ref && col.ref[col.ref.length - 1] === 'LastChangeDateTime')
|
|
1099
1151
|
if (inProcessByUser && !lastChangeDateTime) {
|
|
1100
1152
|
columns.push({ ref: [...inProcessByUser.ref.slice(0, inProcessByUser.ref.length - 1), 'LastChangeDateTime'] })
|
|
1101
1153
|
return true
|
|
@@ -1107,7 +1159,11 @@ const enhanceQueryForTimeoutIfNeeded = (scenario, columns = []) => {
|
|
|
1107
1159
|
const _getLocalizedEntity = (model, target, user) => {
|
|
1108
1160
|
const prefix = 'localized'
|
|
1109
1161
|
let localizedEntity
|
|
1110
|
-
|
|
1162
|
+
/*
|
|
1163
|
+
* REVISIT: in case of not sqlite, model.definitions[`${prefix}.${user.locale}.${target.name}`] is undefined
|
|
1164
|
+
* and the fallback lookup model.definitions[`${prefix}.${target.name}`] gets the entity -> bad coding
|
|
1165
|
+
*/
|
|
1166
|
+
if (cds.env.i18n.for_sqlite.includes(user.locale)) {
|
|
1111
1167
|
localizedEntity = model.definitions[`${prefix}.${user.locale}.${target.name}`]
|
|
1112
1168
|
}
|
|
1113
1169
|
return localizedEntity || model.definitions[`${prefix}.${target.name}`]
|
|
@@ -1118,12 +1174,10 @@ const _getLocalizedEntity = (model, target, user) => {
|
|
|
1118
1174
|
*
|
|
1119
1175
|
* @param req
|
|
1120
1176
|
*/
|
|
1177
|
+
// eslint-disable-next-line complexity
|
|
1121
1178
|
const _handler = async function (req) {
|
|
1122
1179
|
// handle localized here as it was previously handled for req.target
|
|
1123
1180
|
req.target = _getLocalizedEntity(this.model, req.target, req.user) || req.target
|
|
1124
|
-
if (req.query.SELECT.limit && req.query.SELECT.limit.rows && req.query.SELECT.limit.rows.val === 0) {
|
|
1125
|
-
return Promise.resolve([])
|
|
1126
|
-
}
|
|
1127
1181
|
|
|
1128
1182
|
// REVISIT
|
|
1129
1183
|
delete req.query._validationQuery
|
|
@@ -1134,18 +1188,22 @@ const _handler = async function (req) {
|
|
|
1134
1188
|
// do not clone with Object.assign as that would skip all non-enumerable properties
|
|
1135
1189
|
const reqClone = { __proto__: req, query: _copyCQNPartial(sqlQuery) }
|
|
1136
1190
|
|
|
1191
|
+
// ensure draft restrictions are copied to new query
|
|
1192
|
+
reqClone.query._draftRestrictions = req.query._draftRestrictions
|
|
1193
|
+
|
|
1137
1194
|
if (req.query._streaming) {
|
|
1138
1195
|
adaptStreamCQN(reqClone.query)
|
|
1139
1196
|
reqClone.query._streaming = true
|
|
1140
1197
|
return cds.tx(req).run(reqClone.query)
|
|
1141
1198
|
}
|
|
1142
|
-
|
|
1143
|
-
const cqnScenario = _generateCQN(req, reqClone, _getColumns(reqClone, this.model), this.
|
|
1199
|
+
|
|
1200
|
+
const cqnScenario = _generateCQN(req, reqClone, _getColumns(reqClone, this.model), this.model)
|
|
1144
1201
|
|
|
1145
1202
|
if (!cqnScenario) {
|
|
1146
1203
|
req.reject(400)
|
|
1147
1204
|
return
|
|
1148
1205
|
}
|
|
1206
|
+
|
|
1149
1207
|
const enhacnedWithLastChangeDateTime = enhanceQueryForTimeoutIfNeeded(
|
|
1150
1208
|
cqnScenario.scenario,
|
|
1151
1209
|
cqnScenario.cqn.SELECT.columns
|
|
@@ -1157,13 +1215,14 @@ const _handler = async function (req) {
|
|
|
1157
1215
|
|
|
1158
1216
|
// unlocalize for db and after handlers as it was before
|
|
1159
1217
|
req.target = this.model.definitions[ensureUnlocalized(req.target.name)]
|
|
1160
|
-
|
|
1218
|
+
|
|
1219
|
+
const result = await cds.tx(req).send({ query: cqnScenario.cqn, target: req.target })
|
|
1161
1220
|
|
|
1162
1221
|
const resultAsArray = Array.isArray(result) ? result : result ? [result] : []
|
|
1163
1222
|
|
|
1164
1223
|
removeDraftUUIDIfNecessary(resultAsArray, req)
|
|
1165
1224
|
|
|
1166
|
-
if (cqnScenario.scenario ===
|
|
1225
|
+
if (cqnScenario.scenario === SCENARIO.DRAFT_ADMIN) {
|
|
1167
1226
|
if (!result || (Array.isArray(result) && !result.length)) return result
|
|
1168
1227
|
|
|
1169
1228
|
_calculateDraftAdminColumns(resultAsArray[0], req.user.id)
|
|
@@ -1171,12 +1230,9 @@ const _handler = async function (req) {
|
|
|
1171
1230
|
|
|
1172
1231
|
calculateDraftTimeout(cqnScenario.scenario, resultAsArray, enhacnedWithLastChangeDateTime)
|
|
1173
1232
|
|
|
1174
|
-
if (cqnScenario.scenario ===
|
|
1233
|
+
if (cqnScenario.scenario === SCENARIO.SIBLING_ENTITY) {
|
|
1175
1234
|
if (!result || (Array.isArray(result) && !result.length)) return result
|
|
1176
|
-
|
|
1177
|
-
if (resultAsArray[0].draftAdmin_inProcessByUser !== req.user.id) {
|
|
1178
|
-
return []
|
|
1179
|
-
}
|
|
1235
|
+
if (resultAsArray[0].draftAdmin_inProcessByUser !== req.user.id) return []
|
|
1180
1236
|
|
|
1181
1237
|
delete resultAsArray[0].draftAdmin_inProcessByUser
|
|
1182
1238
|
_adaptDraftColumnsForSiblingEntity(resultAsArray[0], cqnScenario.isSiblingActive)
|
|
@@ -1187,7 +1243,7 @@ const _handler = async function (req) {
|
|
|
1187
1243
|
row.DraftAdministrativeData && _calculateDraftAdminColumns(row.DraftAdministrativeData, req.user.id)
|
|
1188
1244
|
})
|
|
1189
1245
|
}
|
|
1190
|
-
|
|
1246
|
+
|
|
1191
1247
|
return result
|
|
1192
1248
|
}
|
|
1193
1249
|
|