@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
|
@@ -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,21 +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
|
-
const { getElementDeep } = require('../../common/utils/csn')
|
|
25
24
|
|
|
26
|
-
//
|
|
27
|
-
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
|
+
}
|
|
28
49
|
|
|
29
50
|
const _isTrue = val => val === true || val === 'true'
|
|
30
51
|
|
|
@@ -114,7 +135,8 @@ const _getDraftPropertiesDetermineDraft = (req, where, tableName, calcDraftUUID
|
|
|
114
135
|
|
|
115
136
|
const hasDraftQuery = SELECT.from(tableName, [{ val: 1 }])
|
|
116
137
|
if (where && where.length > 0) {
|
|
117
|
-
|
|
138
|
+
// clone where to protect from later modification
|
|
139
|
+
hasDraftQuery.where([...where])
|
|
118
140
|
}
|
|
119
141
|
|
|
120
142
|
let draftUUIDColumn
|
|
@@ -159,13 +181,9 @@ function _copyCQNPartial(partial) {
|
|
|
159
181
|
}
|
|
160
182
|
|
|
161
183
|
function _copyArray(array) {
|
|
162
|
-
|
|
184
|
+
return array.map(entry => {
|
|
163
185
|
return typeof entry === 'object' && !(entry instanceof String) ? _copyCQNPartial(entry) : entry
|
|
164
186
|
})
|
|
165
|
-
if (array[SYMBOL_FROM_ANNOTATION] === true) {
|
|
166
|
-
copy[SYMBOL_FROM_ANNOTATION] = true
|
|
167
|
-
}
|
|
168
|
-
return copy
|
|
169
187
|
}
|
|
170
188
|
|
|
171
189
|
const _whereContainsKeys = (req, whereDraft) => {
|
|
@@ -277,12 +295,12 @@ const _draftAdminTable = req => {
|
|
|
277
295
|
}
|
|
278
296
|
|
|
279
297
|
return {
|
|
280
|
-
cqn: getEnrichedCQN(cqn, req.query.SELECT,
|
|
281
|
-
scenario:
|
|
298
|
+
cqn: getEnrichedCQN(cqn, req.query.SELECT, req.query.SELECT.where),
|
|
299
|
+
scenario: SCENARIO.DRAFT_ADMIN
|
|
282
300
|
}
|
|
283
301
|
}
|
|
284
302
|
|
|
285
|
-
const _allInactive = (req, columns
|
|
303
|
+
const _allInactive = (req, columns) => {
|
|
286
304
|
const table = {
|
|
287
305
|
ref: [ensureDraftsSuffix(req.query.SELECT.from.ref[0])],
|
|
288
306
|
as: req.query.SELECT.from.as || 'drafts'
|
|
@@ -293,17 +311,6 @@ const _allInactive = (req, columns, model) => {
|
|
|
293
311
|
_getDefaultDraftProperties({ hasDraft: false, isActive: false, withDraftUUID: false })
|
|
294
312
|
)
|
|
295
313
|
|
|
296
|
-
// determine name of primary key to use in HasActiveEntity expression
|
|
297
|
-
const pk = req.target['@assert.unique.locale']
|
|
298
|
-
? req.target['@assert.unique.locale'].map(o => o['=']).find(k => k !== 'locale')
|
|
299
|
-
: getKeyProperty(req.target.keys)
|
|
300
|
-
|
|
301
|
-
const xpr = {
|
|
302
|
-
xpr: ['case', 'when', `active.${pk}`, 'IS NOT NULL', 'then', 'true', 'else', 'false', 'end'],
|
|
303
|
-
as: 'HasActiveEntity',
|
|
304
|
-
cast: { type: 'cds.Boolean' }
|
|
305
|
-
}
|
|
306
|
-
|
|
307
314
|
const ids = filterKeys(req.target.keys)
|
|
308
315
|
const isCount = columns.some(element => element.func === 'count')
|
|
309
316
|
|
|
@@ -312,7 +319,7 @@ const _allInactive = (req, columns, model) => {
|
|
|
312
319
|
if (isCount) {
|
|
313
320
|
cqn.columns(...outerMostColumns)
|
|
314
321
|
} else {
|
|
315
|
-
cqn.columns(...outerMostColumns.filter(o => o.as !== 'HasActiveEntity'),
|
|
322
|
+
cqn.columns(...outerMostColumns.filter(o => o.as !== 'HasActiveEntity'), { ref: ['HasActiveEntity'] })
|
|
316
323
|
cqn.leftJoin(ensureNoDraftsSuffix(table.ref[0]) + ' as active').on(`${table.as}.${ids[0]} = active.${ids[0]}`)
|
|
317
324
|
|
|
318
325
|
for (let i = 1; i < ids.length; i++) {
|
|
@@ -322,9 +329,8 @@ const _allInactive = (req, columns, model) => {
|
|
|
322
329
|
}
|
|
323
330
|
|
|
324
331
|
cqn.where(req.query.SELECT.where)
|
|
325
|
-
removeAnnotationWhere(cqn.SELECT.where)
|
|
326
332
|
|
|
327
|
-
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, []), scenario:
|
|
333
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, []), scenario: SCENARIO.ALL_INACTIVE }
|
|
328
334
|
}
|
|
329
335
|
|
|
330
336
|
const _setRefAlias = (ref, as) => {
|
|
@@ -362,7 +368,7 @@ const _buildOrderBy = (query, columns, table) => {
|
|
|
362
368
|
}
|
|
363
369
|
}
|
|
364
370
|
|
|
365
|
-
const _allActive = (req, columns) => {
|
|
371
|
+
const _allActive = (req, columns, model) => {
|
|
366
372
|
const { table } = _getTableName(req)
|
|
367
373
|
if (!table.as) {
|
|
368
374
|
table.as = 'active'
|
|
@@ -406,12 +412,20 @@ const _allActive = (req, columns) => {
|
|
|
406
412
|
}
|
|
407
413
|
}
|
|
408
414
|
|
|
415
|
+
const scenarioAlias = 'active'
|
|
416
|
+
|
|
417
|
+
req.query.SELECT.where = _getWhereWithAppendedDraftRestrictions(req.query.SELECT.where, req, scenarioAlias, model)
|
|
418
|
+
|
|
409
419
|
if (req.query.SELECT.where) {
|
|
410
420
|
_buildWhere(req.query.SELECT.where, table)
|
|
411
421
|
}
|
|
422
|
+
|
|
412
423
|
_buildOrderBy(req.query, cqn.SELECT.columns, table)
|
|
413
424
|
|
|
414
|
-
return {
|
|
425
|
+
return {
|
|
426
|
+
cqn: getEnrichedCQN(cqn, req.query.SELECT, req.query.SELECT.where, scenarioAlias),
|
|
427
|
+
scenario: SCENARIO.ALL_ACTIVE
|
|
428
|
+
}
|
|
415
429
|
}
|
|
416
430
|
|
|
417
431
|
const _active = (req, draftWhere, columns) => {
|
|
@@ -421,7 +435,9 @@ const _active = (req, draftWhere, columns) => {
|
|
|
421
435
|
|
|
422
436
|
const cqn = SELECT.from(table).columns(...outerMostColumns)
|
|
423
437
|
|
|
424
|
-
|
|
438
|
+
draftWhere = _getWhereWithAppendedDraftRestrictions(draftWhere, req)
|
|
439
|
+
|
|
440
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.ACTIVE }
|
|
425
441
|
}
|
|
426
442
|
|
|
427
443
|
const _activeWithoutDraft = (req, draftWhere, columns) => {
|
|
@@ -449,7 +465,9 @@ const _activeWithoutDraft = (req, draftWhere, columns) => {
|
|
|
449
465
|
.columns(...outerMostColumns)
|
|
450
466
|
.where(['not exists', subSelect])
|
|
451
467
|
|
|
452
|
-
|
|
468
|
+
draftWhere = _getWhereWithAppendedDraftRestrictions(draftWhere, req)
|
|
469
|
+
|
|
470
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.ACTIVE_WITHOUT_DRAFT }
|
|
453
471
|
}
|
|
454
472
|
|
|
455
473
|
const _draftOfWhichIAmOwner = (req, draftWhere, columns) => {
|
|
@@ -469,9 +487,7 @@ const _draftOfWhichIAmOwner = (req, draftWhere, columns) => {
|
|
|
469
487
|
])
|
|
470
488
|
.where(_inProcessByUserWhere(req.user.id))
|
|
471
489
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
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 }
|
|
475
491
|
}
|
|
476
492
|
|
|
477
493
|
const _activeWithDraftInProcess = (req, draftWhere, columns, isLocked) => {
|
|
@@ -504,7 +520,7 @@ const _activeWithDraftInProcess = (req, draftWhere, columns, isLocked) => {
|
|
|
504
520
|
'and',
|
|
505
521
|
{
|
|
506
522
|
func: 'seconds_between',
|
|
507
|
-
args: [{ ref: ['filterAdmin', 'LastChangeDateTime'] },
|
|
523
|
+
args: [{ ref: ['filterAdmin', 'LastChangeDateTime'] }, 'CURRENT_TIMESTAMP']
|
|
508
524
|
},
|
|
509
525
|
isLocked ? '<' : '>',
|
|
510
526
|
{ val: DRAFT_CANCEL_TIMEOUT_IN_SEC }
|
|
@@ -515,11 +531,13 @@ const _activeWithDraftInProcess = (req, draftWhere, columns, isLocked) => {
|
|
|
515
531
|
subSelect
|
|
516
532
|
)
|
|
517
533
|
|
|
534
|
+
subSelect.SELECT.where = _getWhereWithAppendedDraftRestrictions(subSelect.SELECT.where, req)
|
|
535
|
+
|
|
518
536
|
const outerMostColumns = _getOuterMostColumns(columns, draftColumns)
|
|
519
537
|
|
|
520
538
|
const cqn = SELECT.from(active.table).columns(outerMostColumns).where(['exists', subSelect])
|
|
521
539
|
|
|
522
|
-
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario:
|
|
540
|
+
return { cqn: getEnrichedCQN(cqn, req.query.SELECT, draftWhere), scenario: SCENARIO.DRAFT_IN_PROCESS }
|
|
523
541
|
}
|
|
524
542
|
|
|
525
543
|
const _alignAliasForUnion = (table, as, select) => {
|
|
@@ -536,37 +554,27 @@ const _alignAliasForUnion = (table, as, select) => {
|
|
|
536
554
|
return select
|
|
537
555
|
}
|
|
538
556
|
|
|
539
|
-
const
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
return _findKeysInQuery(query.SELECT.where[indexExists + 1], keys)
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
_findKeysInWhereAndAddToResult(query.SELECT.where, keys, result)
|
|
561
|
-
}
|
|
562
|
-
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 []
|
|
563
575
|
}
|
|
564
576
|
|
|
565
|
-
const _isFiltered = where =>
|
|
566
|
-
return where.some(element => {
|
|
567
|
-
return !(element in ['(', ')']) && element[SYMBOL_FROM_ANNOTATION] !== true
|
|
568
|
-
})
|
|
569
|
-
}
|
|
577
|
+
const _isFiltered = where => where.some(element => !(element in ['(', ')']))
|
|
570
578
|
|
|
571
579
|
const _isDraftField = element => element.ref && element.ref.length > 1 && element.ref[0] === 'DraftAdministrativeData'
|
|
572
580
|
|
|
@@ -614,40 +622,112 @@ const _getWhereForActive = where => {
|
|
|
614
622
|
return activeWhere
|
|
615
623
|
}
|
|
616
624
|
|
|
617
|
-
const _siblingEntity = (
|
|
618
|
-
const
|
|
619
|
-
const keys =
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
const
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
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
|
+
}
|
|
629
648
|
|
|
630
|
-
if (
|
|
649
|
+
if (isSiblingDraft) {
|
|
631
650
|
cqn
|
|
632
|
-
.join(
|
|
633
|
-
.on(
|
|
634
|
-
Object.keys(keys)
|
|
635
|
-
.map(k => `target.${k} = target_draft.${k}`)
|
|
636
|
-
.join(' AND ')
|
|
637
|
-
)
|
|
651
|
+
.join(ensureNoDraftsSuffix(target.name), siblingAlias)
|
|
652
|
+
.on(onCond)
|
|
638
653
|
.join('DRAFT.DraftAdministrativeData', 'draftAdmin')
|
|
639
|
-
.on(
|
|
654
|
+
.on(`${table.as}.DraftAdministrativeData_DraftUUID = draftAdmin.DraftUUID`)
|
|
640
655
|
} else {
|
|
641
656
|
cqn
|
|
657
|
+
.join(ensureDraftsSuffix(target.name), siblingAlias)
|
|
658
|
+
.on(onCond)
|
|
642
659
|
.join('DRAFT.DraftAdministrativeData', 'draftAdmin')
|
|
643
|
-
.on(
|
|
660
|
+
.on(`${siblingAlias}.DraftAdministrativeData_DraftUUID = draftAdmin.DraftUUID`)
|
|
644
661
|
}
|
|
645
662
|
|
|
646
663
|
for (const key in keys) {
|
|
647
|
-
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])
|
|
648
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
|
+
}
|
|
649
678
|
|
|
650
|
-
|
|
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)
|
|
716
|
+
}
|
|
717
|
+
return _getSiblingQueryFromWhere(req.query, siblingIndex)
|
|
718
|
+
}
|
|
719
|
+
|
|
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)
|
|
651
731
|
}
|
|
652
732
|
|
|
653
733
|
const _getDraftDoc = (req, draftName, draftWhere) => {
|
|
@@ -706,7 +786,7 @@ const _getUnionCQN = (req, draftName, columns, subSelect, draftWhere) => {
|
|
|
706
786
|
const activeDocs = getEnrichedCQN(SELECT.from(req.target), req.query.SELECT, draftActiveWhere, undefined, false)
|
|
707
787
|
|
|
708
788
|
_replaceDraftAlias(draftWhere)
|
|
709
|
-
const draftDocs = _getDraftDoc(req, draftName,
|
|
789
|
+
const draftDocs = _getDraftDoc(req, draftName, draftWhere)
|
|
710
790
|
|
|
711
791
|
const union = SELECT.from({ SET: { op: 'union', all: true, args: [draftDocs, activeDocs] } })
|
|
712
792
|
if (req.query.SELECT.count) union.SELECT.count = true
|
|
@@ -809,6 +889,8 @@ const _excludeActiveDraftExists = (req, draftWhere, columns) => {
|
|
|
809
889
|
subSelect.where([{ ref: [ensureNoDraftsSuffix(req.target.name), key] }, '=', { ref: [draftName, key] }])
|
|
810
890
|
}
|
|
811
891
|
|
|
892
|
+
draftWhere = _getWhereWithAppendedDraftRestrictions(draftWhere, req)
|
|
893
|
+
|
|
812
894
|
draftWhere = removeIsActiveEntityRecursively(draftWhere)
|
|
813
895
|
const cqn = _getUnionCQN(req, draftName, columns, subSelect, draftWhere)
|
|
814
896
|
cqn.SELECT.from.as = name
|
|
@@ -821,7 +903,7 @@ const _excludeActiveDraftExists = (req, draftWhere, columns) => {
|
|
|
821
903
|
}
|
|
822
904
|
}
|
|
823
905
|
|
|
824
|
-
return { cqn: cqn, scenario:
|
|
906
|
+
return { cqn: cqn, scenario: SCENARIO.UNION }
|
|
825
907
|
}
|
|
826
908
|
|
|
827
909
|
const _readDraftParameters = where => {
|
|
@@ -865,37 +947,46 @@ const _validatedActive = (req, draftWhere, draftParameters, columns) =>
|
|
|
865
947
|
const _validatedDraftOfWhichIAmOwner = (req, draftWhere, draftParameters, columns) =>
|
|
866
948
|
_isValidDraftOfWhichIAmOwner(draftParameters.isActiveEntity) && _draftOfWhichIAmOwner(req, draftWhere, columns)
|
|
867
949
|
|
|
868
|
-
const _draftInSubSelect = where => {
|
|
950
|
+
const _draftInSubSelect = (where, req) => {
|
|
869
951
|
return where.some(({ SELECT }) => {
|
|
870
952
|
if (SELECT && SELECT.where) {
|
|
871
953
|
const isActiveEntity = readAndDeleteKeywords(['IsActiveEntity'], SELECT.where, false)
|
|
872
954
|
if (isActiveEntity) {
|
|
873
|
-
|
|
955
|
+
const isFalse = _isFalse(isActiveEntity.value.val)
|
|
956
|
+
if (isFalse) SELECT.where = _getWhereWithAppendedDraftRestrictions(SELECT.where, req)
|
|
957
|
+
return isFalse
|
|
874
958
|
}
|
|
875
959
|
|
|
876
|
-
return _draftInSubSelect(SELECT.where)
|
|
960
|
+
return _draftInSubSelect(SELECT.where, req)
|
|
877
961
|
}
|
|
878
962
|
|
|
879
963
|
return false
|
|
880
964
|
})
|
|
881
965
|
}
|
|
882
966
|
|
|
883
|
-
const
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
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
|
+
}
|
|
887
982
|
}
|
|
888
983
|
|
|
889
|
-
if (
|
|
890
|
-
req.target.query &&
|
|
891
|
-
req.target.query._target &&
|
|
892
|
-
req.target.query._target.name === 'DRAFT.DraftAdministrativeData'
|
|
893
|
-
) {
|
|
984
|
+
if (_isDraftAdminScenario(req)) {
|
|
894
985
|
return _draftAdminTable(req)
|
|
895
986
|
}
|
|
896
987
|
|
|
897
988
|
if (!req.query.SELECT.where || !_isFiltered(req.query.SELECT.where)) {
|
|
898
|
-
return _allActive(req, columns)
|
|
989
|
+
return _allActive(req, columns, model)
|
|
899
990
|
}
|
|
900
991
|
|
|
901
992
|
if (req.query.SELECT.where.length === 1 && req.query.SELECT.where[0].xpr) {
|
|
@@ -915,8 +1006,11 @@ const _generateCQN = (reqOriginal, req, columns, serviceName, model) => {
|
|
|
915
1006
|
}
|
|
916
1007
|
|
|
917
1008
|
if (!draftParameters.isActiveEntity) {
|
|
918
|
-
|
|
919
|
-
|
|
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)
|
|
920
1014
|
}
|
|
921
1015
|
return _allActive(req, columns)
|
|
922
1016
|
}
|
|
@@ -943,52 +1037,39 @@ const _getColumns = ({ query: { SELECT } }, model) => {
|
|
|
943
1037
|
)
|
|
944
1038
|
: getColumns(model.definitions[ensureNoDraftsSuffix(SELECT.from.ref[0])], {
|
|
945
1039
|
onlyNames: true,
|
|
946
|
-
removeIgnore: true
|
|
947
|
-
filterVirtual: true
|
|
1040
|
+
removeIgnore: true
|
|
948
1041
|
})
|
|
949
1042
|
}
|
|
950
1043
|
|
|
951
|
-
const _isIsActiveEntity = element =>
|
|
952
|
-
element.ref &&
|
|
953
|
-
(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'
|
|
954
1045
|
|
|
955
1046
|
const _adaptSubSelects = ({ SELECT: { from, where } }, scenario) => {
|
|
956
|
-
if (!where)
|
|
957
|
-
return
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
let indexDel = -1
|
|
1047
|
+
if (!where) return
|
|
961
1048
|
|
|
962
1049
|
if (scenario === 'ALL_INACTIVE') {
|
|
963
1050
|
replaceRefWithDraft(from.ref)
|
|
964
1051
|
}
|
|
965
|
-
let _removeAnnotationWhere = false
|
|
966
1052
|
|
|
967
|
-
for (let i = 0
|
|
1053
|
+
for (let i = 0; i < where.length; i++) {
|
|
968
1054
|
const element = where[i]
|
|
969
1055
|
|
|
970
|
-
if (_isIsActiveEntity(element) &&
|
|
971
|
-
if (
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
} 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
|
+
) {
|
|
976
1061
|
replaceRefWithDraft(from.ref)
|
|
977
|
-
_removeAnnotationWhere = true
|
|
978
1062
|
}
|
|
979
1063
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
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) {
|
|
984
1070
|
_adaptSubSelects(element, scenario)
|
|
985
1071
|
}
|
|
986
1072
|
}
|
|
987
|
-
|
|
988
|
-
if (indexDel !== -1) {
|
|
989
|
-
deleteCondition(indexDel, where)
|
|
990
|
-
}
|
|
991
|
-
if (_removeAnnotationWhere) removeAnnotationWhere(where)
|
|
992
1073
|
}
|
|
993
1074
|
|
|
994
1075
|
const _calculateDraftAdminColumns = (result, user) => {
|
|
@@ -1013,16 +1094,6 @@ const _adaptDraftColumnsForSiblingEntity = (result, isSiblingActive) => {
|
|
|
1013
1094
|
result.HasActiveEntity = !isSiblingActive
|
|
1014
1095
|
}
|
|
1015
1096
|
|
|
1016
|
-
const _addAlias = (whereElement, aliases) => {
|
|
1017
|
-
if (whereElement.ref) {
|
|
1018
|
-
const table = whereElement.ref[0].replace(/\./g, '_')
|
|
1019
|
-
const alias = aliases.get(table)
|
|
1020
|
-
if (alias) {
|
|
1021
|
-
whereElement.ref.splice(0, 1, aliases.get(table))
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
1097
|
const _collectAliases = (from, aliases) => {
|
|
1027
1098
|
if (from) {
|
|
1028
1099
|
if (from.ref && from.as) {
|
|
@@ -1041,39 +1112,13 @@ const _collectAliases = (from, aliases) => {
|
|
|
1041
1112
|
}
|
|
1042
1113
|
}
|
|
1043
1114
|
|
|
1044
|
-
const _adaptAliasForSubSelect = (subselect, aliases) => {
|
|
1045
|
-
if (subselect.where) {
|
|
1046
|
-
for (const whereElement of subselect.where) {
|
|
1047
|
-
if (whereElement.ref) {
|
|
1048
|
-
_addAlias(whereElement, aliases)
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
if (whereElement.SELECT) {
|
|
1052
|
-
_adaptAliasForSubSelect(whereElement.SELECT, aliases)
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
1115
|
const _adaptAnnotationAliases = cqn => {
|
|
1059
1116
|
const aliases = new Map()
|
|
1060
1117
|
_collectAliases(cqn.SELECT.from, aliases)
|
|
1061
|
-
|
|
1062
|
-
if (cqn.SELECT.where) {
|
|
1063
|
-
for (const whereElement of cqn.SELECT.where) {
|
|
1064
|
-
if (
|
|
1065
|
-
whereElement.SELECT &&
|
|
1066
|
-
whereElement.SELECT.from.ref &&
|
|
1067
|
-
whereElement.SELECT.from.ref[SYMBOL_FROM_ANNOTATION] === true
|
|
1068
|
-
) {
|
|
1069
|
-
_adaptAliasForSubSelect(whereElement.SELECT, aliases)
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
1118
|
}
|
|
1074
1119
|
|
|
1075
1120
|
const calculateDraftTimeout = (scenario, result, deleteLastChangeDateTime) => {
|
|
1076
|
-
if (scenario ===
|
|
1121
|
+
if (scenario === SCENARIO.DRAFT_ADMIN) {
|
|
1077
1122
|
if (!draftIsLocked(result[0].LastChangeDateTime)) {
|
|
1078
1123
|
result[0].InProcessByUser = ''
|
|
1079
1124
|
}
|
|
@@ -1097,12 +1142,12 @@ const calculateDraftTimeout = (scenario, result, deleteLastChangeDateTime) => {
|
|
|
1097
1142
|
}
|
|
1098
1143
|
|
|
1099
1144
|
const enhanceQueryForTimeoutIfNeeded = (scenario, columns = []) => {
|
|
1100
|
-
if (scenario !==
|
|
1145
|
+
if (scenario !== SCENARIO.DRAFT_ADMIN) {
|
|
1101
1146
|
const draftAdmin = columns.find(col => col.ref && col.ref[col.ref.length - 1] === 'DraftAdministrativeData')
|
|
1102
1147
|
columns = (draftAdmin && draftAdmin.expand) || []
|
|
1103
1148
|
}
|
|
1104
|
-
const inProcessByUser = columns.find(col => col.ref[col.ref.length - 1] === 'InProcessByUser')
|
|
1105
|
-
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')
|
|
1106
1151
|
if (inProcessByUser && !lastChangeDateTime) {
|
|
1107
1152
|
columns.push({ ref: [...inProcessByUser.ref.slice(0, inProcessByUser.ref.length - 1), 'LastChangeDateTime'] })
|
|
1108
1153
|
return true
|
|
@@ -1114,7 +1159,11 @@ const enhanceQueryForTimeoutIfNeeded = (scenario, columns = []) => {
|
|
|
1114
1159
|
const _getLocalizedEntity = (model, target, user) => {
|
|
1115
1160
|
const prefix = 'localized'
|
|
1116
1161
|
let localizedEntity
|
|
1117
|
-
|
|
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)) {
|
|
1118
1167
|
localizedEntity = model.definitions[`${prefix}.${user.locale}.${target.name}`]
|
|
1119
1168
|
}
|
|
1120
1169
|
return localizedEntity || model.definitions[`${prefix}.${target.name}`]
|
|
@@ -1125,6 +1174,7 @@ const _getLocalizedEntity = (model, target, user) => {
|
|
|
1125
1174
|
*
|
|
1126
1175
|
* @param req
|
|
1127
1176
|
*/
|
|
1177
|
+
// eslint-disable-next-line complexity
|
|
1128
1178
|
const _handler = async function (req) {
|
|
1129
1179
|
// handle localized here as it was previously handled for req.target
|
|
1130
1180
|
req.target = _getLocalizedEntity(this.model, req.target, req.user) || req.target
|
|
@@ -1138,18 +1188,22 @@ const _handler = async function (req) {
|
|
|
1138
1188
|
// do not clone with Object.assign as that would skip all non-enumerable properties
|
|
1139
1189
|
const reqClone = { __proto__: req, query: _copyCQNPartial(sqlQuery) }
|
|
1140
1190
|
|
|
1191
|
+
// ensure draft restrictions are copied to new query
|
|
1192
|
+
reqClone.query._draftRestrictions = req.query._draftRestrictions
|
|
1193
|
+
|
|
1141
1194
|
if (req.query._streaming) {
|
|
1142
1195
|
adaptStreamCQN(reqClone.query)
|
|
1143
1196
|
reqClone.query._streaming = true
|
|
1144
1197
|
return cds.tx(req).run(reqClone.query)
|
|
1145
1198
|
}
|
|
1146
|
-
|
|
1147
|
-
const cqnScenario = _generateCQN(req, reqClone, _getColumns(reqClone, this.model), this.
|
|
1199
|
+
|
|
1200
|
+
const cqnScenario = _generateCQN(req, reqClone, _getColumns(reqClone, this.model), this.model)
|
|
1148
1201
|
|
|
1149
1202
|
if (!cqnScenario) {
|
|
1150
1203
|
req.reject(400)
|
|
1151
1204
|
return
|
|
1152
1205
|
}
|
|
1206
|
+
|
|
1153
1207
|
const enhacnedWithLastChangeDateTime = enhanceQueryForTimeoutIfNeeded(
|
|
1154
1208
|
cqnScenario.scenario,
|
|
1155
1209
|
cqnScenario.cqn.SELECT.columns
|
|
@@ -1161,13 +1215,14 @@ const _handler = async function (req) {
|
|
|
1161
1215
|
|
|
1162
1216
|
// unlocalize for db and after handlers as it was before
|
|
1163
1217
|
req.target = this.model.definitions[ensureUnlocalized(req.target.name)]
|
|
1164
|
-
|
|
1218
|
+
|
|
1219
|
+
const result = await cds.tx(req).send({ query: cqnScenario.cqn, target: req.target })
|
|
1165
1220
|
|
|
1166
1221
|
const resultAsArray = Array.isArray(result) ? result : result ? [result] : []
|
|
1167
1222
|
|
|
1168
1223
|
removeDraftUUIDIfNecessary(resultAsArray, req)
|
|
1169
1224
|
|
|
1170
|
-
if (cqnScenario.scenario ===
|
|
1225
|
+
if (cqnScenario.scenario === SCENARIO.DRAFT_ADMIN) {
|
|
1171
1226
|
if (!result || (Array.isArray(result) && !result.length)) return result
|
|
1172
1227
|
|
|
1173
1228
|
_calculateDraftAdminColumns(resultAsArray[0], req.user.id)
|
|
@@ -1175,12 +1230,9 @@ const _handler = async function (req) {
|
|
|
1175
1230
|
|
|
1176
1231
|
calculateDraftTimeout(cqnScenario.scenario, resultAsArray, enhacnedWithLastChangeDateTime)
|
|
1177
1232
|
|
|
1178
|
-
if (cqnScenario.scenario ===
|
|
1233
|
+
if (cqnScenario.scenario === SCENARIO.SIBLING_ENTITY) {
|
|
1179
1234
|
if (!result || (Array.isArray(result) && !result.length)) return result
|
|
1180
|
-
|
|
1181
|
-
if (resultAsArray[0].draftAdmin_inProcessByUser !== req.user.id) {
|
|
1182
|
-
return []
|
|
1183
|
-
}
|
|
1235
|
+
if (resultAsArray[0].draftAdmin_inProcessByUser !== req.user.id) return []
|
|
1184
1236
|
|
|
1185
1237
|
delete resultAsArray[0].draftAdmin_inProcessByUser
|
|
1186
1238
|
_adaptDraftColumnsForSiblingEntity(resultAsArray[0], cqnScenario.isSiblingActive)
|
|
@@ -1191,7 +1243,7 @@ const _handler = async function (req) {
|
|
|
1191
1243
|
row.DraftAdministrativeData && _calculateDraftAdminColumns(row.DraftAdministrativeData, req.user.id)
|
|
1192
1244
|
})
|
|
1193
1245
|
}
|
|
1194
|
-
|
|
1246
|
+
|
|
1195
1247
|
return result
|
|
1196
1248
|
}
|
|
1197
1249
|
|