@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
|
@@ -3,30 +3,14 @@ const cds = require('../../cds')
|
|
|
3
3
|
const { SELECT } = cds.ql
|
|
4
4
|
|
|
5
5
|
const { isNavigationToMany } = require('../utils/req')
|
|
6
|
-
const { getKeysCondition } = require('../utils/where')
|
|
6
|
+
const { getKeysCondition, removeIsActiveEntityRecursively } = require('../utils/where')
|
|
7
7
|
const { isDraftActivateAction, ensureNoDraftsSuffix, ensureDraftsSuffix, draftIsLocked } = require('../utils/handler')
|
|
8
8
|
|
|
9
|
-
const { isCustomOperation } = require('../../cds-services/adapter/odata-v4/utils/request')
|
|
10
|
-
|
|
11
9
|
const { DRAFT_COLUMNS_ADMIN_MAP } = require('../../common/constants/draft')
|
|
10
|
+
const { deepCopyArray } = require('../../common/utils/copy')
|
|
12
11
|
const DRAFT_COLUMNS_ADMIN = Object.keys(DRAFT_COLUMNS_ADMIN_MAP)
|
|
13
12
|
const PREFIX_DRAFT_COLUMNS = DRAFT_COLUMNS_ADMIN.map(col => ({ ref: ['DRAFT_DraftAdministrativeData', col] }))
|
|
14
13
|
|
|
15
|
-
// copied from adapter/odata-v4/utils/context-object
|
|
16
|
-
const _getTargetEntityName = (service, pathSegments) => {
|
|
17
|
-
if (isCustomOperation(pathSegments, false)) return
|
|
18
|
-
|
|
19
|
-
let navSegmentName
|
|
20
|
-
let entityName = `${service.name}.${pathSegments[0].getEntitySet().getName()}`
|
|
21
|
-
|
|
22
|
-
for (const navSegment of pathSegments.filter(segment => segment.getNavigationProperty() !== null)) {
|
|
23
|
-
navSegmentName = navSegment.getNavigationProperty().getName()
|
|
24
|
-
entityName = service.model.definitions[entityName].elements[navSegmentName].target
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return entityName
|
|
28
|
-
}
|
|
29
|
-
|
|
30
14
|
/**
|
|
31
15
|
* Provide information about the parent entity, i.e. the entity that has the to-many composition element.
|
|
32
16
|
* Limitation: only works for one key (besides IsActiveEntity)
|
|
@@ -36,34 +20,6 @@ const _getTargetEntityName = (service, pathSegments) => {
|
|
|
36
20
|
* @returns {object}
|
|
37
21
|
* @private
|
|
38
22
|
*/
|
|
39
|
-
const _getParent = (req, service) => {
|
|
40
|
-
// REVISIT: get rid of getUriInfo
|
|
41
|
-
if (!req.getUriInfo) return
|
|
42
|
-
|
|
43
|
-
const segments = req.getUriInfo().getPathSegments()
|
|
44
|
-
if (segments.length === 1) return
|
|
45
|
-
|
|
46
|
-
const parent = {
|
|
47
|
-
entityName: _getTargetEntityName(service, segments.slice(0, segments.length - 1))
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const parentKeyPredicates = segments[segments.length - 2].getKeyPredicates()
|
|
51
|
-
let keyPredicateName, keyPredicateText
|
|
52
|
-
|
|
53
|
-
for (const keyPredicate of parentKeyPredicates) {
|
|
54
|
-
keyPredicateName = keyPredicate.getEdmRef().getName()
|
|
55
|
-
keyPredicateText = keyPredicate.getText()
|
|
56
|
-
|
|
57
|
-
if (keyPredicateName === 'IsActiveEntity') {
|
|
58
|
-
parent.IsActiveEntity = keyPredicateText === 'true'
|
|
59
|
-
} else {
|
|
60
|
-
parent.keyName = keyPredicateName
|
|
61
|
-
parent.keyValue = keyPredicateText
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return parent
|
|
66
|
-
}
|
|
67
23
|
|
|
68
24
|
const _validateDraft = (req, draftResult, isBoundAction) => {
|
|
69
25
|
if (!draftResult || draftResult.length === 0) req.reject(404)
|
|
@@ -102,36 +58,48 @@ const _getSelectDraftDataCqn = (entityName, where) => {
|
|
|
102
58
|
.where(where)
|
|
103
59
|
}
|
|
104
60
|
|
|
105
|
-
const
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
61
|
+
const _getRoot = req => {
|
|
62
|
+
if (!req.query) return
|
|
63
|
+
const refObj = req.query.SELECT?.from || req.query.UPDATE?.entity || req.query.INSERT?.into || req.query.DELETE?.from
|
|
64
|
+
const root = {
|
|
65
|
+
entityName: ensureDraftsSuffix(refObj.ref[0].id),
|
|
66
|
+
where: removeIsActiveEntityRecursively(deepCopyArray(refObj.ref[0].where))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const item of refObj.ref[0].where) {
|
|
70
|
+
if (item.ref && item.ref[item.ref.length - 1] === 'IsActiveEntity') {
|
|
71
|
+
const index = refObj.ref[0].where.indexOf(item)
|
|
72
|
+
root.IsActiveEntity = refObj.ref[0].where[index + 2].val
|
|
73
|
+
break
|
|
112
74
|
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return root
|
|
78
|
+
}
|
|
113
79
|
|
|
114
|
-
|
|
80
|
+
const _getDraftDataFromExistingDraft = async (req, root) => {
|
|
81
|
+
if (!root) return []
|
|
82
|
+
if (root?.IsActiveEntity === false) {
|
|
83
|
+
const query = _getSelectDraftDataCqn(root.entityName, root.where)
|
|
84
|
+
const result = await cds.tx(req).run(query)
|
|
85
|
+
return result
|
|
115
86
|
}
|
|
116
87
|
|
|
117
|
-
const rootWhere = getKeysCondition(req
|
|
88
|
+
const rootWhere = getKeysCondition(req)
|
|
118
89
|
const query = _getSelectDraftDataCqn(ensureNoDraftsSuffix(req.target.name), rootWhere)
|
|
119
90
|
const result = await cds.tx(req).run(query)
|
|
120
91
|
return result
|
|
121
92
|
}
|
|
122
93
|
|
|
123
|
-
const _addDraftDataFromExistingDraft = async
|
|
124
|
-
const
|
|
125
|
-
const result = await _getDraftDataFromExistingDraft(req,
|
|
126
|
-
|
|
127
|
-
if (parent) {
|
|
128
|
-
if (parent.IsActiveEntity === false) {
|
|
129
|
-
_validateDraft(req, result)
|
|
130
|
-
_addDraftDataToContext(req, result)
|
|
131
|
-
return result
|
|
132
|
-
}
|
|
94
|
+
const _addDraftDataFromExistingDraft = async req => {
|
|
95
|
+
const root = _getRoot(req)
|
|
96
|
+
const result = await _getDraftDataFromExistingDraft(req, root)
|
|
133
97
|
|
|
134
|
-
|
|
98
|
+
if (!root) return []
|
|
99
|
+
if (root.IsActiveEntity === false) {
|
|
100
|
+
_validateDraft(req, result)
|
|
101
|
+
_addDraftDataToContext(req, result)
|
|
102
|
+
return result
|
|
135
103
|
}
|
|
136
104
|
|
|
137
105
|
if (result && result.length > 0) _validateDraft(req, result)
|
|
@@ -147,7 +115,7 @@ const _new = async function (req) {
|
|
|
147
115
|
|
|
148
116
|
if (isNavigationToMany(req)) {
|
|
149
117
|
// REVISIT: How can NEW be a navigation to many?
|
|
150
|
-
const result = await _addDraftDataFromExistingDraft(req
|
|
118
|
+
const result = await _addDraftDataFromExistingDraft(req)
|
|
151
119
|
|
|
152
120
|
// in order to fix corner case where active subitems are created in draft case
|
|
153
121
|
if (result.length === 0) req.reject(404)
|
|
@@ -165,7 +133,7 @@ const _new = async function (req) {
|
|
|
165
133
|
const _patchUpdate = async function (req) {
|
|
166
134
|
if (isDraftActivateAction(req)) return
|
|
167
135
|
|
|
168
|
-
const result = await _addDraftDataFromExistingDraft(req
|
|
136
|
+
const result = await _addDraftDataFromExistingDraft(req)
|
|
169
137
|
|
|
170
138
|
// means that the draft does not exists
|
|
171
139
|
if (result.length === 0) req.reject(404)
|
|
@@ -175,11 +143,11 @@ const _patchUpdate = async function (req) {
|
|
|
175
143
|
* Generic Handler for before DELETE and CANCEL requests.
|
|
176
144
|
*/
|
|
177
145
|
const _deleteCancel = async function (req) {
|
|
178
|
-
await _addDraftDataFromExistingDraft(req
|
|
146
|
+
await _addDraftDataFromExistingDraft(req)
|
|
179
147
|
}
|
|
180
148
|
|
|
181
|
-
const _validateDraftBoundAction = async function (req
|
|
182
|
-
const result = await _getDraftDataFromExistingDraft(req,
|
|
149
|
+
const _validateDraftBoundAction = async function (req) {
|
|
150
|
+
const result = await _getDraftDataFromExistingDraft(req, _getRoot(req))
|
|
183
151
|
const isBoundAction = true
|
|
184
152
|
if (result && result.length > 0) _validateDraft(req, result, isBoundAction)
|
|
185
153
|
}
|
|
@@ -196,7 +164,7 @@ const _registerBoundActionHandlers = function (entityName, actions) {
|
|
|
196
164
|
)
|
|
197
165
|
|
|
198
166
|
for (const action of boundActions) {
|
|
199
|
-
this.before(action.name, entityName, req => _validateDraftBoundAction(req
|
|
167
|
+
this.before(action.name, entityName, req => _validateDraftBoundAction(req))
|
|
200
168
|
}
|
|
201
169
|
}
|
|
202
170
|
|
|
@@ -8,10 +8,10 @@ const { deleteDraft } = require('../utils/delete')
|
|
|
8
8
|
*
|
|
9
9
|
* @param req
|
|
10
10
|
*/
|
|
11
|
-
const
|
|
11
|
+
const fioriGenericCancel = function (req) {
|
|
12
12
|
return deleteDraft(req, this)
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
16
|
-
srv.on('CANCEL', entity,
|
|
16
|
+
srv.on('CANCEL', entity, fioriGenericCancel)
|
|
17
17
|
})
|
|
@@ -8,12 +8,12 @@ const { deleteDraft } = require('../utils/delete')
|
|
|
8
8
|
*
|
|
9
9
|
* @param req
|
|
10
10
|
*/
|
|
11
|
-
const
|
|
11
|
+
const fioriGenericDelete = function (req) {
|
|
12
12
|
// we should call deleteDraft only for draft tables and call next
|
|
13
13
|
// to pass delete of active tables to our general implementation
|
|
14
14
|
return deleteDraft(req, this, true)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
18
|
-
srv.on('DELETE', entity,
|
|
18
|
+
srv.on('DELETE', entity, fioriGenericDelete)
|
|
19
19
|
})
|
|
@@ -68,7 +68,7 @@ const _select = async (lockRecordCQN, draftExistsCQN, selectCQNs, req, dbtx) =>
|
|
|
68
68
|
*
|
|
69
69
|
* @param req
|
|
70
70
|
*/
|
|
71
|
-
const
|
|
71
|
+
const fioriGenericEdit = async function (req) {
|
|
72
72
|
if (!isActiveEntityRequested(req.query.SELECT.where || [])) {
|
|
73
73
|
req.reject(400)
|
|
74
74
|
}
|
|
@@ -160,5 +160,5 @@ const _handler = async function (req) {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
163
|
-
srv.on('EDIT', entity,
|
|
163
|
+
srv.on('EDIT', entity, fioriGenericEdit)
|
|
164
164
|
})
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
|
-
const { INSERT,
|
|
2
|
+
const { INSERT, UPDATE } = cds.ql
|
|
3
3
|
|
|
4
4
|
const onDraftActivate = require('./activate')._handler
|
|
5
5
|
const { isNavigationToMany } = require('../utils/req')
|
|
6
|
-
const { getKeysCondition } = require('../utils/where')
|
|
7
6
|
const { ensureDraftsSuffix } = require('../utils/handler')
|
|
8
|
-
const { DRAFT_COLUMNS_MAP } = require('../../common/constants/draft')
|
|
9
7
|
|
|
10
8
|
const _getUpdateDraftAdminCQN = ({ user, timestamp }, draftUUID) => {
|
|
11
9
|
return UPDATE('DRAFT.DraftAdministrativeData')
|
|
@@ -50,7 +48,7 @@ const _getInsertDataCQN = (req, draftUUID) => {
|
|
|
50
48
|
* @param req
|
|
51
49
|
* @param next
|
|
52
50
|
*/
|
|
53
|
-
const
|
|
51
|
+
const fioriGenericNew = async function (req, next) {
|
|
54
52
|
if (!req._draftMetadata) {
|
|
55
53
|
// REVISIT: when is this the case?
|
|
56
54
|
return onDraftActivate(req, next)
|
|
@@ -72,5 +70,5 @@ const _handler = async function (req, next) {
|
|
|
72
70
|
}
|
|
73
71
|
|
|
74
72
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
75
|
-
srv.on('NEW', entity,
|
|
73
|
+
srv.on('NEW', entity, fioriGenericNew)
|
|
76
74
|
})
|
|
@@ -1,46 +1,25 @@
|
|
|
1
1
|
const cds = require('../../cds')
|
|
2
2
|
const { UPDATE, SELECT } = cds.ql
|
|
3
3
|
|
|
4
|
-
const {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const _getSelectCQN = (model, { target: { name } }, keysCondition, checkUser = true) => {
|
|
16
|
-
const activeName = ensureNoDraftsSuffix(name)
|
|
17
|
-
const draftName = ensureDraftsSuffix(name)
|
|
18
|
-
|
|
19
|
-
const columns = [
|
|
20
|
-
...addColumnAlias(
|
|
21
|
-
getColumns(model.definitions[activeName], { removeIgnore: true, filterVirtual: true }).map(obj => obj.name),
|
|
22
|
-
draftName
|
|
23
|
-
),
|
|
24
|
-
...DRAFT_COLUMNS_CQN
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
if (checkUser) {
|
|
28
|
-
columns.push({ ref: ['DRAFT.DraftAdministrativeData', 'inProcessByUser'], as: 'draftAdmin_inProcessByUser' })
|
|
4
|
+
const { getUpdateDraftAdminCQN, ensureDraftsSuffix } = require('../utils/handler')
|
|
5
|
+
const { removeIsActiveEntityRecursively } = require('../utils/where')
|
|
6
|
+
const { deepCopyArray } = require('../../common/utils/copy')
|
|
7
|
+
const { cqn2cqn4sql } = require('../../common/utils/cqn2cqn4sql')
|
|
8
|
+
|
|
9
|
+
const _getSelectCQN = ({ query }) => {
|
|
10
|
+
const fromRef = deepCopyArray(query.UPDATE.entity.ref)
|
|
11
|
+
for (const item of fromRef) {
|
|
12
|
+
if (item.where) {
|
|
13
|
+
item.where = removeIsActiveEntityRecursively(item.where)
|
|
14
|
+
}
|
|
29
15
|
}
|
|
16
|
+
fromRef[0].id = ensureDraftsSuffix(fromRef[0].id)
|
|
17
|
+
const from = { ref: fromRef }
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
return SELECT.one(draftName)
|
|
33
|
-
.columns(columns)
|
|
34
|
-
.join('DRAFT.DraftAdministrativeData')
|
|
35
|
-
.on([
|
|
36
|
-
{ ref: [draftName, 'DraftAdministrativeData_DraftUUID'] },
|
|
37
|
-
'=',
|
|
38
|
-
{ ref: ['DRAFT.DraftAdministrativeData', 'DraftUUID'] }
|
|
39
|
-
])
|
|
40
|
-
.where(keysCondition)
|
|
19
|
+
return SELECT.from(from)
|
|
41
20
|
}
|
|
42
21
|
|
|
43
|
-
const _getUpdateDraftCQN = ({ query
|
|
22
|
+
const _getUpdateDraftCQN = ({ query }, where, targetRef) => {
|
|
44
23
|
const set = {}
|
|
45
24
|
|
|
46
25
|
for (const entry in query.UPDATE.data) {
|
|
@@ -52,7 +31,23 @@ const _getUpdateDraftCQN = ({ query, target: { name } }, keysCondition) => {
|
|
|
52
31
|
}
|
|
53
32
|
|
|
54
33
|
if (set.IsActiveEntity) set.IsActiveEntity = false
|
|
55
|
-
|
|
34
|
+
|
|
35
|
+
return UPDATE(targetRef).data(set).where(where)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const _joinDraftAdministrativeData = (selectResolved, target) => {
|
|
39
|
+
const columns = []
|
|
40
|
+
columns.push({ ref: ['DRAFT.DraftAdministrativeData', 'inProcessByUser'], as: 'draftAdmin_inProcessByUser' })
|
|
41
|
+
columns.push({ ref: [target, 'DraftAdministrativeData_DraftUUID'] })
|
|
42
|
+
|
|
43
|
+
return selectResolved
|
|
44
|
+
.columns(columns)
|
|
45
|
+
.join('DRAFT.DraftAdministrativeData')
|
|
46
|
+
.on([
|
|
47
|
+
{ ref: [target, 'DraftAdministrativeData_DraftUUID'] },
|
|
48
|
+
'=',
|
|
49
|
+
{ ref: ['DRAFT.DraftAdministrativeData', 'DraftUUID'] }
|
|
50
|
+
])
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
/**
|
|
@@ -63,20 +58,31 @@ const _getUpdateDraftCQN = ({ query, target: { name } }, keysCondition) => {
|
|
|
63
58
|
*
|
|
64
59
|
* @param req
|
|
65
60
|
*/
|
|
66
|
-
const
|
|
61
|
+
const fioriGenericPatch = async function (req) {
|
|
67
62
|
if (req.data.IsActiveEntity === true) req.reject(400, 'Patch can only be applied to a draft entity')
|
|
68
63
|
|
|
69
|
-
const keysCondition = getKeysCondition(req.target, req.data)
|
|
70
64
|
const dbtx = cds.tx(req)
|
|
71
|
-
|
|
65
|
+
|
|
66
|
+
const selectResolved = cqn2cqn4sql(_getSelectCQN(req), this.model)
|
|
67
|
+
|
|
68
|
+
const targetName = selectResolved.SELECT.from.ref[selectResolved.SELECT.from.ref.length - 1]
|
|
69
|
+
const alias = selectResolved.SELECT.from.as
|
|
70
|
+
const selectWithAdmin = _joinDraftAdministrativeData(selectResolved, alias || targetName)
|
|
71
|
+
const results = await dbtx.run(selectWithAdmin)
|
|
72
|
+
|
|
73
|
+
if (results.length === 0) req.reject(404)
|
|
74
|
+
|
|
75
|
+
const result = results[0]
|
|
72
76
|
|
|
73
77
|
// Potential timeout scenario supported
|
|
74
78
|
if (result.draftAdmin_inProcessByUser && result.draftAdmin_inProcessByUser !== req.user.id) {
|
|
75
79
|
// REVISIT: security log?
|
|
76
80
|
req.reject(403)
|
|
77
81
|
}
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
const updateDraftCQN = _getUpdateDraftCQN(req, selectResolved.SELECT.where, {
|
|
83
|
+
ref: [targetName],
|
|
84
|
+
as: alias || targetName
|
|
85
|
+
})
|
|
80
86
|
const updateDraftAdminCQN = getUpdateDraftAdminCQN(req, result.DraftAdministrativeData_DraftUUID)
|
|
81
87
|
|
|
82
88
|
await Promise.all([dbtx.run(updateDraftCQN), dbtx.run(updateDraftAdminCQN)])
|
|
@@ -86,5 +92,5 @@ const _handler = async function (req) {
|
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
89
|
-
srv.on('PATCH', entity,
|
|
95
|
+
srv.on('PATCH', entity, fioriGenericPatch)
|
|
90
96
|
})
|
|
@@ -11,7 +11,7 @@ const { getColumns } = require('../../cds-services/services/utils/columns')
|
|
|
11
11
|
*
|
|
12
12
|
* @param req
|
|
13
13
|
*/
|
|
14
|
-
const
|
|
14
|
+
const fioriGenericPrepare = async function (req) {
|
|
15
15
|
if (req.query.SELECT.from.ref.length > 1 || isActiveEntityRequested(req.query.SELECT.from.ref[0].where || [])) {
|
|
16
16
|
req.reject(400, 'Action "draftPrepare" can only be called on a draft entity')
|
|
17
17
|
}
|
|
@@ -44,5 +44,5 @@ const _handler = async function (req) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
47
|
-
srv.on('draftPrepare', entity,
|
|
47
|
+
srv.on('draftPrepare', entity, fioriGenericPrepare)
|
|
48
48
|
})
|
|
@@ -4,6 +4,7 @@ const { SELECT } = cds.ql
|
|
|
4
4
|
const { cqn2cqn4sql, convertWhereExists } = require('../../common/utils/cqn2cqn4sql')
|
|
5
5
|
const { getElementDeep } = require('../../common/utils/csn')
|
|
6
6
|
const { DRAFT_COLUMNS_MAP, SCENARIO } = require('../../common/constants/draft')
|
|
7
|
+
const { filterNonDraftColumns } = require('../../common/utils/draft')
|
|
7
8
|
const {
|
|
8
9
|
addColumnAlias,
|
|
9
10
|
draftIsLocked,
|
|
@@ -16,15 +17,11 @@ const {
|
|
|
16
17
|
filterKeys
|
|
17
18
|
} = require('../utils/handler')
|
|
18
19
|
const { deleteCondition, readAndDeleteKeywords, removeIsActiveEntityRecursively } = require('../utils/where')
|
|
19
|
-
const { getColumns } = require('../../cds-services/services/utils/columns')
|
|
20
20
|
const { adaptStreamCQN } = require('../../cds-services/adapter/odata-v4/utils/stream')
|
|
21
21
|
|
|
22
22
|
const _findSubselect = where => {
|
|
23
23
|
return where.find((e, i) => {
|
|
24
|
-
if (e.xpr)
|
|
25
|
-
return _findSubselect(e.xpr)
|
|
26
|
-
}
|
|
27
|
-
|
|
24
|
+
if (e.xpr) return _findSubselect(e.xpr)
|
|
28
25
|
return e.SELECT && where[i - 1] === 'exists'
|
|
29
26
|
})
|
|
30
27
|
}
|
|
@@ -626,6 +623,9 @@ const _siblingEntity = (
|
|
|
626
623
|
|
|
627
624
|
if (siblingIndex === 0) {
|
|
628
625
|
const columnCqnPartial = columns.map(col => {
|
|
626
|
+
if (col.val) {
|
|
627
|
+
return Object.assign({}, col)
|
|
628
|
+
}
|
|
629
629
|
const colName = col.ref ? col.ref[col.ref.length - 1] : col
|
|
630
630
|
const ref = col.ref ? [table.as, ...col.ref] : [table.as, colName]
|
|
631
631
|
return Object.assign({}, col, { ref })
|
|
@@ -694,7 +694,7 @@ function _siblingSubScenario(nav, siblingIndex, siblingQuery, target, params, mo
|
|
|
694
694
|
const existsIdx = siblingQuery.SELECT.where.indexOf('exists')
|
|
695
695
|
if (existsIdx > -1) subReq.query.where(siblingQuery.SELECT.where.slice(existsIdx, existsIdx + 2))
|
|
696
696
|
const subOrigFrom = { ref: [...subNav].reverse() }
|
|
697
|
-
subScenario = _generateCQN(
|
|
697
|
+
subScenario = _generateCQN(subReq, [{ val: 1 }], subOrigFrom, model)
|
|
698
698
|
subScenario.cqn.where(onCond)
|
|
699
699
|
}
|
|
700
700
|
|
|
@@ -757,9 +757,8 @@ const _replaceWhereExists = (query, _siblingIndex, siblingCQN) => {
|
|
|
757
757
|
}
|
|
758
758
|
}
|
|
759
759
|
|
|
760
|
-
const _mergeSiblingIntoCQN = (cqn, { cqn: siblingCQN }, siblingIndex) =>
|
|
761
|
-
|
|
762
|
-
}
|
|
760
|
+
const _mergeSiblingIntoCQN = (cqn, { cqn: siblingCQN }, siblingIndex) =>
|
|
761
|
+
_replaceWhereExists(cqn, siblingIndex, siblingCQN)
|
|
763
762
|
|
|
764
763
|
const _getDraftDoc = (req, draftName, draftWhere) => {
|
|
765
764
|
const refDraft = req.query.SELECT.from.as ? { ref: [draftName], as: req.query.SELECT.from.as } : draftName
|
|
@@ -784,8 +783,10 @@ const _getDraftDoc = (req, draftName, draftWhere) => {
|
|
|
784
783
|
|
|
785
784
|
const _getOrderByEnrichedColumns = (orderBy, columns, entity) => {
|
|
786
785
|
const enrichedCol = []
|
|
786
|
+
|
|
787
787
|
if (orderBy && orderBy.length > 1) {
|
|
788
788
|
const colNames = columns.map(el => el.ref[el.ref.length - 1])
|
|
789
|
+
|
|
789
790
|
// REVISIT: GET Books?$select=title&$expand=NotBooks($select=pages)&$orderby=NotBooks/title - what's then?
|
|
790
791
|
for (const el of orderBy) {
|
|
791
792
|
// For associations we need to 'materialise' the resulting field, otherwise we cannot access it in an outer SELECT.
|
|
@@ -906,11 +907,11 @@ const _getUnionCQN = (req, draftName, columns, subSelect, draftWhere, model, ent
|
|
|
906
907
|
}
|
|
907
908
|
|
|
908
909
|
return union
|
|
909
|
-
.columns(...columns)
|
|
910
|
+
.columns(...columns.map(ref => (ref.as ? { ref: [ref.as], as: ref.as } : ref))) // needed for aliased stream property ref@odata.mediaContentType
|
|
910
911
|
.columns(..._filterDraftColumnsBySelected(DRAFT_COLUMNS_CASTED, req.query.SELECT.columns))
|
|
911
912
|
}
|
|
912
913
|
|
|
913
|
-
const _excludeActiveDraftExists = (req,
|
|
914
|
+
const _excludeActiveDraftExists = (req, columns, draftWhere, model) => {
|
|
914
915
|
const { table, name } = _getTableName(req, true)
|
|
915
916
|
const draftName = table.ref[0]
|
|
916
917
|
|
|
@@ -964,8 +965,9 @@ const _validatedWithSiblingInProcess = (req, draftWhere, draftParameters, column
|
|
|
964
965
|
if (
|
|
965
966
|
!draftInProcessByUser &&
|
|
966
967
|
_isValidExcludeActiveDraftExists(draftParameters.isActiveEntity, draftParameters.siblingIsActive)
|
|
967
|
-
)
|
|
968
|
-
return _excludeActiveDraftExists(req,
|
|
968
|
+
) {
|
|
969
|
+
return _excludeActiveDraftExists(req, columns, draftWhere, model)
|
|
970
|
+
}
|
|
969
971
|
|
|
970
972
|
if (
|
|
971
973
|
draftInProcessByUser &&
|
|
@@ -1005,8 +1007,8 @@ const _draftInSubSelect = (where, req) => {
|
|
|
1005
1007
|
const _isDraftAdminScenario = req =>
|
|
1006
1008
|
req.target.query && req.target.query._target && req.target.query._target.name === 'DRAFT.DraftAdministrativeData'
|
|
1007
1009
|
|
|
1008
|
-
const _generateCQN = (
|
|
1009
|
-
const nav = [...
|
|
1010
|
+
const _generateCQN = (req, columns, from, model) => {
|
|
1011
|
+
const nav = [...from.ref].reverse() || []
|
|
1010
1012
|
let siblingIndex = nav.indexOf('SiblingEntity')
|
|
1011
1013
|
|
|
1012
1014
|
// it can also be a property access (new parser), then we must shift it
|
|
@@ -1018,20 +1020,12 @@ const _generateCQN = (originalFrom, req, columns, model) => {
|
|
|
1018
1020
|
let siblingScenario
|
|
1019
1021
|
if (siblingIndex > -1) {
|
|
1020
1022
|
siblingScenario = _getSiblingScenario(req, columns, model, siblingIndex, nav)
|
|
1021
|
-
if (siblingIndex === 0)
|
|
1022
|
-
return siblingScenario
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1023
|
+
if (siblingIndex === 0) return siblingScenario
|
|
1025
1024
|
_mergeSiblingIntoCQN(req.query, siblingScenario, siblingIndex - 1)
|
|
1026
1025
|
}
|
|
1027
1026
|
|
|
1028
|
-
if (_isDraftAdminScenario(req))
|
|
1029
|
-
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
if (!req.query.SELECT.where) {
|
|
1033
|
-
return _allActive(req, columns)
|
|
1034
|
-
}
|
|
1027
|
+
if (_isDraftAdminScenario(req)) return _draftAdminTable(req)
|
|
1028
|
+
if (!req.query.SELECT.where) return _allActive(req, columns)
|
|
1035
1029
|
|
|
1036
1030
|
// REVISIT this function does not only read, but modifies where!
|
|
1037
1031
|
const draftParameters = _readDraftParameters(req.query.SELECT.where)
|
|
@@ -1065,11 +1059,6 @@ const _generateCQN = (originalFrom, req, columns, model) => {
|
|
|
1065
1059
|
return _validatedDraftOfWhichIAmOwner(req, req.query.SELECT.where, draftParameters, columns)
|
|
1066
1060
|
}
|
|
1067
1061
|
|
|
1068
|
-
const _getColumns = ({ query: { SELECT } }) =>
|
|
1069
|
-
SELECT.columns.filter(
|
|
1070
|
-
col => (col.ref && !(col.ref[col.ref.length - 1] in DRAFT_COLUMNS_MAP)) || (!col.ref && !(col in DRAFT_COLUMNS_MAP))
|
|
1071
|
-
)
|
|
1072
|
-
|
|
1073
1062
|
const _isIsActiveEntity = element => element.ref && element.ref[element.ref.length - 1] === 'IsActiveEntity'
|
|
1074
1063
|
|
|
1075
1064
|
const _adaptSubSelects = ({ SELECT: { from, where } }, scenario) => {
|
|
@@ -1182,6 +1171,7 @@ const _setLastSubQuery = (query, last, prev = query) => {
|
|
|
1182
1171
|
const _adaptDraftAdminExpand = cqn => {
|
|
1183
1172
|
const draftAdminExpand =
|
|
1184
1173
|
cqn.SELECT.columns && cqn.SELECT.columns.find(c => c.expand && c.ref[0] === 'DraftAdministrativeData')
|
|
1174
|
+
|
|
1185
1175
|
if (draftAdminExpand) {
|
|
1186
1176
|
_ensureDraftAdminColumnsForCalculation(draftAdminExpand.expand)
|
|
1187
1177
|
}
|
|
@@ -1274,7 +1264,7 @@ const _adaptColumns4readAfterWrite = (req, cqnScenario, query4sql) => {
|
|
|
1274
1264
|
*
|
|
1275
1265
|
* @param req
|
|
1276
1266
|
*/
|
|
1277
|
-
const
|
|
1267
|
+
const fioriGenericRead = async function (req) {
|
|
1278
1268
|
const query = req.query
|
|
1279
1269
|
const originalFrom = _copyCQNPartial(query.SELECT.from)
|
|
1280
1270
|
|
|
@@ -1299,12 +1289,12 @@ const _handler = async function (req) {
|
|
|
1299
1289
|
// just to make existing tests working with new parser. not really tested, not needed to be supported
|
|
1300
1290
|
if (reqClone.query.SELECT.from.SELECT) {
|
|
1301
1291
|
const subQueryReq = { __proto__: req, query: _copyCQNPartial(_getLastSubQuery(reqClone.query)) }
|
|
1302
|
-
const
|
|
1303
|
-
cqnScenario = _generateCQN(originalFrom.SELECT.from,
|
|
1292
|
+
const nonDraftColumns = filterNonDraftColumns(subQueryReq.query.SELECT.columns)
|
|
1293
|
+
cqnScenario = _generateCQN(subQueryReq, nonDraftColumns, originalFrom.SELECT.from, this.model)
|
|
1304
1294
|
cqnScenario.cqn = _setLastSubQuery(reqClone.query, cqnScenario.cqn)
|
|
1305
1295
|
} else {
|
|
1306
|
-
const
|
|
1307
|
-
cqnScenario = _generateCQN(
|
|
1296
|
+
const nonDraftColumns = filterNonDraftColumns(reqClone.query.SELECT.columns)
|
|
1297
|
+
cqnScenario = _generateCQN(reqClone, nonDraftColumns, originalFrom, this.model)
|
|
1308
1298
|
}
|
|
1309
1299
|
|
|
1310
1300
|
if (!cqnScenario) req.reject(400)
|
|
@@ -1334,5 +1324,5 @@ const _handler = async function (req) {
|
|
|
1334
1324
|
}
|
|
1335
1325
|
|
|
1336
1326
|
module.exports = cds.service.impl(function (srv, entity) {
|
|
1337
|
-
srv.on('READ', entity,
|
|
1327
|
+
srv.on('READ', entity, fioriGenericRead)
|
|
1338
1328
|
})
|
|
@@ -210,11 +210,13 @@ const extractKeyConditions = whereCondition => {
|
|
|
210
210
|
return result
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
const getKeysCondition =
|
|
213
|
+
const getKeysCondition = req => {
|
|
214
|
+
const data = req.data
|
|
215
|
+
const target = req.target
|
|
214
216
|
const where = []
|
|
215
217
|
for (const k in target.keys) {
|
|
216
218
|
const key = target.keys[k]
|
|
217
|
-
if (!key.isAssociation && key.name !== 'IsActiveEntity') {
|
|
219
|
+
if (!key.isAssociation && key.name !== 'IsActiveEntity' && data[key.name] != undefined) {
|
|
218
220
|
if (where.length) where.push('and')
|
|
219
221
|
where.push({ ref: [key.name] }, '=', { val: data[key.name] })
|
|
220
222
|
}
|
|
@@ -163,10 +163,8 @@ class HanaDatabase extends DatabaseService {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
// REVISIT: should happen automatically after a configurable time
|
|
166
|
-
|
|
167
|
-
async disconnect(tenant, poolOnly) {
|
|
166
|
+
async disconnect(tenant) {
|
|
168
167
|
await pool.drain(tenant)
|
|
169
|
-
if (!poolOnly) super.disconnect(tenant)
|
|
170
168
|
}
|
|
171
169
|
}
|
|
172
170
|
|
|
@@ -55,6 +55,7 @@ const convertToString = element => {
|
|
|
55
55
|
const HANA_TYPE_CONVERSION_MAP = new Map([
|
|
56
56
|
['cds.Boolean', convertToBoolean],
|
|
57
57
|
['cds.Integer64', convertInt64ToString],
|
|
58
|
+
['cds.Int64', convertInt64ToString],
|
|
58
59
|
['cds.DateTime', convertToISONoMillis],
|
|
59
60
|
['cds.Timestamp', convertToISO],
|
|
60
61
|
['cds.LargeString', convertToString],
|
|
@@ -62,10 +63,12 @@ const HANA_TYPE_CONVERSION_MAP = new Map([
|
|
|
62
63
|
])
|
|
63
64
|
|
|
64
65
|
if (cds.env.features.bigjs) {
|
|
66
|
+
// eslint-disable-next-line cds/no-missing-dependencies -- needs to be added by app dev
|
|
65
67
|
const Big = require('big.js')
|
|
66
68
|
const convertToBig = value => new Big(value)
|
|
67
69
|
|
|
68
70
|
HANA_TYPE_CONVERSION_MAP.set('cds.Integer64', convertToBig)
|
|
71
|
+
HANA_TYPE_CONVERSION_MAP.set('cds.Int64', convertToBig)
|
|
69
72
|
HANA_TYPE_CONVERSION_MAP.set('cds.Decimal', convertToBig)
|
|
70
73
|
}
|
|
71
74
|
|