@sap/cds 7.9.2 → 8.0.3
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 +139 -3656
- package/_i18n/i18n_en_US_saptrc.properties +113 -0
- package/_i18n/i18n_zh_CN.properties +7 -4
- package/app/index.css +129 -0
- package/app/index.html +16 -64
- package/app/index.js +14 -9
- package/bin/args.js +34 -0
- package/bin/serve.js +18 -24
- package/bin/test.js +97 -0
- package/common.cds +5 -12
- package/eslint.config.mjs +133 -0
- package/lib/auth/basic-auth.js +16 -20
- package/lib/auth/dummy-auth.js +1 -1
- package/lib/auth/ias-auth.js +12 -30
- package/lib/auth/index.js +1 -14
- package/lib/auth/jwt-auth.js +14 -30
- package/lib/compile/cds-compile.js +1 -2
- package/lib/compile/cdsc.js +21 -26
- package/lib/compile/etc/_localized.js +1 -6
- package/lib/compile/etc/csv.js +1 -1
- package/lib/compile/etc/properties.js +1 -1
- package/lib/compile/for/java.js +1 -1
- package/lib/compile/for/lean_drafts.js +4 -6
- package/lib/compile/for/nodejs.js +1 -1
- package/lib/compile/parse.js +4 -0
- package/lib/compile/resolve.js +4 -4
- package/lib/compile/to/edm-files.js +16 -23
- package/lib/compile/to/hana.js +27 -0
- package/lib/compile/to/json.js +1 -1
- package/lib/compile/to/sql.js +5 -1
- package/lib/compile/to/srvinfo.js +1 -1
- package/lib/compile/to/yaml.js +3 -3
- package/lib/dbs/cds-deploy.js +4 -2
- package/lib/env/cds-env.js +10 -14
- package/lib/env/cds-requires.js +29 -13
- package/lib/env/defaults.js +46 -16
- package/lib/env/plugins.js +1 -1
- package/lib/env/schemas/cds-rc.js +8 -4
- package/lib/env/schemas/index.js +7 -7
- package/lib/env/serviceBindings.js +1 -1
- package/lib/index.js +12 -10
- package/lib/lazy.js +1 -1
- package/lib/linked/classes.js +36 -8
- package/lib/linked/entities.js +2 -10
- package/lib/linked/models.js +2 -1
- package/lib/linked/validate.js +292 -0
- package/lib/log/cds-error.js +0 -6
- package/lib/log/cds-log.js +3 -3
- package/lib/log/format/json.js +1 -1
- package/lib/log/service/index.js +0 -1
- package/lib/plugins.js +3 -3
- package/lib/ql/Query.js +2 -10
- package/lib/ql/SELECT.js +1 -1
- package/lib/ql/Whereable.js +3 -2
- package/lib/req/cds-context.js +14 -25
- package/lib/req/context.js +23 -25
- package/lib/req/request.js +1 -34
- package/lib/req/user.js +47 -35
- package/lib/srv/bindings.js +1 -1
- package/lib/srv/cds-connect.js +4 -4
- package/lib/srv/cds-serve.js +2 -2
- package/lib/srv/factory.js +1 -1
- package/lib/srv/middlewares/cds-context.js +11 -22
- package/lib/srv/middlewares/ctx-model.js +2 -3
- package/lib/srv/middlewares/errors.js +41 -8
- package/lib/srv/middlewares/index.js +3 -3
- package/lib/srv/middlewares/trace.js +0 -2
- package/lib/srv/protocols/hcql.js +15 -10
- package/lib/srv/protocols/http.js +44 -49
- package/lib/srv/protocols/index.js +1 -23
- package/lib/srv/protocols/odata-v4.js +12 -74
- package/lib/srv/protocols/rest.js +1 -13
- package/lib/srv/srv-api.js +0 -20
- package/lib/srv/srv-dispatch.js +3 -2
- package/lib/srv/srv-handlers.js +22 -11
- package/lib/srv/srv-methods.js +2 -2
- package/lib/srv/srv-models.js +3 -36
- package/lib/test/expect.js +343 -0
- package/lib/test/index.js +2 -0
- package/lib/test/reporter.js +176 -0
- package/lib/utils/axios.js +10 -9
- package/lib/utils/cds-test.js +86 -37
- package/lib/utils/cds-utils.js +54 -7
- package/lib/utils/check-version.js +0 -4
- package/lib/utils/colors.js +49 -0
- package/lib/utils/data.js +5 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +3 -30
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +6 -12
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +4 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +12 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +2 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +1 -0
- 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/index.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -3
- 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/edm/AbstractEdmStructuredType.js +1 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +5 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +9 -43
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +0 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +8 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +4 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +1 -3
- package/libx/_runtime/cds-services/util/assert.js +1 -1
- package/libx/_runtime/cds.js +10 -3
- package/libx/_runtime/common/Service.js +12 -32
- package/libx/_runtime/common/aspects/any.js +1 -0
- package/libx/_runtime/common/code-ext/execute.js +1 -1
- package/libx/_runtime/common/code-ext/worker.js +0 -1
- package/libx/_runtime/common/composition/data.js +0 -1
- package/libx/_runtime/common/composition/delete.js +0 -1
- package/libx/_runtime/common/composition/insert.js +2 -2
- package/libx/_runtime/common/composition/tree.js +0 -1
- package/libx/_runtime/common/composition/update.js +3 -3
- package/libx/_runtime/common/error/frontend.js +21 -12
- package/libx/_runtime/common/error/log.js +36 -0
- package/libx/_runtime/common/error/utils.js +2 -5
- package/libx/_runtime/common/generic/auth/autoexpose.js +18 -17
- package/libx/_runtime/common/generic/auth/expand.js +1 -1
- package/libx/_runtime/common/generic/auth/readOnly.js +1 -2
- package/libx/_runtime/common/generic/auth/restrict.js +23 -42
- package/libx/_runtime/common/generic/auth/restrictions.js +2 -7
- package/libx/_runtime/common/generic/auth/utils.js +91 -88
- package/libx/_runtime/common/generic/crud.js +6 -5
- package/libx/_runtime/common/generic/etag.js +7 -12
- package/libx/_runtime/common/generic/input.js +70 -68
- package/libx/_runtime/common/generic/paging.js +1 -0
- package/libx/_runtime/common/generic/sorting.js +1 -0
- package/libx/_runtime/common/generic/temporal.js +8 -2
- package/libx/_runtime/common/i18n/index.js +1 -1
- package/libx/_runtime/common/i18n/messages.properties +3 -1
- package/libx/_runtime/common/utils/binary.js +8 -2
- package/libx/_runtime/common/utils/compareJson.js +5 -1
- package/libx/_runtime/common/utils/copy.js +6 -11
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +16 -14
- package/libx/_runtime/common/utils/differ.js +3 -6
- package/libx/_runtime/common/utils/keys.js +77 -18
- package/libx/_runtime/common/utils/postProcess.js +12 -15
- package/libx/_runtime/common/utils/propagateForeignKeys.js +0 -1
- package/libx/_runtime/common/utils/resolveView.js +2 -3
- package/libx/_runtime/common/utils/restrictions.js +45 -17
- package/libx/_runtime/common/utils/rewriteAsterisks.js +1 -8
- package/libx/_runtime/common/utils/stream.js +3 -16
- package/libx/_runtime/common/utils/streamProp.js +8 -18
- package/libx/_runtime/common/utils/structured.js +1 -1
- package/libx/_runtime/common/utils/ucsn.js +0 -2
- package/libx/_runtime/db/Service.js +0 -72
- package/libx/_runtime/db/data-conversion/post-processing.js +0 -1
- package/libx/_runtime/db/expand/expandCQNToJoin.js +9 -9
- package/libx/_runtime/db/expand/rawToExpanded.js +0 -8
- package/libx/_runtime/db/generic/input.js +3 -8
- package/libx/_runtime/db/generic/rewrite.js +27 -4
- package/libx/_runtime/db/query/read.js +2 -2
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -1
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
- package/libx/_runtime/db/utils/columns.js +2 -6
- package/libx/_runtime/fiori/lean-draft.js +138 -56
- package/libx/_runtime/hana/Service.js +0 -1
- package/libx/_runtime/hana/driver.js +1 -1
- package/libx/_runtime/hana/dynatrace.js +1 -2
- package/libx/_runtime/hana/pool.js +11 -21
- package/libx/_runtime/hana/streaming.js +0 -1
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +0 -1
- package/libx/_runtime/messaging/common-utils/authorizedRequest.js +1 -1
- package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -33
- package/libx/_runtime/messaging/event-broker.js +0 -12
- package/libx/_runtime/messaging/file-based.js +3 -3
- package/libx/_runtime/messaging/http-utils/token.js +1 -1
- package/libx/_runtime/messaging/kafka.js +2 -2
- package/libx/_runtime/messaging/redis-messaging.js +0 -1
- package/libx/_runtime/remote/Service.js +25 -25
- package/libx/_runtime/remote/utils/client.js +4 -5
- package/libx/_runtime/remote/utils/cloudSdkProvider.js +0 -3
- package/libx/_runtime/remote/utils/data.js +0 -1
- package/libx/_runtime/sqlite/Service.js +1 -2
- package/libx/_runtime/ucl/Service.js +37 -78
- package/libx/common/assert/index.js +22 -21
- package/libx/common/assert/type-relaxed.js +39 -0
- package/libx/common/assert/utils.js +3 -2
- package/libx/common/assert/validation.js +3 -8
- package/libx/common/utils/index.js +5 -0
- package/libx/common/utils/path.js +51 -0
- package/libx/odata/ODataAdapter.js +126 -0
- package/libx/odata/index.js +15 -2
- package/libx/odata/middleware/batch.js +261 -72
- package/libx/odata/middleware/body-parser.js +33 -0
- package/libx/odata/middleware/create.js +44 -59
- package/libx/odata/middleware/delete.js +23 -12
- package/libx/odata/middleware/error.js +30 -6
- package/libx/odata/middleware/metadata.js +38 -26
- package/libx/odata/middleware/operation.js +93 -69
- package/libx/odata/middleware/parse.js +6 -8
- package/libx/odata/middleware/read.js +117 -93
- package/libx/odata/middleware/service-document.js +22 -19
- package/libx/odata/middleware/stream.js +54 -56
- package/libx/odata/middleware/update.js +79 -87
- package/libx/odata/parse/afterburner.js +191 -175
- package/libx/odata/parse/cqn2odata.js +8 -8
- package/libx/odata/parse/grammar.peggy +27 -20
- package/libx/odata/parse/multipartToJson.js +17 -9
- package/libx/odata/parse/parser.js +1 -1
- package/libx/odata/utils/etag.js +14 -6
- package/libx/odata/utils/index.js +84 -12
- package/libx/odata/utils/metadata.js +161 -0
- package/libx/odata/utils/postProcess.js +89 -0
- package/libx/odata/utils/readAfterWrite.js +134 -17
- package/libx/odata/utils/result.js +36 -142
- package/libx/outbox/index.js +5 -4
- package/libx/rest/RestAdapter.js +115 -182
- package/libx/rest/middleware/create.js +28 -24
- package/libx/rest/middleware/delete.js +7 -10
- package/libx/rest/middleware/error.js +19 -16
- package/libx/rest/middleware/operation.js +48 -41
- package/libx/rest/middleware/parse.js +128 -126
- package/libx/rest/middleware/read.js +20 -27
- package/libx/rest/middleware/update.js +26 -31
- package/package.json +16 -12
- package/server.js +4 -2
- package/tasks/enterprise-messaging-deploy.js +1 -1
- package/apis/cds.d.ts +0 -3
- package/apis/core.d.ts +0 -21
- package/apis/cqn.d.ts +0 -18
- package/apis/csn.d.ts +0 -21
- package/apis/events.d.ts +0 -18
- package/apis/internal/inference.d.ts +0 -18
- package/apis/linked.d.ts +0 -18
- package/apis/log.d.ts +0 -20
- package/apis/models.d.ts +0 -18
- package/apis/ql.d.ts +0 -18
- package/apis/reflect.d.ts +0 -32
- package/apis/server.d.ts +0 -18
- package/apis/services.d.ts +0 -22
- package/bin/cds-serve.js +0 -56
- package/lib/compile/to/gql.js +0 -15
- package/lib/srv/protocols/_legacy.js +0 -44
- package/lib/utils/jest.js +0 -43
- package/libx/_runtime/auth/index.js +0 -193
- package/libx/_runtime/auth/strategies/JWT.js +0 -37
- package/libx/_runtime/auth/strategies/basic.js +0 -20
- package/libx/_runtime/auth/strategies/dummy.js +0 -14
- package/libx/_runtime/auth/strategies/ias-auth.js +0 -1
- package/libx/_runtime/auth/strategies/mock.js +0 -77
- package/libx/_runtime/auth/strategies/xssecUtils.js +0 -93
- package/libx/_runtime/auth/strategies/xsuaa.js +0 -38
- package/libx/_runtime/common/perf/index.js +0 -19
- package/libx/_runtime/common/utils/ensureIEEE754.js +0 -29
- package/libx/_runtime/fiori/draft.js +0 -2
- package/libx/_runtime/fiori/generic/activate.js +0 -190
- package/libx/_runtime/fiori/generic/before.js +0 -201
- package/libx/_runtime/fiori/generic/cancel.js +0 -19
- package/libx/_runtime/fiori/generic/delete.js +0 -21
- package/libx/_runtime/fiori/generic/edit.js +0 -157
- package/libx/_runtime/fiori/generic/index.js +0 -25
- package/libx/_runtime/fiori/generic/new.js +0 -82
- package/libx/_runtime/fiori/generic/patch.js +0 -101
- package/libx/_runtime/fiori/generic/prepare.js +0 -57
- package/libx/_runtime/fiori/generic/read.js +0 -1340
- package/libx/_runtime/fiori/generic/readOverDraft.js +0 -146
- package/libx/_runtime/fiori/utils/csn.js +0 -13
- package/libx/_runtime/fiori/utils/delete.js +0 -114
- package/libx/_runtime/fiori/utils/handler.js +0 -264
- package/libx/_runtime/fiori/utils/lockInfo.js +0 -27
- package/libx/_runtime/fiori/utils/req.js +0 -23
- package/libx/_runtime/fiori/utils/stream.js +0 -36
- package/libx/_runtime/fiori/utils/where.js +0 -254
- package/libx/_runtime/index.js +0 -22
- package/libx/odata/utils/handler.js +0 -120
- package/libx/odata/utils/metaInfo.js +0 -410
- package/libx/odata/utils/path.js +0 -75
- package/libx/rest/RestRequest.js +0 -32
- package/libx/rest/index.js +0 -3
- package/libx/rest/readme.md +0 -1
- /package/libx/common/assert/{type.js → type-strict.js} +0 -0
|
@@ -68,25 +68,22 @@ const handleAliasInResult = (columns, result) => {
|
|
|
68
68
|
// REVISIT: todo renaming for expanded entities
|
|
69
69
|
// REVISIT: todo renaming for deep operations
|
|
70
70
|
const postProcess = (query, result, service, onlySelectAliases = false) => {
|
|
71
|
+
if (!result) return result //> null and other falsy values must be returned
|
|
72
|
+
|
|
73
|
+
if (query.DELETE) return result
|
|
74
|
+
|
|
71
75
|
if (query.SELECT) {
|
|
72
|
-
if (query.SELECT.columns
|
|
73
|
-
return [{ $count: result }]
|
|
74
|
-
}
|
|
75
|
-
handleAliasInResult(query.SELECT.columns, result)
|
|
76
|
+
if (query.SELECT.columns?.find(col => col.func === 'count' && col.as === '$count')) return [{ $count: result }]
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
const transition =
|
|
79
|
-
query.SELECT && query.SELECT._transitions && query.SELECT._transitions[query.SELECT._transitions.length - 1]
|
|
80
|
-
if (transition && result) return revertData(result, transition, service)
|
|
81
|
-
}
|
|
78
|
+
handleAliasInResult(query.SELECT.columns, result)
|
|
82
79
|
|
|
83
|
-
return result
|
|
80
|
+
if (onlySelectAliases) return result
|
|
84
81
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
return
|
|
82
|
+
|
|
83
|
+
const transitions = query.SELECT?._transitions || query.INSERT?._transitions || query.UPDATE?._transitions
|
|
84
|
+
if (transitions) return revertData(result, transitions[transitions.length - 1], service)
|
|
85
|
+
|
|
86
|
+
return result
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
module.exports = postProcess
|
|
@@ -106,7 +106,6 @@ const _newNestedData = (queryTarget, newData, ref, value) => {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
// eslint-disable-next-line complexity
|
|
110
109
|
const _newData = (data, transition, inverse, service) => {
|
|
111
110
|
if (data === null) return null
|
|
112
111
|
|
|
@@ -592,7 +591,7 @@ const _checkForForbiddenViews = queryTarget => {
|
|
|
592
591
|
const _getTransitionData = (target, columns, service, skipForbiddenViewCheck) => {
|
|
593
592
|
// REVISIT: Find less param polluting way to skip forbidden view check for reads
|
|
594
593
|
if (!skipForbiddenViewCheck) _checkForForbiddenViews(target)
|
|
595
|
-
const targetStartsWithSrvName = service.
|
|
594
|
+
const targetStartsWithSrvName = service.definition?.name && target.name.startsWith(`${service.definition.name}.`)
|
|
596
595
|
const persistenceTable = _isPersistenceTable(target)
|
|
597
596
|
const isDatabaseService = service.isDatabaseService
|
|
598
597
|
columns = _queryColumns(target, columns, persistenceTable, !isDatabaseService && !targetStartsWithSrvName)
|
|
@@ -611,7 +610,7 @@ const _getTransitionData = (target, columns, service, skipForbiddenViewCheck) =>
|
|
|
611
610
|
if (target.query && target.query._target) {
|
|
612
611
|
const newTarget = target.query._target
|
|
613
612
|
|
|
614
|
-
if (isDatabaseService || !(service.
|
|
613
|
+
if (isDatabaseService || !(service.definition?.name && newTarget.name.startsWith(`${service.definition.name}.`))) {
|
|
615
614
|
return _getTransitionData(newTarget, columns, service, skipForbiddenViewCheck)
|
|
616
615
|
}
|
|
617
616
|
|
|
@@ -1,27 +1,55 @@
|
|
|
1
|
+
// CLEANUP: This is only used in our Okra-based stuff now -> should move over there
|
|
1
2
|
const cds = require('../../cds')
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
const $cache = Symbol('service contains any restrictions cache')
|
|
5
|
+
|
|
4
6
|
const containsAnyRestrictions = srv => {
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
let { model } = srv
|
|
8
|
+
if (srv.isExtensible) model = cds.context?.model || srv.model // REVISIT: extensions are not allowed to add or change restrictions, are they?
|
|
9
|
+
|
|
10
|
+
if (!model[$cache]) model[$cache] = new Map() // REVIST: reuse model._cached instead of introducing a separate one
|
|
11
|
+
const cache = model[$cache]
|
|
12
|
+
|
|
13
|
+
if (cache.has(srv.name)) return cache.get(srv.name)
|
|
14
|
+
|
|
15
|
+
cache.set(srv.name, false)
|
|
16
|
+
|
|
17
|
+
const accessRestrictions = getAccessRestrictions(model.definitions[srv.definition.name])
|
|
18
|
+
if (accessRestrictions.length > 1 || accessRestrictions[0] !== 'any') {
|
|
19
|
+
cache.set(srv.name, true)
|
|
20
|
+
} else {
|
|
21
|
+
// REVISIT: Use srv.definiton.entities instead
|
|
22
|
+
const entities = Object.keys(model.definitions).filter(k => {
|
|
23
|
+
const d = model.definitions[k]
|
|
24
|
+
return d.kind === 'entity' && d.name.startsWith(srv.definition.name + '.')
|
|
25
|
+
})
|
|
26
|
+
// REVISIT: Use srv.definiton.actions instead
|
|
27
|
+
const operations = Object.keys(model.definitions).filter(k => {
|
|
28
|
+
const d = model.definitions[k]
|
|
29
|
+
return (d.kind === 'action' || d.kind === 'function') && d.name.startsWith(srv.definition.name + '.')
|
|
30
|
+
})
|
|
31
|
+
// REVISIT: @requires and @restrict on single entities or operations DOES NOT mean that all service is restricted !
|
|
32
|
+
cache.set(
|
|
33
|
+
srv.name,
|
|
34
|
+
!!(
|
|
35
|
+
entities.some(ek => model.definitions[ek]['@requires'] || model.definitions[ek]['@restrict']) ||
|
|
36
|
+
entities.some(ek => {
|
|
37
|
+
const actions = model.definitions[ek].actions
|
|
38
|
+
actions && Object.keys(actions).some(action => actions[action]['@requires'] || actions[action]['@restrict'])
|
|
39
|
+
}) ||
|
|
40
|
+
operations.some(ok => model.definitions[ok]['@requires'] || model.definitions[ok]['@restrict'])
|
|
41
|
+
)
|
|
19
42
|
)
|
|
20
|
-
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return cache.get(srv.name)
|
|
21
46
|
}
|
|
22
47
|
|
|
48
|
+
// REVISIT: this is the legacy variant of HttpAdapter.early_access_check4, isn't it?
|
|
23
49
|
const getAccessRestrictions = srv => {
|
|
24
|
-
|
|
50
|
+
const srvDefinition = srv.definition || srv
|
|
51
|
+
|
|
52
|
+
let restrictions = srvDefinition['@restrict'] || srvDefinition['@requires']
|
|
25
53
|
if (restrictions) {
|
|
26
54
|
if (typeof restrictions === 'string') return [restrictions]
|
|
27
55
|
return restrictions.map(r => r.to || r).flat()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { getNavigationIfStruct } = require('./structured')
|
|
2
2
|
const getColumns = require('../../db/utils/columns')
|
|
3
|
-
const { ensureNoDraftsSuffix
|
|
3
|
+
const { ensureNoDraftsSuffix } = require('./draft')
|
|
4
4
|
const { getEntityNameFromCQN } = require('./entityFromCqn')
|
|
5
5
|
const cds = require('../../cds')
|
|
6
6
|
|
|
@@ -14,11 +14,6 @@ const isDuplicate = newColumn => column => {
|
|
|
14
14
|
return newColumn.ref ? newColumn.ref.join('_') === column.ref.join('_') : newColumn === column.ref.join('_')
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const _cqlDraftColumns = target => {
|
|
18
|
-
if (target.name.endsWith('DraftAdministrativeData')) return []
|
|
19
|
-
return getDraftColumnsCQNForActive(target)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
17
|
const _expandColumn = (column, target, _4db) => {
|
|
23
18
|
if (!(column.ref && column.expand)) return
|
|
24
19
|
const nextTarget = getNavigationIfStruct(target, column.ref)
|
|
@@ -146,8 +141,6 @@ const rewriteAsterisks = (query, model, options) => {
|
|
|
146
141
|
query.SELECT.columns = getColumns(target, { _4db, omitStream: !cds.env.features.stream_compat }).map(col => ({
|
|
147
142
|
ref: [col.name]
|
|
148
143
|
}))
|
|
149
|
-
if (_4db && target._isDraftEnabled && !cds.env.fiori.lean_draft)
|
|
150
|
-
query.SELECT.columns.push(..._cqlDraftColumns(target))
|
|
151
144
|
}
|
|
152
145
|
}
|
|
153
146
|
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const LOG = cds.log('odata')
|
|
3
3
|
const { SELECT } = cds.ql
|
|
4
|
-
const {
|
|
4
|
+
const { deepCopy } = require('./copy')
|
|
5
5
|
const { getTransition } = require('./resolveView')
|
|
6
|
-
const { cqn2cqn4sql } = require('./cqn2cqn4sql')
|
|
7
|
-
const { adaptStreamCQN } = require('../../fiori/utils/stream.js')
|
|
8
|
-
const { isPathToDraft } = require('./cqn')
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
const _getStreamProperties = (req, query, model) => {
|
|
7
|
+
const _getStreamProperties = (req, query) => {
|
|
12
8
|
// new odata parser sets streaming property in SELECT.from
|
|
13
9
|
const ref = (query.SELECT.columns && query.SELECT.columns[0].ref) || query.SELECT.from.ref
|
|
14
10
|
const propertyName = ref[ref.length - 1]
|
|
@@ -74,17 +70,8 @@ const _getStreamProperties = (req, query, model) => {
|
|
|
74
70
|
|
|
75
71
|
if (columns.length && cds.db && !req.target._hasPersistenceSkip) {
|
|
76
72
|
// used cloned path
|
|
77
|
-
let select = SELECT.one
|
|
78
|
-
.from({ ref: deepCopyArray(query.SELECT.from.ref), as: query.SELECT.from.as })
|
|
79
|
-
.columns(columns)
|
|
73
|
+
let select = SELECT.one.from({ ref: deepCopy(query.SELECT.from.ref), as: query.SELECT.from.as }).columns(columns)
|
|
80
74
|
if (query.SELECT.where?.length) select.SELECT.where = query.SELECT.where
|
|
81
|
-
if (!cds.env.fiori.lean_draft) {
|
|
82
|
-
const draft = req.target._isDraftEnabled && isPathToDraft(select.SELECT.from.ref, model)
|
|
83
|
-
if (draft) {
|
|
84
|
-
select = cqn2cqn4sql(select, model)
|
|
85
|
-
adaptStreamCQN(select, draft)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
75
|
|
|
89
76
|
return cds
|
|
90
77
|
.tx(req)
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
-
const { ensureNoDraftsSuffix, ensureUnlocalized } = require('
|
|
2
|
+
const { ensureNoDraftsSuffix, ensureUnlocalized } = require('./draft')
|
|
3
3
|
const { isDuplicate } = require('./rewriteAsterisks')
|
|
4
4
|
|
|
5
5
|
const _addColumn = (name, type, columns, url) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
let mType = type['='].replaceAll(/\./g, '_')
|
|
11
|
-
const ref = {
|
|
12
|
-
ref: [mType],
|
|
13
|
-
as: `${name}@odata.mediaContentType`
|
|
14
|
-
}
|
|
15
|
-
if (!columns.find(isDuplicate(ref))) columns.push(ref)
|
|
16
|
-
} else {
|
|
17
|
-
const val = { val: type, as: `${name}@odata.mediaContentType` }
|
|
18
|
-
if (!columns.find(isDuplicate(val))) columns.push(val)
|
|
6
|
+
const mediaType = typeof type === 'object' ? { ref: [type['='].replaceAll(/\./g, '_')] } : { val: type }
|
|
7
|
+
const col = {
|
|
8
|
+
xpr: ['case', 'when', { ref: [name] }, '=', { val: null }, 'then', 'NULL', 'else', mediaType, 'end'],
|
|
9
|
+
as: `${name}@odata.mediaContentType`
|
|
19
10
|
}
|
|
20
11
|
|
|
12
|
+
if (!columns.find(isDuplicate(col))) columns.push(col)
|
|
13
|
+
|
|
21
14
|
if (url) {
|
|
22
15
|
const ref = {
|
|
23
16
|
ref: [name],
|
|
@@ -28,17 +21,14 @@ const _addColumn = (name, type, columns, url) => {
|
|
|
28
21
|
}
|
|
29
22
|
|
|
30
23
|
const _addColumns = (target, columns) => {
|
|
31
|
-
if (cds.env.features.odata_new_adapter) return
|
|
32
|
-
|
|
33
24
|
for (const k in target.elements) {
|
|
34
25
|
const el = target.elements[k]
|
|
35
26
|
if (el['@Core.MediaType']) {
|
|
36
|
-
_addColumn(el.name, el['@Core.MediaType'], columns, el['@Core.IsURL'])
|
|
27
|
+
_addColumn(el.name, el['@Core.MediaType'], columns, el['@Core.IsURL'] && el.type === 'cds.String')
|
|
37
28
|
}
|
|
38
29
|
}
|
|
39
30
|
}
|
|
40
31
|
|
|
41
|
-
// eslint-disable-next-line complexity
|
|
42
32
|
const handleStreamProperties = (target, columns, model) => {
|
|
43
33
|
if (!target || !model || !columns) return
|
|
44
34
|
|
|
@@ -160,7 +160,7 @@ const _transformStructToFlatWhereHaving = ([first, op, second], resArray, struct
|
|
|
160
160
|
let structData = val
|
|
161
161
|
try {
|
|
162
162
|
structData = JSON.parse(val)
|
|
163
|
-
} catch
|
|
163
|
+
} catch {
|
|
164
164
|
/* since val === string */
|
|
165
165
|
}
|
|
166
166
|
if (flattenedElement && (structData === val || `${structData}` === val)) {
|
|
@@ -62,8 +62,6 @@ const _processor = ({ row, key, plain: { category }, element }) => {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
// REVISIT: check function complexity
|
|
66
|
-
// eslint-disable-next-line complexity
|
|
67
65
|
const _cleanup = (row, definition, cleanupNull, cleanupStruct, errors, prefix = []) => {
|
|
68
66
|
if (!row || !definition) return
|
|
69
67
|
const elements = definition.elements || definition.params
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
const cds = require('../cds')
|
|
2
|
-
const { SELECT } = cds.ql
|
|
3
|
-
const { Transform } = require('stream')
|
|
4
2
|
|
|
5
3
|
/*
|
|
6
4
|
* generic queries
|
|
@@ -12,10 +10,6 @@ const queries = require('./query')
|
|
|
12
10
|
*/
|
|
13
11
|
const generic = require('./generic')
|
|
14
12
|
|
|
15
|
-
// not able to pass in stream method into cds.utils.deprecated for unknown reason
|
|
16
|
-
// workaround: extract and deprecate helper function
|
|
17
|
-
const _streamDeprecation = () => {}
|
|
18
|
-
|
|
19
13
|
class DatabaseService extends cds.Service {
|
|
20
14
|
constructor(...args) {
|
|
21
15
|
super(...args)
|
|
@@ -93,72 +87,6 @@ class DatabaseService extends cds.Service {
|
|
|
93
87
|
}
|
|
94
88
|
})
|
|
95
89
|
}
|
|
96
|
-
|
|
97
|
-
stream(query) {
|
|
98
|
-
cds.utils.deprecated(_streamDeprecation, { old: 'cds.stream' })()
|
|
99
|
-
// aynchronous API: cds.stream(query)
|
|
100
|
-
if (typeof query === 'object') {
|
|
101
|
-
// eslint-disable-next-line no-async-promise-executor
|
|
102
|
-
return new Promise(async (resolve, reject) => {
|
|
103
|
-
try {
|
|
104
|
-
if (cds.env.features.stream_compat) {
|
|
105
|
-
const res = await this.run(Object.assign(query, { _streaming: true }))
|
|
106
|
-
resolve(res && res.value)
|
|
107
|
-
} else {
|
|
108
|
-
const res = await this.run(query)
|
|
109
|
-
// rely on query returning correct column (as documented for srv.stream(query))
|
|
110
|
-
if (Array.isArray(res)) {
|
|
111
|
-
resolve(res.length ? Object.values(res[0])[0] : undefined)
|
|
112
|
-
} else {
|
|
113
|
-
resolve(res && Object.values(res)[0])
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
} catch (e) {
|
|
117
|
-
reject(e)
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// synchronous API: cds.stream('column').from(entity).where(...)
|
|
123
|
-
return {
|
|
124
|
-
from: (...args) => {
|
|
125
|
-
const streamQuery = SELECT.one.from(...args)
|
|
126
|
-
if (query && (!streamQuery.SELECT.columns || streamQuery.SELECT.columns.length !== 0)) {
|
|
127
|
-
streamQuery.columns([query])
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (cds.env.features.stream_compat) streamQuery._streaming = true
|
|
131
|
-
|
|
132
|
-
const result = new Transform({
|
|
133
|
-
transform(chunk, encoding, callback) {
|
|
134
|
-
this.push(chunk)
|
|
135
|
-
callback()
|
|
136
|
-
}
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
!streamQuery.SELECT.where &&
|
|
141
|
-
!(
|
|
142
|
-
streamQuery.SELECT.from &&
|
|
143
|
-
streamQuery.SELECT.from.ref &&
|
|
144
|
-
streamQuery.SELECT.from.ref[streamQuery.SELECT.from.ref.length - 1].where
|
|
145
|
-
)
|
|
146
|
-
) {
|
|
147
|
-
return {
|
|
148
|
-
where: (...args) => {
|
|
149
|
-
streamQuery.where(...args)
|
|
150
|
-
this._runStream(streamQuery, result)
|
|
151
|
-
return result
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
this._runStream(streamQuery, result)
|
|
157
|
-
|
|
158
|
-
return result
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
90
|
}
|
|
163
91
|
|
|
164
92
|
DatabaseService.prototype.isDatabaseService = true
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
|
|
3
|
+
const { Object_keys } = cds.utils
|
|
4
|
+
|
|
3
5
|
const { getAllKeys } = require('../../cds-services/adapter/odata-v4/odata-to-cqn/utils')
|
|
4
6
|
|
|
5
|
-
const {
|
|
7
|
+
const { deepCopy } = require('../../common/utils/copy')
|
|
6
8
|
const { getNavigationIfStruct } = require('../../common/utils/structured')
|
|
7
9
|
const { ensureNoDraftsSuffix, ensureDraftsSuffix, ensureUnlocalized } = require('../../common/utils/draft')
|
|
8
10
|
const { isAsteriskColumn } = require('../../common/utils/rewriteAsterisks')
|
|
@@ -10,8 +12,6 @@ const { getCQNUnionFrom } = require('../../common/utils/union')
|
|
|
10
12
|
|
|
11
13
|
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
12
14
|
|
|
13
|
-
const { entity_keys } = require('../../fiori/utils/handler')
|
|
14
|
-
|
|
15
15
|
const getError = require('../../common/error')
|
|
16
16
|
|
|
17
17
|
// Symbols are used to add extra information in response structure
|
|
@@ -26,7 +26,7 @@ const CLEANUP_KEYS = Symbol.for('sap.cds.cleanupKeys')
|
|
|
26
26
|
|
|
27
27
|
function getCqnCopy(readToOneCQN) {
|
|
28
28
|
// REVISIT: Use query.clone() instead
|
|
29
|
-
const readToOneCQNCopy =
|
|
29
|
+
const readToOneCQNCopy = deepCopy(readToOneCQN)
|
|
30
30
|
if (readToOneCQN[GET_KEY_VALUE] !== undefined) readToOneCQNCopy[GET_KEY_VALUE] = readToOneCQN[GET_KEY_VALUE]
|
|
31
31
|
if (readToOneCQN[TO_MANY] !== undefined) readToOneCQNCopy[TO_MANY] = readToOneCQN[TO_MANY]
|
|
32
32
|
if (readToOneCQN[TO_ACTIVE] !== undefined) readToOneCQNCopy[TO_ACTIVE] = readToOneCQN[TO_ACTIVE]
|
|
@@ -38,6 +38,9 @@ function getCqnCopy(readToOneCQN) {
|
|
|
38
38
|
return readToOneCQNCopy
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
const entity_keys = entity =>
|
|
42
|
+
Object_keys(entity.keys).filter(key => key !== 'IsActiveEntity' && !entity.keys[key].isAssociation)
|
|
43
|
+
|
|
41
44
|
class JoinCQNFromExpanded {
|
|
42
45
|
constructor(cqn, csn, locale) {
|
|
43
46
|
this._SELECT = {}
|
|
@@ -493,7 +496,6 @@ class JoinCQNFromExpanded {
|
|
|
493
496
|
* @param {boolean} arg.defaultLanguage - Use default language for localized fields
|
|
494
497
|
* @private
|
|
495
498
|
*/
|
|
496
|
-
// eslint-disable-next-line complexity
|
|
497
499
|
_expandedToFlat({ entity, givenColumns, readToOneCQN, tableAlias, toManyTree, defaultLanguage }) {
|
|
498
500
|
const toManyColumns = []
|
|
499
501
|
const mappings = this._getMappingObject(toManyTree)
|
|
@@ -654,7 +656,6 @@ class JoinCQNFromExpanded {
|
|
|
654
656
|
* @param args.defaultLanguage
|
|
655
657
|
* @private
|
|
656
658
|
*/
|
|
657
|
-
// eslint-disable-next-line complexity
|
|
658
659
|
_addJoinAndElements({ column, entity, readToOneCQN, toManyTree, parentAlias, defaultLanguage }) {
|
|
659
660
|
const extendedToManyTree = toManyTree.concat(column.ref[0] === parentAlias ? column.ref.slice(1) : column.ref)
|
|
660
661
|
const tableAlias = this._createAlias(extendedToManyTree.join(':'))
|
|
@@ -702,7 +703,7 @@ class JoinCQNFromExpanded {
|
|
|
702
703
|
const ks = Object.keys(expandedEntity.keys).filter(
|
|
703
704
|
c => !expandedEntity.keys[c].isAssociation && !(c in DRAFT_COLUMNS_MAP)
|
|
704
705
|
)
|
|
705
|
-
const user =
|
|
706
|
+
const user = cds.context?.user.id
|
|
706
707
|
|
|
707
708
|
const assoc = entity.associations[column.ref[0]]
|
|
708
709
|
if (assoc.is2one && assoc.on) {
|
|
@@ -1157,7 +1158,6 @@ class JoinCQNFromExpanded {
|
|
|
1157
1158
|
* @returns {object}
|
|
1158
1159
|
* @private
|
|
1159
1160
|
*/
|
|
1160
|
-
// eslint-disable-next-line complexity
|
|
1161
1161
|
_buildExpandedCQN({ column, entity, readToOneCQN, toManyTree, mappings, parentAlias, defaultLanguage }) {
|
|
1162
1162
|
const isUnion = !!readToOneCQN.from.SET
|
|
1163
1163
|
const colRef = parentAlias === column.ref[0] ? column.ref.slice(1) : column.ref.slice(0)
|
|
@@ -1233,7 +1233,7 @@ class JoinCQNFromExpanded {
|
|
|
1233
1233
|
const ks = Object.keys(expandedEntity.keys).filter(
|
|
1234
1234
|
c => !expandedEntity.keys[c].isAssociation && !(c in DRAFT_COLUMNS_MAP)
|
|
1235
1235
|
)
|
|
1236
|
-
const user =
|
|
1236
|
+
const user = cds.context?.user.id
|
|
1237
1237
|
const unionFrom = getCQNUnionFrom(cols, ref.replace(/_drafts$/, ''), ref, ks, user)
|
|
1238
1238
|
|
|
1239
1239
|
for (const each of cqn.columns) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
2
2
|
const DRAFT_COLUMNS_ARRAY = Object.keys(DRAFT_COLUMNS_MAP)
|
|
3
|
-
const cds = require('../../cds')
|
|
4
3
|
|
|
5
4
|
const EXPAND = Symbol.for('sap.cds.expand')
|
|
6
5
|
const GET_KEY_VALUE = Symbol.for('sap.cds.getKeyValue')
|
|
@@ -85,7 +84,6 @@ class RawToExpanded {
|
|
|
85
84
|
* @returns {object}
|
|
86
85
|
* @private
|
|
87
86
|
*/
|
|
88
|
-
// eslint-disable-next-line complexity
|
|
89
87
|
_parseRaw({ mappings, toManyTree, conversionMapper, entry }) {
|
|
90
88
|
let isEntityNull
|
|
91
89
|
|
|
@@ -110,12 +108,6 @@ class RawToExpanded {
|
|
|
110
108
|
if (mapping[TO_MANY]) {
|
|
111
109
|
let expandedItems = this._getResultCache(toManyTree.concat(key))[mapping[GET_KEY_VALUE](false, entry)] || []
|
|
112
110
|
|
|
113
|
-
// the expanded items may include the actives of the deleted drafts -> filter out
|
|
114
|
-
if (!cds.env.fiori.lean_draft && rootIsActiveEntity !== null) {
|
|
115
|
-
if (mapping[TO_ACTIVE]) expandedItems = expandedItems.filter(ele => ele.IsActiveEntity !== false)
|
|
116
|
-
else expandedItems = expandedItems.filter(ele => !!ele.IsActiveEntity === rootIsActiveEntity)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
111
|
row[key] = !mapping[CLEANUP_KEYS]
|
|
120
112
|
? expandedItems
|
|
121
113
|
: expandedItems.map(item => {
|
|
@@ -87,8 +87,8 @@ const _processCategory = (req, category, { row, key, element }) => {
|
|
|
87
87
|
req.error({
|
|
88
88
|
code: 'MUST_NOT_BE_NULL',
|
|
89
89
|
message: 'Value is required',
|
|
90
|
-
target: key + '[' + k + ']',
|
|
91
|
-
args: [key + '[' + k + ']']
|
|
90
|
+
target: key + '[' + k.name + ']',
|
|
91
|
+
args: [key + '[' + k.name + ']']
|
|
92
92
|
})
|
|
93
93
|
return
|
|
94
94
|
}
|
|
@@ -102,12 +102,7 @@ const _processCategory = (req, category, { row, key, element }) => {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// generate UUIDs
|
|
105
|
-
if (
|
|
106
|
-
category === 'uuid' &&
|
|
107
|
-
!val &&
|
|
108
|
-
req.event === 'CREATE' &&
|
|
109
|
-
!element.parent.elements[element._foreignKey4]?._isAssociationStrict
|
|
110
|
-
) {
|
|
105
|
+
if (category === 'uuid' && !val && req.event === 'CREATE' && !element._foreignKey4) {
|
|
111
106
|
row[key] = cds.utils.uuid()
|
|
112
107
|
}
|
|
113
108
|
}
|
|
@@ -2,13 +2,33 @@ const cds = require('../../cds')
|
|
|
2
2
|
const { cqn2cqn4sql } = require('../../common/utils/cqn2cqn4sql')
|
|
3
3
|
const { generateAliases } = require('../utils/generateAliases')
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Restores the link of `req.data` and `req.query` in case `req.query` was overwritten.
|
|
7
|
+
* Only applicable for `UPDATE`s and `INSERT`s.
|
|
8
|
+
*
|
|
9
|
+
* @param { import('@sap/cds').Request } req
|
|
10
|
+
*/
|
|
5
11
|
const _restoreLink = req => {
|
|
6
12
|
if (req.query.INSERT?.entries) {
|
|
7
|
-
|
|
13
|
+
if (Array.isArray(req.query.INSERT.entries)) req.data = req.query.INSERT.entries[0]
|
|
14
|
+
else req.data = req.query.INSERT.entries
|
|
15
|
+
} else if (req.query.UPDATE?.data) {
|
|
16
|
+
req.data = req.query.UPDATE.data
|
|
8
17
|
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const _isLinked = req => {
|
|
21
|
+
if (req.query.INSERT?.entries) {
|
|
22
|
+
// in case of more than one entry, the array reference stays in tact
|
|
23
|
+
if (Array.isArray(req.query.INSERT.entries)) return req.data === req.query.INSERT.entries[0]
|
|
24
|
+
return req.data === req.query.INSERT.entries
|
|
25
|
+
}
|
|
26
|
+
|
|
9
27
|
if (req.query.UPDATE?.data) {
|
|
10
|
-
return
|
|
28
|
+
return req.data === req.query.UPDATE.data
|
|
11
29
|
}
|
|
30
|
+
|
|
31
|
+
return false
|
|
12
32
|
}
|
|
13
33
|
|
|
14
34
|
function handler(req) {
|
|
@@ -30,14 +50,17 @@ function handler(req) {
|
|
|
30
50
|
|
|
31
51
|
const _streaming = cds.env.features.stream_compat && req.query._streaming
|
|
32
52
|
|
|
53
|
+
// for restore link to req.data
|
|
54
|
+
const linked = _isLinked(req)
|
|
55
|
+
|
|
33
56
|
// convert to sql cqn
|
|
34
57
|
req.query = cqn2cqn4sql(req.query, this.model, { service: this })
|
|
35
58
|
|
|
59
|
+
// REVISIT: should not be necessary
|
|
36
60
|
// restore link to req.data
|
|
37
|
-
_restoreLink(req)
|
|
61
|
+
if (linked) _restoreLink(req)
|
|
38
62
|
|
|
39
63
|
if (_streaming) req.query._streaming = _streaming
|
|
40
|
-
|
|
41
64
|
generateAliases(req.query)
|
|
42
65
|
}
|
|
43
66
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const normalizeTimestamp = require('../../common/utils/normalizeTimestamp')
|
|
3
|
-
const {
|
|
3
|
+
const { deepCopy } = require('../../common/utils/copy')
|
|
4
4
|
const getError = require('../../common/error')
|
|
5
5
|
|
|
6
6
|
function _arrayWithCount(a, count) {
|
|
@@ -14,7 +14,7 @@ function _arrayWithCount(a, count) {
|
|
|
14
14
|
|
|
15
15
|
function _createCountQuery(query) {
|
|
16
16
|
// REVISIT: Use query.clone() instead
|
|
17
|
-
let _query = { SELECT:
|
|
17
|
+
let _query = { SELECT: deepCopy(query.SELECT) }
|
|
18
18
|
delete _query.SELECT.orderBy // not necessary to keep that
|
|
19
19
|
delete _query.SELECT.limit
|
|
20
20
|
// Also change columns in sub queries
|
|
@@ -139,7 +139,6 @@ class ExpressionBuilder extends BaseBuilder {
|
|
|
139
139
|
* @returns {number}
|
|
140
140
|
* @private
|
|
141
141
|
*/
|
|
142
|
-
// eslint-disable-next-line complexity
|
|
143
142
|
_reseverdKeyWords(objects, i) {
|
|
144
143
|
const NOT_EQUAL = { '!=': 1, '<>': 1 }
|
|
145
144
|
if (objects[i] === 'not' && objects[i + 1].func) {
|
|
@@ -161,7 +161,7 @@ class InsertBuilder extends BaseBuilder {
|
|
|
161
161
|
const uuidKeys = []
|
|
162
162
|
if (this._csn && this._csn.definitions[entityName] && this._csn.definitions[entityName].keys) {
|
|
163
163
|
for (const key of Object.values(this._csn.definitions[entityName].keys)) {
|
|
164
|
-
if (key.isUUID) {
|
|
164
|
+
if (key.isUUID && !key._foreignKey4) {
|
|
165
165
|
uuidKeys.push(key.name)
|
|
166
166
|
}
|
|
167
167
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const resolveStructured = require('../../common/utils/resolveStructured')
|
|
3
3
|
|
|
4
|
-
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
5
|
-
|
|
6
4
|
const _isStreamProperty = element => {
|
|
7
|
-
return element.type === 'cds.LargeBinary' || element['@Core.IsURL']
|
|
5
|
+
return element.type === 'cds.LargeBinary' || (element['@Core.MediaType'] && element['@Core.IsURL'])
|
|
8
6
|
}
|
|
9
7
|
|
|
10
8
|
/**
|
|
@@ -15,13 +13,12 @@ const _isStreamProperty = element => {
|
|
|
15
13
|
* @param entity - the csn entity
|
|
16
14
|
* @returns {Array} - array of columns
|
|
17
15
|
*/
|
|
18
|
-
const getColumns = (entity, {
|
|
16
|
+
const getColumns = (entity, { onlyKeys, omitStream } = { onlyKeys: false, omitStream: false }) => {
|
|
19
17
|
// REVISIT is this correct or just a problem that occurs because of new structure we do not deal with yet?
|
|
20
18
|
if (!(entity && entity.elements)) return []
|
|
21
19
|
const columnNames = []
|
|
22
20
|
// REVISIT!!!
|
|
23
21
|
const { structs = cds.env.features.ucsn_struct_conversion } = cds.env.effective.odata
|
|
24
|
-
const { lean_draft } = cds.env.fiori
|
|
25
22
|
const elements = entity.elements
|
|
26
23
|
for (const elementName in elements) {
|
|
27
24
|
const element = elements[elementName]
|
|
@@ -29,7 +26,6 @@ const getColumns = (entity, { _4db, onlyKeys, omitStream } = { _4db: true, onlyK
|
|
|
29
26
|
if (onlyKeys && !element.key) continue
|
|
30
27
|
if (omitStream && _isStreamProperty(element)) continue
|
|
31
28
|
if (element.isAssociation) continue
|
|
32
|
-
if (!lean_draft && _4db && entity._isDraftEnabled && elementName in DRAFT_COLUMNS_MAP) continue
|
|
33
29
|
if (structs && element.elements) {
|
|
34
30
|
columnNames.push(...resolveStructured({ element, structProperties: [] }, false))
|
|
35
31
|
continue
|