@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,9 +1,7 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
|
|
3
|
-
const getColumns = require('../utils/columns')
|
|
4
3
|
const { getAllKeys } = require('../../cds-services/adapter/odata-v4/odata-to-cqn/utils')
|
|
5
4
|
const { getOnCond } = require('../../common/utils/generateOnCond')
|
|
6
|
-
const sqliteLocales = ['de', 'fr']
|
|
7
5
|
|
|
8
6
|
const { getNavigationIfStruct } = require('../../common/utils/structured')
|
|
9
7
|
const { ensureNoDraftsSuffix, ensureDraftsSuffix, ensureUnlocalized } = require('../../common/utils/draft')
|
|
@@ -12,6 +10,7 @@ const { filterKeys } = require('../../fiori/utils/handler')
|
|
|
12
10
|
// Symbols are used to add extra information in response structure
|
|
13
11
|
const GET_KEY_VALUE = Symbol.for('sap.cds.getKeyValue')
|
|
14
12
|
const TO_MANY = Symbol.for('sap.cds.toMany')
|
|
13
|
+
const TO_ACTIVE = Symbol.for('sap.cds.toActive')
|
|
15
14
|
|
|
16
15
|
const SKIP_MAPPING = Symbol.for('sap.cds.skipMapping')
|
|
17
16
|
const IDENTIFIER = Symbol.for('sap.cds.identifier')
|
|
@@ -19,15 +18,14 @@ const IS_ACTIVE = Symbol.for('sap.cds.isActive')
|
|
|
19
18
|
const IS_UNION_DRAFT = Symbol.for('sap.cds.isUnionDraft')
|
|
20
19
|
const { DRAFT_COLUMNS } = require('../../common/constants/draft')
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
const SYMBOL_FROM_ANNOTATION = Symbol.for('sap.cds.FROM_ANNOTATION')
|
|
21
|
+
const { getCQNUnionFrom } = require('../../common/utils/union')
|
|
24
22
|
|
|
25
23
|
class JoinCQNFromExpanded {
|
|
26
|
-
constructor(cqn, csn,
|
|
27
|
-
this._useWindow = useWindow
|
|
24
|
+
constructor(cqn, csn, locale) {
|
|
28
25
|
this._SELECT = Object.assign({}, cqn.SELECT)
|
|
29
26
|
this._csn = csn
|
|
30
|
-
|
|
27
|
+
// REVISIT: locale is only passed in case of sqlite -> bad coding
|
|
28
|
+
if (cds.env.i18n.for_sqlite.includes(locale)) {
|
|
31
29
|
this._locale = locale
|
|
32
30
|
}
|
|
33
31
|
this.queries = []
|
|
@@ -93,24 +91,42 @@ class JoinCQNFromExpanded {
|
|
|
93
91
|
* @private
|
|
94
92
|
*/
|
|
95
93
|
_createJoinCQNFromExpanded(SELECT, toManyTree, defaultLanguage) {
|
|
94
|
+
const unionArgs = SELECT.from.args
|
|
95
|
+
const isJoinOfTwoUnions = unionArgs && unionArgs.every(a => a.SELECT)
|
|
96
|
+
|
|
96
97
|
const unionTableRef = this._getUnionTable(SELECT)
|
|
97
98
|
const unionTable = unionTableRef && unionTableRef.table
|
|
98
99
|
const tableAlias = this._getTableAlias(SELECT, toManyTree, unionTable)
|
|
99
|
-
const readToOneCQN = this._getReadToOneCQN(SELECT, tableAlias)
|
|
100
|
-
const table = unionTable || this._getRef(SELECT).table
|
|
101
|
-
const isDraftTree = this._isDraftTree(table)
|
|
102
|
-
const entity = this._getEntityForTable(table)
|
|
103
100
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
const readToOneCQN = this._getReadToOneCQN(SELECT, isJoinOfTwoUnions ? 'filterExpand' : tableAlias)
|
|
102
|
+
|
|
103
|
+
if (isJoinOfTwoUnions) {
|
|
104
|
+
// mappings
|
|
105
|
+
const mappings = this._getMappingObject(toManyTree)
|
|
106
|
+
const prefix = `${tableAlias}_`
|
|
107
|
+
SELECT.columns
|
|
108
|
+
.filter(c => c.as && c.as.startsWith(prefix) && c[SKIP_MAPPING] !== true)
|
|
109
|
+
.forEach(c => {
|
|
110
|
+
mappings[c.as.replace(prefix, '')] = c.as
|
|
111
|
+
})
|
|
112
|
+
// expand to one
|
|
113
|
+
const entity = this._csn.definitions[unionArgs[0].SELECT.from.SET.args[1].SELECT.from.ref[0]]
|
|
114
|
+
const givenColumns = readToOneCQN.columns
|
|
115
|
+
readToOneCQN.columns = []
|
|
116
|
+
this._expandedToFlat({ entity, givenColumns, readToOneCQN, tableAlias, toManyTree, defaultLanguage })
|
|
117
|
+
} else {
|
|
118
|
+
const table = unionTable || this._getRef(SELECT).table
|
|
119
|
+
const isDraftTree = this._isDraftTree(table)
|
|
120
|
+
const entity = this._getEntityForTable(table)
|
|
107
121
|
|
|
108
|
-
|
|
122
|
+
if (unionTable) readToOneCQN[IS_UNION_DRAFT] = true
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
readToOneCQN.columns = []
|
|
124
|
+
readToOneCQN[IS_ACTIVE] = isDraftTree ? this._isDraftTargetActive(table) : true
|
|
112
125
|
|
|
113
|
-
|
|
126
|
+
const givenColumns = readToOneCQN.columns
|
|
127
|
+
readToOneCQN.columns = []
|
|
128
|
+
this._expandedToFlat({ entity, givenColumns, readToOneCQN, tableAlias, toManyTree, defaultLanguage })
|
|
129
|
+
}
|
|
114
130
|
|
|
115
131
|
// Add at start, so that the deepest level is post processed first
|
|
116
132
|
this.queries.push({
|
|
@@ -207,7 +223,7 @@ class JoinCQNFromExpanded {
|
|
|
207
223
|
const cqn = Object.assign({}, SELECT, { from: Object.assign({}, SELECT.from) })
|
|
208
224
|
|
|
209
225
|
if (Object.prototype.hasOwnProperty.call(cqn.from, 'join')) {
|
|
210
|
-
this._adaptJoin(tableAlias, cqn)
|
|
226
|
+
this._adaptJoin(tableAlias, cqn, cqn.from)
|
|
211
227
|
} else {
|
|
212
228
|
if (cqn.from.SET) {
|
|
213
229
|
cqn.from.SET = Object.assign({}, cqn.from.SET, { args: this._adaptUnionArgs(cqn.from.SET.args) })
|
|
@@ -225,16 +241,19 @@ class JoinCQNFromExpanded {
|
|
|
225
241
|
: column
|
|
226
242
|
}
|
|
227
243
|
|
|
228
|
-
_adaptJoin(tableAlias, cqn) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
244
|
+
_adaptJoin(tableAlias, cqn, from) {
|
|
245
|
+
from.args = from.args.slice(0)
|
|
246
|
+
if (Object.prototype.hasOwnProperty.call(from.args[0], 'join')) {
|
|
247
|
+
this._adaptJoin(tableAlias, cqn, from.args[0])
|
|
248
|
+
} else {
|
|
249
|
+
const index = from.args[0].ref ? 0 : from.args.length - 1
|
|
250
|
+
const target = Object.assign({}, from.args[index], { as: tableAlias })
|
|
251
|
+
const originalIdentifier = from.args[index].as || from.args[index].ref[0]
|
|
234
252
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
253
|
+
from.args[index] = target
|
|
254
|
+
from.on = from.on.map(column => this._adaptTableNameInColumn(column, originalIdentifier, tableAlias))
|
|
255
|
+
cqn.columns = cqn.columns.map(column => this._adaptTableNameInColumn(column, originalIdentifier, tableAlias))
|
|
256
|
+
}
|
|
238
257
|
}
|
|
239
258
|
|
|
240
259
|
_adaptUnionArgs(args) {
|
|
@@ -293,11 +312,6 @@ class JoinCQNFromExpanded {
|
|
|
293
312
|
return cqn
|
|
294
313
|
}
|
|
295
314
|
|
|
296
|
-
_addAliasAndDeleteSymbol(whereElement) {
|
|
297
|
-
this._addAlias(whereElement)
|
|
298
|
-
delete whereElement.ref[SYMBOL_FROM_ANNOTATION]
|
|
299
|
-
}
|
|
300
|
-
|
|
301
315
|
_addAlias(whereElement) {
|
|
302
316
|
whereElement.ref && whereElement.ref.splice(0, 1, Object.values(this._aliases)[0])
|
|
303
317
|
}
|
|
@@ -318,10 +332,6 @@ class JoinCQNFromExpanded {
|
|
|
318
332
|
_adaptAliasForWhere(where) {
|
|
319
333
|
if (where) {
|
|
320
334
|
for (const whereElement of where) {
|
|
321
|
-
if (whereElement.ref && whereElement.ref[SYMBOL_FROM_ANNOTATION] === true) {
|
|
322
|
-
this._addAliasAndDeleteSymbol(whereElement)
|
|
323
|
-
}
|
|
324
|
-
|
|
325
335
|
if (whereElement.SELECT) {
|
|
326
336
|
if (whereElement.SELECT.where) {
|
|
327
337
|
this._adaptAliasForWhere(whereElement.SELECT.where)
|
|
@@ -473,17 +483,28 @@ class JoinCQNFromExpanded {
|
|
|
473
483
|
for (const column of givenColumns) {
|
|
474
484
|
let navigation
|
|
475
485
|
if (column.expand) {
|
|
476
|
-
navigation = getNavigationIfStruct(entity, column.ref)
|
|
486
|
+
navigation = getNavigationIfStruct(entity, tableAlias === column.ref[0] ? column.ref.slice(1) : column.ref)
|
|
477
487
|
if (this._skip(navigation && navigation._target)) continue
|
|
478
488
|
}
|
|
479
489
|
|
|
480
|
-
// To many can only be build, once all other columns have been processed.
|
|
481
490
|
if (this._isExpandToMany(column, entity, navigation)) {
|
|
482
|
-
|
|
491
|
+
// To many can only be build, once all other columns have been processed.
|
|
492
|
+
const trgt = column.ref[column.ref.length - 1]
|
|
493
|
+
mappings[trgt] = { [TO_MANY]: true }
|
|
494
|
+
if (entity._isDraftEnabled && entity.elements[trgt]._isAssociationStrict) mappings[trgt][TO_ACTIVE] = true
|
|
483
495
|
toManyColumns.push({ parentAlias: tableAlias, column: column })
|
|
484
|
-
|
|
485
|
-
// Expands with to one target can be processed directly
|
|
486
496
|
} else if (typeof column.expand === 'object') {
|
|
497
|
+
// Expands with to one target can be processed directly
|
|
498
|
+
const navProp = column.ref[column.ref.length - 1]
|
|
499
|
+
const navTarget = entity.elements[navProp]
|
|
500
|
+
if (
|
|
501
|
+
entity._isDraftEnabled &&
|
|
502
|
+
navTarget._isAssociationStrict &&
|
|
503
|
+
!navTarget['@odata.draft.enclosed'] &&
|
|
504
|
+
navTarget.name !== 'DraftAdministrativeData'
|
|
505
|
+
) {
|
|
506
|
+
mappings[navProp] = { [TO_ACTIVE]: true }
|
|
507
|
+
}
|
|
487
508
|
this._addJoinAndElements({
|
|
488
509
|
column,
|
|
489
510
|
entity,
|
|
@@ -529,15 +550,10 @@ class JoinCQNFromExpanded {
|
|
|
529
550
|
*/
|
|
530
551
|
_getMappingObject(toManyTree) {
|
|
531
552
|
let mappings = this.mappings
|
|
532
|
-
|
|
533
553
|
for (const element of toManyTree) {
|
|
534
|
-
if (!mappings[element]) {
|
|
535
|
-
mappings[element] = {}
|
|
536
|
-
}
|
|
537
|
-
|
|
554
|
+
if (!mappings[element]) mappings[element] = {}
|
|
538
555
|
mappings = mappings[element]
|
|
539
556
|
}
|
|
540
|
-
|
|
541
557
|
return mappings
|
|
542
558
|
}
|
|
543
559
|
|
|
@@ -588,6 +604,7 @@ class JoinCQNFromExpanded {
|
|
|
588
604
|
* @param args.defaultLanguage
|
|
589
605
|
* @private
|
|
590
606
|
*/
|
|
607
|
+
// eslint-disable-next-line complexity
|
|
591
608
|
_addJoinAndElements({ column, entity, readToOneCQN, toManyTree, parentAlias, defaultLanguage }) {
|
|
592
609
|
const extendedToManyTree = toManyTree.concat(column.ref)
|
|
593
610
|
const tableAlias = this._createAlias(extendedToManyTree.join(':'))
|
|
@@ -608,29 +625,52 @@ class JoinCQNFromExpanded {
|
|
|
608
625
|
entity['@cds.localized'] === false ||
|
|
609
626
|
(colTarget && this._csn.definitions[colTarget] && this._csn.definitions[colTarget]['@cds.localized'] === false)
|
|
610
627
|
|
|
611
|
-
|
|
628
|
+
const join =
|
|
629
|
+
column.ref[0] === 'DraftAdministrativeData' || !entity.elements[column.ref[0]].notNull || this._isDraft
|
|
630
|
+
? 'left'
|
|
631
|
+
: 'inner'
|
|
632
|
+
|
|
633
|
+
const args = [
|
|
634
|
+
readToOneCQN.from.SET ? this._unionToSubQuery(readToOneCQN) : readToOneCQN.from,
|
|
635
|
+
{
|
|
636
|
+
ref: [this._refFromRefByExpand(column.ref[0], colTarget, defaultLanguageThis, activeTableRequired)],
|
|
637
|
+
as: tableAlias
|
|
638
|
+
}
|
|
639
|
+
]
|
|
640
|
+
|
|
612
641
|
readToOneCQN.from = {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
642
|
+
join,
|
|
643
|
+
args,
|
|
644
|
+
on: null
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const expandedEntity = this._getEntityForTable(target)
|
|
648
|
+
if (readToOneCQN[IS_UNION_DRAFT] && expandedEntity.drafts) {
|
|
649
|
+
const cols = column.expand.filter(c => !c.expand && !DRAFT_COLUMNS.includes(c.ref[0])).map(c => c.ref[0])
|
|
650
|
+
const ks = Object.keys(expandedEntity.keys).filter(
|
|
651
|
+
c => !expandedEntity.keys[c].isAssociation && !DRAFT_COLUMNS.includes(c)
|
|
652
|
+
)
|
|
653
|
+
const user = (cds.context && cds.context.user && cds.context.user.id) || 'anonymous'
|
|
654
|
+
const unionFrom = getCQNUnionFrom(cols, expandedEntity.name, expandedEntity.name + '.drafts', ks, user)
|
|
655
|
+
readToOneCQN.from.args[1] = {
|
|
656
|
+
SELECT: {
|
|
657
|
+
columns: cols,
|
|
658
|
+
from: unionFrom,
|
|
659
|
+
as: 'b'
|
|
618
660
|
}
|
|
619
|
-
|
|
620
|
-
join:
|
|
621
|
-
column.ref[0] === 'DraftAdministrativeData' || !entity.elements[column.ref[0]].notNull || this._isDraft
|
|
622
|
-
? 'left'
|
|
623
|
-
: 'inner',
|
|
624
|
-
on: this._getOnCond(entity, column.ref, tableAlias, parentAlias, readToOneCQN)
|
|
661
|
+
}
|
|
625
662
|
}
|
|
626
663
|
|
|
664
|
+
// note: set the on condition after the join kind and args are set
|
|
665
|
+
readToOneCQN.from.on = this._getOnCond(entity, column.ref, tableAlias, parentAlias, readToOneCQN)
|
|
666
|
+
|
|
627
667
|
if (column.ref[0] !== 'DraftAdministrativeData') {
|
|
628
668
|
this._addJoinKeyColumnsToUnion(readToOneCQN.from.args, readToOneCQN.from.on, parentAlias)
|
|
629
669
|
}
|
|
630
670
|
|
|
631
671
|
// special case of navigation to one requires additional LEFT JOIN and CASE for HasDraftEntity
|
|
632
672
|
const compToOne = this._isNavigationToOne(readToOneCQN[IS_ACTIVE], entity.elements[column.ref[0]])
|
|
633
|
-
const index = column.expand.findIndex(col => col.ref[
|
|
673
|
+
const index = column.expand.findIndex(col => col.ref && col.ref[col.ref.length - 1] === 'HasDraftEntity')
|
|
634
674
|
|
|
635
675
|
if (compToOne && index !== -1) {
|
|
636
676
|
readToOneCQN.from = this._addJoinCompToOne(readToOneCQN.from, entity.elements[column.ref[0]], tableAlias)
|
|
@@ -659,25 +699,27 @@ class JoinCQNFromExpanded {
|
|
|
659
699
|
}
|
|
660
700
|
}
|
|
661
701
|
|
|
702
|
+
const givenColumns = column.expand.map(col => {
|
|
703
|
+
if (
|
|
704
|
+
activeTableRequired &&
|
|
705
|
+
col.ref &&
|
|
706
|
+
col.ref.length &&
|
|
707
|
+
(col.ref[0] === 'IsActiveEntity' || col.ref[0] === 'HasActiveEntity')
|
|
708
|
+
) {
|
|
709
|
+
return {
|
|
710
|
+
val: col.ref[0] === 'IsActiveEntity',
|
|
711
|
+
as: col.ref[0],
|
|
712
|
+
cast: { type: 'cds.Boolean' }
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return col
|
|
716
|
+
})
|
|
717
|
+
|
|
662
718
|
this._expandedToFlat({
|
|
663
719
|
entity: this._getEntityForTable(target),
|
|
664
|
-
givenColumns
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
col.ref &&
|
|
668
|
-
col.ref.length &&
|
|
669
|
-
(col.ref[0] === 'IsActiveEntity' || col.ref[0] === 'HasActiveEntity')
|
|
670
|
-
) {
|
|
671
|
-
return {
|
|
672
|
-
val: col.ref[0] === 'IsActiveEntity',
|
|
673
|
-
as: col.ref[0],
|
|
674
|
-
cast: { type: 'cds.Boolean' }
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
return col
|
|
678
|
-
}),
|
|
679
|
-
readToOneCQN: readToOneCQN,
|
|
680
|
-
tableAlias: tableAlias,
|
|
720
|
+
givenColumns,
|
|
721
|
+
readToOneCQN,
|
|
722
|
+
tableAlias,
|
|
681
723
|
toManyTree: extendedToManyTree,
|
|
682
724
|
defaultLanguage: defaultLanguageThis
|
|
683
725
|
})
|
|
@@ -774,10 +816,10 @@ class JoinCQNFromExpanded {
|
|
|
774
816
|
return [{ ref: [tableAlias, 'DraftUUID'] }, '=', { ref: [parentAlias, 'DraftAdministrativeData_DraftUUID'] }]
|
|
775
817
|
}
|
|
776
818
|
|
|
777
|
-
// No
|
|
819
|
+
// No sub select
|
|
778
820
|
const subSelectColumns = this._getSubSelectColumns(readToOneCQN)
|
|
779
821
|
|
|
780
|
-
const navigation = getNavigationIfStruct(entity, columns)
|
|
822
|
+
const navigation = getNavigationIfStruct(entity, tableAlias === columns[0] ? columns.slice(1) : columns)
|
|
781
823
|
const onConditionOptions = {
|
|
782
824
|
associationNames: columns,
|
|
783
825
|
csn: this._csn,
|
|
@@ -903,7 +945,7 @@ class JoinCQNFromExpanded {
|
|
|
903
945
|
|
|
904
946
|
_getIdentifier(column, tableAlias) {
|
|
905
947
|
if (column.as) {
|
|
906
|
-
return column.as.startsWith(`${tableAlias}_`) ? column.ref[column.ref.length - 1] : column.as
|
|
948
|
+
return column.as.startsWith(`${tableAlias}_`) && column.ref ? column.ref[column.ref.length - 1] : column.as
|
|
907
949
|
}
|
|
908
950
|
|
|
909
951
|
return column.ref[column.ref.length - 1]
|
|
@@ -931,19 +973,16 @@ class JoinCQNFromExpanded {
|
|
|
931
973
|
this._addKeysIfNeeded({ entity, readToOneCQN, tableAlias })
|
|
932
974
|
|
|
933
975
|
for (const { column, parentAlias } of toManyColumns) {
|
|
934
|
-
this.
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
parentAlias,
|
|
942
|
-
defaultLanguage
|
|
943
|
-
}),
|
|
944
|
-
toManyTree.concat([column.ref[0]]),
|
|
976
|
+
const select = this._buildExpandedCQN({
|
|
977
|
+
column,
|
|
978
|
+
entity,
|
|
979
|
+
readToOneCQN,
|
|
980
|
+
toManyTree,
|
|
981
|
+
mappings,
|
|
982
|
+
parentAlias,
|
|
945
983
|
defaultLanguage
|
|
946
|
-
)
|
|
984
|
+
})
|
|
985
|
+
this._createJoinCQNFromExpanded(select, toManyTree.concat([column.ref[column.ref.length - 1]]), defaultLanguage)
|
|
947
986
|
}
|
|
948
987
|
}
|
|
949
988
|
|
|
@@ -1009,8 +1048,13 @@ class JoinCQNFromExpanded {
|
|
|
1009
1048
|
* @returns {object}
|
|
1010
1049
|
* @private
|
|
1011
1050
|
*/
|
|
1051
|
+
// eslint-disable-next-line complexity
|
|
1012
1052
|
_buildExpandedCQN({ column, entity, readToOneCQN, toManyTree, mappings, parentAlias, defaultLanguage }) {
|
|
1013
|
-
const
|
|
1053
|
+
const isUnion = !!readToOneCQN.from.SET
|
|
1054
|
+
|
|
1055
|
+
const colRef = parentAlias === column.ref[0] ? column.ref.slice(1) : column.ref.slice(0)
|
|
1056
|
+
const element = entity.elements[colRef[0]]
|
|
1057
|
+
const colTarget = ensureUnlocalized(element.target)
|
|
1014
1058
|
const defaultLanguageThis =
|
|
1015
1059
|
defaultLanguage ||
|
|
1016
1060
|
entity['@cds.localized'] === false ||
|
|
@@ -1018,25 +1062,24 @@ class JoinCQNFromExpanded {
|
|
|
1018
1062
|
|
|
1019
1063
|
const expandActive =
|
|
1020
1064
|
readToOneCQN[IS_ACTIVE] ||
|
|
1021
|
-
(
|
|
1022
|
-
!entity.elements[column.ref[0]]['@odata.draft.enclosed']) ||
|
|
1065
|
+
(element.type === 'cds.Association' && !element['@odata.draft.enclosed']) ||
|
|
1023
1066
|
!this._csn.definitions[colTarget]._isDraftEnabled
|
|
1024
|
-
const ref = this._getJoinRef(entity.elements,
|
|
1025
|
-
const tableAlias = this._createAlias(toManyTree.concat(
|
|
1067
|
+
const ref = this._getJoinRef(entity.elements, colRef[0], expandActive, defaultLanguageThis)
|
|
1068
|
+
const tableAlias = this._createAlias(toManyTree.concat(colRef).join(':'))
|
|
1026
1069
|
const onConditionOptions = {
|
|
1027
|
-
associationNames:
|
|
1070
|
+
associationNames: colRef[0],
|
|
1028
1071
|
csn: this._csn,
|
|
1029
1072
|
aliases: {
|
|
1030
1073
|
select: tableAlias,
|
|
1031
1074
|
join: 'filterExpand'
|
|
1032
1075
|
}
|
|
1033
1076
|
}
|
|
1034
|
-
const on = getOnCond(
|
|
1077
|
+
const on = getOnCond(element, onConditionOptions)
|
|
1035
1078
|
const filterExpand = this._getFilterExpandCQN(readToOneCQN, on, parentAlias, entity.keys)
|
|
1036
|
-
const expandedEntity = this._csn.definitions[
|
|
1037
|
-
const joinColumns = this._getJoinColumnsFromOnAddToMapping(mappings[
|
|
1079
|
+
const expandedEntity = this._csn.definitions[colTarget]
|
|
1080
|
+
const joinColumns = this._getJoinColumnsFromOnAddToMapping(mappings[colRef[0]], parentAlias, on, entity)
|
|
1038
1081
|
|
|
1039
|
-
|
|
1082
|
+
let cqn = {
|
|
1040
1083
|
from: {
|
|
1041
1084
|
join: 'inner',
|
|
1042
1085
|
args: [{ ref: [ref], as: tableAlias }, filterExpand],
|
|
@@ -1065,11 +1108,52 @@ class JoinCQNFromExpanded {
|
|
|
1065
1108
|
cqn.orderBy = this._copyOrderBy(column.orderBy, tableAlias, expandedEntity)
|
|
1066
1109
|
}
|
|
1067
1110
|
|
|
1068
|
-
if (column.limit
|
|
1069
|
-
|
|
1111
|
+
if (column.limit) cqn.limit = column.limit
|
|
1112
|
+
|
|
1113
|
+
cqn = this._adaptWhereOrderBy(cqn, tableAlias)
|
|
1114
|
+
|
|
1115
|
+
if (isUnion) {
|
|
1116
|
+
const cols = column.expand.filter(c => !c.expand && !DRAFT_COLUMNS.includes(c.ref[0])).map(c => c.ref[0])
|
|
1117
|
+
// ensure the join columns are selected
|
|
1118
|
+
for (const each of joinColumns) {
|
|
1119
|
+
const col = each.ref[each.ref.length - 1]
|
|
1120
|
+
if (!cols.includes(col)) cols.push(col)
|
|
1121
|
+
}
|
|
1122
|
+
// ensure the foreign keys are selected in case of expand to one
|
|
1123
|
+
for (const each of cqn.columns) {
|
|
1124
|
+
if (each.expand) {
|
|
1125
|
+
const assoc = expandedEntity.associations[each.ref[0]]
|
|
1126
|
+
if (assoc.is2one) {
|
|
1127
|
+
const fks = Object.values(expandedEntity.elements).filter(ele => ele['@odata.foreignKey4'] === assoc.name)
|
|
1128
|
+
cols.push(...fks.map(fk => fk.name))
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
const ks = Object.keys(expandedEntity.keys).filter(
|
|
1133
|
+
c => !expandedEntity.keys[c].isAssociation && !DRAFT_COLUMNS.includes(c)
|
|
1134
|
+
)
|
|
1135
|
+
const user = (cds.context && cds.context.user && cds.context.user.id) || 'anonymous'
|
|
1136
|
+
const unionFrom = getCQNUnionFrom(cols, ref.replace(/_drafts$/, ''), ref, ks, user)
|
|
1137
|
+
for (const each of cqn.columns) {
|
|
1138
|
+
if (!each.as) continue
|
|
1139
|
+
// replace val with ref
|
|
1140
|
+
if (each.as === 'IsActiveEntity' || each.as === 'HasActiveEntity') {
|
|
1141
|
+
delete each.val
|
|
1142
|
+
each.ref = [tableAlias, each.as]
|
|
1143
|
+
each.as = tableAlias + '_' + each.as
|
|
1144
|
+
}
|
|
1145
|
+
// ensure the cast
|
|
1146
|
+
if (each.as.match(/IsActiveEntity$/) || each.as.match(/HasActiveEntity$/) || each.as.match(/HasDraftEntity$/)) {
|
|
1147
|
+
each.cast = { type: 'cds.Boolean' }
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
const cs = cqn.columns.filter(c => !c.expand && c.ref && c.ref[0] === tableAlias).map(c => ({ ref: [c.ref[1]] }))
|
|
1151
|
+
const unionArgs = cqn.from.args
|
|
1152
|
+
unionArgs[0].SELECT = { columns: cs, from: unionFrom, distinct: true }
|
|
1153
|
+
delete unionArgs[0].ref
|
|
1070
1154
|
}
|
|
1071
1155
|
|
|
1072
|
-
return
|
|
1156
|
+
return cqn
|
|
1073
1157
|
}
|
|
1074
1158
|
|
|
1075
1159
|
_getJoinRef(elements, column, isActive, defaultLanguage) {
|
|
@@ -1080,24 +1164,6 @@ class JoinCQNFromExpanded {
|
|
|
1080
1164
|
return assoc.target + '_drafts'
|
|
1081
1165
|
}
|
|
1082
1166
|
|
|
1083
|
-
/**
|
|
1084
|
-
* Solve limit by group with a sub select at the join clause.
|
|
1085
|
-
*
|
|
1086
|
-
* @param cqn
|
|
1087
|
-
* @param column
|
|
1088
|
-
* @param tableAlias
|
|
1089
|
-
* @param expandedEntity
|
|
1090
|
-
* @private
|
|
1091
|
-
*/
|
|
1092
|
-
_addLimitToCqn(cqn, column, tableAlias, expandedEntity) {
|
|
1093
|
-
const columns = this._getKeyColumnForTarget(tableAlias, cqn[IS_ACTIVE], expandedEntity)
|
|
1094
|
-
const inSelect = this._getLimitInSelect(cqn, columns, column.limit, column.orderBy, expandedEntity)
|
|
1095
|
-
|
|
1096
|
-
cqn.from.on.push('and')
|
|
1097
|
-
cqn.from.on.push({ list: columns })
|
|
1098
|
-
cqn.from.on.push('IN', inSelect)
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
1167
|
/**
|
|
1102
1168
|
* Get the list of key columns in ref format.
|
|
1103
1169
|
* Add the table alias to avoid ambiguity issues.
|
|
@@ -1156,48 +1222,11 @@ class JoinCQNFromExpanded {
|
|
|
1156
1222
|
})
|
|
1157
1223
|
}
|
|
1158
1224
|
|
|
1159
|
-
|
|
1160
|
-
return { [IDENTIFIER]: name, ref: [tableAlias, name], as: `${tableAlias}_${name}` }
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
_getWindowVal(tableAlias, name, val) {
|
|
1164
|
-
return { [IDENTIFIER]: name, val: val, as: `${tableAlias}_${name}` }
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
_draftColumnsToCQN(cqn, tableAlias, expandedEntity) {
|
|
1168
|
-
return DRAFT_COLUMNS.map(name => {
|
|
1169
|
-
if (name === 'IsActiveEntity') {
|
|
1170
|
-
return this._getWindowVal(tableAlias, name, cqn[IS_ACTIVE])
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
if (cqn[IS_ACTIVE]) {
|
|
1174
|
-
if (name === 'DraftAdministrativeData_DraftUUID') {
|
|
1175
|
-
return this._getWindowVal(tableAlias, name, null)
|
|
1176
|
-
}
|
|
1177
|
-
if (name === 'HasActiveEntity') {
|
|
1178
|
-
return this._getWindowVal(tableAlias, name, false)
|
|
1179
|
-
}
|
|
1180
|
-
if (name === 'HasDraftEntity') {
|
|
1181
|
-
return this._getHasDraftEntityXpr(expandedEntity, tableAlias)
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
return this._getWindowRef(tableAlias, name)
|
|
1186
|
-
})
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
_getHasDraftEntityXpr(expandedEntity, tableAlias, columns = []) {
|
|
1225
|
+
_getHasDraftEntityXpr(expandedEntity, tableAlias) {
|
|
1190
1226
|
const draftTable = ensureDraftsSuffix(expandedEntity.name)
|
|
1191
1227
|
const where = filterKeys(expandedEntity.keys).reduce((res, keyName) => {
|
|
1192
|
-
let keyAlias
|
|
1193
|
-
if (this._useWindow) {
|
|
1194
|
-
const element = columns.find(
|
|
1195
|
-
col => col.as && col.ref && col.ref.length === 2 && col.ref[1] === keyName && col.ref[0] === tableAlias
|
|
1196
|
-
)
|
|
1197
|
-
keyAlias = element && element.as
|
|
1198
|
-
}
|
|
1199
1228
|
if (res.length !== 0) res.push('and')
|
|
1200
|
-
res.push({ ref: [draftTable, keyName] }, '=', { ref: [tableAlias,
|
|
1229
|
+
res.push({ ref: [draftTable, keyName] }, '=', { ref: [tableAlias, keyName] })
|
|
1201
1230
|
return res
|
|
1202
1231
|
}, [])
|
|
1203
1232
|
const hasDraftQuery = {
|
|
@@ -1214,124 +1243,6 @@ class JoinCQNFromExpanded {
|
|
|
1214
1243
|
}
|
|
1215
1244
|
}
|
|
1216
1245
|
|
|
1217
|
-
_getWindowPartitions(on) {
|
|
1218
|
-
const partitions = []
|
|
1219
|
-
|
|
1220
|
-
for (const element of on) {
|
|
1221
|
-
if (
|
|
1222
|
-
element.ref &&
|
|
1223
|
-
element.ref[0] !== 'filterExpand' &&
|
|
1224
|
-
element.ref[element.ref.length - 1] !== 'IsActiveEntity'
|
|
1225
|
-
) {
|
|
1226
|
-
if (partitions.length !== 0) {
|
|
1227
|
-
partitions.push(',')
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
partitions.push(element)
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
return partitions
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
_getWindowColumns(cqn, column, tableAlias, expandedEntity) {
|
|
1238
|
-
const columns = cqn.columns
|
|
1239
|
-
.filter(entry => entry.val || (entry.ref && !entry.expand && entry.ref[0] !== tableAlias))
|
|
1240
|
-
.concat(
|
|
1241
|
-
getColumns(expandedEntity)
|
|
1242
|
-
.filter(col => !col.virtual)
|
|
1243
|
-
.map(element => {
|
|
1244
|
-
return this._getWindowRef(tableAlias, element.name)
|
|
1245
|
-
})
|
|
1246
|
-
)
|
|
1247
|
-
|
|
1248
|
-
if (expandedEntity._isDraftEnabled) {
|
|
1249
|
-
columns.push(...this._draftColumnsToCQN(cqn, tableAlias, expandedEntity))
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
columns.push(
|
|
1253
|
-
this._getWindowXpr(
|
|
1254
|
-
this._getWindowPartitions(cqn.from.on),
|
|
1255
|
-
this._copyOrderBy(column.orderBy || [], tableAlias, expandedEntity)
|
|
1256
|
-
)
|
|
1257
|
-
)
|
|
1258
|
-
|
|
1259
|
-
return columns
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
_getWhereForLimit(column) {
|
|
1263
|
-
const offset = (column.limit.offset && column.limit.offset.val) || 0
|
|
1264
|
-
return [
|
|
1265
|
-
{ ref: ['rowNumber'] },
|
|
1266
|
-
'>',
|
|
1267
|
-
{ val: offset },
|
|
1268
|
-
'and',
|
|
1269
|
-
{ ref: ['rowNumber'] },
|
|
1270
|
-
'<',
|
|
1271
|
-
{ val: offset + column.limit.rows.val + 1 }
|
|
1272
|
-
]
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
_addWindowIfNeeded(cqn, column, tableAlias, expandedEntity) {
|
|
1276
|
-
if (!this._useWindow || (!column.orderBy && !column.limit)) {
|
|
1277
|
-
return cqn
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
const windowCQN = {
|
|
1281
|
-
columns: cqn.columns.map(entry => {
|
|
1282
|
-
if (entry.ref && entry.as) {
|
|
1283
|
-
const newRef = entry.ref[0] === 'filterExpand' ? [entry.as] : [entry.ref[0], entry.as]
|
|
1284
|
-
return Object.assign({}, entry, { [IDENTIFIER]: entry.ref[1], ref: newRef })
|
|
1285
|
-
}
|
|
1286
|
-
|
|
1287
|
-
if (entry.val) {
|
|
1288
|
-
const returnValue = { [IDENTIFIER]: entry.as, ref: [tableAlias, entry.as], as: entry.as }
|
|
1289
|
-
if (SKIP_MAPPING in entry) {
|
|
1290
|
-
returnValue[SKIP_MAPPING] = entry[SKIP_MAPPING]
|
|
1291
|
-
}
|
|
1292
|
-
return returnValue
|
|
1293
|
-
}
|
|
1294
|
-
|
|
1295
|
-
return Object.assign({}, entry)
|
|
1296
|
-
}),
|
|
1297
|
-
from: {
|
|
1298
|
-
SELECT: cqn
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
cqn.columns = this._getWindowColumns(cqn, column, tableAlias, expandedEntity)
|
|
1303
|
-
|
|
1304
|
-
if (column.limit) {
|
|
1305
|
-
windowCQN.where = this._getWhereForLimit(column)
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
return windowCQN
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
_getOrderByForWindowFn(orderBy) {
|
|
1312
|
-
return orderBy.reduce((arr, value, i) => {
|
|
1313
|
-
arr.push(value)
|
|
1314
|
-
if (i < orderBy.length - 1) {
|
|
1315
|
-
arr.push(',')
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
return arr
|
|
1319
|
-
}, [])
|
|
1320
|
-
}
|
|
1321
|
-
|
|
1322
|
-
_getWindowXpr(columns, orderBy) {
|
|
1323
|
-
const xpr = [{ func: 'ROW_NUMBER', args: [] }, 'OVER', '(']
|
|
1324
|
-
if (columns.length > 0) {
|
|
1325
|
-
xpr.push('PARTITION BY', ...columns)
|
|
1326
|
-
}
|
|
1327
|
-
if (orderBy.length !== 0) {
|
|
1328
|
-
xpr.push('ORDER BY', ...this._getOrderByForWindowFn(orderBy))
|
|
1329
|
-
}
|
|
1330
|
-
xpr.push(')')
|
|
1331
|
-
|
|
1332
|
-
return { xpr: xpr, as: 'rowNumber' }
|
|
1333
|
-
}
|
|
1334
|
-
|
|
1335
1246
|
_copyColumns(columns, alias) {
|
|
1336
1247
|
return columns.map(element => {
|
|
1337
1248
|
const column = {
|
|
@@ -1466,7 +1377,7 @@ class JoinCQNFromExpanded {
|
|
|
1466
1377
|
const ele = struct.elements[k]
|
|
1467
1378
|
const l = key + '_' + k
|
|
1468
1379
|
if (ele._isStructured) value.push(...this._getValueFromEntry(entry, parentAlias, l, ele))
|
|
1469
|
-
else value.push(entry
|
|
1380
|
+
else value.push(this._getValueFromEntry(entry, parentAlias, l))
|
|
1470
1381
|
}
|
|
1471
1382
|
}
|
|
1472
1383
|
}
|
|
@@ -1594,20 +1505,17 @@ class JoinCQNFromExpanded {
|
|
|
1594
1505
|
if (typeof isActive === 'boolean') {
|
|
1595
1506
|
if (columnName === 'IsActiveEntity') {
|
|
1596
1507
|
columns.push(this._createCalculatedBooleanColumn('IsActiveEntity', isActive))
|
|
1597
|
-
|
|
1598
1508
|
return
|
|
1599
1509
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
return
|
|
1510
|
+
if (isActive) {
|
|
1511
|
+
if (columnName === 'HasActiveEntity') {
|
|
1512
|
+
columns.push(this._createCalculatedBooleanColumn('HasActiveEntity', false))
|
|
1513
|
+
return
|
|
1514
|
+
}
|
|
1515
|
+
if (columnName === 'HasDraftEntity') {
|
|
1516
|
+
columns.push(this._getHasDraftEntityXpr(entity, tableAlias))
|
|
1517
|
+
return
|
|
1518
|
+
}
|
|
1611
1519
|
}
|
|
1612
1520
|
}
|
|
1613
1521
|
|
|
@@ -1681,13 +1589,12 @@ class JoinCQNFromExpanded {
|
|
|
1681
1589
|
*
|
|
1682
1590
|
* @param {object} cqn - CQN with expanded columns
|
|
1683
1591
|
* @param {object} csn - Services CSN
|
|
1684
|
-
* @param {boolean} useWindow - If sub select or window function should be used for top/skip at expand
|
|
1685
1592
|
* @param {string} locale
|
|
1686
1593
|
* @returns {object}
|
|
1687
1594
|
* @private
|
|
1688
1595
|
*/
|
|
1689
|
-
const createJoinCQNFromExpanded = (cqn, csn,
|
|
1690
|
-
return new JoinCQNFromExpanded(cqn, csn,
|
|
1596
|
+
const createJoinCQNFromExpanded = (cqn, csn, locale) => {
|
|
1597
|
+
return new JoinCQNFromExpanded(cqn, csn, locale).buildJoinQueries()
|
|
1691
1598
|
}
|
|
1692
1599
|
|
|
1693
1600
|
/**
|