@sap/cds 6.1.2 → 6.2.1
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 +92 -8
- package/apis/cds.d.ts +18 -6
- package/apis/connect.d.ts +1 -1
- package/apis/cqn.d.ts +1 -1
- package/apis/log.d.ts +23 -5
- package/apis/ql.d.ts +128 -61
- package/apis/services.d.ts +11 -0
- package/apis/test.d.ts +61 -0
- package/apis/utils.d.ts +15 -0
- package/app/fiori/preview.js +1 -0
- package/bin/build/buildTaskEngine.js +70 -22
- package/bin/build/buildTaskFactory.js +18 -11
- package/bin/build/buildTaskHandler.js +1 -1
- package/bin/build/buildTaskProviderFactory.js +3 -13
- package/bin/build/constants.js +0 -1
- package/bin/build/index.js +14 -6
- package/bin/build/provider/buildTaskHandlerEdmx.js +2 -3
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +2 -2
- package/bin/build/provider/buildTaskHandlerInternal.js +3 -6
- package/bin/build/provider/buildTaskProviderInternal.js +51 -39
- package/bin/build/provider/fiori/index.js +3 -3
- package/bin/build/provider/hana/2migration.js +1 -1
- package/bin/build/provider/hana/index.js +34 -27
- package/bin/build/provider/java/index.js +6 -7
- package/bin/build/provider/mtx/index.js +20 -18
- package/bin/build/provider/mtx/resourcesTarBuilder.js +8 -11
- package/bin/build/provider/mtx-sidecar/index.js +13 -17
- package/bin/build/provider/nodejs/index.js +8 -7
- package/bin/build/util.js +22 -4
- package/bin/cds.js +8 -4
- package/bin/deploy/to-hana/cfUtil.js +53 -18
- package/bin/mtx/in-cds.js +1 -0
- package/bin/serve.js +37 -30
- package/lib/auth/basic-auth.js +33 -0
- package/lib/auth/dummy-auth.js +7 -0
- package/lib/auth/ias-auth.js +2 -0
- package/lib/auth/index.js +31 -0
- package/lib/auth/jwt-auth.js +3 -0
- package/lib/auth/mocked-users.js +72 -0
- package/lib/auth/passport-basic.js +12 -0
- package/lib/auth/passport-digest.js +14 -0
- package/lib/auth/xsuaa-auth.js +3 -0
- package/lib/compile/cds-compile.js +3 -3
- package/lib/compile/to/cdl.js +5 -1
- package/lib/compile/to/edm.js +8 -0
- package/lib/compile/to/gql.js +1 -0
- package/lib/compile/to/json.js +30 -5
- package/lib/compile/to/sql.js +3 -1
- package/lib/core/index.js +5 -1
- package/lib/dbs/cds-deploy.js +36 -6
- package/lib/env/cds-env.js +15 -5
- package/lib/env/cds-requires.js +51 -58
- package/lib/env/defaults.js +1 -0
- package/lib/env/schemas/cds-package.json +4 -0
- package/lib/env/schemas/cds-rc.json +63 -77
- package/lib/i18n/localize.js +16 -5
- package/lib/index.js +9 -4
- package/lib/log/cds-error.js +4 -6
- package/lib/log/cds-log.js +89 -53
- package/lib/log/service/index.js +1 -0
- package/lib/ql/CREATE.js +2 -5
- package/lib/ql/DELETE.js +1 -1
- package/lib/ql/DROP.js +1 -3
- package/lib/ql/INSERT.js +3 -3
- package/lib/ql/Query.js +10 -23
- package/lib/ql/SELECT.js +1 -2
- package/lib/ql/UPDATE.js +2 -2
- package/lib/ql/Whereable.js +7 -15
- package/lib/ql/cds-ql.js +9 -3
- package/lib/req/cds-context.js +11 -3
- package/lib/req/context.js +29 -23
- package/lib/req/locale.js +9 -5
- package/lib/req/request.js +1 -0
- package/lib/req/user.js +2 -1
- package/lib/srv/cds-connect.js +1 -1
- package/lib/srv/cds-serve.js +21 -14
- package/lib/srv/middlewares/cds-context.js +29 -0
- package/lib/srv/middlewares/ctx-model.js +24 -0
- package/lib/srv/middlewares/errors.js +9 -0
- package/lib/srv/middlewares/index.js +22 -0
- package/lib/srv/middlewares/sap-statistics.js +13 -0
- package/lib/srv/middlewares/trace.js +102 -0
- package/lib/srv/protocols/_legacy.js +42 -0
- package/lib/srv/protocols/graphql.js +39 -0
- package/lib/srv/protocols/hcql.js +37 -0
- package/lib/srv/protocols/index.js +86 -0
- package/lib/srv/protocols/odata-v2-proxy.js +3767 -0
- package/lib/srv/protocols/odata-v2.js +26 -0
- package/lib/srv/protocols/odata-v4.js +16 -0
- package/lib/srv/protocols/rest.js +13 -0
- package/lib/srv/srv-api.js +5 -0
- package/lib/srv/srv-models.js +4 -6
- package/lib/utils/axios.js +3 -2
- package/lib/utils/cds-test.js +27 -21
- package/lib/utils/cds-utils.js +19 -20
- package/lib/utils/tar.js +175 -0
- package/libx/_runtime/audit/generic/personal/utils.js +18 -7
- package/libx/_runtime/audit/utils/v2.js +1 -0
- package/libx/_runtime/auth/index.js +4 -0
- package/libx/_runtime/auth/strategies/ias-auth.js +76 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +8 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +15 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/orderByToCQN.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ResourcePathParser.js +9 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriInfo.js +5 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriParser.js +12 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/BufferedWriter.js +6 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/RequestValidator.js +47 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +0 -2
- package/libx/_runtime/cds-services/services/utils/compareJson.js +3 -1
- package/libx/_runtime/cds-services/util/assert.js +7 -0
- package/libx/_runtime/common/aspects/relation.js +1 -1
- package/libx/_runtime/common/composition/data.js +61 -15
- package/libx/_runtime/common/composition/delete.js +0 -1
- package/libx/_runtime/common/composition/insert.js +0 -1
- package/libx/_runtime/common/composition/tree.js +4 -10
- package/libx/_runtime/common/composition/update.js +44 -21
- package/libx/_runtime/common/generic/auth/capabilities.js +8 -10
- package/libx/_runtime/common/generic/crud.js +1 -2
- package/libx/_runtime/common/generic/etag.js +4 -4
- package/libx/_runtime/common/generic/input.js +21 -6
- package/libx/_runtime/common/generic/paging.js +3 -3
- package/libx/_runtime/common/generic/put.js +7 -4
- package/libx/_runtime/common/generic/sorting.js +4 -4
- package/libx/_runtime/common/generic/temporal.js +3 -6
- package/libx/_runtime/common/i18n/messages.properties +0 -7
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +11 -6
- package/libx/_runtime/common/utils/csn.js +0 -28
- package/libx/_runtime/common/utils/draft.js +8 -1
- package/libx/_runtime/common/utils/path.js +7 -1
- package/libx/_runtime/common/utils/propagateForeignKeys.js +122 -0
- package/libx/_runtime/common/utils/resolveView.js +2 -3
- package/libx/_runtime/common/utils/template.js +2 -3
- package/libx/_runtime/db/data-conversion/post-processing.js +3 -44
- package/libx/_runtime/db/generic/input.js +6 -6
- package/libx/_runtime/db/sql-builder/dataTypes.js +4 -0
- package/libx/_runtime/fiori/generic/activate.js +2 -2
- package/libx/_runtime/fiori/generic/before.js +40 -72
- package/libx/_runtime/fiori/generic/cancel.js +2 -2
- package/libx/_runtime/fiori/generic/delete.js +2 -2
- package/libx/_runtime/fiori/generic/edit.js +2 -2
- package/libx/_runtime/fiori/generic/new.js +3 -5
- package/libx/_runtime/fiori/generic/patch.js +49 -43
- package/libx/_runtime/fiori/generic/prepare.js +2 -2
- package/libx/_runtime/fiori/generic/read.js +27 -37
- package/libx/_runtime/fiori/utils/where.js +4 -2
- package/libx/_runtime/hana/Service.js +1 -3
- package/libx/_runtime/hana/conversion.js +3 -0
- package/libx/_runtime/hana/driver.js +33 -3
- package/libx/_runtime/hana/dynatrace.js +1 -0
- package/libx/_runtime/hana/search2Contains.js +12 -1
- package/libx/_runtime/hana/search2cqn4sql.js +10 -27
- package/libx/_runtime/hana/streaming.js +1 -0
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +4 -2
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +1 -0
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +5 -2
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -0
- package/libx/_runtime/messaging/enterprise-messaging.js +62 -3
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/messaging/redis-messaging.js +1 -0
- package/libx/_runtime/remote/Service.js +2 -2
- package/libx/_runtime/remote/utils/client.js +35 -11
- package/libx/_runtime/remote/utils/data.js +7 -2
- package/libx/_runtime/sqlite/Service.js +18 -7
- package/libx/_runtime/sqlite/conversion.js +3 -0
- package/libx/_runtime/sqlite/convertAssocToOneManaged.js +3 -3
- package/libx/_runtime/sqlite/localized.js +8 -8
- package/libx/odata/afterburner.js +39 -7
- package/libx/odata/cqn2odata.js +6 -3
- package/libx/odata/grammar.pegjs +66 -18
- package/libx/odata/index.js +3 -2
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +2 -0
- package/libx/rest/RestAdapter.js +62 -43
- package/libx/rest/middleware/input.js +2 -3
- package/libx/rest/middleware/parse.js +2 -1
- package/libx/rest/middleware/update.js +1 -1
- package/package.json +2 -2
- package/server.js +5 -4
- package/srv/mtx.cds +1 -1
- package/srv/mtx.js +4 -24
- package/lib/srv/adapters.js +0 -85
- package/lib/utils/resources/index.js +0 -48
- package/lib/utils/resources/tar.js +0 -49
- package/lib/utils/resources/utils.js +0 -11
- package/libx/_runtime/db/utils/propagateForeignKeys.js +0 -93
- package/libx/_runtime/extensibility/activate.js +0 -69
- package/libx/_runtime/extensibility/add.js +0 -50
- package/libx/_runtime/extensibility/addExtension.js +0 -72
- package/libx/_runtime/extensibility/defaults.js +0 -34
- package/libx/_runtime/extensibility/handler/transformREAD.js +0 -121
- package/libx/_runtime/extensibility/handler/transformRESULT.js +0 -51
- package/libx/_runtime/extensibility/handler/transformWRITE.js +0 -64
- package/libx/_runtime/extensibility/linter/allowlist_checker.js +0 -373
- package/libx/_runtime/extensibility/linter/annotations_checker.js +0 -113
- package/libx/_runtime/extensibility/linter/checker_base.js +0 -20
- package/libx/_runtime/extensibility/linter/namespace_checker.js +0 -180
- package/libx/_runtime/extensibility/linter.js +0 -32
- package/libx/_runtime/extensibility/push.js +0 -118
- package/libx/_runtime/extensibility/service.js +0 -38
- package/libx/_runtime/extensibility/token.js +0 -57
- package/libx/_runtime/extensibility/utils.js +0 -131
- package/libx/_runtime/extensibility/validation.js +0 -50
- package/libx/_runtime/extensibility/views.js +0 -12
- package/srv/extensibility-service.cds +0 -59
- package/srv/extensibility-service.js +0 -1
- package/srv/extensions.cds +0 -8
- package/srv/model-provider.cds +0 -61
- package/srv/model-provider.js +0 -143
|
@@ -11,6 +11,7 @@ const cds = require('../../cds')
|
|
|
11
11
|
const LOG = cds.log('app')
|
|
12
12
|
const { enrichDataWithKeysFromWhere } = require('../utils/keys')
|
|
13
13
|
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
14
|
+
const propagateForeignKeys = require('../utils/propagateForeignKeys')
|
|
14
15
|
const { checkInputConstraints, assertTargets } = require('../../cds-services/util/assert')
|
|
15
16
|
const getTemplate = require('../utils/template')
|
|
16
17
|
const templateProcessor = require('../utils/templateProcessor')
|
|
@@ -126,6 +127,11 @@ const _processCategory = (req, category, value, elementInfo, assertMap) => {
|
|
|
126
127
|
const { row, key, element, isRoot } = elementInfo
|
|
127
128
|
category = _getSimpleCategory(category)
|
|
128
129
|
|
|
130
|
+
if (category === 'propagateForeignKeys') {
|
|
131
|
+
propagateForeignKeys(key, row, element._foreignKeys, element.isComposition, { enumerable: false })
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
|
|
129
135
|
// remember mandatory
|
|
130
136
|
if (category === 'mandatory') {
|
|
131
137
|
value.mandatory = true
|
|
@@ -147,7 +153,7 @@ const _processCategory = (req, category, value, elementInfo, assertMap) => {
|
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
// generate UUIDs
|
|
150
|
-
if (category === 'uuid' && !value.val && (event !== 'UPDATE' || !isRoot)) {
|
|
156
|
+
if (category === 'uuid' && !value.val && ((event !== 'UPDATE' && event !== 'PATCH') || !isRoot)) {
|
|
151
157
|
value.val = row[key] = cds.utils.uuid()
|
|
152
158
|
}
|
|
153
159
|
|
|
@@ -186,6 +192,11 @@ const _pick = element => {
|
|
|
186
192
|
// collect actions to apply
|
|
187
193
|
const categories = []
|
|
188
194
|
|
|
195
|
+
// REVISIT: element._foreignKeys.length seems to be a very broad check
|
|
196
|
+
if (element.isAssociation && element._foreignKeys.length) {
|
|
197
|
+
categories.push({ category: 'propagateForeignKeys' })
|
|
198
|
+
}
|
|
199
|
+
|
|
189
200
|
if (element['@assert.range'] || element['@assert.enum'] || element['@assert.format']) {
|
|
190
201
|
categories.push('assert')
|
|
191
202
|
}
|
|
@@ -237,11 +248,14 @@ const _getBoundActionBindingParameter = req => {
|
|
|
237
248
|
return (actions && actions[action] && actions[action]['@cds.odata.bindingparameter.name']) || 'in'
|
|
238
249
|
}
|
|
239
250
|
|
|
240
|
-
async function
|
|
251
|
+
async function commonGenericInput(req) {
|
|
241
252
|
if (!req.query) return // FIXME: the code below expects req.query to be defined
|
|
242
253
|
if (!req.target) return
|
|
243
254
|
|
|
244
|
-
const template = getTemplate('app-input', this, req.target, {
|
|
255
|
+
const template = getTemplate('app-input', this, req.target, {
|
|
256
|
+
pick: _pick,
|
|
257
|
+
ignore: element => element._isAssociationStrict
|
|
258
|
+
})
|
|
245
259
|
if (template.elements.size === 0) return
|
|
246
260
|
|
|
247
261
|
const errors = []
|
|
@@ -301,7 +315,8 @@ const _processActionFunctionRow = (row, param, key, errors, event, service) => {
|
|
|
301
315
|
|
|
302
316
|
// structured
|
|
303
317
|
const template = getTemplate('app-input-operation', service, param, {
|
|
304
|
-
pick: _pick
|
|
318
|
+
pick: _pick,
|
|
319
|
+
ignore: element => element._isAssociationStrict
|
|
305
320
|
})
|
|
306
321
|
|
|
307
322
|
if (template && template.elements.size) {
|
|
@@ -371,11 +386,11 @@ function _actionFunctionHandler(req) {
|
|
|
371
386
|
_callError(req, errors)
|
|
372
387
|
}
|
|
373
388
|
|
|
374
|
-
|
|
389
|
+
commonGenericInput._initial = true
|
|
375
390
|
_actionFunctionHandler._initial = true
|
|
376
391
|
|
|
377
392
|
module.exports = cds.service.impl(function () {
|
|
378
|
-
this.before(['CREATE', 'UPDATE', 'NEW', 'PATCH'], '*',
|
|
393
|
+
this.before(['CREATE', 'UPDATE', 'NEW', 'PATCH'], '*', commonGenericInput)
|
|
379
394
|
const operationNames = []
|
|
380
395
|
|
|
381
396
|
for (const operation of this.operations) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const { getDefaultPageSize, getMaxPageSize } = require('../utils/page')
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const commonGenericPaging = function (req) {
|
|
5
5
|
// only if http request
|
|
6
6
|
if (!req._.req) return
|
|
7
7
|
|
|
@@ -24,6 +24,6 @@ const _addPaging = function (query, target) {
|
|
|
24
24
|
* handler registration
|
|
25
25
|
*/
|
|
26
26
|
module.exports = cds.service.impl(function () {
|
|
27
|
-
|
|
28
|
-
this.before('READ', '*',
|
|
27
|
+
commonGenericPaging._initial = true
|
|
28
|
+
this.before('READ', '*', commonGenericPaging)
|
|
29
29
|
})
|
|
@@ -55,7 +55,7 @@ const _pick = element => {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function
|
|
58
|
+
function commonGenericPut(req) {
|
|
59
59
|
if (req.method !== 'PUT') return
|
|
60
60
|
if (!req.query) return // FIXME: the code below expects req.query to be defined
|
|
61
61
|
if (!req.target) return
|
|
@@ -64,7 +64,10 @@ function _handler(req) {
|
|
|
64
64
|
const { elements } = req.target
|
|
65
65
|
for (const k in req.data) if (k in elements && elements[k]['@Core.MediaType']) return
|
|
66
66
|
|
|
67
|
-
const template = getTemplate('app-put', this, req.target, {
|
|
67
|
+
const template = getTemplate('app-put', this, req.target, {
|
|
68
|
+
pick: _pick,
|
|
69
|
+
ignore: element => element._isAssociationStrict
|
|
70
|
+
})
|
|
68
71
|
if (template.elements.size === 0) return
|
|
69
72
|
|
|
70
73
|
// REVISIT: req.data should point into req.query
|
|
@@ -84,8 +87,8 @@ function _handler(req) {
|
|
|
84
87
|
setDataFromCQN(req)
|
|
85
88
|
}
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
commonGenericPut._initial = true
|
|
88
91
|
|
|
89
92
|
module.exports = cds.service.impl(function () {
|
|
90
|
-
this.before(['UPDATE'], '*',
|
|
93
|
+
this.before(['UPDATE'], '*', commonGenericPut)
|
|
91
94
|
})
|
|
@@ -43,7 +43,7 @@ const _getStaticOrders = req => {
|
|
|
43
43
|
*
|
|
44
44
|
* @param req
|
|
45
45
|
*/
|
|
46
|
-
const
|
|
46
|
+
const commonGenericSorting = function (req) {
|
|
47
47
|
if (!req.query || !req.query.SELECT || req.query.SELECT.one) return
|
|
48
48
|
|
|
49
49
|
let select = req.query.SELECT
|
|
@@ -77,9 +77,9 @@ const _handler = function (req) {
|
|
|
77
77
|
* handler registration
|
|
78
78
|
*/
|
|
79
79
|
module.exports = cds.service.impl(function () {
|
|
80
|
-
|
|
81
|
-
this.before('READ', '*',
|
|
80
|
+
commonGenericSorting._initial = true
|
|
81
|
+
this.before('READ', '*', commonGenericSorting)
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
// REVISIT: remove (currently needed for test)
|
|
85
|
-
module.exports.handler =
|
|
85
|
+
module.exports.handler = commonGenericSorting
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
-
const LOG = cds.log('app')
|
|
3
2
|
|
|
4
3
|
const _getDateFromQueryOptions = str => {
|
|
5
4
|
if (str) {
|
|
@@ -11,8 +10,6 @@ const _getDateFromQueryOptions = str => {
|
|
|
11
10
|
|
|
12
11
|
const _isDate = dateStr => !dateStr.includes(':')
|
|
13
12
|
const _isTimestamp = dateStr => dateStr.includes('.')
|
|
14
|
-
const _isWarningRequired = (warning, queryOptions) =>
|
|
15
|
-
!warning && queryOptions && (queryOptions['sap-valid-from'] || queryOptions['sap-valid-to'])
|
|
16
13
|
const _isAsOfNow = queryOptions =>
|
|
17
14
|
!queryOptions || (!queryOptions['sap-valid-at'] && !queryOptions['sap-valid-to'] && !queryOptions['sap-valid-from'])
|
|
18
15
|
|
|
@@ -41,7 +38,7 @@ const _getTimeDelta = (target, queryOption) => {
|
|
|
41
38
|
*
|
|
42
39
|
* @param req
|
|
43
40
|
*/
|
|
44
|
-
const
|
|
41
|
+
const commonGenericTemporal = function (req) {
|
|
45
42
|
// REVISIT: public API for query options
|
|
46
43
|
const { _queryOptions } = req
|
|
47
44
|
|
|
@@ -70,7 +67,7 @@ const _handler = function (req) {
|
|
|
70
67
|
* handler registration
|
|
71
68
|
*/
|
|
72
69
|
module.exports = cds.service.impl(function () {
|
|
73
|
-
|
|
70
|
+
commonGenericTemporal._initial = true
|
|
74
71
|
// always run to allow interaction with temporal data in custom handlers
|
|
75
|
-
this.before('*',
|
|
72
|
+
this.before('*', commonGenericTemporal)
|
|
76
73
|
})
|
|
@@ -49,10 +49,6 @@ ASSERT_REFERENCE_INTEGRITY=Reference integrity is violated for association "{0}"
|
|
|
49
49
|
ASSERT_TARGET="Value doesn't exist"
|
|
50
50
|
ASSERT_DEEP_ASSOCIATION=It is not allowed to modify sub documents in {0} Association "{1}"
|
|
51
51
|
|
|
52
|
-
# persistence
|
|
53
|
-
PERSISTENCE_SKIP_NO_GENERIC_CRUD=Entity "{0}" is annotated with "@sap.persistence.skip" and cannot be served generically.
|
|
54
|
-
NON_WRITABLE_VIEW={0} on views with join and/or union is not supported
|
|
55
|
-
|
|
56
52
|
# db
|
|
57
53
|
NO_DATABASE_CONNECTION=No database connection
|
|
58
54
|
ENTITY_ALREADY_EXISTS=Entity already exists
|
|
@@ -74,9 +70,6 @@ ENTITY_IS_NOT_CRUD=Entity "{0}" is not {1}
|
|
|
74
70
|
ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via navigation "{2}"
|
|
75
71
|
ENTITY_IS_AUTOEXPOSED=Entity "{0}" is not explicitly exposed as part of the service
|
|
76
72
|
EXPAND_IS_RESTRICTED=Navigation property "{0}" is not allowed for expand operation
|
|
77
|
-
EXPAND_COUNT_UNSUPPORTED="/$count" is not supported for expand operation
|
|
78
|
-
ORDERBY_LAMBDA_UNSUPPORTED="$orderby" does not support lambda
|
|
79
|
-
EXPAND_APPLY_UNSUPPORTED="$apply" is not supported for expand operation
|
|
80
73
|
|
|
81
74
|
# rest protocol adapter
|
|
82
75
|
INVALID_RESOURCE="{0}" is not a valid resource
|
|
@@ -5,7 +5,7 @@ const { SELECT, INSERT, DELETE, UPDATE } = cds.ql
|
|
|
5
5
|
const Query = require('../../../../lib/ql/Query')
|
|
6
6
|
|
|
7
7
|
const { resolveView } = require('./resolveView')
|
|
8
|
-
const { ensureNoDraftsSuffix, getDraftColumnsCQNForDraft } = require('./draft')
|
|
8
|
+
const { ensureNoDraftsSuffix, getDraftColumnsCQNForDraft, ensureDraftsSuffix } = require('./draft')
|
|
9
9
|
const { flattenStructuredSelect, OPERATIONS_MAP } = require('./structured')
|
|
10
10
|
const search2cqn4sql = require('./search2cqn4sql')
|
|
11
11
|
const { getEntityNameFromCQN } = require('./entityFromCqn')
|
|
@@ -43,11 +43,11 @@ const convertPathExpressionToWhere = (fromClause, model, options) => {
|
|
|
43
43
|
return { target, alias, where, cardinality, args }
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
let previousSelect, previousEntityName, previousTableAlias, structParent, previousArgs
|
|
46
|
+
let previousSelect, previousEntityName, previousTableAlias, structParent, previousArgs, draft
|
|
47
47
|
let prefix = []
|
|
48
48
|
let columns
|
|
49
49
|
for (let i = 0; i < fromClause.ref.length; i++) {
|
|
50
|
-
const entity = structParent || model.definitions[previousEntityName]
|
|
50
|
+
const entity = structParent || (previousEntityName && model.definitions[ensureNoDraftsSuffix(previousEntityName)])
|
|
51
51
|
const element = _elementFromRef(fromClause.ref[i], entity)
|
|
52
52
|
|
|
53
53
|
if (element && element._isStructured) {
|
|
@@ -55,6 +55,7 @@ const convertPathExpressionToWhere = (fromClause, model, options) => {
|
|
|
55
55
|
structParent = element
|
|
56
56
|
continue
|
|
57
57
|
} else if (element && element.isAssociation) {
|
|
58
|
+
if (element._isAssociationStrict && !element['@odata.draft.enclosed']) draft = false
|
|
58
59
|
_modifyNavigationInWhere(fromClause.ref[i].where, element._target)
|
|
59
60
|
} else if (element && previousSelect && i === fromClause.ref.length - 1) {
|
|
60
61
|
columns = [{ ref: [...prefix, element.name] }]
|
|
@@ -62,8 +63,10 @@ const convertPathExpressionToWhere = (fromClause, model, options) => {
|
|
|
62
63
|
continue
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
const
|
|
66
|
+
const entityName = _getEntityName(fromClause, entity, i)
|
|
67
|
+
const currentEntityName = draft ? entityName && ensureDraftsSuffix(entityName) : entityName
|
|
66
68
|
if (!currentEntityName) continue
|
|
69
|
+
if (!draft && currentEntityName.endsWith('_drafts')) draft = true
|
|
67
70
|
const tableAlias = `T${i}`
|
|
68
71
|
const currentSelect = SELECT.from(`${currentEntityName} as ${tableAlias}`)
|
|
69
72
|
|
|
@@ -81,7 +84,10 @@ const convertPathExpressionToWhere = (fromClause, model, options) => {
|
|
|
81
84
|
if (previousSelect) {
|
|
82
85
|
const navigation = _getTargetFromRef(fromClause.ref[i])
|
|
83
86
|
previousSelect.where(
|
|
84
|
-
model.definitions[previousEntityName]._relations[[...prefix, navigation]].join(
|
|
87
|
+
model.definitions[ensureNoDraftsSuffix(previousEntityName)]._relations[[...prefix, navigation]].join(
|
|
88
|
+
tableAlias,
|
|
89
|
+
previousTableAlias
|
|
90
|
+
)
|
|
85
91
|
)
|
|
86
92
|
_convertSelect(previousSelect, model, options)
|
|
87
93
|
currentSelect.where('exists', previousSelect)
|
|
@@ -613,7 +619,6 @@ const _convertPathExpression = (query, model, options = {}) => {
|
|
|
613
619
|
for (const whereEl of query.SELECT.where || []) {
|
|
614
620
|
if (typeof whereEl === 'object' && whereEl.SELECT) _convertPathExpression(whereEl, model)
|
|
615
621
|
}
|
|
616
|
-
|
|
617
622
|
const conversion = convertPathExpressionToWhere(query.SELECT.from, model, options)
|
|
618
623
|
if (!conversion) return
|
|
619
624
|
const { target, alias, where, cardinality, columns, args } = conversion
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const resolveStructured = require('../../common/utils/resolveStructured')
|
|
3
3
|
|
|
4
|
-
const { ensureNoDraftsSuffix } = require('./draft')
|
|
5
|
-
|
|
6
4
|
const getEtagElement = entity => {
|
|
7
5
|
return Object.values(entity.elements).find(element => element['@odata.etag'])
|
|
8
6
|
}
|
|
@@ -165,31 +163,6 @@ const getElementDeep = (entity, ref) => {
|
|
|
165
163
|
return current
|
|
166
164
|
}
|
|
167
165
|
|
|
168
|
-
const isRootEntity = (definitions, entityName) => {
|
|
169
|
-
const entity = definitions[entityName]
|
|
170
|
-
if (!entity) return false
|
|
171
|
-
|
|
172
|
-
// TODO: There can be unmanaged relations to some parent -> not detected by the following code
|
|
173
|
-
const associationElements = Object.keys(entity.elements)
|
|
174
|
-
.map(key => entity.elements[key])
|
|
175
|
-
.filter(element => element._isAssociationStrict)
|
|
176
|
-
|
|
177
|
-
for (const { target } of associationElements) {
|
|
178
|
-
const parentEntity = definitions[target]
|
|
179
|
-
for (const parentElementName in parentEntity.elements) {
|
|
180
|
-
const parentElement = parentEntity.elements[parentElementName]
|
|
181
|
-
if (
|
|
182
|
-
parentElement.isComposition &&
|
|
183
|
-
parentElement.target === entityName &&
|
|
184
|
-
!(parentElement.parent && ensureNoDraftsSuffix(parentElement.parent.name) === entityName)
|
|
185
|
-
) {
|
|
186
|
-
return false
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return true
|
|
191
|
-
}
|
|
192
|
-
|
|
193
166
|
const _setAlias2ref = entity => {
|
|
194
167
|
const _ref2alias = {}
|
|
195
168
|
const _alias2ref = {}
|
|
@@ -270,7 +243,6 @@ module.exports = {
|
|
|
270
243
|
getEtagElement,
|
|
271
244
|
findCsnTargetFor,
|
|
272
245
|
getElementDeep,
|
|
273
|
-
isRootEntity,
|
|
274
246
|
getDataSubject,
|
|
275
247
|
alias2ref,
|
|
276
248
|
getComp2oneParents,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
+
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
2
3
|
|
|
3
4
|
const _4sqlite = cds.env.i18n && Array.isArray(cds.env.i18n.for_sqlite) ? cds.env.i18n.for_sqlite : []
|
|
4
5
|
// compiler reserves 'localized' and raises a corresponding exception if used in models
|
|
@@ -65,10 +66,16 @@ const getDraftColumnsCQNForDraft = () => {
|
|
|
65
66
|
]
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
const filterNonDraftColumns = columns =>
|
|
70
|
+
columns.filter(
|
|
71
|
+
col => (col.ref && !(col.ref[col.ref.length - 1] in DRAFT_COLUMNS_MAP)) || (!col.ref && !(col in DRAFT_COLUMNS_MAP))
|
|
72
|
+
)
|
|
73
|
+
|
|
68
74
|
module.exports = {
|
|
69
75
|
ensureUnlocalized,
|
|
70
76
|
ensureDraftsSuffix,
|
|
71
77
|
ensureNoDraftsSuffix,
|
|
72
78
|
getDraftColumnsCQNForActive,
|
|
73
|
-
getDraftColumnsCQNForDraft
|
|
79
|
+
getDraftColumnsCQNForDraft,
|
|
80
|
+
filterNonDraftColumns
|
|
74
81
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
+
const { ensureNoDraftsSuffix } = require('./draft')
|
|
2
3
|
|
|
3
4
|
/*
|
|
4
5
|
* returns path like <service>.<entity>:<prop1>.<prop2> for ref = [{ id: '<service>.<entity>' }, '<prop1>', '<prop2>']
|
|
@@ -22,7 +23,12 @@ const getEntityFromPath = (path, def) => {
|
|
|
22
23
|
path = typeof path === 'string' ? cds.parse.path(path) : path
|
|
23
24
|
const segments = [...path.ref]
|
|
24
25
|
while (segments.length) {
|
|
25
|
-
|
|
26
|
+
let segment = segments.shift()
|
|
27
|
+
if (segment.id && typeof segment.id === 'string') {
|
|
28
|
+
segment.id = ensureNoDraftsSuffix(segment.id)
|
|
29
|
+
} else if (typeof segment === 'string') {
|
|
30
|
+
segment = ensureNoDraftsSuffix(segment)
|
|
31
|
+
}
|
|
26
32
|
current = current.elements[segment.id || segment]
|
|
27
33
|
if (current && current.target) current = current._target
|
|
28
34
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const cds = require('../../cds')
|
|
2
|
+
|
|
3
|
+
const { prefixForStruct } = require('../../common/utils/csn')
|
|
4
|
+
|
|
5
|
+
const _autoGenerate = e => e && e.isUUID && e.key
|
|
6
|
+
|
|
7
|
+
const _set = (row, value, element, enumerable) => {
|
|
8
|
+
if (!element.parent.elements[element.name]) return // only when in model
|
|
9
|
+
if (!enumerable && element.foreignKeySource) {
|
|
10
|
+
// only for foreign keys
|
|
11
|
+
Object.defineProperty(row, element.name, {
|
|
12
|
+
get() {
|
|
13
|
+
return value
|
|
14
|
+
},
|
|
15
|
+
set(v) {
|
|
16
|
+
// Make sure that it becomes enumerable again if set manually afterwards
|
|
17
|
+
Object.defineProperty(row, element.name, { value: v, configurable: true, enumerable: true })
|
|
18
|
+
},
|
|
19
|
+
enumerable: false,
|
|
20
|
+
configurable: true
|
|
21
|
+
})
|
|
22
|
+
} else {
|
|
23
|
+
row[element.name] = value
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const _generateParentField = ({ parentElement }, row, enumerable) => {
|
|
28
|
+
if (_autoGenerate(parentElement) && !row[parentElement.name]) {
|
|
29
|
+
_set(row, cds.utils.uuid(), parentElement, enumerable)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const _generateChildField = ({ deep, childElement }, childRow, enumerable) => {
|
|
34
|
+
if (deep) {
|
|
35
|
+
_generateChildField(deep.propagation, childRow[deep.targetName], enumerable)
|
|
36
|
+
} else if (_autoGenerate(childElement) && childRow && !childRow[childElement.name]) {
|
|
37
|
+
_set(childRow, cds.utils.uuid(), childElement, enumerable)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const _getNestedVal = (row, prefix) => {
|
|
42
|
+
let val = row
|
|
43
|
+
const splitted = prefix.split('_')
|
|
44
|
+
splitted.pop() // remove last `_`
|
|
45
|
+
let k = ''
|
|
46
|
+
|
|
47
|
+
while (splitted.length > 0) {
|
|
48
|
+
k += splitted.shift()
|
|
49
|
+
if (k in val) {
|
|
50
|
+
val = val[k]
|
|
51
|
+
k = ''
|
|
52
|
+
} else {
|
|
53
|
+
k += '_'
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return val
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const _propagateToChild = ({ parentElement, childElement, parentFieldValue }, row, childRow, enumerable) => {
|
|
61
|
+
if (!childElement || !childElement.parent.elements[childElement.name]) return
|
|
62
|
+
if (parentElement) {
|
|
63
|
+
const prefix = prefixForStruct(parentElement)
|
|
64
|
+
if (prefix) {
|
|
65
|
+
const nested = _getNestedVal(row, prefix)
|
|
66
|
+
_set(childRow, nested[parentElement.name], childElement, enumerable)
|
|
67
|
+
} else {
|
|
68
|
+
_set(childRow, row[parentElement.name], childElement, enumerable)
|
|
69
|
+
}
|
|
70
|
+
} else if (parentFieldValue !== undefined) {
|
|
71
|
+
_set(childRow, parentFieldValue, childElement, enumerable)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const _propagateToParent = ({ parentElement, childElement, deep }, childRow, row, enumerable) => {
|
|
76
|
+
if (deep) {
|
|
77
|
+
_propagateToParent(deep.propagation, childRow[deep.targetName], childRow, enumerable)
|
|
78
|
+
}
|
|
79
|
+
if (parentElement && childElement && childRow && childElement.name in childRow) {
|
|
80
|
+
_set(row, childRow[childElement.name], parentElement, enumerable)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = (
|
|
85
|
+
tKey,
|
|
86
|
+
row,
|
|
87
|
+
foreignKeyPropagations,
|
|
88
|
+
isCompositionEffective,
|
|
89
|
+
{ deleteAssocs = false, enumerable = true } = {}
|
|
90
|
+
) => {
|
|
91
|
+
if (!row || !(tKey in row)) return
|
|
92
|
+
if (row[tKey] === null) {
|
|
93
|
+
for (const foreignKeyPropagation of foreignKeyPropagations) {
|
|
94
|
+
if (!foreignKeyPropagation.fillChild) {
|
|
95
|
+
_set(row, null, foreignKeyPropagation.parentElement, enumerable)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (deleteAssocs && !isCompositionEffective) delete row[tKey]
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const childRows = Array.isArray(row[tKey]) ? row[tKey] : [row[tKey]]
|
|
103
|
+
|
|
104
|
+
for (const childRow of childRows) {
|
|
105
|
+
if (!childRow) return
|
|
106
|
+
|
|
107
|
+
for (const foreignKeyPropagation of foreignKeyPropagations) {
|
|
108
|
+
if (foreignKeyPropagation.fillChild) {
|
|
109
|
+
// propagate or generate in parent
|
|
110
|
+
const pk = foreignKeyPropagation.parentElement && foreignKeyPropagation.parentElement.name
|
|
111
|
+
if (pk && !(pk in row)) _propagateToParent(foreignKeyPropagation, childRow, row, enumerable)
|
|
112
|
+
if (!(pk in row)) _generateParentField(foreignKeyPropagation, row, enumerable)
|
|
113
|
+
|
|
114
|
+
if (isCompositionEffective) _propagateToChild(foreignKeyPropagation, row, childRow, enumerable)
|
|
115
|
+
} else {
|
|
116
|
+
_generateChildField(foreignKeyPropagation, childRow, enumerable)
|
|
117
|
+
_propagateToParent(foreignKeyPropagation, childRow, row, enumerable)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (deleteAssocs && !isCompositionEffective) delete row[tKey]
|
|
122
|
+
}
|
|
@@ -501,9 +501,8 @@ const _checkForForbiddenViews = queryTarget => {
|
|
|
501
501
|
if (!select.from || select.from.join || select.from.length > 1) {
|
|
502
502
|
throw getError({
|
|
503
503
|
code: 501,
|
|
504
|
-
message: '
|
|
505
|
-
target: queryTarget.name
|
|
506
|
-
args: [_event || 'INSERT|UPDATE|DELETE']
|
|
504
|
+
message: `${_event || 'INSERT|UPDATE|DELETE'} on views with join and/or union is not supported`,
|
|
505
|
+
target: queryTarget.name
|
|
507
506
|
})
|
|
508
507
|
}
|
|
509
508
|
if (select.where) {
|
|
@@ -67,7 +67,7 @@ const _getNextTarget = (model, element, currentPath = []) => {
|
|
|
67
67
|
* @param {object} targetEntity The target entity which needs to be traversed
|
|
68
68
|
* @param {object} callbacks
|
|
69
69
|
* @param {function} callbacks.pick Callback function to pick elements. If it returns a truthy value, the element will be picked. The returned value is part of the template.
|
|
70
|
-
* @param {function} callbacks.ignore Callback function to ignore
|
|
70
|
+
* @param {function} callbacks.ignore Callback function to ignore the target of an element. If it returns a truthy value, the element's target will be ignored.
|
|
71
71
|
* @param {object} [parent=null] The parent entity
|
|
72
72
|
* @param {Map} [_entityMap] This parameter is an implementation side-effect — don't use it
|
|
73
73
|
* @param {array} [targetPath=[]]
|
|
@@ -92,8 +92,6 @@ function _getTemplate(model, cache, targetEntity, callbacks, parent = null, _ent
|
|
|
92
92
|
|
|
93
93
|
for (const elementName in elements) {
|
|
94
94
|
const element = elements[elementName]
|
|
95
|
-
if (ignore && ignore(element, targetEntity, parent)) continue
|
|
96
|
-
|
|
97
95
|
_pick(pick, element, targetEntity, parent, templateElements, elementName)
|
|
98
96
|
|
|
99
97
|
if (element.items) {
|
|
@@ -101,6 +99,7 @@ function _getTemplate(model, cache, targetEntity, callbacks, parent = null, _ent
|
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
const { nextTargetName, nextTarget } = _getNextTarget(model, element, currentPath)
|
|
102
|
+
if (ignore && ignore(element)) continue
|
|
104
103
|
const nextTargetCached = _entityMap.get(nextTargetName)
|
|
105
104
|
|
|
106
105
|
if (nextTargetCached) {
|
|
@@ -3,55 +3,14 @@ const { ensureNoDraftsSuffix } = require('../../common/utils/draft')
|
|
|
3
3
|
const { proxifyIfFlattened } = require('../../../common/utils/ucsn')
|
|
4
4
|
const cds = require('../../../../lib')
|
|
5
5
|
|
|
6
|
-
const _refs = (refs, as) => {
|
|
7
|
-
const arr = []
|
|
8
|
-
for (const element of refs) {
|
|
9
|
-
// multiple join are nested, so we need to find all the table names in there as well
|
|
10
|
-
if (Object.prototype.hasOwnProperty.call(element, 'join')) {
|
|
11
|
-
arr.push(..._extractRefs(element))
|
|
12
|
-
// Likely a union
|
|
13
|
-
} else if (Object.prototype.hasOwnProperty.call(element, 'SELECT')) {
|
|
14
|
-
arr.push(..._extractRefs(element.SELECT.from, element.as))
|
|
15
|
-
} else {
|
|
16
|
-
arr.push(..._extractRefs(element, as))
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return arr
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const _getActiveFromUnion = refs => {
|
|
24
|
-
if (refs.length !== 2) return
|
|
25
|
-
const [maybeDraft, maybeActive] = refs
|
|
26
|
-
if (ensureNoDraftsSuffix(maybeDraft.ref[0]) === maybeActive.ref[0]) return maybeActive
|
|
27
|
-
if (ensureNoDraftsSuffix(maybeActive.ref[0]) === maybeDraft.ref[0]) return maybeDraft
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const _extractRefs = (from, as) => {
|
|
31
|
-
if (from.SELECT) {
|
|
32
|
-
return _extractRefs(from.SELECT.from, as || from.SELECT.as)
|
|
33
|
-
}
|
|
34
|
-
if (Object.prototype.hasOwnProperty.call(from, 'join')) {
|
|
35
|
-
// cqn with join in from
|
|
36
|
-
return _refs(from.args)
|
|
37
|
-
}
|
|
38
|
-
if (Object.prototype.hasOwnProperty.call(from, 'SET')) {
|
|
39
|
-
let refs = _refs(from.SET.args).filter(a => !a.as || a.as !== 'filterAdmin')
|
|
40
|
-
refs = _getActiveFromUnion(refs) ? [_getActiveFromUnion(refs)] : refs
|
|
41
|
-
if (as) return refs.map(({ ref }) => ({ as, ref }))
|
|
42
|
-
return refs
|
|
43
|
-
}
|
|
44
|
-
if (!from.ref) return []
|
|
45
|
-
const ref = { ref: [...from.ref] }
|
|
46
|
-
if (as || from.as) ref.as = as || from.as
|
|
47
|
-
return [ref]
|
|
48
|
-
}
|
|
49
|
-
|
|
50
6
|
const _getCastFunction = ({ type }) => {
|
|
51
7
|
switch (type) {
|
|
52
8
|
case 'cds.Boolean':
|
|
53
9
|
return Boolean
|
|
54
10
|
case 'cds.Integer':
|
|
11
|
+
case 'cds.UInt8':
|
|
12
|
+
case 'cds.Int16':
|
|
13
|
+
case 'cds.Int32':
|
|
55
14
|
return Number
|
|
56
15
|
default:
|
|
57
16
|
return String
|
|
@@ -14,7 +14,7 @@ const cds = require('../../cds')
|
|
|
14
14
|
const normalizeTimeData = require('../utils/normalizeTimeData')
|
|
15
15
|
|
|
16
16
|
const { enrichDataWithKeysFromWhere } = require('../../common/utils/keys')
|
|
17
|
-
const propagateForeignKeys = require('
|
|
17
|
+
const propagateForeignKeys = require('../../common/utils/propagateForeignKeys')
|
|
18
18
|
const getTemplate = require('../../common/utils/template')
|
|
19
19
|
const templateProcessor = require('../../common/utils/templateProcessor')
|
|
20
20
|
|
|
@@ -32,8 +32,8 @@ const _processComplexCategory = ({ row, key, val, category, req, element }) => {
|
|
|
32
32
|
category = category.category
|
|
33
33
|
|
|
34
34
|
// propagate keys
|
|
35
|
-
if (category === 'propagateForeignKeys'
|
|
36
|
-
propagateForeignKeys(key, row, element._foreignKeys, element.isComposition)
|
|
35
|
+
if (category === 'propagateForeignKeys') {
|
|
36
|
+
propagateForeignKeys(key, row, element._foreignKeys, element.isComposition, { deleteAssocs: true })
|
|
37
37
|
return
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -197,7 +197,7 @@ const _pickDraft = element => {
|
|
|
197
197
|
if (categories.length) return { categories }
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
function
|
|
200
|
+
function dbGenericInput(req) {
|
|
201
201
|
if (!this.model || typeof req.query === 'string' || !req.target) return
|
|
202
202
|
|
|
203
203
|
// call with this for this.model
|
|
@@ -231,6 +231,6 @@ function _handler(req) {
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
dbGenericInput._initial = true
|
|
235
235
|
|
|
236
|
-
module.exports =
|
|
236
|
+
module.exports = dbGenericInput
|
|
@@ -3,7 +3,11 @@ const typeConversionMap = new Map()
|
|
|
3
3
|
typeConversionMap.set('cds.UUID', { type: 'NVARCHAR', length: 36 })
|
|
4
4
|
typeConversionMap.set('cds.Boolean', 'BOOLEAN')
|
|
5
5
|
typeConversionMap.set('cds.Integer', 'INTEGER')
|
|
6
|
+
typeConversionMap.set('cds.UInt8', 'INTEGER')
|
|
7
|
+
typeConversionMap.set('cds.Int16', 'INTEGER')
|
|
8
|
+
typeConversionMap.set('cds.Int32', 'INTEGER')
|
|
6
9
|
typeConversionMap.set('cds.Integer64', 'BIGINT')
|
|
10
|
+
typeConversionMap.set('cds.Int64', 'BIGINT')
|
|
7
11
|
typeConversionMap.set('cds.Decimal', { type: 'DECIMAL' })
|
|
8
12
|
typeConversionMap.set('cds.DecimalFloat', { type: 'DECIMAL' })
|
|
9
13
|
typeConversionMap.set('cds.Double', 'DOUBLE')
|
|
@@ -106,7 +106,7 @@ const _draftCompositionTree = async (service, req) => {
|
|
|
106
106
|
*
|
|
107
107
|
* @param req
|
|
108
108
|
*/
|
|
109
|
-
const
|
|
109
|
+
const fioriGenericActivate = async function (req) {
|
|
110
110
|
if (
|
|
111
111
|
isActiveEntityRequested(req.query.SELECT.from.ref[0].where || []) ||
|
|
112
112
|
req.query.SELECT.from.ref.length > 2 ||
|
|
@@ -178,5 +178,5 @@ const _handler = async function (req) {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
181
|
-
srv.on('draftActivate', entity,
|
|
181
|
+
srv.on('draftActivate', entity, fioriGenericActivate)
|
|
182
182
|
})
|