@sap/cds-compiler 6.7.3 → 6.9.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 +70 -0
- package/README.md +4 -0
- package/bin/cdsc.js +5 -5
- package/bin/cdshi.js +1 -0
- package/bin/cdsse.js +1 -1
- package/lib/api/main.js +17 -9
- package/lib/api/options.js +5 -2
- package/lib/api/validate.js +1 -1
- package/lib/base/builtins.js +13 -9
- package/lib/{model → base}/csnRefs.js +8 -10
- package/lib/base/error.js +2 -0
- package/lib/base/message-registry.js +68 -4
- package/lib/base/messages.js +4 -2
- package/lib/{optionProcessor.js → base/optionProcessor.js} +5 -3
- package/lib/base/{model.js → specialOptions.js} +16 -39
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/elements.js +1 -1
- package/lib/checks/enricher.js +2 -2
- package/lib/checks/featureFlags.js +54 -24
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/onConditions.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +1 -1
- package/lib/checks/validator.js +10 -14
- package/lib/compiler/assert-consistency.js +11 -9
- package/lib/compiler/base.js +5 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +3 -3
- package/lib/compiler/define.js +6 -3
- package/lib/{base → compiler}/dictionaries.js +4 -3
- package/lib/compiler/extend.js +121 -21
- package/lib/compiler/generate.js +2 -2
- package/lib/compiler/index.js +11 -3
- package/lib/compiler/kick-start.js +1 -1
- package/lib/compiler/lsp-api.js +3 -3
- package/lib/compiler/populate.js +6 -7
- package/lib/compiler/resolve.js +53 -36
- package/lib/compiler/shared.js +68 -18
- package/lib/compiler/tweak-assocs.js +2 -2
- package/lib/compiler/utils.js +28 -27
- package/lib/compiler/xpr-rewrite.js +3 -3
- package/lib/edm/EdmPrimitiveTypeDefinitions.js +4 -1
- package/lib/edm/annotations/edmJson.js +2 -4
- package/lib/edm/annotations/genericTranslation.js +51 -7
- package/lib/edm/csn2edm.js +3 -2
- package/lib/edm/edmAnnoPreprocessor.js +1 -1
- package/lib/edm/edmInboundChecks.js +2 -1
- package/lib/edm/edmPreprocessor.js +3 -3
- package/lib/edm/edmUtils.js +2 -2
- package/lib/gen/BaseParser.js +59 -108
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +2052 -1965
- package/lib/gen/Dictionary.json +67 -7
- package/lib/json/from-csn.js +14 -14
- package/lib/json/to-csn.js +77 -38
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +2 -2
- package/lib/modelCompare/compare.js +1 -1
- package/lib/modelCompare/utils/filter.js +1 -0
- package/lib/parsers/AstBuildingParser.js +83 -33
- package/lib/parsers/index.js +1 -1
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +49 -30
- package/lib/render/toHdbcds.js +2 -2
- package/lib/render/toSql.js +16 -7
- package/lib/render/utils/common.js +11 -3
- package/lib/render/utils/sql.js +14 -5
- package/lib/render/utils/standardDatabaseFunctions.js +108 -99
- package/lib/sql-identifier.js +9 -1
- package/lib/{model → tool-lib}/enrichCsn.js +3 -2
- package/lib/{model → tool-lib}/revealInternalProperties.js +2 -1
- package/lib/transform/addTenantFields.js +1 -1
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +1 -1
- package/lib/transform/db/backlinks.js +2 -2
- package/lib/transform/db/expansion.js +2 -2
- package/lib/transform/db/flattening.js +3 -4
- package/lib/transform/db/killAnnotations.js +1 -0
- package/lib/transform/db/processSqlServices.js +2 -1
- package/lib/transform/db/rewriteCalculatedElements.js +2 -2
- package/lib/transform/db/temporal.js +30 -5
- package/lib/transform/db/views.js +16 -20
- package/lib/transform/draft/db.js +1 -2
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +6 -5
- package/lib/transform/effective/main.js +24 -4
- package/lib/transform/effective/types.js +1 -1
- package/lib/transform/{odata/fioriTreeViews.js → fioriTreeViews.js} +48 -25
- package/lib/transform/forOdata.js +25 -7
- package/lib/transform/forRelationalDB.js +48 -12
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/createForeignKeys.js +1 -1
- package/lib/transform/odata/flattening.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +3 -2
- package/lib/transform/odata/typesExposure.js +3 -2
- package/lib/transform/transformUtils.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +2 -1
- package/lib/transform/tupleExpansion.js +44 -4
- package/lib/transform/universalCsn/universalCsnEnricher.js +7 -3
- package/lib/transform/universalCsn/utils.js +1 -1
- package/lib/{base → utils}/lazyload.js +9 -0
- package/lib/{base → utils}/node-helpers.js +2 -0
- package/lib/utils/objectUtils.js +29 -6
- package/lib/{base → utils}/optionProcessorHelper.js +16 -6
- package/package.json +3 -40
- /package/lib/{model → base}/cloneCsn.js +0 -0
- /package/lib/{model/api.js → base/model-api.js} +0 -0
- /package/lib/{api → base}/trace.js +0 -0
- /package/lib/{model → base}/xprAsTree.js +0 -0
- /package/lib/{inspect → tool-lib}/index.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectModelStatistics.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectPropagation.js +0 -0
- /package/lib/{inspect → tool-lib}/inspectUtils.js +0 -0
- /package/lib/{base → utils}/shuffle.js +0 -0
|
@@ -10,35 +10,35 @@ const oDataFunctions = {
|
|
|
10
10
|
// https://www.sqlite.org/lang_corefunc.html
|
|
11
11
|
sqlite: {
|
|
12
12
|
contains(signature) {
|
|
13
|
-
const
|
|
13
|
+
const args = getArgs(signature);
|
|
14
14
|
checkArgs.call(this, 'contains', args, 2);
|
|
15
15
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
16
16
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
17
17
|
return `(ifnull(instr(${ x }, ${ y }),0) <> 0)`;
|
|
18
18
|
},
|
|
19
19
|
startswith(signature) {
|
|
20
|
-
const
|
|
20
|
+
const args = getArgs(signature);
|
|
21
21
|
checkArgs.call(this, 'startswith', args, 2);
|
|
22
22
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
23
23
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
24
24
|
return `coalesce((instr(${ x }, ${ y }) = 1), false)`;
|
|
25
25
|
}, // instr is 1 indexed
|
|
26
26
|
endswith(signature) {
|
|
27
|
-
const
|
|
27
|
+
const args = getArgs(signature);
|
|
28
28
|
checkArgs.call(this, 'endswith', args, 2);
|
|
29
29
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
30
30
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
31
31
|
return `coalesce((substr(${ x }, length(${ x }) + 1 - length(${ y })) = ${ y }), false)`;
|
|
32
32
|
},
|
|
33
33
|
indexof(signature) {
|
|
34
|
-
const
|
|
34
|
+
const args = getArgs(signature);
|
|
35
35
|
checkArgs.call(this, 'indexof', args, 2);
|
|
36
36
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
37
37
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
38
38
|
return `(instr(${ x }, ${ y }) - 1)`; // instr is 1 indexed
|
|
39
39
|
},
|
|
40
40
|
matchespattern(signature) {
|
|
41
|
-
const
|
|
41
|
+
const args = getArgs(signature);
|
|
42
42
|
checkArgs.call(this, 'matchespattern', args, 2);
|
|
43
43
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
44
44
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -48,37 +48,37 @@ const oDataFunctions = {
|
|
|
48
48
|
return oDataFunctions.sqlite.matchespattern.call(this, signature);
|
|
49
49
|
},
|
|
50
50
|
year(signature) {
|
|
51
|
-
const
|
|
51
|
+
const args = getArgs(signature);
|
|
52
52
|
checkArgs.call(this, 'year', args, 1);
|
|
53
53
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
54
54
|
return `cast(strftime('%Y', ${ x }) as Integer)`;
|
|
55
55
|
},
|
|
56
56
|
month(signature) {
|
|
57
|
-
const
|
|
57
|
+
const args = getArgs(signature);
|
|
58
58
|
checkArgs.call(this, 'month', args, 1);
|
|
59
59
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
60
60
|
return `cast(strftime('%m', ${ x }) as Integer)`;
|
|
61
61
|
},
|
|
62
62
|
day(signature) {
|
|
63
|
-
const
|
|
63
|
+
const args = getArgs(signature);
|
|
64
64
|
checkArgs.call(this, 'day', args, 1);
|
|
65
65
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
66
66
|
return `cast(strftime('%d', ${ x }) as Integer)`;
|
|
67
67
|
},
|
|
68
68
|
hour(signature) {
|
|
69
|
-
const
|
|
69
|
+
const args = getArgs(signature);
|
|
70
70
|
checkArgs.call(this, 'hour', args, 1);
|
|
71
71
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
72
72
|
return `cast(strftime('%H', ${ x }) as Integer)`;
|
|
73
73
|
},
|
|
74
74
|
minute(signature) {
|
|
75
|
-
const
|
|
75
|
+
const args = getArgs(signature);
|
|
76
76
|
checkArgs.call(this, 'minute', args, 1);
|
|
77
77
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
78
78
|
return `cast(strftime('%M', ${ x }) as Integer)`;
|
|
79
79
|
},
|
|
80
80
|
second(signature) {
|
|
81
|
-
const
|
|
81
|
+
const args = getArgs(signature);
|
|
82
82
|
checkArgs.call(this, 'second', args, 1);
|
|
83
83
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
84
84
|
return `cast(strftime('%S', ${ x }) as Integer)`;
|
|
@@ -86,20 +86,20 @@ const oDataFunctions = {
|
|
|
86
86
|
// REVISIT: currently runtimes normalize to milliseconds
|
|
87
87
|
// we could allow this to be more precise
|
|
88
88
|
fractionalseconds(signature) {
|
|
89
|
-
const
|
|
89
|
+
const args = getArgs(signature);
|
|
90
90
|
checkArgs.call(this, 'fractionalseconds', args, 1);
|
|
91
91
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
92
92
|
return `cast(substr(strftime('%f', ${ x }), length(strftime('%f', ${ x })) - 3) as REAL)`;
|
|
93
93
|
},
|
|
94
94
|
// The date(), time(), and datetime() functions all return text, and so their strftime() equivalents are exact.
|
|
95
95
|
time(signature) {
|
|
96
|
-
const
|
|
96
|
+
const args = getArgs(signature);
|
|
97
97
|
checkArgs.call(this, 'time', args, 1);
|
|
98
98
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
99
99
|
return `time(${ x })`;
|
|
100
100
|
},
|
|
101
101
|
date(signature) {
|
|
102
|
-
const
|
|
102
|
+
const args = getArgs(signature);
|
|
103
103
|
checkArgs.call(this, 'date', args, 1);
|
|
104
104
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
105
105
|
return `date(${ x })`;
|
|
@@ -111,7 +111,7 @@ const oDataFunctions = {
|
|
|
111
111
|
// considering the case where the duration is negative.
|
|
112
112
|
// --> We do not support this function.
|
|
113
113
|
// totalseconds(signature) {
|
|
114
|
-
// const
|
|
114
|
+
// const args = getArgs(signature);
|
|
115
115
|
// checkArgs.call(this, 'totalseconds', args, 1);
|
|
116
116
|
// let x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
117
117
|
// const isNegative = x.startsWith("'-"); // Check for leading '-'
|
|
@@ -124,35 +124,35 @@ const oDataFunctions = {
|
|
|
124
124
|
// https://www.postgresql.org/docs/current/functions-math.html
|
|
125
125
|
postgres: {
|
|
126
126
|
contains(signature) {
|
|
127
|
-
const
|
|
127
|
+
const args = getArgs(signature);
|
|
128
128
|
checkArgs.call(this, 'contains', args, 2);
|
|
129
129
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
130
130
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
131
131
|
return `(coalesce(strpos(${ x }, ${ y }),0) > 0)`;
|
|
132
132
|
},
|
|
133
133
|
startswith(signature) {
|
|
134
|
-
const
|
|
134
|
+
const args = getArgs(signature);
|
|
135
135
|
checkArgs.call(this, 'startswith', args, 2);
|
|
136
136
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
137
137
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
138
138
|
return `coalesce((strpos(${ x }, ${ y }) = 1), false)`; // strpos is 1 indexed
|
|
139
139
|
},
|
|
140
140
|
endswith(signature) {
|
|
141
|
-
const
|
|
141
|
+
const args = getArgs(signature);
|
|
142
142
|
checkArgs.call(this, 'endswith', args, 2);
|
|
143
143
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
144
144
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
145
145
|
return `coalesce((substr(${ x }, (length(${ x }) + 1) - length(${ y })) = ${ y }), false)`;
|
|
146
146
|
},
|
|
147
147
|
indexof(signature) {
|
|
148
|
-
const
|
|
148
|
+
const args = getArgs(signature);
|
|
149
149
|
checkArgs.call(this, 'indexof', args, 2);
|
|
150
150
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
151
151
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
152
152
|
return `(strpos(${ x }, ${ y }) - 1)`; // strpos is 1 indexed
|
|
153
153
|
},
|
|
154
154
|
matchespattern(signature) {
|
|
155
|
-
const
|
|
155
|
+
const args = getArgs(signature);
|
|
156
156
|
checkArgs.call(this, 'matchespattern', args, 2);
|
|
157
157
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
158
158
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -164,37 +164,37 @@ const oDataFunctions = {
|
|
|
164
164
|
// TODO: PG docu recommends to use the "EXTRACT" function for improved precision
|
|
165
165
|
// https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
|
|
166
166
|
year(signature) {
|
|
167
|
-
const
|
|
167
|
+
const args = getArgs(signature);
|
|
168
168
|
checkArgs.call(this, 'year', args, 1);
|
|
169
169
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
170
170
|
return `cast(date_part('year', ${ x }) as Integer)`;
|
|
171
171
|
},
|
|
172
172
|
month(signature) {
|
|
173
|
-
const
|
|
173
|
+
const args = getArgs(signature);
|
|
174
174
|
checkArgs.call(this, 'month', args, 1);
|
|
175
175
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
176
176
|
return `cast(date_part('month', ${ x }) as Integer)`;
|
|
177
177
|
},
|
|
178
178
|
day(signature) {
|
|
179
|
-
const
|
|
179
|
+
const args = getArgs(signature);
|
|
180
180
|
checkArgs.call(this, 'day', args, 1);
|
|
181
181
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
182
182
|
return `cast(date_part('day', ${ x }) as Integer)`;
|
|
183
183
|
},
|
|
184
184
|
hour(signature) {
|
|
185
|
-
const
|
|
185
|
+
const args = getArgs(signature);
|
|
186
186
|
checkArgs.call(this, 'hour', args, 1);
|
|
187
187
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
188
188
|
return `cast(date_part('hour', ${ x }) as Integer)`;
|
|
189
189
|
},
|
|
190
190
|
minute(signature) {
|
|
191
|
-
const
|
|
191
|
+
const args = getArgs(signature);
|
|
192
192
|
checkArgs.call(this, 'minute', args, 1);
|
|
193
193
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
194
194
|
return `cast(date_part('minute', ${ x }) as Integer)`;
|
|
195
195
|
},
|
|
196
196
|
second(signature) {
|
|
197
|
-
const
|
|
197
|
+
const args = getArgs(signature);
|
|
198
198
|
checkArgs.call(this, 'second', args, 1);
|
|
199
199
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
200
200
|
return `cast(floor(date_part('second', ${ x })) as Integer)`;
|
|
@@ -202,19 +202,19 @@ const oDataFunctions = {
|
|
|
202
202
|
// REVISIT: currently runtimes normalize to milliseconds
|
|
203
203
|
// we could allow this to be more precise
|
|
204
204
|
fractionalseconds(signature) {
|
|
205
|
-
const
|
|
205
|
+
const args = getArgs(signature);
|
|
206
206
|
checkArgs.call(this, 'fractionalseconds', args, 1);
|
|
207
207
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
208
208
|
return `cast(date_part('second', ${ x }) - floor(date_part('second', ${ x })) AS DECIMAL(3,3))`;
|
|
209
209
|
},
|
|
210
210
|
time(signature) {
|
|
211
|
-
const
|
|
211
|
+
const args = getArgs(signature);
|
|
212
212
|
checkArgs.call(this, 'time', args, 1);
|
|
213
213
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
214
214
|
return `to_char(${ x }, 'HH24:MI:SS')::TIME`;
|
|
215
215
|
},
|
|
216
216
|
date(signature) {
|
|
217
|
-
const
|
|
217
|
+
const args = getArgs(signature);
|
|
218
218
|
checkArgs.call(this, 'date', args, 1);
|
|
219
219
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
220
220
|
return `${ x }::DATE`;
|
|
@@ -223,11 +223,11 @@ const oDataFunctions = {
|
|
|
223
223
|
// https://help.sap.com/docs/HANA_SERVICE_CF/7c78579ce9b14a669c1f3295b0d8ca16/f12b86a6284c4aeeb449e57eb5dd3ebd.html?locale=en-US
|
|
224
224
|
hana: {
|
|
225
225
|
contains(signature) {
|
|
226
|
-
const
|
|
226
|
+
const args = getArgs(signature);
|
|
227
227
|
checkArgs.call(this, 'contains', args, 2, 3);
|
|
228
228
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
229
229
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
230
|
-
if (
|
|
230
|
+
if (args.length > 2) {
|
|
231
231
|
const z = this.renderArgs({ ...signature, args: [ args[2] ] });
|
|
232
232
|
// While CONTAINS() looks like a function because of its syntax,
|
|
233
233
|
// it is classified as a predicate because it is designed to evaluate a condition
|
|
@@ -235,24 +235,24 @@ const oDataFunctions = {
|
|
|
235
235
|
return `CONTAINS(${ x }, ${ y }, ${ z })`;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
return `(CASE WHEN coalesce(locate(${ this.renderArgs(signature) }),0)>0 THEN TRUE ELSE FALSE END)`;
|
|
238
|
+
return `(CASE WHEN coalesce(locate(${ this.renderArgs({ ...signature, args }) }),0)>0 THEN TRUE ELSE FALSE END)`;
|
|
239
239
|
},
|
|
240
240
|
startswith(signature) {
|
|
241
|
-
const
|
|
241
|
+
const args = getArgs(signature);
|
|
242
242
|
checkArgs.call(this, 'startswith', args, 2);
|
|
243
243
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
244
244
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
245
245
|
return `(CASE WHEN locate(${ x }, ${ y }) = 1 THEN TRUE ELSE FALSE END)`;
|
|
246
246
|
}, // locate is 1 indexed
|
|
247
247
|
endswith(signature) {
|
|
248
|
-
const
|
|
248
|
+
const args = getArgs(signature);
|
|
249
249
|
checkArgs.call(this, 'endswith', args, 2);
|
|
250
250
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
251
251
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
252
252
|
return `(CASE WHEN substring(${ x }, (length(${ x }) + 1) - length(${ y })) = ${ y } THEN TRUE ELSE FALSE END)`;
|
|
253
253
|
},
|
|
254
254
|
indexof(signature) {
|
|
255
|
-
const
|
|
255
|
+
const args = getArgs(signature);
|
|
256
256
|
checkArgs.call(this, 'indexof', args, 2);
|
|
257
257
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
258
258
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -261,7 +261,7 @@ const oDataFunctions = {
|
|
|
261
261
|
matchespattern(signature) {
|
|
262
262
|
// case … when only works as column expression (not in where)
|
|
263
263
|
// in the where clause, only "${x} LIKE_REGEXPR ${y}" works
|
|
264
|
-
const
|
|
264
|
+
const args = getArgs(signature);
|
|
265
265
|
checkArgs.call(this, 'matchespattern', args, 2);
|
|
266
266
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
267
267
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -271,37 +271,37 @@ const oDataFunctions = {
|
|
|
271
271
|
return oDataFunctions.hana.matchespattern.call(this, signature);
|
|
272
272
|
},
|
|
273
273
|
year(signature) {
|
|
274
|
-
const
|
|
274
|
+
const args = getArgs(signature);
|
|
275
275
|
checkArgs.call(this, 'year', args, 1);
|
|
276
276
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
277
277
|
return `year(${ x })`;
|
|
278
278
|
},
|
|
279
279
|
month(signature) {
|
|
280
|
-
const
|
|
280
|
+
const args = getArgs(signature);
|
|
281
281
|
checkArgs.call(this, 'month', args, 1);
|
|
282
282
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
283
283
|
return `month(${ x })`;
|
|
284
284
|
},
|
|
285
285
|
day(signature) {
|
|
286
|
-
const
|
|
286
|
+
const args = getArgs(signature);
|
|
287
287
|
checkArgs.call(this, 'day', args, 1);
|
|
288
288
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
289
289
|
return `dayofmonth(${ x })`;
|
|
290
290
|
},
|
|
291
291
|
hour(signature) {
|
|
292
|
-
const
|
|
292
|
+
const args = getArgs(signature);
|
|
293
293
|
checkArgs.call(this, 'hour', args, 1);
|
|
294
294
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
295
295
|
return `hour(${ x })`;
|
|
296
296
|
},
|
|
297
297
|
minute(signature) {
|
|
298
|
-
const
|
|
298
|
+
const args = getArgs(signature);
|
|
299
299
|
checkArgs.call(this, 'minute', args, 1);
|
|
300
300
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
301
301
|
return `minute(${ x })`;
|
|
302
302
|
},
|
|
303
303
|
second(signature) {
|
|
304
|
-
const
|
|
304
|
+
const args = getArgs(signature);
|
|
305
305
|
checkArgs.call(this, 'second', args, 1);
|
|
306
306
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
307
307
|
return `to_integer(second(${ x }))`;
|
|
@@ -309,19 +309,19 @@ const oDataFunctions = {
|
|
|
309
309
|
// REVISIT: currently runtimes normalize to milliseconds
|
|
310
310
|
// we could allow this to be more precise
|
|
311
311
|
fractionalseconds(signature) {
|
|
312
|
-
const
|
|
312
|
+
const args = getArgs(signature);
|
|
313
313
|
checkArgs.call(this, 'fractionalseconds', args, 1);
|
|
314
314
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
315
315
|
return `(to_decimal(second(${ x }),5,3) - to_integer(second(${ x })))`;
|
|
316
316
|
},
|
|
317
317
|
time(signature) {
|
|
318
|
-
const
|
|
318
|
+
const args = getArgs(signature);
|
|
319
319
|
checkArgs.call(this, 'time', args, 1);
|
|
320
320
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
321
321
|
return `to_time(${ x })`;
|
|
322
322
|
},
|
|
323
323
|
date(signature) {
|
|
324
|
-
const
|
|
324
|
+
const args = getArgs(signature);
|
|
325
325
|
checkArgs.call(this, 'date', args, 1);
|
|
326
326
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
327
327
|
return `to_date(${ x })`;
|
|
@@ -330,7 +330,7 @@ const oDataFunctions = {
|
|
|
330
330
|
// https://www.h2database.com/html/functions.html
|
|
331
331
|
h2: {
|
|
332
332
|
contains(signature) {
|
|
333
|
-
const args = [ ...signature
|
|
333
|
+
const args = [ ...getArgs(signature) ];
|
|
334
334
|
checkArgs.call(this, 'contains', args, 2);
|
|
335
335
|
// defined as { LOCATE(searchString, string [, startInt]) }
|
|
336
336
|
args.reverse();
|
|
@@ -339,7 +339,7 @@ const oDataFunctions = {
|
|
|
339
339
|
return `(coalesce(locate(${ x }, ${ y }),0) > 0)`;
|
|
340
340
|
},
|
|
341
341
|
startswith(signature) {
|
|
342
|
-
const args = [ ...signature
|
|
342
|
+
const args = [ ...getArgs(signature) ];
|
|
343
343
|
checkArgs.call(this, 'startswith', args, 2);
|
|
344
344
|
// defined as { LOCATE(searchString, string [, startInt]) }
|
|
345
345
|
args.reverse();
|
|
@@ -348,14 +348,14 @@ const oDataFunctions = {
|
|
|
348
348
|
return `coalesce((locate(${ x }, ${ y }) = 1), false)`; // locate is 1 indexed
|
|
349
349
|
},
|
|
350
350
|
endswith(signature) {
|
|
351
|
-
const
|
|
351
|
+
const args = getArgs(signature);
|
|
352
352
|
checkArgs.call(this, 'endswith', args, 2);
|
|
353
353
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
354
354
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
355
355
|
return `coalesce((substring(${ x } FROM (char_length(${ x }) + 1) - char_length(${ y })) = ${ y }), false)`;
|
|
356
356
|
},
|
|
357
357
|
substring(signature) {
|
|
358
|
-
const
|
|
358
|
+
const args = getArgs(signature);
|
|
359
359
|
checkArgs.call(this, 'substring', args, 2, 3);
|
|
360
360
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
361
361
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -369,13 +369,13 @@ const oDataFunctions = {
|
|
|
369
369
|
// char_length is preferred over length -> REVISIT: returns a BIGINT, is this ok?
|
|
370
370
|
// https://www.h2database.com/html/functions.html#char_length
|
|
371
371
|
length(signature) {
|
|
372
|
-
const
|
|
372
|
+
const args = getArgs(signature);
|
|
373
373
|
checkArgs.call(this, 'length', args, 1);
|
|
374
374
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
375
375
|
return `cast(char_length(${ x }) as Integer)`;
|
|
376
376
|
},
|
|
377
377
|
indexof(signature) {
|
|
378
|
-
const args = [ ...signature
|
|
378
|
+
const args = [ ...getArgs(signature) ];
|
|
379
379
|
checkArgs.call(this, 'indexof', args, 2);
|
|
380
380
|
// defined as { LOCATE(searchString, string [, startInt]) }
|
|
381
381
|
args.reverse();
|
|
@@ -384,7 +384,7 @@ const oDataFunctions = {
|
|
|
384
384
|
return `(locate(${ x }, ${ y }) - 1)`; // locate is 1 indexed
|
|
385
385
|
},
|
|
386
386
|
matchespattern(signature) {
|
|
387
|
-
const
|
|
387
|
+
const args = getArgs(signature);
|
|
388
388
|
checkArgs.call(this, 'matchespattern', args, 2);
|
|
389
389
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
390
390
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -394,37 +394,37 @@ const oDataFunctions = {
|
|
|
394
394
|
return oDataFunctions.h2.matchespattern.call(this, signature);
|
|
395
395
|
},
|
|
396
396
|
year(signature) {
|
|
397
|
-
const
|
|
397
|
+
const args = getArgs(signature);
|
|
398
398
|
checkArgs.call(this, 'year', args, 1);
|
|
399
399
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
400
400
|
return `extract(YEAR FROM ${ x })`;
|
|
401
401
|
},
|
|
402
402
|
month(signature) {
|
|
403
|
-
const
|
|
403
|
+
const args = getArgs(signature);
|
|
404
404
|
checkArgs.call(this, 'month', args, 1);
|
|
405
405
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
406
406
|
return `extract(MONTH FROM ${ x })`;
|
|
407
407
|
},
|
|
408
408
|
day(signature) {
|
|
409
|
-
const
|
|
409
|
+
const args = getArgs(signature);
|
|
410
410
|
checkArgs.call(this, 'day', args, 1);
|
|
411
411
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
412
412
|
return `extract(DAY FROM ${ x })`;
|
|
413
413
|
},
|
|
414
414
|
hour(signature) {
|
|
415
|
-
const
|
|
415
|
+
const args = getArgs(signature);
|
|
416
416
|
checkArgs.call(this, 'hour', args, 1);
|
|
417
417
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
418
418
|
return `extract(HOUR FROM ${ x })`;
|
|
419
419
|
},
|
|
420
420
|
minute(signature) {
|
|
421
|
-
const
|
|
421
|
+
const args = getArgs(signature);
|
|
422
422
|
checkArgs.call(this, 'minute', args, 1);
|
|
423
423
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
424
424
|
return `extract(MINUTE FROM ${ x })`;
|
|
425
425
|
},
|
|
426
426
|
second(signature) {
|
|
427
|
-
const
|
|
427
|
+
const args = getArgs(signature);
|
|
428
428
|
checkArgs.call(this, 'second', args, 1);
|
|
429
429
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
430
430
|
return `extract(SECOND FROM ${ x })`;
|
|
@@ -432,19 +432,19 @@ const oDataFunctions = {
|
|
|
432
432
|
// REVISIT: currently runtimes normalize to milliseconds
|
|
433
433
|
// we could allow this to be more precise
|
|
434
434
|
fractionalseconds(signature) {
|
|
435
|
-
const
|
|
435
|
+
const args = getArgs(signature);
|
|
436
436
|
checkArgs.call(this, 'fractionalseconds', args, 1);
|
|
437
437
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
438
438
|
return `cast(extract(MILLISECOND FROM ${ x }) / 1000.0 AS NUMERIC(3,3))`;
|
|
439
439
|
},
|
|
440
440
|
time(signature) {
|
|
441
|
-
const
|
|
441
|
+
const args = getArgs(signature);
|
|
442
442
|
checkArgs.call(this, 'time', args, 1);
|
|
443
443
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
444
444
|
return `cast(${ x } AS TIME)`;
|
|
445
445
|
},
|
|
446
446
|
date(signature) {
|
|
447
|
-
const
|
|
447
|
+
const args = getArgs(signature);
|
|
448
448
|
checkArgs.call(this, 'date', args, 1);
|
|
449
449
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
450
450
|
return `cast(${ x } AS DATE)`;
|
|
@@ -453,7 +453,7 @@ const oDataFunctions = {
|
|
|
453
453
|
common: {
|
|
454
454
|
concat(signature) {
|
|
455
455
|
const separator = '||';
|
|
456
|
-
const args = signature.
|
|
456
|
+
const args = getArgs(signature).reduce((acc, current, index) => {
|
|
457
457
|
if (index > 0)
|
|
458
458
|
acc.push(separator);
|
|
459
459
|
|
|
@@ -464,26 +464,26 @@ const oDataFunctions = {
|
|
|
464
464
|
return `(${ res })`;
|
|
465
465
|
},
|
|
466
466
|
ceiling(signature) {
|
|
467
|
-
const
|
|
467
|
+
const args = getArgs(signature);
|
|
468
468
|
checkArgs.call(this, 'ceiling', args, 1);
|
|
469
469
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
470
470
|
return `ceil(${ x })`;
|
|
471
471
|
},
|
|
472
472
|
floor(signature) {
|
|
473
|
-
const
|
|
473
|
+
const args = getArgs(signature);
|
|
474
474
|
checkArgs.call(this, 'floor', args, 1);
|
|
475
475
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
476
476
|
return `floor(${ x })`;
|
|
477
477
|
},
|
|
478
478
|
trim(signature) {
|
|
479
|
-
const
|
|
479
|
+
const args = getArgs(signature);
|
|
480
480
|
checkArgs.call(this, 'trim', args, 1);
|
|
481
481
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
482
482
|
return `trim(${ x })`;
|
|
483
483
|
},
|
|
484
484
|
// SAP HANA, sqlite and postgres share the same implementation
|
|
485
485
|
substring(signature) {
|
|
486
|
-
const
|
|
486
|
+
const args = getArgs(signature);
|
|
487
487
|
checkArgs.call(this, 'substring', args, 2, 3);
|
|
488
488
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
489
489
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -495,52 +495,52 @@ const oDataFunctions = {
|
|
|
495
495
|
: `substr(${ x }, CASE WHEN ${ y } < 0 THEN length(${ x }) + ${ y } + 1 ELSE ${ y } + 1 END)`;
|
|
496
496
|
},
|
|
497
497
|
min(signature) {
|
|
498
|
-
const
|
|
498
|
+
const args = getArgs(signature);
|
|
499
499
|
checkArgs.call(this, 'min', args, 1);
|
|
500
500
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
501
501
|
return `min(${ x })`;
|
|
502
502
|
},
|
|
503
503
|
max(signature) {
|
|
504
|
-
const
|
|
504
|
+
const args = getArgs(signature);
|
|
505
505
|
checkArgs.call(this, 'max', args, 1);
|
|
506
506
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
507
507
|
return `max(${ x })`;
|
|
508
508
|
},
|
|
509
509
|
sum(signature) {
|
|
510
|
-
const
|
|
510
|
+
const args = getArgs(signature);
|
|
511
511
|
checkArgs.call(this, 'sum', args, 1);
|
|
512
512
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
513
513
|
return `sum(${ x })`;
|
|
514
514
|
},
|
|
515
515
|
count(signature) {
|
|
516
|
-
const
|
|
516
|
+
const args = getArgs(signature);
|
|
517
517
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
518
518
|
return `count(${ x || '*' })`;
|
|
519
519
|
},
|
|
520
520
|
countdistinct(signature) {
|
|
521
|
-
const
|
|
522
|
-
return `count(distinct ${ args.length > 0 ? this.renderArgs(signature) : "'*'" })`;
|
|
521
|
+
const args = getArgs(signature);
|
|
522
|
+
return `count(distinct ${ args.length > 0 ? this.renderArgs({ ...signature, args }) : "'*'" })`;
|
|
523
523
|
},
|
|
524
524
|
average(signature) {
|
|
525
|
-
const
|
|
525
|
+
const args = getArgs(signature);
|
|
526
526
|
checkArgs.call(this, 'average', args, 1);
|
|
527
527
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
528
528
|
return `avg(${ x })`;
|
|
529
529
|
},
|
|
530
530
|
length(signature) {
|
|
531
|
-
const
|
|
531
|
+
const args = getArgs(signature);
|
|
532
532
|
checkArgs.call(this, 'length', args, 1);
|
|
533
533
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
534
534
|
return `length(${ x })`;
|
|
535
535
|
},
|
|
536
536
|
tolower(signature) {
|
|
537
|
-
const
|
|
537
|
+
const args = getArgs(signature);
|
|
538
538
|
checkArgs.call(this, 'tolower', args, 1);
|
|
539
539
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
540
540
|
return `lower(${ x })`;
|
|
541
541
|
},
|
|
542
542
|
toupper(signature) {
|
|
543
|
-
const
|
|
543
|
+
const args = getArgs(signature);
|
|
544
544
|
checkArgs.call(this, 'toupper', args, 1);
|
|
545
545
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
546
546
|
return `upper(${ x })`;
|
|
@@ -570,7 +570,7 @@ const hanaFunctions = {
|
|
|
570
570
|
* @returns {string} - SQL expression to calculate the nano100 difference in SQLite.
|
|
571
571
|
*/
|
|
572
572
|
nano100_between(signature) {
|
|
573
|
-
const
|
|
573
|
+
const args = getArgs(signature);
|
|
574
574
|
checkArgs.call(this, 'nano100_between', args, 2);
|
|
575
575
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
576
576
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -578,7 +578,7 @@ const hanaFunctions = {
|
|
|
578
578
|
return `CAST(((julianday(${ y }) - julianday(${ x })) * 864000000000) as INTEGER)`;
|
|
579
579
|
},
|
|
580
580
|
seconds_between(signature) {
|
|
581
|
-
const
|
|
581
|
+
const args = getArgs(signature);
|
|
582
582
|
checkArgs.call(this, 'seconds_between', args, 2);
|
|
583
583
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
584
584
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -586,7 +586,7 @@ const hanaFunctions = {
|
|
|
586
586
|
return `CAST(strftime('%s', ${ y }) - strftime('%s', ${ x }) AS INTEGER)`;
|
|
587
587
|
},
|
|
588
588
|
days_between(signature) {
|
|
589
|
-
const
|
|
589
|
+
const args = getArgs(signature);
|
|
590
590
|
checkArgs.call(this, 'days_between', args, 2);
|
|
591
591
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
592
592
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -619,12 +619,13 @@ const hanaFunctions = {
|
|
|
619
619
|
* @returns {string} A SQL expression that calculates the adjusted month difference.
|
|
620
620
|
*/
|
|
621
621
|
months_between(signature) {
|
|
622
|
+
const args = getArgs(signature);
|
|
622
623
|
// Ensure exactly two arguments (startDate, endDate)
|
|
623
|
-
checkArgs.call(this, 'months_between',
|
|
624
|
+
checkArgs.call(this, 'months_between', args, 2);
|
|
624
625
|
|
|
625
626
|
// Render the arguments as SQL expressions.
|
|
626
|
-
const x = this.renderArgs({ ...signature, args: [
|
|
627
|
-
const y = this.renderArgs({ ...signature, args: [
|
|
627
|
+
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
628
|
+
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
628
629
|
|
|
629
630
|
// Construct the SQL expression:
|
|
630
631
|
// 1. Base month difference from the year and month components.
|
|
@@ -654,14 +655,14 @@ const hanaFunctions = {
|
|
|
654
655
|
return res.replace(/\s+/g, ' ');
|
|
655
656
|
},
|
|
656
657
|
years_between(signature) {
|
|
657
|
-
const
|
|
658
|
+
const args = getArgs(signature);
|
|
658
659
|
checkArgs.call(this, 'years_between', args, 2);
|
|
659
660
|
return `floor((${ hanaFunctions.sqlite.months_between.call(this, signature) }) / 12)`;
|
|
660
661
|
},
|
|
661
662
|
},
|
|
662
663
|
postgres: {
|
|
663
664
|
nano100_between(signature) {
|
|
664
|
-
const
|
|
665
|
+
const args = getArgs(signature);
|
|
665
666
|
checkArgs.call(this, 'nano100_between', args, 2);
|
|
666
667
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
667
668
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -669,7 +670,7 @@ const hanaFunctions = {
|
|
|
669
670
|
return `(EXTRACT(EPOCH FROM (${ y })::TIMESTAMP - (${ x })::TIMESTAMP) * 10000000)::BIGINT`;
|
|
670
671
|
},
|
|
671
672
|
seconds_between(signature) {
|
|
672
|
-
const
|
|
673
|
+
const args = getArgs(signature);
|
|
673
674
|
checkArgs.call(this, 'seconds_between', args, 2);
|
|
674
675
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
675
676
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -677,14 +678,14 @@ const hanaFunctions = {
|
|
|
677
678
|
return `EXTRACT(EPOCH FROM (${ y })::TIMESTAMP - (${ x })::TIMESTAMP)::BIGINT`;
|
|
678
679
|
},
|
|
679
680
|
days_between(signature) {
|
|
680
|
-
const
|
|
681
|
+
const args = getArgs(signature);
|
|
681
682
|
checkArgs.call(this, 'days_between', args, 2);
|
|
682
683
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
683
684
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
684
685
|
return `EXTRACT(DAY FROM ${ y }::timestamp - ${ x }::timestamp)::integer`;
|
|
685
686
|
},
|
|
686
687
|
months_between(signature) {
|
|
687
|
-
const
|
|
688
|
+
const args = getArgs(signature);
|
|
688
689
|
checkArgs.call(this, 'months_between', args, 2);
|
|
689
690
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
690
691
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -692,14 +693,14 @@ const hanaFunctions = {
|
|
|
692
693
|
return `(EXTRACT(YEAR FROM AGE(${ y }, ${ x })) * 12 + EXTRACT(MONTH FROM AGE(${ y }, ${ x })))::INTEGER`;
|
|
693
694
|
},
|
|
694
695
|
years_between(signature) {
|
|
695
|
-
const
|
|
696
|
+
const args = getArgs(signature);
|
|
696
697
|
checkArgs.call(this, 'years_between', args, 2);
|
|
697
698
|
return `floor((${ hanaFunctions.postgres.months_between.call(this, signature) }) / 12)::INTEGER`;
|
|
698
699
|
},
|
|
699
700
|
},
|
|
700
701
|
h2: {
|
|
701
702
|
nano100_between(signature) {
|
|
702
|
-
const
|
|
703
|
+
const args = getArgs(signature);
|
|
703
704
|
checkArgs.call(this, 'nano100_between', args, 2);
|
|
704
705
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
705
706
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -707,7 +708,7 @@ const hanaFunctions = {
|
|
|
707
708
|
return `CAST(DATEDIFF('MICROSECOND', ${ x }, ${ y }) * 10 AS BIGINT)`;
|
|
708
709
|
},
|
|
709
710
|
seconds_between(signature) {
|
|
710
|
-
const
|
|
711
|
+
const args = getArgs(signature);
|
|
711
712
|
checkArgs.call(this, 'seconds_between', args, 2);
|
|
712
713
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
713
714
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -715,7 +716,7 @@ const hanaFunctions = {
|
|
|
715
716
|
return `CAST(DATEDIFF('SECOND', ${ x }, ${ y }) AS BIGINT)`;
|
|
716
717
|
},
|
|
717
718
|
days_between(signature) {
|
|
718
|
-
const
|
|
719
|
+
const args = getArgs(signature);
|
|
719
720
|
checkArgs.call(this, 'days_between', args, 2);
|
|
720
721
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
721
722
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -726,7 +727,7 @@ const hanaFunctions = {
|
|
|
726
727
|
* forward and backward (negative) scenarios.
|
|
727
728
|
*/
|
|
728
729
|
months_between(signature) {
|
|
729
|
-
const
|
|
730
|
+
const args = getArgs(signature);
|
|
730
731
|
checkArgs.call(this, 'months_between', args, 2);
|
|
731
732
|
|
|
732
733
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
@@ -752,7 +753,7 @@ const hanaFunctions = {
|
|
|
752
753
|
return res.replace(/\s+/g, ' ');
|
|
753
754
|
},
|
|
754
755
|
years_between(signature) {
|
|
755
|
-
const
|
|
756
|
+
const args = getArgs(signature);
|
|
756
757
|
checkArgs.call(this, 'years_between', args, 2);
|
|
757
758
|
return `floor((${ hanaFunctions.h2.months_between.call(this, signature) }) / 12)`;
|
|
758
759
|
},
|
|
@@ -761,7 +762,7 @@ const hanaFunctions = {
|
|
|
761
762
|
// identity functions + argument check
|
|
762
763
|
hana: {
|
|
763
764
|
nano100_between(signature) {
|
|
764
|
-
const
|
|
765
|
+
const args = getArgs(signature);
|
|
765
766
|
checkArgs.call(this, 'nano100_between', args, 2);
|
|
766
767
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
767
768
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -769,7 +770,7 @@ const hanaFunctions = {
|
|
|
769
770
|
return `nano100_between(${ x }, ${ y })`;
|
|
770
771
|
},
|
|
771
772
|
seconds_between(signature) {
|
|
772
|
-
const
|
|
773
|
+
const args = getArgs(signature);
|
|
773
774
|
checkArgs.call(this, 'seconds_between', args, 2);
|
|
774
775
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
775
776
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -777,14 +778,14 @@ const hanaFunctions = {
|
|
|
777
778
|
return `seconds_between(${ x }, ${ y })`;
|
|
778
779
|
},
|
|
779
780
|
days_between(signature) {
|
|
780
|
-
const
|
|
781
|
+
const args = getArgs(signature);
|
|
781
782
|
checkArgs.call(this, 'days_between', args, 2);
|
|
782
783
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
783
784
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
784
785
|
return `days_between(${ x }, ${ y })`;
|
|
785
786
|
},
|
|
786
787
|
months_between(signature) {
|
|
787
|
-
const
|
|
788
|
+
const args = getArgs(signature);
|
|
788
789
|
checkArgs.call(this, 'months_between', args, 2);
|
|
789
790
|
const x = this.renderArgs({ ...signature, args: [ args[0] ] });
|
|
790
791
|
const y = this.renderArgs({ ...signature, args: [ args[1] ] });
|
|
@@ -792,13 +793,21 @@ const hanaFunctions = {
|
|
|
792
793
|
return `months_between(${ x }, ${ y })`;
|
|
793
794
|
},
|
|
794
795
|
years_between(signature) {
|
|
795
|
-
const
|
|
796
|
+
const args = getArgs(signature);
|
|
796
797
|
checkArgs.call(this, 'years_between', args, 2);
|
|
797
|
-
return `years_between(${ this.renderArgs(signature) })`;
|
|
798
|
+
return `years_between(${ this.renderArgs({ ...signature, args }) })`;
|
|
798
799
|
},
|
|
799
800
|
},
|
|
800
801
|
};
|
|
801
802
|
|
|
803
|
+
/**
|
|
804
|
+
* Normalizes `signature.args` to a positional array, handling both
|
|
805
|
+
* positional (array) and named (object) argument forms from CSN.
|
|
806
|
+
*/
|
|
807
|
+
function getArgs( signature ) {
|
|
808
|
+
return Array.isArray(signature.args) ? signature.args : Object.values(signature.args);
|
|
809
|
+
}
|
|
810
|
+
|
|
802
811
|
function checkArgs( funcName, receivedArgs, expectedLength, alternativeLength = null ) {
|
|
803
812
|
const expectedMismatch = receivedArgs.length < expectedLength;
|
|
804
813
|
const alternativeMismatch
|