@sap/cds 5.4.6 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +208 -2
- package/apis/ql.d.ts +17 -15
- package/app/index.js +1 -1
- package/bin/build/buildTaskEngine.js +26 -42
- package/bin/build/buildTaskFactory.js +6 -10
- package/bin/build/buildTaskHandler.js +2 -4
- package/bin/build/buildTaskProvider.js +3 -1
- package/bin/build/buildTaskProviderFactory.js +9 -15
- package/bin/build/constants.js +15 -3
- package/bin/build/index.js +5 -4
- package/bin/build/mtaUtil.js +8 -11
- package/bin/build/provider/buildTaskHandlerEdmx.js +63 -6
- package/bin/build/provider/buildTaskHandlerInternal.js +2 -34
- package/bin/build/provider/buildTaskProviderInternal.js +16 -42
- package/bin/build/provider/fiori/index.js +13 -24
- package/bin/build/provider/hana/2migration.js +17 -15
- package/bin/build/provider/hana/2tabledata.js +52 -48
- package/bin/build/provider/hana/index.js +27 -25
- package/bin/build/provider/hana/migrationtable.js +91 -67
- package/bin/build/provider/java-cf/index.js +14 -24
- package/bin/build/provider/mtx/index.js +12 -14
- package/bin/build/provider/node-cf/index.js +18 -32
- package/bin/cds.js +5 -5
- package/bin/serve.js +29 -23
- package/bin/version.js +0 -1
- package/lib/compile/etc/_localized.js +4 -9
- package/lib/compile/for/sql.js +5 -2
- package/lib/compile/parse.js +25 -17
- package/lib/compile/to/srvinfo.js +2 -1
- package/lib/connect/bindings.js +2 -1
- package/lib/connect/index.js +48 -49
- package/lib/core/classes.js +1 -1
- package/lib/core/reflect.js +10 -2
- package/lib/deploy.js +26 -23
- package/lib/env/defaults.js +13 -6
- package/lib/env/index.js +73 -78
- package/lib/env/requires.js +38 -19
- package/lib/index.js +9 -10
- package/lib/lazy.js +2 -2
- package/lib/log/index.js +33 -45
- package/lib/log/service/index.js +2 -2
- package/lib/ql/CREATE.js +14 -9
- package/lib/ql/DELETE.js +6 -5
- package/lib/ql/DROP.js +12 -9
- package/lib/ql/INSERT.js +40 -16
- package/lib/ql/Query.js +67 -40
- package/lib/ql/SELECT.js +162 -127
- package/lib/ql/UPDATE.js +74 -42
- package/lib/ql/Whereable.js +77 -87
- package/lib/ql/index.js +36 -24
- package/lib/ql/parse.js +35 -0
- package/lib/req/context.js +44 -8
- package/lib/req/locale.js +7 -7
- package/lib/serve/Service-api.js +21 -14
- package/lib/serve/Service-dispatch.js +28 -12
- package/lib/serve/Transaction.js +22 -10
- package/lib/serve/index.js +16 -11
- package/lib/utils/axios.js +23 -16
- package/lib/utils/data.js +35 -0
- package/lib/utils/tests.js +27 -18
- package/libx/_runtime/audit/generic/personal/access.js +81 -0
- package/libx/_runtime/audit/generic/personal/constants.js +4 -0
- package/libx/_runtime/audit/generic/personal/index.js +50 -0
- package/libx/_runtime/audit/generic/personal/modification.js +138 -0
- package/libx/_runtime/audit/generic/personal/utils.js +186 -0
- package/libx/_runtime/audit/utils/v2.js +10 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +5 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +6 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +5 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +5 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +2 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +4 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +7 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +59 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +11 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +6 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +3 -46
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +2 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/createToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/deleteToCQN.js +4 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -2
- 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/selectHelper.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +16 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/EdmEntityType.js +6 -3
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/format/RepresentationKind.js +4 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/core/OdataRequest.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/SerializerFactory.js +15 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/validator/OperationValidator.js +1 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +8 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +6 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/omitValues.js +12 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +7 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +14 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +13 -13
- package/libx/_runtime/cds-services/adapter/rest/handlers/create.js +0 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +2 -1
- package/libx/_runtime/cds-services/adapter/rest/handlers/read.js +2 -2
- package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/index.js +2 -4
- package/libx/_runtime/cds-services/adapter/rest/utils/result.js +4 -2
- package/libx/_runtime/cds-services/services/Service.js +40 -5
- package/libx/_runtime/cds-services/services/utils/columns.js +13 -7
- package/libx/_runtime/cds-services/services/utils/compareJson.js +88 -4
- package/libx/_runtime/cds-services/services/utils/differ.js +24 -6
- package/libx/_runtime/cds-services/services/utils/handlerUtils.js +2 -2
- package/libx/_runtime/common/composition/data.js +44 -55
- package/libx/_runtime/common/composition/delete.js +97 -71
- package/libx/_runtime/common/composition/index.js +2 -1
- package/libx/_runtime/common/composition/insert.js +34 -11
- package/libx/_runtime/common/composition/tree.js +119 -92
- package/libx/_runtime/common/composition/update.js +4 -1
- package/libx/_runtime/common/composition/utils.js +1 -3
- package/libx/_runtime/common/constants/draft.js +12 -1
- package/libx/_runtime/common/generic/auth.js +6 -22
- package/libx/_runtime/common/generic/crud.js +14 -13
- package/libx/_runtime/common/generic/input.js +23 -26
- package/libx/_runtime/common/generic/put.js +1 -1
- package/libx/_runtime/common/generic/sorting.js +16 -16
- package/libx/_runtime/common/i18n/index.js +1 -1
- package/libx/_runtime/common/i18n/messages.properties +4 -0
- package/libx/_runtime/common/utils/backlinks.js +12 -5
- package/libx/_runtime/common/utils/cqn.js +6 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +102 -101
- package/libx/_runtime/common/utils/csn.js +47 -4
- package/libx/_runtime/common/utils/data.js +0 -37
- package/libx/_runtime/common/utils/enrichWithKeysFromWhere.js +1 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +7 -24
- package/libx/_runtime/common/utils/foreignKeyPropagations.js +39 -7
- package/libx/_runtime/common/utils/generateOnCond.js +11 -12
- package/libx/_runtime/common/utils/onlyKeysRemain.js +10 -0
- package/libx/_runtime/common/utils/path.js +35 -0
- package/libx/_runtime/common/utils/postProcessing.js +86 -0
- package/libx/_runtime/common/utils/quotingStyles.js +37 -26
- package/libx/_runtime/common/utils/resolveView.js +223 -171
- package/libx/_runtime/common/utils/rewriteAsterisk.js +46 -26
- package/libx/_runtime/common/utils/structured.js +6 -12
- package/libx/_runtime/common/utils/template.js +10 -5
- package/libx/_runtime/common/utils/templateDelimiter.js +1 -0
- package/libx/_runtime/common/utils/templateProcessor.js +22 -30
- package/libx/_runtime/common/utils/union.js +31 -0
- package/libx/_runtime/common/utils/unionCqnTemplate.js +184 -0
- package/libx/_runtime/db/Service.js +1 -1
- package/libx/_runtime/db/data-conversion/timestamp.js +2 -9
- package/libx/_runtime/db/expand/expandCQNToJoin.js +204 -297
- package/libx/_runtime/db/expand/index.js +3 -3
- package/libx/_runtime/db/expand/rawToExpanded.js +36 -7
- package/libx/_runtime/db/generic/index.js +1 -1
- package/libx/_runtime/db/generic/input.js +5 -7
- package/libx/_runtime/db/generic/integrity.js +1 -1
- package/libx/_runtime/db/generic/rewrite.js +2 -10
- package/libx/_runtime/db/generic/update.js +13 -5
- package/libx/_runtime/db/generic/virtual.js +22 -58
- package/libx/_runtime/db/query/delete.js +7 -4
- package/libx/_runtime/db/query/insert.js +6 -4
- package/libx/_runtime/db/query/read.js +13 -20
- package/libx/_runtime/db/query/run.js +4 -1
- package/libx/_runtime/db/query/update.js +5 -4
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +35 -2
- package/libx/_runtime/db/sql-builder/FunctionBuilder.js +17 -2
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +6 -5
- package/libx/_runtime/db/sql-builder/ReferenceBuilder.js +10 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +35 -24
- package/libx/_runtime/db/sql-builder/UpdateBuilder.js +14 -4
- package/libx/_runtime/db/sql-builder/arrayed.js +4 -0
- package/libx/_runtime/db/utils/deep.js +8 -0
- package/libx/_runtime/db/utils/generateAliases.js +2 -1
- package/libx/_runtime/fiori/generic/activate.js +19 -15
- package/libx/_runtime/fiori/generic/before.js +3 -11
- package/libx/_runtime/fiori/generic/cancel.js +1 -1
- package/libx/_runtime/fiori/generic/delete.js +3 -1
- package/libx/_runtime/fiori/generic/edit.js +12 -2
- package/libx/_runtime/fiori/generic/new.js +5 -5
- package/libx/_runtime/fiori/generic/patch.js +0 -18
- package/libx/_runtime/fiori/generic/read.js +241 -189
- package/libx/_runtime/fiori/utils/delete.js +36 -7
- package/libx/_runtime/fiori/utils/handler.js +43 -44
- package/libx/_runtime/fiori/utils/where.js +30 -15
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +4 -6
- package/libx/_runtime/hana/execute.js +2 -2
- package/libx/_runtime/hana/localized.js +4 -4
- package/libx/_runtime/hana/pool.js +29 -14
- package/libx/_runtime/hana/search2cqn4sql.js +2 -1
- package/libx/_runtime/hana/searchToContains.js +18 -14
- package/libx/_runtime/index.js +0 -5
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +13 -5
- package/libx/_runtime/messaging/common-utils/naming-conventions.js +4 -1
- package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +31 -19
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +1 -2
- package/libx/_runtime/messaging/enterprise-messaging.js +6 -4
- package/libx/_runtime/messaging/service.js +7 -6
- package/libx/_runtime/odata/cqn2odata.js +110 -43
- package/libx/_runtime/odata/index.js +26 -48
- package/libx/_runtime/odata/odata2cqn.js +1 -6154
- package/libx/_runtime/odata/odata2cqn.pegjs +559 -0
- package/libx/_runtime/odata/readToCqn.js +94 -64
- package/libx/_runtime/remote/Service.js +74 -21
- package/libx/_runtime/remote/cqn2odata/index.js +1 -5
- package/libx/_runtime/remote/utils/client.js +24 -101
- package/libx/_runtime/remote/utils/dataConversion.js +27 -12
- package/libx/_runtime/sqlite/Service.js +3 -5
- package/libx/_runtime/sqlite/execute.js +23 -24
- package/libx/_runtime/sqlite/localized.js +12 -7
- package/libx/_runtime/types/api.js +10 -0
- package/package.json +1 -1
- package/server.js +16 -2
- package/lib/ql/grammar.pegjs +0 -208
- package/lib/ql/parser.js +0 -1
- package/lib/ql/rt/DELETE.js +0 -29
- package/lib/ql/rt/INSERT.js +0 -23
- package/lib/ql/rt/Query.js +0 -84
- package/lib/ql/rt/SELECT.js +0 -174
- package/lib/ql/rt/UPDATE.js +0 -119
- package/lib/ql/rt/_helpers.js +0 -91
- package/lib/ql/rt/index.js +0 -32
- package/libx/_runtime/audit/generic/personal.js +0 -260
- package/libx/_runtime/cds-services/statements/BaseStatement.js +0 -72
- package/libx/_runtime/cds-services/statements/Create.js +0 -57
- package/libx/_runtime/cds-services/statements/Delete.js +0 -33
- package/libx/_runtime/cds-services/statements/Drop.js +0 -42
- package/libx/_runtime/cds-services/statements/Insert.js +0 -201
- package/libx/_runtime/cds-services/statements/Select.js +0 -826
- package/libx/_runtime/cds-services/statements/Update.js +0 -181
- package/libx/_runtime/cds-services/statements/Where.js +0 -726
- package/libx/_runtime/cds-services/statements/index.js +0 -25
- package/libx/_runtime/common/generic/resolve-mock.js +0 -9
|
@@ -1,726 +0,0 @@
|
|
|
1
|
-
const cds = require('../../cds')
|
|
2
|
-
const BaseStatement = require('./BaseStatement')
|
|
3
|
-
const { ensureNoDraftsSuffix } = require('../../common/utils/draft')
|
|
4
|
-
const { unexpectedFunctionCallError, invalidFunctionArgumentError } = require('../util/errors')
|
|
5
|
-
|
|
6
|
-
const MODEL = Symbol.for('sap.cds.model')
|
|
7
|
-
const fnChain = Symbol.for('sap.cds.fnChain')
|
|
8
|
-
const ON = Symbol.for('cqn.from.on')
|
|
9
|
-
|
|
10
|
-
const OPERATIONS = ['=', '>', '<', '!=', '<>', '>=', '<=', 'like', 'between', 'in', 'not in']
|
|
11
|
-
const VALUES = [null, undefined, true, false]
|
|
12
|
-
|
|
13
|
-
class Where extends BaseStatement {
|
|
14
|
-
get cqn() {
|
|
15
|
-
return this.SELECT || this.UPDATE || this.DELETE
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Build 'where' cqn object. Can be chained and will always connect the chained where with an 'and'.
|
|
20
|
-
*
|
|
21
|
-
* Possible uses:
|
|
22
|
-
* where('ID', '<operator>', <value>)
|
|
23
|
-
* where('ID', 'between', <value>, <value>)
|
|
24
|
-
* where('Association.name', '<operator>', <value>)
|
|
25
|
-
* where('lower(column)', '<operator>', <value>)
|
|
26
|
-
* where(<object>)
|
|
27
|
-
* Fluid usage with alternating string value arguments
|
|
28
|
-
* where(arg1, arg2, arg3, ...)
|
|
29
|
-
* Array with partial CQNs
|
|
30
|
-
* where([arg1, arg2, arg3, ...])
|
|
31
|
-
*
|
|
32
|
-
* @param {...any} args
|
|
33
|
-
* @example
|
|
34
|
-
* where('ID', '>', 7411)
|
|
35
|
-
* where({ ID: 7411})
|
|
36
|
-
* where({ or: [{ ID: 7411}, { ID: 2511}]})
|
|
37
|
-
* Fluid usage:
|
|
38
|
-
* where(`name like`, 'foo', `and ( ratio between`, 0.1, `and`, 0.3, `or ratio >`, 0.9, ')')
|
|
39
|
-
* Array with partial CQNs
|
|
40
|
-
* where([{ref: ['x']}, '=', {val: 1}])
|
|
41
|
-
*
|
|
42
|
-
* @returns {object} this object instance for chaining.
|
|
43
|
-
* @throws Error - If .having() called before .where() or if no valid first argument provided
|
|
44
|
-
*/
|
|
45
|
-
where(...args) {
|
|
46
|
-
if (args.length === 0) return this // ignore attempts to add nothing
|
|
47
|
-
const { cqn } = this
|
|
48
|
-
if (cqn.having) throw unexpectedFunctionCallError('.having()', '.where()')
|
|
49
|
-
if (cqn.where) return this._andWhere(...args)
|
|
50
|
-
cqn.where = []
|
|
51
|
-
this[fnChain] = this[fnChain].concat('.where()')
|
|
52
|
-
return this._where(...args)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* .and can only be used after .join has been called.
|
|
57
|
-
*
|
|
58
|
-
* @param {string | object} arg1 Can be object if argument is passed as an object or can be a string when an identifier is directly passed.
|
|
59
|
-
* @param {*} [arg2] Can be a value or an operator if the 3rd argument is the value.
|
|
60
|
-
* @param [arg3] Value or CQN if second argument is operator.
|
|
61
|
-
* @param [arg4] Value in case the second argument is the 'between' operator; Otherwise ignored.
|
|
62
|
-
* @param {...any} args
|
|
63
|
-
* @returns {object} this object instance for chaining.
|
|
64
|
-
* @throws Error - If called without calling join or where before.
|
|
65
|
-
*/
|
|
66
|
-
and(...args) {
|
|
67
|
-
if (args.length === 0) return this
|
|
68
|
-
this[fnChain] = this[fnChain].concat('.and()')
|
|
69
|
-
return this._logicOperation('and', ...args)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* .byId filters on the column 'id'. It can only be used if .where has not been called yet.
|
|
74
|
-
*
|
|
75
|
-
* @param {string} arg1 is the value on which the filtering should be performed.
|
|
76
|
-
* @returns {object} this object instance for chaining
|
|
77
|
-
*/
|
|
78
|
-
byId(arg1) {
|
|
79
|
-
this[fnChain] = this[fnChain].concat('.byId()')
|
|
80
|
-
return this.where('id', '=', arg1)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @param {string | object} arg1 Can be object if argument is passed as an object or can be a string when an identifier is directly passed.
|
|
85
|
-
* @param {*} [arg2] Can be a value or an operator if the 3rd argument is the value.
|
|
86
|
-
* @param [arg3] Value or CQN if second argument is operator.
|
|
87
|
-
* @param [arg4] Value in case the second argument is the 'between' operator; Otherwise ignored.
|
|
88
|
-
* @param {...any} args
|
|
89
|
-
* @returns {object} this object instance for chaining.
|
|
90
|
-
* @throws Error - If called without calling join or where before.
|
|
91
|
-
*/
|
|
92
|
-
or(...args) {
|
|
93
|
-
this[fnChain] = this[fnChain].concat('.or()')
|
|
94
|
-
return this._logicOperation('or', ...args)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
_andWhere(...args) {
|
|
98
|
-
return this._setAndOrBracket('and', 'where', ...args)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
_setAndOrBracket(operator, clause, ...args) {
|
|
102
|
-
if (operator === 'and') {
|
|
103
|
-
this.cqn[clause].unshift('(')
|
|
104
|
-
this.cqn[clause].push(')')
|
|
105
|
-
}
|
|
106
|
-
this.cqn[clause].push(operator)
|
|
107
|
-
return this._condition(clause, ...args)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
_logicOperation(operator, ...args) {
|
|
111
|
-
const cqn = this.cqn
|
|
112
|
-
const isJoin = cqn.from && Object.prototype.hasOwnProperty.call(cqn.from, 'join')
|
|
113
|
-
const isWhere = cqn.where && cqn.where.length > 0
|
|
114
|
-
const isHaving = cqn.having && cqn.having.length > 0
|
|
115
|
-
const clause = (isHaving && 'having') || (isWhere && 'where') || (isJoin && ON)
|
|
116
|
-
|
|
117
|
-
if (clause) return this._setAndOrBracket(operator, clause, ...args)
|
|
118
|
-
|
|
119
|
-
throw unexpectedFunctionCallError(operator, this[fnChain])
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
_getList(arr) {
|
|
123
|
-
const list = []
|
|
124
|
-
for (const element of arr) {
|
|
125
|
-
if (typeof element === 'object' && element !== null) list.push(element)
|
|
126
|
-
else list.push({ val: element })
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return { list: list }
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
_fluidValue(val) {
|
|
133
|
-
if (val === null) {
|
|
134
|
-
return { val: null }
|
|
135
|
-
}
|
|
136
|
-
if (val === undefined || val.xpr || val.ref || val.val || val.func || val.list) return val
|
|
137
|
-
if (Array.isArray(val)) {
|
|
138
|
-
return this._getList(val)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (isNaN(val)) {
|
|
142
|
-
if (val[0] === "'" && val[val.length - 1] === "'") {
|
|
143
|
-
return { val: val.slice(1, -1) }
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return { val: val }
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
_replacePlaceholders(xpr, placeholderMap) {
|
|
151
|
-
xpr.forEach((each, i) => {
|
|
152
|
-
if (each.SELECT && each.SELECT.from && each.SELECT.from.ref && each.SELECT.from.ref[0] === '$placeholder') {
|
|
153
|
-
xpr[i] = placeholderMap[each.SELECT.from.ref[1]]
|
|
154
|
-
}
|
|
155
|
-
if (each.xpr) this._replacePlaceholders(each.xpr, placeholderMap)
|
|
156
|
-
})
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// fluid usage uses cds-compiler
|
|
160
|
-
_fluidUsage(...args) {
|
|
161
|
-
const placeholderMap = {}
|
|
162
|
-
let placeholderNum = 0
|
|
163
|
-
let expr = ''
|
|
164
|
-
const values = []
|
|
165
|
-
|
|
166
|
-
// 1. construct a full expr string with ? for values collected in values
|
|
167
|
-
args.forEach((element, index) => {
|
|
168
|
-
if (index % 2 === 0) {
|
|
169
|
-
expr = expr.concat(element)
|
|
170
|
-
} else {
|
|
171
|
-
if (element && element.SELECT) {
|
|
172
|
-
const placeholder = ` (SELECT FROM $placeholder:_${++placeholderNum}) `
|
|
173
|
-
placeholderMap['_' + placeholderNum] = element
|
|
174
|
-
expr = expr.concat(placeholder)
|
|
175
|
-
} else {
|
|
176
|
-
expr = expr.concat(' ? ')
|
|
177
|
-
values.push(element)
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
// 2. parse the expr string
|
|
182
|
-
const { xpr } = cds.parse.expr(expr)
|
|
183
|
-
|
|
184
|
-
// 3. replace {params} in there with collected values
|
|
185
|
-
const _replaceParamsIn = xpr => {
|
|
186
|
-
const result = []
|
|
187
|
-
for (const element of xpr) {
|
|
188
|
-
if (element.xpr) result.push({ xpr: _replaceParamsIn(element.xpr) })
|
|
189
|
-
else {
|
|
190
|
-
const v = element.param ? this._fluidValue(values.shift()) : element
|
|
191
|
-
result.push(v)
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return result
|
|
195
|
-
}
|
|
196
|
-
const result = _replaceParamsIn(xpr)
|
|
197
|
-
|
|
198
|
-
// 4. replace sub-selects
|
|
199
|
-
this._replacePlaceholders(result, placeholderMap)
|
|
200
|
-
|
|
201
|
-
return result
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
_simpleArguments(...args) {
|
|
205
|
-
if (args.length < 3 || args.length > 4) return
|
|
206
|
-
|
|
207
|
-
// eslint-disable-next-line no-useless-escape
|
|
208
|
-
if (typeof args[0] !== 'string' || /[\=\s\(\)]/.test(args[0])) return
|
|
209
|
-
|
|
210
|
-
if (typeof args[1] !== 'string' || !OPERATIONS.includes(args[1].toLowerCase())) return
|
|
211
|
-
|
|
212
|
-
if (
|
|
213
|
-
typeof args[2] !== 'string' &&
|
|
214
|
-
typeof args[2] !== 'number' &&
|
|
215
|
-
!VALUES.includes(args[2]) &&
|
|
216
|
-
!(args[2] instanceof RegExp) &&
|
|
217
|
-
!Array.isArray(args[2])
|
|
218
|
-
)
|
|
219
|
-
return
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
args[3] !== undefined &&
|
|
223
|
-
typeof args[3] !== 'string' &&
|
|
224
|
-
typeof args[3] !== 'number' &&
|
|
225
|
-
!VALUES.includes(args[3])
|
|
226
|
-
) {
|
|
227
|
-
return false
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return true
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
_copyCondition(kind, arr) {
|
|
234
|
-
if (arr.length === 0) {
|
|
235
|
-
throw invalidFunctionArgumentError(this[fnChain], [])
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (this.cqn[kind].length !== 0) {
|
|
239
|
-
this.cqn[kind].push('(', ...arr, ')')
|
|
240
|
-
} else {
|
|
241
|
-
this.cqn[kind].push(...arr)
|
|
242
|
-
}
|
|
243
|
-
return this
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
_conditionObject(kind, obj) {
|
|
247
|
-
obj.or && this.cqn[kind].length !== 0
|
|
248
|
-
? this.cqn[kind].push('(', ...this._parseObjectArgument(obj), ')')
|
|
249
|
-
: this.cqn[kind].push(...this._parseObjectArgument(obj))
|
|
250
|
-
return this
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
_condition(kind, ...args) {
|
|
254
|
-
// copy existing array with partial CQNs
|
|
255
|
-
if (Array.isArray(args[0])) {
|
|
256
|
-
return this._copyCondition(kind, args[0])
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// single object
|
|
260
|
-
if (typeof args[0] === 'object') {
|
|
261
|
-
return this._conditionObject(kind, ...args)
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// simple comparison "ref op val"
|
|
265
|
-
if (this._simpleArguments(...args)) {
|
|
266
|
-
this.cqn[kind].push(...this._parseSimpleArguments(...args))
|
|
267
|
-
return this
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// fluid usage is used by dafault
|
|
271
|
-
if (this.cqn[kind].length !== 0) {
|
|
272
|
-
this.cqn[kind].push('(', ...this._fluidUsage(...args), ')')
|
|
273
|
-
} else {
|
|
274
|
-
this.cqn[kind].push(...this._fluidUsage(...args))
|
|
275
|
-
}
|
|
276
|
-
return this
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
_where(...args) {
|
|
280
|
-
return this._condition('where', ...args)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
_parseValOrRef(str) {
|
|
284
|
-
if (str === '*' || this._isNumber(str)) {
|
|
285
|
-
return { val: str }
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const valString = str.match(/^'(.*)'$/)
|
|
289
|
-
if (valString) {
|
|
290
|
-
return { val: valString[1] }
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return this._buildRef(str.trim())
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
_isNumber(obj) {
|
|
297
|
-
return !isNaN(obj)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
_valOrCqn(arg) {
|
|
301
|
-
if (this._isCqn(arg)) {
|
|
302
|
-
return arg
|
|
303
|
-
}
|
|
304
|
-
if (Array.isArray(arg)) {
|
|
305
|
-
return this._getList(arg)
|
|
306
|
-
}
|
|
307
|
-
return { val: arg }
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
_isCqn(arg) {
|
|
311
|
-
return arg && (arg.xpr || Object.prototype.hasOwnProperty.call(arg, 'val') || arg.ref || arg.func || arg.SELECT)
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
_getTableNamesFrom(fromObj) {
|
|
315
|
-
if (typeof fromObj === 'string') {
|
|
316
|
-
// delete with string in from
|
|
317
|
-
return [fromObj]
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (fromObj.name) {
|
|
321
|
-
// delete with entity in from
|
|
322
|
-
return [fromObj.name]
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// select
|
|
326
|
-
return this._extractRefs(fromObj)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
_extractRefs(from) {
|
|
330
|
-
const hasOwnProperty = Object.prototype.hasOwnProperty
|
|
331
|
-
|
|
332
|
-
if (hasOwnProperty.call(from, 'join')) {
|
|
333
|
-
// cqn with join in from
|
|
334
|
-
return this._refs(from.args)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (hasOwnProperty.call(from, 'SET')) {
|
|
338
|
-
// cqn UNION
|
|
339
|
-
return from.as ? [from.as] : []
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
return from.as ? [from.ref[0], from.as] : [from.ref[0]]
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
_refs(refs) {
|
|
346
|
-
const arr = []
|
|
347
|
-
|
|
348
|
-
for (const element of refs) {
|
|
349
|
-
if (Object.prototype.hasOwnProperty.call(element, 'join')) {
|
|
350
|
-
// multiple join are nested, se we need to find all the table names in there as well
|
|
351
|
-
arr.push(...this._extractRefs(element))
|
|
352
|
-
} else {
|
|
353
|
-
arr.push(element.ref[0])
|
|
354
|
-
|
|
355
|
-
if (element.as) {
|
|
356
|
-
arr.push(element.as)
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return arr
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
_getTableNamesEntity(entityObj) {
|
|
365
|
-
if (typeof entityObj === 'string') {
|
|
366
|
-
// update with string in entity
|
|
367
|
-
return entityObj
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
if (entityObj.name) {
|
|
371
|
-
// update with entity in entity
|
|
372
|
-
return ensureNoDraftsSuffix(entityObj.name)
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
_getTableNames() {
|
|
377
|
-
const tableNames = []
|
|
378
|
-
const cqn = this.cqn
|
|
379
|
-
|
|
380
|
-
if (cqn.from) {
|
|
381
|
-
// select and delete
|
|
382
|
-
tableNames.push(...this._getTableNamesFrom(cqn.from))
|
|
383
|
-
} else if (cqn.entity) {
|
|
384
|
-
// update
|
|
385
|
-
tableNames.push(this._getTableNamesEntity(cqn.entity))
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
return tableNames
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
_matchTableColumn(name = '') {
|
|
392
|
-
const matches = name.match(/^(?:"(\w+(?:\.\w+)*)"|(\w+))\.(?:"(\w+(?:\.\w+)*)"|(\w+))$/)
|
|
393
|
-
|
|
394
|
-
if (matches) {
|
|
395
|
-
return matches.filter(this._filterForTableAndColumn)
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
_matchInline(name) {
|
|
400
|
-
return name.replace(/{/g, '').replace(/}/g, '').split(/\./)
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
_filterForTableAndColumn(element, index) {
|
|
404
|
-
return index && element != null
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
_parseInlineAssociation(element, tableNames) {
|
|
408
|
-
if (element.includes('.{')) {
|
|
409
|
-
return { ref: this._matchInline(element) }
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const parts = element.split(/\./)
|
|
413
|
-
if (parts && this[MODEL]) {
|
|
414
|
-
for (const table of tableNames) {
|
|
415
|
-
// inline or column name with dot
|
|
416
|
-
if (this._isAssociation(table, parts[0])) {
|
|
417
|
-
return { ref: parts }
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
_buildWithTableName(element) {
|
|
424
|
-
const tableNames = this._getTableNames()
|
|
425
|
-
const matched = this._matchTableColumn(element)
|
|
426
|
-
|
|
427
|
-
if (matched && tableNames.indexOf(matched[0]) !== -1) {
|
|
428
|
-
return { ref: [matched[0], matched[1]] }
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (element.includes('.')) {
|
|
432
|
-
return this._parseInlineAssociation(element, tableNames)
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
_buildRef(element) {
|
|
437
|
-
const ref = this._buildWithTableName(element)
|
|
438
|
-
|
|
439
|
-
if (ref) {
|
|
440
|
-
return ref
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
return { ref: [element] }
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
_buildValOrRef(element) {
|
|
447
|
-
if (typeof element === 'string') {
|
|
448
|
-
const ref = this._buildWithTableName(element)
|
|
449
|
-
if (ref) {
|
|
450
|
-
return ref
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
return this._valOrCqn(element)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
_refOrCqn(arg) {
|
|
458
|
-
if (!this._isCqn(arg)) {
|
|
459
|
-
return this._buildRef(arg)
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return arg
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
_comparison(...args) {
|
|
466
|
-
if (args.length > 2) {
|
|
467
|
-
return args[1]
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return '='
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
_value(...args) {
|
|
474
|
-
if (args.length > 2) {
|
|
475
|
-
return args[2]
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
return args[1]
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
_parseSimpleObjectArguments(...args) {
|
|
482
|
-
const ref = this._refOrCqn(args[0])
|
|
483
|
-
const comparison = this._comparison(...args)
|
|
484
|
-
const value = this._value(...args)
|
|
485
|
-
|
|
486
|
-
if (args.length === 1) {
|
|
487
|
-
return [ref]
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (value != null) {
|
|
491
|
-
// skip null / undefined
|
|
492
|
-
if (value instanceof RegExp) {
|
|
493
|
-
return [ref, 'regexp', { val: String(value) }]
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
if (value.SELECT) {
|
|
497
|
-
return [ref, comparison, value]
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (args.length === 4) {
|
|
502
|
-
return [ref, comparison, { val: value }, 'and', { val: args[3] }]
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
return [ref, comparison, this._buildValOrRef(value)]
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
_isNestedObject(object) {
|
|
509
|
-
return object && typeof object === 'object' && !Array.isArray(object) && !(object instanceof RegExp)
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
_isAndOr(key) {
|
|
513
|
-
return key === 'or' || key === 'and'
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
_validateObjectArgument(object) {
|
|
517
|
-
if (!object || Object.keys(object).length === 0) {
|
|
518
|
-
throw invalidFunctionArgumentError(this[fnChain], object)
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
_parseObjectArgument(object, inAnd) {
|
|
523
|
-
this._validateObjectArgument(object)
|
|
524
|
-
|
|
525
|
-
if (this._isCqn(object)) {
|
|
526
|
-
return [object]
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
const arrayReturn = []
|
|
530
|
-
const keys = Object.keys(object)
|
|
531
|
-
for (let i = 0; i < keys.length; i++) {
|
|
532
|
-
const key = keys[i]
|
|
533
|
-
if (this._isAndOr(key)) {
|
|
534
|
-
Array.isArray(object[key])
|
|
535
|
-
? this._andOrAsArray(key, object[key], arrayReturn, keys.length === 1)
|
|
536
|
-
: this._andOrAsObject(key, object[key], arrayReturn, i === keys.length - 1)
|
|
537
|
-
} else if (/^(:?not )?exists$/.test(key)) {
|
|
538
|
-
arrayReturn.push(key, object[key])
|
|
539
|
-
} else if (this._isNestedObject(object[key])) {
|
|
540
|
-
this._addLogicOperatorIfNeeded(arrayReturn)
|
|
541
|
-
arrayReturn.push(...this._parseNestedObject(key, object[key]))
|
|
542
|
-
} else {
|
|
543
|
-
this._addLogicOperatorIfNeeded(arrayReturn)
|
|
544
|
-
const comparison = Array.isArray(object[key]) ? 'in' : '='
|
|
545
|
-
arrayReturn.push(...this._parseSimpleObjectArguments(key, comparison, object[key]))
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
if (inAnd && object.or) {
|
|
550
|
-
arrayReturn.unshift('(')
|
|
551
|
-
arrayReturn.push(')')
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
return arrayReturn
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
_parseSimpleArguments(...args) {
|
|
558
|
-
const ref = this._buildRef(args[0])
|
|
559
|
-
const op = args[1]
|
|
560
|
-
const value = args[2]
|
|
561
|
-
|
|
562
|
-
if (value != null && value instanceof RegExp) {
|
|
563
|
-
return [ref, 'regexp', { val: String(value) }]
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
if (args.length === 4) {
|
|
567
|
-
return [ref, op, { val: value }, 'and', { val: args[3] }]
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
return [ref, op, this._buildValOrRef(value)]
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
_andOrAsArray(key, array, arrayReturn, isOne) {
|
|
574
|
-
this._addLogicOperatorIfNeeded(arrayReturn)
|
|
575
|
-
|
|
576
|
-
if (key === 'or' && !isOne) {
|
|
577
|
-
arrayReturn.push('(')
|
|
578
|
-
}
|
|
579
|
-
arrayReturn.push(...this._parseObjectArgument(array[0]))
|
|
580
|
-
for (let i = 1, length = array.length; i < length; i++) {
|
|
581
|
-
if (this._isAndOr(Object.keys(array[i])[0])) {
|
|
582
|
-
arrayReturn.push(key, '(', ...this._parseObjectArgument(array[i]), ')')
|
|
583
|
-
} else {
|
|
584
|
-
arrayReturn.push(key, ...this._parseObjectArgument(array[i]))
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
if (key === 'or' && !isOne) {
|
|
589
|
-
arrayReturn.push(')')
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
_andOrAsObject(key, obj, arrayReturn, isLast) {
|
|
594
|
-
if (key === 'or' && !isLast) {
|
|
595
|
-
arrayReturn.unshift('(')
|
|
596
|
-
arrayReturn.push(key, ...this._parseObjectArgument(obj), ')')
|
|
597
|
-
} else {
|
|
598
|
-
arrayReturn.push(key, ...this._parseObjectArgument(obj, key === 'and'))
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
_addLogicOperatorIfNeeded(array) {
|
|
603
|
-
const length = array.length
|
|
604
|
-
|
|
605
|
-
if (length === 0) {
|
|
606
|
-
return
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const lastEntry = array[length - 1]
|
|
610
|
-
|
|
611
|
-
if (lastEntry !== 'and' && lastEntry !== 'or') {
|
|
612
|
-
array.push('and')
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
_parseNestedObject(parentKey, object) {
|
|
617
|
-
const keys = Object.keys(object)
|
|
618
|
-
|
|
619
|
-
if (this._isCqn(object)) {
|
|
620
|
-
if (object.SELECT) {
|
|
621
|
-
return this._parseSimpleObjectArguments(parentKey, 'in', object)
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
return this._parseSimpleObjectArguments(parentKey, object)
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
switch (keys.length) {
|
|
628
|
-
case 1:
|
|
629
|
-
return this._parseSimpleObjectArguments(parentKey, keys[0], object[keys[0]])
|
|
630
|
-
case 2:
|
|
631
|
-
return this._parseSimpleObjectArguments(parentKey, keys[0], object[keys[0]], object[keys[1]])
|
|
632
|
-
default:
|
|
633
|
-
throw invalidFunctionArgumentError(this[fnChain], object)
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
_isAssociation(entityName, associationName) {
|
|
638
|
-
const name = typeof entityName === 'object' ? ensureNoDraftsSuffix(entityName.name) : entityName
|
|
639
|
-
const entity = this[MODEL].definitions[name]
|
|
640
|
-
if (entity) {
|
|
641
|
-
return entity.elements[associationName] && entity.elements[associationName]._isAssociationStrict
|
|
642
|
-
}
|
|
643
|
-
throw invalidFunctionArgumentError(this[fnChain], entity)
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
_isFunction(element) {
|
|
647
|
-
if (element === null) {
|
|
648
|
-
return false
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
if (typeof element === 'string') {
|
|
652
|
-
return element.includes('(')
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
return false
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
_parseFunction(func) {
|
|
659
|
-
if (typeof func === 'string') {
|
|
660
|
-
return this._parseFunctionFromString(func)
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
_splitArgs(argsString) {
|
|
665
|
-
let bracketCounter = 0
|
|
666
|
-
|
|
667
|
-
const commaIndex = []
|
|
668
|
-
|
|
669
|
-
for (let i = 0; i < argsString.length; i++) {
|
|
670
|
-
if (argsString.charAt(i) === '(') {
|
|
671
|
-
bracketCounter++
|
|
672
|
-
} else if (argsString.charAt(i) === ')') {
|
|
673
|
-
bracketCounter--
|
|
674
|
-
} else if (argsString.charAt(i) === ',' && bracketCounter === 0) {
|
|
675
|
-
commaIndex.push(i)
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
if (commaIndex.length > 0) {
|
|
680
|
-
const args = []
|
|
681
|
-
let lastIndex = 0
|
|
682
|
-
|
|
683
|
-
for (const index of commaIndex) {
|
|
684
|
-
args.push(argsString.substring(lastIndex, index))
|
|
685
|
-
lastIndex = index + 1
|
|
686
|
-
}
|
|
687
|
-
args.push(argsString.substring(lastIndex, argsString.length))
|
|
688
|
-
return args
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
return []
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
_fnArgs(str) {
|
|
695
|
-
if (str.match(/^([^(]*)\((.*)\)$/)) {
|
|
696
|
-
return this._parseFunctionFromString(str)
|
|
697
|
-
} else {
|
|
698
|
-
return this._parseValOrRef(str)
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
_parseFunctionArgs(argsString, fnArgs = []) {
|
|
703
|
-
if (argsString === '') {
|
|
704
|
-
return []
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
const parts = this._splitArgs(argsString)
|
|
708
|
-
if (parts.length > 0) {
|
|
709
|
-
for (const part of parts) {
|
|
710
|
-
fnArgs.push(this._fnArgs(part))
|
|
711
|
-
}
|
|
712
|
-
} else {
|
|
713
|
-
fnArgs.push(this._fnArgs(argsString))
|
|
714
|
-
}
|
|
715
|
-
return fnArgs
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
_parseFunctionFromString(aggregation, cqnPartial = {}) {
|
|
719
|
-
const fnArray = aggregation.match(/^([^(]*)\((.*)\)$/)
|
|
720
|
-
cqnPartial.func = fnArray[1].toLowerCase()
|
|
721
|
-
cqnPartial.args = fnArray[2] === '*' ? ['*'] : this._parseFunctionArgs(fnArray[2]) // * should not be wrapped as val here
|
|
722
|
-
return cqnPartial
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
module.exports = Where
|