@cap-js/db-service 1.0.1 → 1.1.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 +11 -2
- package/index.js +16 -2
- package/lib/InsertResults.js +20 -3
- package/lib/SQLService.js +112 -28
- package/lib/common/DatabaseService.js +55 -4
- package/lib/common/factory.d.ts +5 -0
- package/lib/converters.d.ts +24 -0
- package/lib/cql-functions.js +191 -4
- package/lib/cqn2sql.js +270 -5
- package/lib/cqn4sql.js +60 -17
- package/lib/deep-queries.js +27 -0
- package/lib/fill-in-keys.js +10 -0
- package/lib/infer/cqn.d.ts +45 -0
- package/lib/infer/index.js +102 -27
- package/lib/infer/join-tree.js +62 -17
- package/package.json +18 -6
package/lib/cql-functions.js
CHANGED
|
@@ -2,49 +2,196 @@ const StandardFunctions = {
|
|
|
2
2
|
// OData: https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_CanonicalFunctions
|
|
3
3
|
|
|
4
4
|
// String and Collection Functions
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Generates SQL statement that produces the length of a given string
|
|
7
|
+
* @param {string} x
|
|
8
|
+
* @returns {string}
|
|
9
|
+
*/
|
|
10
|
+
length: x => `length(${x})`,
|
|
11
|
+
/**
|
|
12
|
+
* Generates SQL statement that produces the average of a given expression
|
|
13
|
+
* @param {string} x
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
6
16
|
average: x => `avg(${x})`,
|
|
17
|
+
/**
|
|
18
|
+
* Generates SQL statement that produces a boolean value indicating whether the search term is contained in the given columns
|
|
19
|
+
* @param {string} ref
|
|
20
|
+
* @param {string} arg
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
7
23
|
search: function (ref, arg) {
|
|
8
24
|
if (!('val' in arg)) throw `SQLite only supports single value arguments for $search`
|
|
9
25
|
const refs = ref.list || [ref],
|
|
10
26
|
{ toString } = ref
|
|
11
27
|
return '(' + refs.map(ref2 => this.contains(this.tolower(toString(ref2)), this.tolower(arg))).join(' or ') + ')'
|
|
12
28
|
},
|
|
29
|
+
/**
|
|
30
|
+
* Generates SQL statement that produces a string with all provided strings concatenated
|
|
31
|
+
* @param {...string} args
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
13
34
|
concat: (...args) => args.join('||'),
|
|
35
|
+
/**
|
|
36
|
+
* Generates SQL statement that produces a boolean value indicating whether the first string contains the second string
|
|
37
|
+
* @param {...string} args
|
|
38
|
+
* @returns {string}
|
|
39
|
+
*/
|
|
14
40
|
contains: (...args) => `ifnull(instr(${args}),0)`,
|
|
41
|
+
/**
|
|
42
|
+
* Generates SQL statement that produces the number of elements in a given collection
|
|
43
|
+
* @param {string} x
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
15
46
|
count: x => `count(${x || '*'})`,
|
|
47
|
+
/**
|
|
48
|
+
* Generates SQL statement that produces the number of distinct values of a given expression
|
|
49
|
+
* @param {string} x
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
16
52
|
countdistinct: x => `count(distinct ${x || '*'})`,
|
|
53
|
+
/**
|
|
54
|
+
* Generates SQL statement that produces the index of the first occurrence of the second string in the first string
|
|
55
|
+
* @param {string} x
|
|
56
|
+
* @param {string} y
|
|
57
|
+
* @returns {string}
|
|
58
|
+
*/
|
|
17
59
|
indexof: (x, y) => `instr(${x},${y}) - 1`, // sqlite instr is 1 indexed
|
|
60
|
+
/**
|
|
61
|
+
* Generates SQL statement that produces a boolean value indicating whether the first string starts with the second string
|
|
62
|
+
* @param {string} x
|
|
63
|
+
* @param {string} y
|
|
64
|
+
* @returns {string}
|
|
65
|
+
*/
|
|
18
66
|
startswith: (x, y) => `instr(${x},${y}) = 1`, // sqlite instr is 1 indexed
|
|
19
67
|
// takes the end of the string of the size of the target and compares it with the target
|
|
68
|
+
/**
|
|
69
|
+
* Generates SQL statement that produces a boolean value indicating whether the first string ends with the second string
|
|
70
|
+
* @param {string} x
|
|
71
|
+
* @param {string} y
|
|
72
|
+
* @returns {string}
|
|
73
|
+
*/
|
|
20
74
|
endswith: (x, y) => `substr(${x}, length(${x}) + 1 - length(${y})) = ${y}`,
|
|
75
|
+
/**
|
|
76
|
+
* Generates SQL statement that produces the substring of a given string
|
|
77
|
+
* @example
|
|
78
|
+
* // returns 'bc'
|
|
79
|
+
* {func:'substring',args:[{val:'abc'},{val:1}]}
|
|
80
|
+
* @example
|
|
81
|
+
* // returns 'b'
|
|
82
|
+
* {func:'substring',args:[{val:'abc'},{val:1},{val:1}]}
|
|
83
|
+
* @param {string} x
|
|
84
|
+
* @param {string} y
|
|
85
|
+
* @param {string} z
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
21
88
|
substring: (x, y, z) =>
|
|
22
89
|
z
|
|
23
90
|
? `substr( ${x}, case when ${y} < 0 then length(${x}) + ${y} + 1 else ${y} + 1 end, ${z} )`
|
|
24
91
|
: `substr( ${x}, case when ${y} < 0 then length(${x}) + ${y} + 1 else ${y} + 1 end )`,
|
|
25
92
|
|
|
26
93
|
// String Functions
|
|
94
|
+
/**
|
|
95
|
+
* Generates SQL statement that matches the given string against a regular expression
|
|
96
|
+
* @param {string} x
|
|
97
|
+
* @param {string} y
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
27
100
|
matchesPattern: (x, y) => `${x} regexp ${y})`,
|
|
101
|
+
/**
|
|
102
|
+
* Generates SQL statement that produces the lower case value of a given string
|
|
103
|
+
* @param {string} x
|
|
104
|
+
* @returns {string}
|
|
105
|
+
*/
|
|
28
106
|
tolower: x => `lower(${x})`,
|
|
107
|
+
/**
|
|
108
|
+
* Generates SQL statement that produces the upper case value of a given string
|
|
109
|
+
* @param {string} x
|
|
110
|
+
* @returns {string}
|
|
111
|
+
*/
|
|
29
112
|
toupper: x => `upper(${x})`,
|
|
30
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Generates SQL statement that produces the trimmed value of a given string
|
|
115
|
+
* @param {string} x
|
|
116
|
+
* @returns {string}
|
|
117
|
+
*/
|
|
118
|
+
trim: x => `trim(${x})`,
|
|
31
119
|
|
|
32
120
|
// Arithmetic Functions
|
|
121
|
+
/**
|
|
122
|
+
* Generates SQL statement that produces the rounded up value of a given number
|
|
123
|
+
* @param {string} x
|
|
124
|
+
* @returns {string}
|
|
125
|
+
*/
|
|
33
126
|
ceiling: x => `ceil(${x})`,
|
|
34
|
-
|
|
35
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Generates SQL statement that produces the rounded down value of a given number
|
|
129
|
+
* @param {string} x
|
|
130
|
+
* @returns {string}
|
|
131
|
+
*/
|
|
132
|
+
floor: x => `floor(${x})`,
|
|
133
|
+
/**
|
|
134
|
+
* Generates SQL statement that produces the rounded value of a given number
|
|
135
|
+
* @param {string} x
|
|
136
|
+
* @param {string} p precision
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
round: (x, p) => `round(${x}${p ? `,${p}` : ''})`,
|
|
36
140
|
|
|
37
141
|
// Date and Time Functions
|
|
142
|
+
/**
|
|
143
|
+
* Generates SQL statement that produces the year of a given timestamp
|
|
144
|
+
* @param {string} x
|
|
145
|
+
* @returns {string}
|
|
146
|
+
*/
|
|
38
147
|
year: x => `cast( strftime('%Y',${x}) as Integer )`,
|
|
148
|
+
/**
|
|
149
|
+
* Generates SQL statement that produces the month of a given timestamp
|
|
150
|
+
* @param {string} x
|
|
151
|
+
* @returns {string}
|
|
152
|
+
*/
|
|
39
153
|
month: x => `cast( strftime('%m',${x}) as Integer )`,
|
|
154
|
+
/**
|
|
155
|
+
* Generates SQL statement that produces the day of a given timestamp
|
|
156
|
+
* @param {string} x
|
|
157
|
+
* @returns {string}
|
|
158
|
+
*/
|
|
40
159
|
day: x => `cast( strftime('%d',${x}) as Integer )`,
|
|
160
|
+
/**
|
|
161
|
+
* Generates SQL statement that produces the hours of a given timestamp
|
|
162
|
+
* @param {string} x
|
|
163
|
+
* @returns {string}
|
|
164
|
+
*/
|
|
41
165
|
hour: x => `cast( strftime('%H',${x}) as Integer )`,
|
|
166
|
+
/**
|
|
167
|
+
* Generates SQL statement that produces the minutes of a given timestamp
|
|
168
|
+
* @param {string} x
|
|
169
|
+
* @returns {string}
|
|
170
|
+
*/
|
|
42
171
|
minute: x => `cast( strftime('%M',${x}) as Integer )`,
|
|
172
|
+
/**
|
|
173
|
+
* Generates SQL statement that produces the seconds of a given timestamp
|
|
174
|
+
* @param {string} x
|
|
175
|
+
* @returns {string}
|
|
176
|
+
*/
|
|
43
177
|
second: x => `cast( strftime('%S',${x}) as Integer )`,
|
|
44
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Generates SQL statement that produces the fractional seconds of a given timestamp
|
|
181
|
+
* @param {string} x
|
|
182
|
+
* @returns {string}
|
|
183
|
+
*/
|
|
45
184
|
fractionalseconds: x => `cast( strftime('%f0000',${x}) as Integer )`,
|
|
46
185
|
|
|
186
|
+
/**
|
|
187
|
+
* maximum date time value
|
|
188
|
+
* @returns {string}
|
|
189
|
+
*/
|
|
47
190
|
maxdatetime: () => '9999-12-31 23:59:59.999',
|
|
191
|
+
/**
|
|
192
|
+
* minimum date time value
|
|
193
|
+
* @returns {string}
|
|
194
|
+
*/
|
|
48
195
|
mindatetime: () => '0001-01-01 00:00:00.000',
|
|
49
196
|
|
|
50
197
|
// odata spec defines the date time offset type as a normal ISO time stamp
|
|
@@ -52,6 +199,11 @@ const StandardFunctions = {
|
|
|
52
199
|
// sqlite understands this so by splitting the timezone from the actual date
|
|
53
200
|
// prefixing it with 1970 it allows sqlite to give back the number of seconds
|
|
54
201
|
// which can be divided by 60 back to minutes
|
|
202
|
+
/**
|
|
203
|
+
* Generates SQL statement that produces the offset in minutes of a given date time offset string
|
|
204
|
+
* @param {string} x
|
|
205
|
+
* @returns {string}
|
|
206
|
+
*/
|
|
55
207
|
totaloffsetminutes: x => `case
|
|
56
208
|
when substr(${x}, length(${x})) = 'z' then 0
|
|
57
209
|
else strftime('%s', '1970-01-01T00:00:00' || substr(${x}, length(${x}) - 5)) / 60
|
|
@@ -65,6 +217,11 @@ const StandardFunctions = {
|
|
|
65
217
|
// the number of seconds in a day
|
|
66
218
|
// As sqlite is most accurate with juliandays it is better to do then then using actual second function
|
|
67
219
|
// while the odata specification states that the seconds has to be fractional which only julianday allows
|
|
220
|
+
/**
|
|
221
|
+
* Generates SQL statement that produces an OData compliant duration string like: P12DT23H59M59.999999999999S
|
|
222
|
+
* @param {string} x
|
|
223
|
+
* @returns {string}
|
|
224
|
+
*/
|
|
68
225
|
totalseconds: x => `(
|
|
69
226
|
(
|
|
70
227
|
(
|
|
@@ -90,12 +247,30 @@ const HANAFunctions = {
|
|
|
90
247
|
// https://help.sap.com/docs/SAP_HANA_PLATFORM/4fe29514fd584807ac9f2a04f6754767/f12b86a6284c4aeeb449e57eb5dd3ebd.html
|
|
91
248
|
|
|
92
249
|
// Time functions
|
|
250
|
+
/**
|
|
251
|
+
* Generates SQL statement that calculates the difference in 100nanoseconds between two timestamps
|
|
252
|
+
* @param {string} x left timestamp
|
|
253
|
+
* @param {string} y right timestamp
|
|
254
|
+
* @returns {string}
|
|
255
|
+
*/
|
|
93
256
|
nano100_between: (x, y) => `(julianday(${y}) - julianday(${x})) * 864000000000`,
|
|
257
|
+
/**
|
|
258
|
+
* Generates SQL statement that calculates the difference in seconds between two timestamps
|
|
259
|
+
* @param {string} x left timestamp
|
|
260
|
+
* @param {string} y right timestamp
|
|
261
|
+
* @returns {string}
|
|
262
|
+
*/
|
|
94
263
|
seconds_between: (x, y) => `(julianday(${y}) - julianday(${x})) * 86400`,
|
|
95
264
|
// Calculates the difference in full days using julian day
|
|
96
265
|
// Using the exact time of the day to determine whether 24 hours have passed or not to add the final day
|
|
97
266
|
// When just comparing the julianday values with each other there are leap seconds included
|
|
98
267
|
// Which on the day resolution are included as the individual days therefor ignoring them to match HANA
|
|
268
|
+
/**
|
|
269
|
+
* Generates SQL statement that calculates the difference in days between two timestamps
|
|
270
|
+
* @param {string} x left timestamp
|
|
271
|
+
* @param {string} y right timestamp
|
|
272
|
+
* @returns {string}
|
|
273
|
+
*/
|
|
99
274
|
days_between: (x, y) => `(
|
|
100
275
|
cast ( julianday(${y}) as Integer ) - cast ( julianday(${x}) as Integer )
|
|
101
276
|
) + (
|
|
@@ -122,6 +297,12 @@ const HANAFunctions = {
|
|
|
122
297
|
|
|
123
298
|
Also check whether the result will be positive or negative to make sure to not subtract an extra month
|
|
124
299
|
*/
|
|
300
|
+
/**
|
|
301
|
+
* Generates SQL statement that calculates the difference in months between two timestamps
|
|
302
|
+
* @param {string} x left timestamp
|
|
303
|
+
* @param {string} y right timestamp
|
|
304
|
+
* @returns {string}
|
|
305
|
+
*/
|
|
125
306
|
months_between: (x, y) => `
|
|
126
307
|
(
|
|
127
308
|
(
|
|
@@ -139,6 +320,12 @@ const HANAFunctions = {
|
|
|
139
320
|
)
|
|
140
321
|
)
|
|
141
322
|
)`,
|
|
323
|
+
/**
|
|
324
|
+
* Generates SQL statement that calculates the difference in years between two timestamps
|
|
325
|
+
* @param {string} x left timestamp
|
|
326
|
+
* @param {string} y right timestamp
|
|
327
|
+
* @returns {string}
|
|
328
|
+
*/
|
|
142
329
|
years_between(x, y) {
|
|
143
330
|
return `floor(${this.months_between(x, y)} / 12)`
|
|
144
331
|
},
|