@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.
Files changed (228) hide show
  1. package/CHANGELOG.md +208 -2
  2. package/apis/ql.d.ts +17 -15
  3. package/app/index.js +1 -1
  4. package/bin/build/buildTaskEngine.js +26 -42
  5. package/bin/build/buildTaskFactory.js +6 -10
  6. package/bin/build/buildTaskHandler.js +2 -4
  7. package/bin/build/buildTaskProvider.js +3 -1
  8. package/bin/build/buildTaskProviderFactory.js +9 -15
  9. package/bin/build/constants.js +15 -3
  10. package/bin/build/index.js +5 -4
  11. package/bin/build/mtaUtil.js +8 -11
  12. package/bin/build/provider/buildTaskHandlerEdmx.js +63 -6
  13. package/bin/build/provider/buildTaskHandlerInternal.js +2 -34
  14. package/bin/build/provider/buildTaskProviderInternal.js +16 -42
  15. package/bin/build/provider/fiori/index.js +13 -24
  16. package/bin/build/provider/hana/2migration.js +17 -15
  17. package/bin/build/provider/hana/2tabledata.js +52 -48
  18. package/bin/build/provider/hana/index.js +27 -25
  19. package/bin/build/provider/hana/migrationtable.js +91 -67
  20. package/bin/build/provider/java-cf/index.js +14 -24
  21. package/bin/build/provider/mtx/index.js +12 -14
  22. package/bin/build/provider/node-cf/index.js +18 -32
  23. package/bin/cds.js +5 -5
  24. package/bin/serve.js +29 -23
  25. package/bin/version.js +0 -1
  26. package/lib/compile/etc/_localized.js +4 -9
  27. package/lib/compile/for/sql.js +5 -2
  28. package/lib/compile/parse.js +25 -17
  29. package/lib/compile/to/srvinfo.js +2 -1
  30. package/lib/connect/bindings.js +2 -1
  31. package/lib/connect/index.js +48 -49
  32. package/lib/core/classes.js +1 -1
  33. package/lib/core/reflect.js +10 -2
  34. package/lib/deploy.js +26 -23
  35. package/lib/env/defaults.js +13 -6
  36. package/lib/env/index.js +73 -78
  37. package/lib/env/requires.js +38 -19
  38. package/lib/index.js +9 -10
  39. package/lib/lazy.js +2 -2
  40. package/lib/log/index.js +33 -45
  41. package/lib/log/service/index.js +2 -2
  42. package/lib/ql/CREATE.js +14 -9
  43. package/lib/ql/DELETE.js +6 -5
  44. package/lib/ql/DROP.js +12 -9
  45. package/lib/ql/INSERT.js +40 -16
  46. package/lib/ql/Query.js +67 -40
  47. package/lib/ql/SELECT.js +162 -127
  48. package/lib/ql/UPDATE.js +74 -42
  49. package/lib/ql/Whereable.js +77 -87
  50. package/lib/ql/index.js +36 -24
  51. package/lib/ql/parse.js +35 -0
  52. package/lib/req/context.js +44 -8
  53. package/lib/req/locale.js +7 -7
  54. package/lib/serve/Service-api.js +21 -14
  55. package/lib/serve/Service-dispatch.js +28 -12
  56. package/lib/serve/Transaction.js +22 -10
  57. package/lib/serve/index.js +16 -11
  58. package/lib/utils/axios.js +23 -16
  59. package/lib/utils/data.js +35 -0
  60. package/lib/utils/tests.js +27 -18
  61. package/libx/_runtime/audit/generic/personal/access.js +81 -0
  62. package/libx/_runtime/audit/generic/personal/constants.js +4 -0
  63. package/libx/_runtime/audit/generic/personal/index.js +50 -0
  64. package/libx/_runtime/audit/generic/personal/modification.js +138 -0
  65. package/libx/_runtime/audit/generic/personal/utils.js +186 -0
  66. package/libx/_runtime/audit/utils/v2.js +10 -4
  67. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +5 -5
  68. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -7
  69. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +5 -7
  70. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -7
  71. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +2 -3
  72. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +4 -0
  73. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +7 -4
  74. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +59 -8
  75. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +11 -1
  76. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +6 -10
  77. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +3 -46
  78. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +2 -5
  79. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/createToCQN.js +2 -2
  80. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/deleteToCQN.js +4 -3
  81. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -2
  82. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +0 -1
  83. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/selectHelper.js +1 -1
  84. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +2 -2
  85. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +16 -18
  86. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityType.js +6 -3
  87. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/format/RepresentationKind.js +4 -1
  88. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/OdataRequest.js +1 -0
  89. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +15 -2
  90. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/OperationValidator.js +1 -0
  91. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
  92. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +8 -1
  93. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +6 -1
  94. package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +12 -5
  95. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -7
  96. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +7 -7
  97. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +14 -18
  98. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +13 -13
  99. package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -1
  100. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +2 -1
  101. package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +2 -2
  102. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +2 -4
  103. package/libx/_runtime/cds-services/adapter/rest/utils/result.js +4 -2
  104. package/libx/_runtime/cds-services/services/Service.js +40 -5
  105. package/libx/_runtime/cds-services/services/utils/columns.js +13 -7
  106. package/libx/_runtime/cds-services/services/utils/compareJson.js +88 -4
  107. package/libx/_runtime/cds-services/services/utils/differ.js +24 -6
  108. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -2
  109. package/libx/_runtime/common/composition/data.js +44 -55
  110. package/libx/_runtime/common/composition/delete.js +97 -71
  111. package/libx/_runtime/common/composition/index.js +2 -1
  112. package/libx/_runtime/common/composition/insert.js +34 -11
  113. package/libx/_runtime/common/composition/tree.js +119 -92
  114. package/libx/_runtime/common/composition/update.js +4 -1
  115. package/libx/_runtime/common/composition/utils.js +1 -3
  116. package/libx/_runtime/common/constants/draft.js +12 -1
  117. package/libx/_runtime/common/generic/auth.js +6 -22
  118. package/libx/_runtime/common/generic/crud.js +14 -13
  119. package/libx/_runtime/common/generic/input.js +23 -26
  120. package/libx/_runtime/common/generic/put.js +1 -1
  121. package/libx/_runtime/common/generic/sorting.js +16 -16
  122. package/libx/_runtime/common/i18n/index.js +1 -1
  123. package/libx/_runtime/common/i18n/messages.properties +4 -0
  124. package/libx/_runtime/common/utils/backlinks.js +12 -5
  125. package/libx/_runtime/common/utils/cqn.js +6 -1
  126. package/libx/_runtime/common/utils/cqn2cqn4sql.js +102 -101
  127. package/libx/_runtime/common/utils/csn.js +47 -4
  128. package/libx/_runtime/common/utils/data.js +0 -37
  129. package/libx/_runtime/common/utils/enrichWithKeysFromWhere.js +1 -1
  130. package/libx/_runtime/common/utils/entityFromCqn.js +7 -24
  131. package/libx/_runtime/common/utils/foreignKeyPropagations.js +39 -7
  132. package/libx/_runtime/common/utils/generateOnCond.js +11 -12
  133. package/libx/_runtime/common/utils/onlyKeysRemain.js +10 -0
  134. package/libx/_runtime/common/utils/path.js +35 -0
  135. package/libx/_runtime/common/utils/postProcessing.js +86 -0
  136. package/libx/_runtime/common/utils/quotingStyles.js +37 -26
  137. package/libx/_runtime/common/utils/resolveView.js +223 -171
  138. package/libx/_runtime/common/utils/rewriteAsterisk.js +46 -26
  139. package/libx/_runtime/common/utils/structured.js +6 -12
  140. package/libx/_runtime/common/utils/template.js +10 -5
  141. package/libx/_runtime/common/utils/templateDelimiter.js +1 -0
  142. package/libx/_runtime/common/utils/templateProcessor.js +22 -30
  143. package/libx/_runtime/common/utils/union.js +31 -0
  144. package/libx/_runtime/common/utils/unionCqnTemplate.js +184 -0
  145. package/libx/_runtime/db/Service.js +1 -1
  146. package/libx/_runtime/db/data-conversion/timestamp.js +2 -9
  147. package/libx/_runtime/db/expand/expandCQNToJoin.js +204 -297
  148. package/libx/_runtime/db/expand/index.js +3 -3
  149. package/libx/_runtime/db/expand/rawToExpanded.js +36 -7
  150. package/libx/_runtime/db/generic/index.js +1 -1
  151. package/libx/_runtime/db/generic/input.js +5 -7
  152. package/libx/_runtime/db/generic/integrity.js +1 -1
  153. package/libx/_runtime/db/generic/rewrite.js +2 -10
  154. package/libx/_runtime/db/generic/update.js +13 -5
  155. package/libx/_runtime/db/generic/virtual.js +22 -58
  156. package/libx/_runtime/db/query/delete.js +7 -4
  157. package/libx/_runtime/db/query/insert.js +6 -4
  158. package/libx/_runtime/db/query/read.js +13 -20
  159. package/libx/_runtime/db/query/run.js +4 -1
  160. package/libx/_runtime/db/query/update.js +5 -4
  161. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +35 -2
  162. package/libx/_runtime/db/sql-builder/FunctionBuilder.js +17 -2
  163. package/libx/_runtime/db/sql-builder/InsertBuilder.js +6 -5
  164. package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +10 -0
  165. package/libx/_runtime/db/sql-builder/SelectBuilder.js +35 -24
  166. package/libx/_runtime/db/sql-builder/UpdateBuilder.js +14 -4
  167. package/libx/_runtime/db/sql-builder/arrayed.js +4 -0
  168. package/libx/_runtime/db/utils/deep.js +8 -0
  169. package/libx/_runtime/db/utils/generateAliases.js +2 -1
  170. package/libx/_runtime/fiori/generic/activate.js +19 -15
  171. package/libx/_runtime/fiori/generic/before.js +3 -11
  172. package/libx/_runtime/fiori/generic/cancel.js +1 -1
  173. package/libx/_runtime/fiori/generic/delete.js +3 -1
  174. package/libx/_runtime/fiori/generic/edit.js +12 -2
  175. package/libx/_runtime/fiori/generic/new.js +5 -5
  176. package/libx/_runtime/fiori/generic/patch.js +0 -18
  177. package/libx/_runtime/fiori/generic/read.js +241 -189
  178. package/libx/_runtime/fiori/utils/delete.js +36 -7
  179. package/libx/_runtime/fiori/utils/handler.js +43 -44
  180. package/libx/_runtime/fiori/utils/where.js +30 -15
  181. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +4 -6
  182. package/libx/_runtime/hana/execute.js +2 -2
  183. package/libx/_runtime/hana/localized.js +4 -4
  184. package/libx/_runtime/hana/pool.js +29 -14
  185. package/libx/_runtime/hana/search2cqn4sql.js +2 -1
  186. package/libx/_runtime/hana/searchToContains.js +18 -14
  187. package/libx/_runtime/index.js +0 -5
  188. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +13 -5
  189. package/libx/_runtime/messaging/common-utils/naming-conventions.js +4 -1
  190. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +31 -19
  191. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -2
  192. package/libx/_runtime/messaging/enterprise-messaging.js +6 -4
  193. package/libx/_runtime/messaging/service.js +7 -6
  194. package/libx/_runtime/odata/cqn2odata.js +110 -43
  195. package/libx/_runtime/odata/index.js +26 -48
  196. package/libx/_runtime/odata/odata2cqn.js +1 -6154
  197. package/libx/_runtime/odata/odata2cqn.pegjs +559 -0
  198. package/libx/_runtime/odata/readToCqn.js +94 -64
  199. package/libx/_runtime/remote/Service.js +74 -21
  200. package/libx/_runtime/remote/cqn2odata/index.js +1 -5
  201. package/libx/_runtime/remote/utils/client.js +24 -101
  202. package/libx/_runtime/remote/utils/dataConversion.js +27 -12
  203. package/libx/_runtime/sqlite/Service.js +3 -5
  204. package/libx/_runtime/sqlite/execute.js +23 -24
  205. package/libx/_runtime/sqlite/localized.js +12 -7
  206. package/libx/_runtime/types/api.js +10 -0
  207. package/package.json +1 -1
  208. package/server.js +16 -2
  209. package/lib/ql/grammar.pegjs +0 -208
  210. package/lib/ql/parser.js +0 -1
  211. package/lib/ql/rt/DELETE.js +0 -29
  212. package/lib/ql/rt/INSERT.js +0 -23
  213. package/lib/ql/rt/Query.js +0 -84
  214. package/lib/ql/rt/SELECT.js +0 -174
  215. package/lib/ql/rt/UPDATE.js +0 -119
  216. package/lib/ql/rt/_helpers.js +0 -91
  217. package/lib/ql/rt/index.js +0 -32
  218. package/libx/_runtime/audit/generic/personal.js +0 -260
  219. package/libx/_runtime/cds-services/statements/BaseStatement.js +0 -72
  220. package/libx/_runtime/cds-services/statements/Create.js +0 -57
  221. package/libx/_runtime/cds-services/statements/Delete.js +0 -33
  222. package/libx/_runtime/cds-services/statements/Drop.js +0 -42
  223. package/libx/_runtime/cds-services/statements/Insert.js +0 -201
  224. package/libx/_runtime/cds-services/statements/Select.js +0 -826
  225. package/libx/_runtime/cds-services/statements/Update.js +0 -181
  226. package/libx/_runtime/cds-services/statements/Where.js +0 -726
  227. package/libx/_runtime/cds-services/statements/index.js +0 -25
  228. 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
- // REVISIT: remove everywhere
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, useWindow, locale) {
27
- this._useWindow = useWindow
24
+ constructor(cqn, csn, locale) {
28
25
  this._SELECT = Object.assign({}, cqn.SELECT)
29
26
  this._csn = csn
30
- if (sqliteLocales.includes(locale)) {
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
- if (unionTable) {
105
- readToOneCQN[IS_UNION_DRAFT] = true
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
- readToOneCQN[IS_ACTIVE] = isDraftTree ? this._isDraftTargetActive(table) : true
122
+ if (unionTable) readToOneCQN[IS_UNION_DRAFT] = true
109
123
 
110
- const givenColumns = readToOneCQN.columns
111
- readToOneCQN.columns = []
124
+ readToOneCQN[IS_ACTIVE] = isDraftTree ? this._isDraftTargetActive(table) : true
112
125
 
113
- this._expandedToFlat({ entity, givenColumns, readToOneCQN, tableAlias, toManyTree, defaultLanguage })
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
- cqn.from.args = cqn.from.args.slice(0)
230
-
231
- const index = cqn.from.args[0].ref ? 0 : cqn.from.args.length - 1
232
- const target = Object.assign({}, cqn.from.args[index], { as: tableAlias })
233
- const originalIdentifier = cqn.from.args[index].as || cqn.from.args[index].ref[0]
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
- cqn.from.args[index] = target
236
- cqn.from.on = cqn.from.on.map(column => this._adaptTableNameInColumn(column, originalIdentifier, tableAlias))
237
- cqn.columns = cqn.columns.map(column => this._adaptTableNameInColumn(column, originalIdentifier, tableAlias))
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
- mappings[column.ref[0]] = { [TO_MANY]: true }
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
- // TODO: If draft union and composition target add union as to be joined
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
- args: [
614
- readToOneCQN.from.SET ? this._unionToSubQuery(readToOneCQN) : readToOneCQN.from,
615
- {
616
- ref: [this._refFromRefByExpand(column.ref[0], colTarget, defaultLanguageThis, activeTableRequired)],
617
- as: tableAlias
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[0] === 'HasDraftEntity')
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: column.expand.map(col => {
665
- if (
666
- activeTableRequired &&
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 window function/ sub select
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._createJoinCQNFromExpanded(
935
- this._buildExpandedCQN({
936
- column,
937
- entity,
938
- readToOneCQN,
939
- toManyTree,
940
- mappings,
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 colTarget = ensureUnlocalized(entity.elements[column.ref[0]].target)
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
- (entity.elements[column.ref[0]].type === 'cds.Association' &&
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, column.ref[0], expandActive, defaultLanguageThis)
1025
- const tableAlias = this._createAlias(toManyTree.concat(column.ref).join(':'))
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: column.ref[0],
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(entity.elements[column.ref[0]], onConditionOptions)
1077
+ const on = getOnCond(element, onConditionOptions)
1035
1078
  const filterExpand = this._getFilterExpandCQN(readToOneCQN, on, parentAlias, entity.keys)
1036
- const expandedEntity = this._csn.definitions[ensureUnlocalized(entity.elements[column.ref[0]].target)]
1037
- const joinColumns = this._getJoinColumnsFromOnAddToMapping(mappings[column.ref[0]], parentAlias, on, entity)
1079
+ const expandedEntity = this._csn.definitions[colTarget]
1080
+ const joinColumns = this._getJoinColumnsFromOnAddToMapping(mappings[colRef[0]], parentAlias, on, entity)
1038
1081
 
1039
- const cqn = {
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 && !this._useWindow) {
1069
- this._addLimitToCqn(cqn, column, tableAlias, expandedEntity)
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 this._adaptWhereOrderBy(this._addWindowIfNeeded(cqn, column, tableAlias, expandedEntity), tableAlias)
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
- _getWindowRef(tableAlias, name) {
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, keyAlias || keyName] })
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[l])
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
- if (columnName === 'HasActiveEntity') {
1602
- columns.push(this._createCalculatedBooleanColumn('HasActiveEntity', false))
1603
-
1604
- return
1605
- }
1606
-
1607
- if (isActive && columnName === 'HasDraftEntity') {
1608
- columns.push(this._getHasDraftEntityXpr(entity, tableAlias, columns))
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, useWindow, locale) => {
1690
- return new JoinCQNFromExpanded(cqn, csn, useWindow, locale).buildJoinQueries()
1596
+ const createJoinCQNFromExpanded = (cqn, csn, locale) => {
1597
+ return new JoinCQNFromExpanded(cqn, csn, locale).buildJoinQueries()
1691
1598
  }
1692
1599
 
1693
1600
  /**