@sap/cds-dk 10.0.7 → 10.1.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 (302) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/bin/add.js +7 -23
  3. package/bin/bind.js +10 -0
  4. package/bin/build.js +20 -34
  5. package/bin/cds.js +1 -1
  6. package/bin/compile/index.js +15 -41
  7. package/bin/completion/completionFs.js +11 -8
  8. package/bin/completion/index.js +592 -80
  9. package/bin/completion/scripts/cds.fish +568 -0
  10. package/bin/completion/scripts/cds.ps1 +329 -0
  11. package/bin/completion/scripts/cds.sh +261 -0
  12. package/bin/completion/scripts/cds.zsh +230 -0
  13. package/bin/completion/templates/cds-tmpl.fish +65 -0
  14. package/bin/completion/templates/cds-tmpl.ps1 +208 -0
  15. package/bin/completion/templates/cds-tmpl.sh +93 -0
  16. package/bin/completion/templates/cds-tmpl.zsh +74 -0
  17. package/bin/deploy/index.js +7 -1
  18. package/bin/deploy/options.js +25 -0
  19. package/{lib → bin}/deploy/to-hana/hana.js +8 -8
  20. package/{lib → bin}/deploy/to-hana/hdiDeployUtil.js +1 -1
  21. package/bin/deploy/{to-hana.js → to-hana/index.js} +1 -1
  22. package/{lib → bin}/deploy/to-hana/mtaUtil.js +1 -1
  23. package/bin/deploy/to-sql.js +0 -2
  24. package/bin/export.js +35 -5
  25. package/bin/help/export.md +3 -0
  26. package/bin/help.js +1 -5
  27. package/bin/import.js +6 -0
  28. package/bin/init.js +5 -24
  29. package/bin/inspect.js +6 -0
  30. package/bin/login.js +26 -20
  31. package/bin/pull.js +19 -6
  32. package/bin/push.js +19 -6
  33. package/bin/up.js +14 -11
  34. package/{lib → bin}/upgrade/constants.js +1 -1
  35. package/bin/{upgrade.js → upgrade/index.js} +2 -2
  36. package/{lib → bin}/upgrade/preflight/consistency.js +1 -1
  37. package/{lib → bin}/upgrade/preflight/index.js +1 -1
  38. package/{lib → bin}/upgrade/steps/analyze/index.js +1 -1
  39. package/{lib → bin}/upgrade/steps/install.js +1 -1
  40. package/{lib → bin}/upgrade/steps/openrewrite.js +1 -1
  41. package/{lib → bin}/upgrade/steps/removals.js +1 -1
  42. package/{lib → bin}/upgrade/steps/rewrite.js +1 -1
  43. package/{lib → bin}/upgrade/steps/verify.js +1 -1
  44. package/{lib/upgrade/index.js → bin/upgrade/upgrade.js} +2 -2
  45. package/{lib → bin}/upgrade/util/pom.js +2 -2
  46. package/{lib → bin}/upgrade/util/prompt.js +1 -1
  47. package/bin/util/containerize.js +8 -4
  48. package/bin/version.js +10 -1
  49. package/{lib → bin}/watch/hot-reload.js +1 -1
  50. package/bin/{watch.js → watch/index.js} +17 -9
  51. package/{lib → bin}/watch/livereload-connect.js +1 -1
  52. package/{lib → bin}/watch/vite-watch.js +1 -1
  53. package/{lib → bin}/watch/watched.js +2 -2
  54. package/lib/build/constants.js +1 -1
  55. package/lib/build/plugins/fiori/index.js +31 -2
  56. package/lib/build/plugins/internal.js +4 -2
  57. package/lib/build/plugins/mtx-sidecar/index.js +7 -8
  58. package/lib/build/plugins/nodejs/index.js +64 -7
  59. package/lib/compile/to_asyncapi.js +1 -1
  60. package/lib/env/schema.js +16 -0
  61. package/lib/env/schemas/cds-rc.js +1 -76
  62. package/lib/import/importapi.js +2 -3
  63. package/lib/import/message.js +0 -2
  64. package/lib/init/constants.js +2 -1
  65. package/lib/init/index.js +2 -2
  66. package/lib/init/merge.js +123 -280
  67. package/lib/init/plugin.js +3 -1
  68. package/lib/init/projectReader.js +22 -6
  69. package/lib/init/registries/xs-app.js +3 -5
  70. package/lib/init/template/ai/files/mta.yaml.hbs +1 -1
  71. package/lib/init/template/ai/index.js +14 -2
  72. package/lib/init/template/ams/index.js +2 -2
  73. package/lib/init/template/app-frontend/files/containerize.yaml.hbs +2 -2
  74. package/lib/init/template/app-frontend/index.js +4 -4
  75. package/lib/init/template/application-logging/index.js +2 -2
  76. package/lib/init/template/approuter/files/package.json +1 -1
  77. package/lib/init/template/approuter/index.js +8 -3
  78. package/lib/init/template/attachments/files/package.json.hbs +1 -1
  79. package/lib/init/template/attachments/index.js +2 -2
  80. package/lib/init/template/audit-logging/index.js +2 -2
  81. package/lib/init/template/cloud-logging/files/package.json.hbs +4 -4
  82. package/lib/init/template/cloud-logging/index.js +2 -2
  83. package/lib/init/template/completion/completionSetup.js +36 -39
  84. package/lib/init/template/connectivity/index.js +2 -2
  85. package/lib/init/template/data/as-csv.js +15 -5
  86. package/lib/init/template/data/as-json.js +114 -42
  87. package/lib/init/template/data/index.js +16 -2
  88. package/lib/init/template/destination/index.js +2 -2
  89. package/lib/init/template/dynatrace/files/package.json.hbs +3 -3
  90. package/lib/init/template/dynatrace/index.js +2 -2
  91. package/lib/init/template/enterprise-messaging/index.js +2 -2
  92. package/lib/init/template/enterprise-messaging-shared/index.js +2 -2
  93. package/lib/init/template/extensibility/files/mta.yaml.hbs +11 -0
  94. package/lib/init/template/extensibility/files/xs-security.json.hbs +1 -1
  95. package/lib/init/template/extensibility/index.js +3 -3
  96. package/lib/init/template/github-actions/index.js +2 -2
  97. package/lib/init/template/hana/index.js +3 -2
  98. package/lib/init/template/hana-serverless/files/db/package.json +14 -0
  99. package/lib/init/template/hana-serverless/files/identity.values.yaml.hbs +10 -0
  100. package/lib/init/template/hana-serverless/files/mta.yaml.hbs +64 -0
  101. package/lib/init/template/hana-serverless/files/package.json.hbs +35 -0
  102. package/lib/init/template/hana-serverless/files/src/.hdiconfig +139 -0
  103. package/lib/init/template/hana-serverless/files/undeploy.json +7 -0
  104. package/lib/init/template/hana-serverless/files/values.yaml.hbs +18 -0
  105. package/lib/init/template/hana-serverless/index.js +184 -0
  106. package/lib/init/template/html5-repo/files/containerize.yaml.hbs +2 -2
  107. package/lib/init/template/html5-repo/files/mta.yaml.hbs +5 -0
  108. package/lib/init/template/html5-repo/index.js +18 -14
  109. package/lib/init/template/http/index.js +123 -26
  110. package/lib/init/template/ias/index.js +2 -2
  111. package/lib/init/template/kafka/index.js +2 -2
  112. package/lib/init/template/kyma/index.js +7 -5
  113. package/lib/init/template/malware-scanner/index.js +2 -2
  114. package/lib/init/template/mta/files/mta.yaml.hbs +1 -1
  115. package/lib/init/template/multitenancy/index.js +18 -3
  116. package/lib/init/template/notifications/index.js +2 -2
  117. package/lib/init/template/portal/files/mta.yaml.hbs +4 -0
  118. package/lib/init/template/portal/index.js +13 -8
  119. package/lib/init/template/postgres/index.js +2 -2
  120. package/lib/init/template/redis/index.js +2 -2
  121. package/lib/init/template/sample/files/db/currencies.cds +2 -0
  122. package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Authors.csv +1 -1
  123. package/lib/init/template/tiny-sample/files/nodejs/db/data/CatalogService.Books.csv +2 -2
  124. package/lib/init/template/workzone-standard/index.js +5 -5
  125. package/lib/init/template/xsuaa/index.js +20 -2
  126. package/lib/lint/eslintHelp.json +1 -1
  127. package/lib/mtx/auth_manager.js +103 -37
  128. package/lib/mtx/params.js +3 -2
  129. package/lib/mtx/settings_manager.js +45 -28
  130. package/lib/mtx/tenant_action.js +0 -1
  131. package/lib/mtx/util/credentials.js +62 -0
  132. package/node_modules/@sap/cds/CHANGELOG.md +57 -0
  133. package/node_modules/@sap/cds/app/index.js +5 -4
  134. package/node_modules/@sap/cds/eslint.config.mjs +1 -0
  135. package/node_modules/@sap/cds/lib/compile/minify.js +14 -10
  136. package/node_modules/@sap/cds/lib/env/cds-env.js +1 -1
  137. package/node_modules/@sap/cds/lib/env/cds-requires.js +22 -11
  138. package/node_modules/@sap/cds/lib/env/defaults.js +4 -1
  139. package/node_modules/@sap/cds/lib/env/schemas/cds-rc.js +5 -2
  140. package/node_modules/@sap/cds/lib/plugins.js +9 -5
  141. package/node_modules/@sap/cds/lib/req/spawn.js +1 -1
  142. package/node_modules/@sap/cds/lib/srv/srv-dispatch.js +1 -1
  143. package/node_modules/@sap/cds/lib/srv/srv-models.js +1 -1
  144. package/node_modules/@sap/cds/lib/utils/cds-utils.js +2 -1
  145. package/node_modules/@sap/cds/libx/_runtime/common/generic/assert.js +2 -3
  146. package/node_modules/@sap/cds/libx/_runtime/common/generic/auth/restrict.js +8 -1
  147. package/node_modules/@sap/cds/libx/_runtime/common/generic/crud.js +18 -8
  148. package/node_modules/@sap/cds/libx/_runtime/fiori/lean-draft.js +25 -17
  149. package/node_modules/@sap/cds/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +9 -3
  150. package/node_modules/@sap/cds/libx/_runtime/remote/Service.js +4 -19
  151. package/node_modules/@sap/cds/libx/_runtime/remote/utils/LruCache.js +42 -0
  152. package/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js +14 -4
  153. package/node_modules/@sap/cds/libx/_runtime/remote/utils/cloudSdkProvider.js +2 -9
  154. package/node_modules/@sap/cds/libx/_runtime/remote/utils/destinationClient.js +150 -0
  155. package/node_modules/@sap/cds/libx/_runtime/remote/utils/error.js +13 -0
  156. package/node_modules/@sap/cds/libx/_runtime/remote/utils/fetchClient.js +26 -18
  157. package/node_modules/@sap/cds/libx/_runtime/remote/utils/query.js +34 -23
  158. package/node_modules/@sap/cds/libx/_runtime/remote/utils/token.js +82 -0
  159. package/node_modules/@sap/cds/libx/_runtime/ucl/Service.js +36 -189
  160. package/node_modules/@sap/cds/libx/common/utils/streaming.js +16 -16
  161. package/node_modules/@sap/cds/libx/http/location.js +3 -3
  162. package/node_modules/@sap/cds/libx/odata/middleware/batch.js +16 -10
  163. package/node_modules/@sap/cds/libx/odata/middleware/metadata.js +9 -6
  164. package/node_modules/@sap/cds/libx/odata/middleware/service-document.js +1 -1
  165. package/node_modules/@sap/cds/libx/odata/parse/afterburner.js +19 -3
  166. package/node_modules/@sap/cds/libx/odata/parse/cqn2odata.js +83 -86
  167. package/node_modules/@sap/cds/libx/queue/SchedulingService.js +17 -2
  168. package/node_modules/@sap/cds/libx/queue/processing.js +1 -3
  169. package/node_modules/@sap/cds/libx/rest/RestAdapter.js +3 -7
  170. package/node_modules/@sap/cds/libx/rest/middleware/delete.js +3 -3
  171. package/node_modules/@sap/cds/libx/rest/middleware/parse.js +13 -8
  172. package/node_modules/@sap/cds/libx/rest/middleware/read.js +3 -3
  173. package/node_modules/@sap/cds/libx/rest/middleware/upsert.js +2 -2
  174. package/node_modules/@sap/cds/package.json +1 -1
  175. package/node_modules/@sap/cds-compiler/CHANGELOG.md +60 -8
  176. package/node_modules/@sap/cds-compiler/bin/cdsc.js +2 -2
  177. package/node_modules/@sap/cds-compiler/doc/IncompatibleChanges_v7.md +46 -19
  178. package/node_modules/@sap/cds-compiler/lib/api/main.js +10 -7
  179. package/node_modules/@sap/cds-compiler/lib/api/options.js +8 -2
  180. package/node_modules/@sap/cds-compiler/lib/base/csnRefs.js +5 -2
  181. package/node_modules/@sap/cds-compiler/lib/base/message-registry.js +4 -0
  182. package/node_modules/@sap/cds-compiler/lib/base/optionProcessor.js +12 -0
  183. package/node_modules/@sap/cds-compiler/lib/checks/enricher.js +1 -0
  184. package/node_modules/@sap/cds-compiler/lib/compiler/assert-consistency.js +8 -7
  185. package/node_modules/@sap/cds-compiler/lib/compiler/checks.js +3 -3
  186. package/node_modules/@sap/cds-compiler/lib/compiler/define.js +301 -75
  187. package/node_modules/@sap/cds-compiler/lib/compiler/dictionaries.js +2 -0
  188. package/node_modules/@sap/cds-compiler/lib/compiler/extend.js +40 -26
  189. package/node_modules/@sap/cds-compiler/lib/compiler/populate.js +45 -60
  190. package/node_modules/@sap/cds-compiler/lib/compiler/propagator.js +16 -7
  191. package/node_modules/@sap/cds-compiler/lib/compiler/resolve.js +41 -15
  192. package/node_modules/@sap/cds-compiler/lib/compiler/shared.js +7 -6
  193. package/node_modules/@sap/cds-compiler/lib/compiler/tweak-assocs.js +62 -50
  194. package/node_modules/@sap/cds-compiler/lib/compiler/utils.js +29 -14
  195. package/node_modules/@sap/cds-compiler/lib/edm/edmAnnoPreprocessor.js +6 -5
  196. package/node_modules/@sap/cds-compiler/lib/gen/CdlGrammar.checksum +1 -1
  197. package/node_modules/@sap/cds-compiler/lib/gen/CdlParser.js +1119 -1109
  198. package/node_modules/@sap/cds-compiler/lib/gen/Dictionary.json +19 -3
  199. package/node_modules/@sap/cds-compiler/lib/json/from-csn.js +10 -16
  200. package/node_modules/@sap/cds-compiler/lib/json/to-csn.js +58 -39
  201. package/node_modules/@sap/cds-compiler/lib/main.d.ts +8 -0
  202. package/node_modules/@sap/cds-compiler/lib/main.js +1 -0
  203. package/node_modules/@sap/cds-compiler/lib/model/csnUtils.js +2 -0
  204. package/node_modules/@sap/cds-compiler/lib/parsers/AstBuildingParser.js +2 -1
  205. package/node_modules/@sap/cds-compiler/lib/parsers/XprTree.js +8 -0
  206. package/node_modules/@sap/cds-compiler/lib/render/toCdl.js +22 -1
  207. package/node_modules/@sap/cds-compiler/lib/render/toSql.js +17 -2
  208. package/node_modules/@sap/cds-compiler/lib/render/utils/common.js +6 -1
  209. package/node_modules/@sap/cds-compiler/lib/render/utils/operators.js +27 -0
  210. package/node_modules/@sap/cds-compiler/lib/render/utils/standardDatabaseFunctions.js +125 -3
  211. package/node_modules/@sap/cds-compiler/lib/tool-lib/revealInternalProperties.js +2 -1
  212. package/node_modules/@sap/cds-compiler/lib/transform/db/applyTransformations.js +3 -0
  213. package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +8 -2
  214. package/node_modules/@sap/cds-compiler/lib/transform/db/backlinks.js +22 -6
  215. package/node_modules/@sap/cds-compiler/lib/transform/db/constraints.js +62 -1
  216. package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +40 -0
  217. package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +1 -0
  218. package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +6 -1
  219. package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +19 -8
  220. package/node_modules/@sap/cds-compiler/package.json +1 -1
  221. package/node_modules/@sap/cds-mtxs/CHANGELOG.md +15 -0
  222. package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +34 -16
  223. package/node_modules/@sap/cds-mtxs/lib/utils.js +19 -4
  224. package/node_modules/@sap/cds-mtxs/package.json +1 -1
  225. package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +1 -1
  226. package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +22 -13
  227. package/node_modules/@sap/cds-mtxs/srv/model-provider.js +17 -2
  228. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +1 -1
  229. package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +4 -8
  230. package/node_modules/@sap/xsenv/CHANGELOG.md +7 -0
  231. package/node_modules/@sap/xsenv/package.json +10 -7
  232. package/node_modules/body-parser/node_modules/content-type/README.md +2 -0
  233. package/node_modules/body-parser/node_modules/content-type/dist/index.d.ts +20 -0
  234. package/node_modules/body-parser/node_modules/content-type/dist/index.js +20 -14
  235. package/node_modules/body-parser/node_modules/content-type/dist/index.js.map +1 -1
  236. package/node_modules/body-parser/node_modules/content-type/package.json +1 -1
  237. package/node_modules/hdb/cfg/VERSION +1 -1
  238. package/node_modules/hdb/lib/protocol/ClientInfo.js +16 -3
  239. package/node_modules/hdb/lib/protocol/Connection.js +1 -0
  240. package/node_modules/hdb/package.json +3 -2
  241. package/node_modules/negotiator/lib/accept.js +54 -0
  242. package/node_modules/negotiator/lib/charset.js +10 -34
  243. package/node_modules/negotiator/lib/encoding.js +9 -30
  244. package/node_modules/negotiator/lib/language.js +15 -36
  245. package/node_modules/negotiator/lib/mediaType.js +16 -134
  246. package/node_modules/negotiator/node_modules/content-type/LICENSE +22 -0
  247. package/node_modules/negotiator/node_modules/content-type/README.md +71 -0
  248. package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +46 -0
  249. package/node_modules/negotiator/node_modules/content-type/dist/index.js +176 -0
  250. package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +1 -0
  251. package/node_modules/negotiator/node_modules/content-type/package.json +52 -0
  252. package/node_modules/negotiator/package.json +16 -10
  253. package/node_modules/qs/.github/THREAT_MODEL.md +3 -3
  254. package/node_modules/qs/CHANGELOG.md +15 -0
  255. package/node_modules/qs/README.md +19 -1
  256. package/node_modules/qs/dist/qs.js +21 -21
  257. package/node_modules/qs/eslint.config.mjs +1 -1
  258. package/node_modules/qs/lib/parse.js +3 -4
  259. package/node_modules/qs/lib/stringify.js +23 -8
  260. package/node_modules/qs/lib/utils.js +10 -3
  261. package/node_modules/qs/package.json +4 -4
  262. package/node_modules/qs/test/parse.js +192 -3
  263. package/node_modules/qs/test/stringify.js +317 -0
  264. package/node_modules/qs/test/utils.js +12 -0
  265. package/node_modules/type-is/node_modules/content-type/README.md +2 -0
  266. package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +20 -0
  267. package/node_modules/type-is/node_modules/content-type/dist/index.js +20 -14
  268. package/node_modules/type-is/node_modules/content-type/dist/index.js.map +1 -1
  269. package/node_modules/type-is/node_modules/content-type/package.json +1 -1
  270. package/node_modules/ws/lib/permessage-deflate.js +3 -1
  271. package/node_modules/ws/package.json +1 -1
  272. package/package.json +3 -3
  273. package/bin/completion/scripts/cds-bash.sh +0 -20
  274. package/bin/completion/scripts/cds-fish.fish +0 -13
  275. package/bin/completion/scripts/cds-ps.ps1 +0 -19
  276. package/bin/completion/scripts/cds-zsh.sh +0 -13
  277. package/lib/deploy/index.js +0 -25
  278. package/lib/import/asyncapi/importAsyncAPI.js +0 -33
  279. package/lib/import/asyncapi/index.js +0 -18
  280. package/lib/import/asyncapi/parserContext.js +0 -454
  281. package/lib/import/asyncapi/utils.js +0 -49
  282. package/node_modules/@sap/cds/libx/_runtime/ucl/queries.js +0 -61
  283. package/node_modules/negotiator/HISTORY.md +0 -114
  284. /package/{lib → bin}/upgrade/context.js +0 -0
  285. /package/{lib → bin}/upgrade/migrations/cds10/migrations.json +0 -0
  286. /package/{lib → bin}/upgrade/preflight/cds-version.js +0 -0
  287. /package/{lib → bin}/upgrade/preflight/project-type.js +0 -0
  288. /package/{lib → bin}/upgrade/steps/analyze/classification.js +0 -0
  289. /package/{lib → bin}/upgrade/steps/analyze/detector.js +0 -0
  290. /package/{lib → bin}/upgrade/steps/analyze/evaluator.js +0 -0
  291. /package/{lib → bin}/upgrade/steps/analyze/reporter.js +0 -0
  292. /package/{lib → bin}/upgrade/steps/analyze/setup.js +0 -0
  293. /package/{lib → bin}/upgrade/steps/analyze/utils/detection.js +0 -0
  294. /package/{lib → bin}/upgrade/steps/analyze/utils/files.js +0 -0
  295. /package/{lib → bin}/upgrade/steps/analyze/utils/grep.js +0 -0
  296. /package/{lib → bin}/upgrade/steps/analyze/utils/yaml.js +0 -0
  297. /package/{lib → bin}/upgrade/util/workspaces.js +0 -0
  298. /package/{lib → bin}/watch/esm-resolve-registration.js +0 -0
  299. /package/{lib → bin}/watch/livereload-server.js +0 -0
  300. /package/{lib → bin}/watch/node-watch.js +0 -0
  301. /package/{lib → bin}/watch/open.js +0 -0
  302. /package/{lib → bin}/watch/watcher.js +0 -0
@@ -18,6 +18,8 @@ const {
18
18
  initExprAnnoBlock,
19
19
  initBoundSelfParam,
20
20
  dependsOnSilent,
21
+ hasSecurityAnno,
22
+ extensionRefContext,
21
23
  pathName,
22
24
  annotationHasEllipsis,
23
25
  forEachInOrder,
@@ -525,14 +527,30 @@ function extend( model ) {
525
527
  prop === 'params' || prop === '$add' )
526
528
  return; // extensions currently handled extra
527
529
  // TODO: columns?
530
+ const isTypeParam = typeParameters.list.includes( prop );
531
+ const isAnnoOrDoc = prop.charAt(0) === '@' || prop === 'doc';
532
+ if (!isAnnoOrDoc && !isTypeParam && prop !== 'orderBy')
533
+ return;
528
534
  if (issue) {
535
+ if (prop === 'orderBy' && issue === 'unrelated') {
536
+ for (const ext of extensions) {
537
+ const clause = ext[prop];
538
+ if (clause) {
539
+ message( 'ext-unstable-order', [ clause[0]?.location || ext.location, ext ],
540
+ { keyword: prop },
541
+ // eslint-disable-next-line @stylistic/max-len
542
+ 'Unstable order of entries in the $(KEYWORD) clause due to another extension in unrelated layer' );
543
+ }
544
+ }
545
+ return;
546
+ }
529
547
  // eslint-disable-next-line no-nested-ternary
530
548
  let msg = (index < 0)
531
549
  ? 'anno-unstable-array'
532
550
  : (issue === true)
533
551
  ? 'anno-duplicate'
534
552
  : 'anno-duplicate-unrelated-layer';
535
- if (prop.charAt(0) !== '@' && prop !== 'doc') {
553
+ if (!isAnnoOrDoc) {
536
554
  msg = (issue === true)
537
555
  ? 'ext-duplicate-extend-type'
538
556
  : 'ext-duplicate-extend-type-unrelated-layer';
@@ -551,7 +569,7 @@ function extend( model ) {
551
569
  }
552
570
  else if (index > 0) { // more than one set (not just ...)
553
571
  const variant = prop === 'doc' ? 'doc' : 'std';
554
- const msgid = (prop.charAt(0) === '@' || prop === 'doc')
572
+ const msgid = (isAnnoOrDoc)
555
573
  ? 'anno-duplicate-same-file' // TODO: always ext-duplicate-…
556
574
  : 'ext-duplicate-same-file';
557
575
  while (index >= 0) { // do not report for trailing [...]
@@ -636,11 +654,27 @@ function extend( model ) {
636
654
  query[prop] = [];
637
655
  query[prop].push( ...clause );
638
656
  }
639
- else {
640
- if (query[prop]) {
641
- error( 'ext-unexpected-sql-clause', [ clause.location, ext ], { art, keyword: prop } );
642
- return;
657
+ else if (prop === 'where' || prop === 'having') {
658
+ const existing = query[prop];
659
+ if (!existing) {
660
+ query[prop] = clause;
661
+ }
662
+ else if (existing.op?.val === 'and' &&
663
+ existing.args.some( a => a.$extended === prop )) {
664
+ existing.args.push( clause );
665
+ }
666
+ else {
667
+ query[prop] = {
668
+ op: { val: 'and', location: art.name.location },
669
+ args: [ existing, clause ],
670
+ location: clause.location,
671
+ };
643
672
  }
673
+ }
674
+ else if (query[prop]) {
675
+ error( 'ext-unexpected-sql-clause', [ clause.location, ext ], { art, keyword: prop } );
676
+ }
677
+ else {
644
678
  query[prop] = clause;
645
679
  }
646
680
  }
@@ -1074,11 +1108,6 @@ function extend( model ) {
1074
1108
  forEachMember( annotate, createSuperAnnotate );
1075
1109
  }
1076
1110
 
1077
- function hasSecurityAnno( ext ) {
1078
- return ext['@restrict'] || ext['@requires'] ||
1079
- Object.keys( ext ).some( prop => prop.startsWith( '@ams.' ) );
1080
- }
1081
-
1082
1111
  function checkRemainingMainExtensions( art, ext ) {
1083
1112
  const refCtx = extensionRefContext( ext );
1084
1113
  if (resolvePath( ext.name, refCtx, ext ) && art?.builtin) {
@@ -1101,21 +1130,6 @@ function extend( model ) {
1101
1130
  }
1102
1131
  }
1103
1132
 
1104
- function extensionRefContext( ext ) {
1105
- if (ext.kind === 'annotate') {
1106
- if (hasSecurityAnno( ext ))
1107
- return 'annotate-sec';
1108
- }
1109
- else if (ext.artifacts || // extend … with definitions
1110
- ext._block.$frontend === 'json' && !ext.elements && !ext.actions) {
1111
- // TODO: not for `extend context` and `extend service` → !ext.expectedKind
1112
- // TODO v7: also fully with CSN input
1113
- if (!ext.doc && !Object.keys( ext ).some( a => a.charAt(0) === '@') )
1114
- return 'annotate'; // TODO: or an extra refCtx ?
1115
- }
1116
- return ext.kind;
1117
- }
1118
-
1119
1133
  // Issue messages for annotations on namespaces and builtins
1120
1134
  // (TODO: really here?, probably split main artifacts vs returns)
1121
1135
  // see also createRemainingAnnotateStatements() where similar messages are reported
@@ -19,7 +19,7 @@
19
19
 
20
20
  const { isDeprecatedEnabled } = require('../base/specialOptions');
21
21
  const {
22
- dictAdd, dictAddArray, dictFirst, dictForEach,
22
+ dictAdd, dictAddArray, dictForEach,
23
23
  } = require('./dictionaries');
24
24
  const { weakLocation, weakRefLocation } = require('../base/location');
25
25
  const { CompilerAssertion } = require('../base/error');
@@ -37,6 +37,7 @@ const {
37
37
  proxyCopyMembers,
38
38
  setExpandStatus,
39
39
  dependsOnSilent,
40
+ isLeadingQuery,
40
41
  columnRefStartsWithSelf,
41
42
  forEachDefinition,
42
43
  forEachMember,
@@ -127,7 +128,7 @@ function populate( model ) {
127
128
  effectiveType( art.targetAspect );
128
129
  forEachGeneric( art.targetAspect, 'elements', traverseElementEnvironments );
129
130
  }
130
- else if (art !== art._main?._leadingQuery) { // already done for leading query elems
131
+ else if (!isLeadingQuery( art )) { // already done for leading query elems
131
132
  while (art.items)
132
133
  art = art.items;
133
134
  forEachMember( art, traverseElementEnvironments );
@@ -209,7 +210,7 @@ function populate( model ) {
209
210
  // For a query and its parent (usually the query entity!), it is the other way
210
211
  // around: to calculate the _effectiveType of the query entity, we might need
211
212
  // to calculate the _effectiveType of a query in FROM first.
212
- if (a.kind !== 'select')
213
+ if (a.kind !== 'select' && a.kind !== '$tableAlias')
213
214
  effectiveType( a._outer || a._main && a._parent );
214
215
  // TODO: forbid $self+$self.elem inline, see expandWildcard()
215
216
  // Without type, value.path or _origin at beginning, link to itself:
@@ -267,24 +268,29 @@ function populate( model ) {
267
268
  }
268
269
 
269
270
  // With properties to be calculated: ----------------------------------------
270
- if (art.query && art.kind !== '$tableAlias') { // query entity
271
+ if (art.kind === '$tableAlias') {
272
+ if (!origEffective)
273
+ return origEffective;
274
+ proxyCopyMembers( art, 'elements', origEffective.elements, art.path?.location,
275
+ '$navElement' );
276
+ return art;
277
+ }
278
+ if (art.query) { // query entity/event/...
271
279
  const leading = art.$queries[0];
272
280
  if (!leading) // parse error
273
281
  return null;
274
282
  if (leading._effectiveType !== undefined) {
275
- // You cannot refer to a query of another artifact:
276
283
  throw new CompilerAssertion(
277
284
  `Unexpected _effectiveType on leading query of ${ art.name.id }`
278
285
  );
279
286
  }
280
- // TODO: try just return (effectiveType( leading )) === 0 ? 0 : art;
281
287
  setLink( leading, '_effectiveType', 0 ); // relevant to detect invalid $self.*
282
288
  populateQuery( leading );
283
289
  setLink( leading, '_effectiveType', leading );
284
290
  leading.$effectiveSeqNo = ++effectiveSeqNo;
285
291
  return art;
286
292
  }
287
- if (art.from)
293
+ if (art.from) // non-leading query
288
294
  return populateQuery( art );
289
295
 
290
296
  if (art.expand) {
@@ -292,7 +298,7 @@ function populate( model ) {
292
298
  // (we could allow that later: then some basic structural check is needed)
293
299
  if (!art.value) {
294
300
  initFromColumns( art, art.expand );
295
- if (origEffective?.target) // consider `{ … } as x: AssocType
301
+ if (origEffective?.target) // consider future feature `{ … } as x: AssocType
296
302
  redirectImplicitly( art, origEffective );
297
303
  }
298
304
  else if (art.value.path) {
@@ -368,35 +374,19 @@ function populate( model ) {
368
374
  }
369
375
 
370
376
  function getOriginRaw( art ) {
371
- if (!art._main) {
372
- if (art.query)
373
- return getOrigin( art.$queries?.[0] );
374
- // TODO: if we add the `includes` mechanism, use resolveUncheckedPath() for
375
- // includes here, because the accept function for includes requires the
376
- // elements to have been calculated!
377
- }
378
- else {
379
- // TODO: write checks for path in enum?
380
- if (art.value?.path)
381
- return resolvePath( art.value, (art.$syntax === 'calc' ? 'calc' : 'column'), art );
382
- if (art.kind === 'select') {
383
- const alias = dictFirst( art.$tableAliases );
384
- // With parse errors, the first “alias” might be $self. Using its origin
385
- // would lead to a cyclic processing dependency.
386
- return (alias.kind === '$tableAlias') ? getOrigin( alias ) : null;
387
- }
377
+ if (art.value?.path)
378
+ return resolvePath( art.value, (art.$syntax === 'calc' ? 'calc' : 'column'), art );
379
+
380
+ if (art.kind === '$tableAlias') {
388
381
  // init sets _origin for alias to sub query, only need to handle ref here:
389
- if (art.kind === '$tableAlias') {
390
- // do not call effectiveType() on the source to avoid a deeper callstack
391
- const source = resolvePath( art, 'from', art._parent );
392
- if (!source?._main)
393
- return source; // direct entity (or undefined)
394
- // Before having done the resolvePath cleanup, do not rely on resolvePath
395
- // to call effectiveType() on the last assoc of a from ref:
382
+ const source = resolvePath( art, 'from', art._parent );
383
+ if (!source?._main)
384
+ return source; // direct entity (or undefined)
385
+ // Before having done the resolvePath cleanup, do not rely on resolvePath
386
+ // to call effectiveType() on the last assoc of a from ref:
396
387
  // TODO: check this with test3/Queries/DollarSelf/CorruptedSource.err.cds
397
- const assoc = effectiveType( source );
398
- return assoc?.target._artifact;
399
- }
388
+ const assoc = effectiveType( source );
389
+ return assoc?.target._artifact;
400
390
  }
401
391
  return '';
402
392
  }
@@ -441,10 +431,6 @@ function populate( model ) {
441
431
  }
442
432
 
443
433
  function expandElements( art, struct ) {
444
- if (art.kind === '$tableAlias') {
445
- proxyCopyMembers( art, 'elements', struct.elements, art.path?.location, '$navElement' );
446
- return true;
447
- }
448
434
  if (art.elements || art.kind === '$inline' ||
449
435
  // no element expansions for "non-proper" types like
450
436
  // entities (as parameter types) etc:
@@ -552,7 +538,6 @@ function populate( model ) {
552
538
  //--------------------------------------------------------------------------
553
539
 
554
540
  // TODO: delete XSN._entities
555
- // TODO: delete ENTITY._from - use _origin? instead _from[0]
556
541
 
557
542
  /**
558
543
  * Merge _specified_ elements with _inferred_ elements in the given view/element,
@@ -779,7 +764,7 @@ function populate( model ) {
779
764
  const elemsParent = query.items || query;
780
765
  if (!inlineHead) {
781
766
  elemsParent.elements = Object.create( null );
782
- if (query._main._leadingQuery === query) // never the case for 'expand'
767
+ if (isLeadingQuery( query )) // never the case for 'expand'
783
768
  query._main.elements = elemsParent.elements;
784
769
  }
785
770
 
@@ -1085,7 +1070,7 @@ function populate( model ) {
1085
1070
  if (assoc.kind === 'mixin')
1086
1071
  return false;
1087
1072
  const query = userQuery( assoc );
1088
- return !query || query._main._leadingQuery === query;
1073
+ return !query || isLeadingQuery( query );
1089
1074
  }
1090
1075
 
1091
1076
  function redirectImplicitlyDo( elem, assoc, target, service ) {
@@ -1258,35 +1243,35 @@ function populate( model ) {
1258
1243
  }
1259
1244
 
1260
1245
  function isDirectProjection( proj, base ) {
1261
- return proj.kind === 'entity' && // not event
1262
- // direct proj (TODO: or should we add them to another list?)
1263
- proj.query && proj.query.op && proj.query.op.val === 'SELECT' &&
1264
- proj._from && proj._from.length === 1 &&
1265
- base === resolvePath( proj._from[0], 'from', proj.query );
1246
+ const { query } = proj;
1247
+ return query?.op?.val === 'SELECT' && proj.kind === 'entity' && // not event
1248
+ query.from?.path &&
1249
+ // TODO: what about navigation along assoc?
1250
+ base === resolvePath( query.from, 'from', query );
1266
1251
  }
1267
1252
 
1268
1253
  // Auto-exposure -----------------------------------------------------------
1269
1254
 
1270
- // TODO: do something in kick-start.js ?
1271
1255
  // Remark: With includes, the compiler propagates @cds.autoexpose early.
1272
1256
  function isAutoExposed( target ) {
1257
+ // remark: effectiveType( target ) has been called → we can use links directly
1273
1258
  if (target.$autoexpose !== undefined)
1274
1259
  return target.$autoexpose;
1275
- // Remark: this can probably be simplified now that we have called
1276
- // effectiveType() on the original target
1260
+
1277
1261
  const origTarget = target;
1278
1262
  const chain = [];
1279
- const alias1 = target._from?.[0]; // TODO: delete ENTITY._from ?
1280
- let source = alias1 && resolvePath( alias1, 'from', alias1._parent );
1281
- // query source ref might not have been resolved yet, cycle avoided as
1282
- // setAutoExposed() sets $autoexpose and a second call on same art would
1283
- // return false
1284
- while (target.$autoexpose === undefined && setAutoExposed( target ) && source) {
1263
+ while (target.$autoexpose === undefined && setAutoExposed( target )) {
1285
1264
  // stop at first ancestor with annotation or at non-query entity
1265
+ let source = target._origin; // first table alias of leading query
1266
+ // no propagation along `Source:assoc` → cannot traverse source._origin
1267
+ // until we find main artifact
1268
+ while (source?._origin?._main) // sub query in from
1269
+ source = source._origin._origin; // its first table alias
1270
+ source = source?._artifact; // different to source._origin if `Source:assoc`
1271
+ if (!source || source._main) // ref error of `Source:assoc`
1272
+ break;
1286
1273
  chain.push( target );
1287
1274
  target = source;
1288
- const alias = target._from?.[0]; // TODO: delete ENTITY._from ?
1289
- source = alias && resolvePath( alias, 'from', alias._parent );
1290
1275
  }
1291
1276
  const autoexpose = target.$autoexpose;
1292
1277
  if (typeof autoexpose === 'boolean') {
@@ -1302,11 +1287,11 @@ function populate( model ) {
1302
1287
  if (anno && anno.val !== null) { // XSN TODO: set val, but no location for anno short form
1303
1288
  // @cds.autoexpose:true or @cds.autoexpose:false
1304
1289
  art.$autoexpose = anno.val === undefined || !!anno.val;
1305
- return false;
1290
+ return false; // stop with @cds.autoexpose
1306
1291
  }
1307
1292
  // no @cds.autoexpose or @cds.autoexpose:null
1308
1293
  art.$autoexpose = model.$compositionTargets[art.name.id] ? true : null;
1309
- return true; // still check for inherited @cds.autoexpose
1294
+ return art.query; // still check for inherited @cds.autoexpose if query entity
1310
1295
  }
1311
1296
 
1312
1297
  function autoExposedName( target, service, elemScope ) {
@@ -12,12 +12,12 @@ const {
12
12
  setLink,
13
13
  linkToOrigin,
14
14
  withAssociation,
15
- viewFromPrimary,
16
15
  copyExpr,
17
16
  forEachDefinition,
18
17
  forEachMember,
19
18
  forEachGeneric,
20
19
  } = require('./utils');
20
+
21
21
  const { propagationRules } = require('../base/builtins');
22
22
  const $inferred = Symbol.for( 'cds.$inferred' );
23
23
  const { xprRewriteFns } = require('./xpr-rewrite');
@@ -328,11 +328,20 @@ function propagate( model ) {
328
328
  }
329
329
 
330
330
  function onlyViaArtifact( prop, target, source ) {
331
- const from = viewFromPrimary( target )?.path;
332
- // do not propagate from member / if follow assoc in from or into `returns` of actions (v4)
333
- if (!(from ? from[from.length - 1]._artifact : source)._main &&
334
- !(target._parent && target._parent.returns === target))
335
- annotation( prop, target, source );
331
+ if (source._main) // don't propagate from member
332
+ return;
333
+ // TODO v8: also do not propagate into member in general, now just not into returns
334
+ if (target._parent?.returns === target)
335
+ return;
336
+ // Additionally, do not propagate for `select from Source:assoc`:
337
+ if (target.query) {
338
+ let alias = target._origin;
339
+ while (alias?._origin?._main) // sub query in from
340
+ alias = alias._origin._origin; // its first table alias
341
+ if (alias?._artifact?._main) // Source:assoc` (BTW, `source` is its target)
342
+ return;
343
+ }
344
+ annotation( prop, target, source );
336
345
  }
337
346
 
338
347
  /**
@@ -426,7 +435,7 @@ function targetMinZero( art ) {
426
435
 
427
436
  function getOrigin( art ) {
428
437
  let origin = art._origin;
429
- while (origin?.kind === 'select')
438
+ while (origin?.kind === '$tableAlias' || origin?.kind === 'select')
430
439
  origin = origin._origin;
431
440
  if (origin)
432
441
  // Do not consider _origin if due to expand of table alias ref
@@ -59,6 +59,7 @@ const {
59
59
  compositionTextVariant,
60
60
  targetCantBeAspect,
61
61
  userParam,
62
+ isLeadingQuery,
62
63
  userQuery,
63
64
  forEachDefinition,
64
65
  forEachMember,
@@ -616,6 +617,8 @@ function resolve( model ) {
616
617
  }
617
618
  }
618
619
 
620
+ checkUnmanagedAssocInType( art );
621
+
619
622
  // Set '@Core.Computed' in the Core Compiler to have it propagated...
620
623
  if (art.kind !== 'element' || art['@Core.Computed'])
621
624
  return;
@@ -877,6 +880,20 @@ function resolve( model ) {
877
880
  }
878
881
  }
879
882
 
883
+ /**
884
+ * Warn if a type contains an unmanaged association, because the ON-condition
885
+ * can't be rewritten if the type is used as element type.
886
+ */
887
+ function checkUnmanagedAssocInType( art ) {
888
+ if (art._main?.kind !== 'type')
889
+ return;
890
+ if (!art.target || !getInheritedProp( art, 'on' ))
891
+ return;
892
+
893
+ warning( 'def-unsupported-assoc', [ art.name.location, art ], {},
894
+ 'With an unmanaged association, a type can only be used as include' );
895
+ }
896
+
880
897
  /**
881
898
  * Issue warnings for restrictions concerning `localized`, i.e. for situations
882
899
  * where a (later) inherited `localized` does not lead to the texts entity
@@ -1016,20 +1033,14 @@ function resolve( model ) {
1016
1033
  resolveExpr( col.value, 'column', col );
1017
1034
  // for (const col of query.$inlines)
1018
1035
  // if (!col.value.path) throw new CompilerAssertion(col.name.element)
1019
- if (query !== query._main._leadingQuery) // will be done later
1036
+ if (!isLeadingQuery( query )) // will be done later
1020
1037
  forEachGeneric( query, 'elements', resolveRefs );
1021
1038
  if (query.from)
1022
1039
  resolveJoinOn( query.from );
1023
- if (query.where) {
1024
- const user = query.where._block ? query.where : query;
1025
- resolveExpr( query.where, 'where', user );
1026
- }
1040
+ resolveWhereOrHaving( query, 'where' );
1027
1041
  if (query.groupBy)
1028
1042
  resolveBy( query.groupBy, 'groupBy', 'groupBy' );
1029
- if (query.having) {
1030
- const user = query.having._block ? query.having : query;
1031
- resolveExpr( query.having, 'having', user );
1032
- }
1043
+ resolveWhereOrHaving( query, 'having' );
1033
1044
  if (query.$orderBy) // ORDER BY from UNION:
1034
1045
  // TODO clarify: can I access the tab alias of outer queries? If not:
1035
1046
  // 4th arg query._main instead query._parent.
@@ -1087,6 +1098,23 @@ function resolve( model ) {
1087
1098
  }
1088
1099
  }
1089
1100
 
1101
+ function resolveWhereOrHaving( query, prop ) {
1102
+ const expr = query[prop];
1103
+ if (!expr)
1104
+ return;
1105
+ const merged = expr.op?.val === 'and' &&
1106
+ expr.args.some( a => a.$extended === prop );
1107
+ if (!merged) {
1108
+ const user = expr._block ? expr : query;
1109
+ resolveExpr( expr, prop, user );
1110
+ return;
1111
+ }
1112
+ for (const arg of expr.args) {
1113
+ const user = arg._block ? arg : query;
1114
+ resolveExpr( arg, prop, user );
1115
+ }
1116
+ }
1117
+
1090
1118
  /**
1091
1119
  * Resolve user-provided target.
1092
1120
  */
@@ -1186,8 +1214,7 @@ function resolve( model ) {
1186
1214
  if (assoc.on.$inferred)
1187
1215
  return;
1188
1216
  const query = userQuery( assoc );
1189
- const main = query?._main;
1190
- if (query && query !== main._leadingQuery) {
1217
+ if (query && !isLeadingQuery( query )) {
1191
1218
  const { txt, op } = getQueryOperatorName( query );
1192
1219
  const { location, id } = path[0];
1193
1220
  error( 'ref-unexpected-self', [ location, assoc ], { '#': txt, id, op } );
@@ -1662,7 +1689,7 @@ function resolve( model ) {
1662
1689
  .filter( i => i ), // _artifact may be `null` if the include cannot be found
1663
1690
  } );
1664
1691
  }
1665
- const query = art._leadingQuery;
1692
+ const query = art.$queries?.[0];
1666
1693
  if (!query)
1667
1694
  return false; // non-query entity
1668
1695
  if (!query.$tableAliases) // previous error in query definition
@@ -1781,8 +1808,7 @@ function resolve( model ) {
1781
1808
  const { query } = expr;
1782
1809
  if (!query.from && !query.args) // parser error
1783
1810
  return type; // ...see also TODO in initQueryExpression()
1784
- if (query._main?.kind === 'type' ||
1785
- (!query.kind && !query._leadingQuery)) { // UNION has _leadingQuery
1811
+ if (query._main?.kind === 'type' || query._origin === undefined) {
1786
1812
  error( 'expr-no-subquery', [ expr.location, user ], {
1787
1813
  '#': query._main?.kind === 'type' ? 'type' : 'std',
1788
1814
  }, {
@@ -1837,7 +1863,7 @@ function resolve( model ) {
1837
1863
  const unexpectedFilter = (expected !== 'annotation' && expected !== 'column' &&
1838
1864
  expected !== 'calc' && 'std') ||
1839
1865
  isQuasiVirtualAssociation( type ) && 'model-only' ||
1840
- last.where?.args?.length === 0 && 'last-empty-filter';
1866
+ expected === 'annotation' && last.where?.args?.length === 0 && 'last-empty-filter';
1841
1867
  reportUnexpectedArgsAndFilter( last, expected, user, art, unexpectedFilter );
1842
1868
  }
1843
1869
  // TODO: we should have different message-ids for the "last" stuff: adding
@@ -63,6 +63,7 @@ function fns( model ) {
63
63
  lexical: userBlock,
64
64
  dynamic: modelDefinitions,
65
65
  notFound: undefinedForAnnotate,
66
+ messageMap: { 'ref-undefined-def': 'ext-undefined-def' },
66
67
  accept: extendableArtifact,
67
68
  },
68
69
  'annotate-sec': {
@@ -1678,16 +1679,15 @@ function fns( model ) {
1678
1679
  /**
1679
1680
  * Returns true, if the artifact is a _real_ artifact that can be used for `extend`/`annotate`.
1680
1681
  */
1681
- function extendableArtifact( art, user, ref ) {
1682
+ function extendableArtifact( art, user, ref, semantics ) {
1682
1683
  if (art.kind !== 'namespace')
1683
1684
  return art;
1684
1685
  const { location } = ref.path[ref.path.length - 1];
1685
- if (user.kind === 'extend' && !(user.elements || user.actions || user.includes))
1686
- return art; // allow `extend with definitions` and empty extends
1686
+ if (user.artifacts)
1687
+ return art; // allow `extend with definitions` on "namespace" without message
1687
1688
 
1688
1689
  // for `annotate`, handle "namespaces" just like unknown artifacts: only emit a warning
1689
- signalNotFound( user.kind === 'annotate' ? 'ext-undefined-def' : 'ref-undefined-def',
1690
- [ location, user ], null, { art } );
1690
+ signalNotFound( 'ref-undefined-def', [ location, user ], null, { art }, semantics );
1691
1691
  return false;
1692
1692
  }
1693
1693
 
@@ -2024,6 +2024,7 @@ function fns( model ) {
2024
2024
  }
2025
2025
 
2026
2026
 
2027
+ // for message text variant and text argument:
2027
2028
  // right of union: parent = main → get correct operator
2028
2029
  // FROM subquery: parent = tab alias of outer query
2029
2030
  // other sub query: parent = outer query
@@ -2033,7 +2034,7 @@ function fns( model ) {
2033
2034
 
2034
2035
  for (let set = query._main.query; set.op; set = set.args[0]) {
2035
2036
  const right = set.args[1];
2036
- if (query.name.id >= ((right._leadingQuery || right).name?.id ?? 0))
2037
+ if (right.name && query.name.id >= (right.name.id ?? 0))
2037
2038
  return { txt: 'setQuery', op: set.op.val };
2038
2039
  }
2039
2040
  throw new CompilerAssertion( 'Did we pass the leading query as argument?' );