@ragestudio/scylla-odm 0.22.2 → 0.22.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/batch/index.d.ts +3 -3
  2. package/batch/index.d.ts.map +1 -1
  3. package/client.d.ts +6 -5
  4. package/client.d.ts.map +1 -1
  5. package/client.js +7 -7
  6. package/client.js.map +1 -1
  7. package/cql_gen/create_table.d.ts +1 -1
  8. package/cql_gen/create_table.d.ts.map +1 -1
  9. package/document/index.d.ts +3 -3
  10. package/document/index.d.ts.map +1 -1
  11. package/driver/LICENSE.txt +177 -0
  12. package/driver/NOTICE.txt +67 -0
  13. package/driver/auth/index.d.ts +37 -0
  14. package/driver/auth/index.js +37 -0
  15. package/driver/auth/no-auth-provider.js +73 -0
  16. package/driver/auth/plain-text-auth-provider.js +81 -0
  17. package/driver/auth/provider.js +77 -0
  18. package/driver/client-options.js +442 -0
  19. package/driver/client.js +1267 -0
  20. package/driver/concurrent/index.d.ts +49 -0
  21. package/driver/concurrent/index.js +366 -0
  22. package/driver/connection.js +1034 -0
  23. package/driver/control-connection.js +1282 -0
  24. package/driver/encoder.js +2316 -0
  25. package/driver/errors.js +223 -0
  26. package/driver/execution-options.js +612 -0
  27. package/driver/execution-profile.js +274 -0
  28. package/driver/host-connection-pool.js +587 -0
  29. package/driver/host.js +699 -0
  30. package/driver/index.d.ts +387 -0
  31. package/driver/index.js +81 -0
  32. package/driver/mapping/cache.js +214 -0
  33. package/driver/mapping/doc-info-adapter.js +171 -0
  34. package/driver/mapping/index.d.ts +219 -0
  35. package/driver/mapping/index.js +57 -0
  36. package/driver/mapping/mapper.js +225 -0
  37. package/driver/mapping/mapping-handler.js +641 -0
  38. package/driver/mapping/model-batch-item.js +215 -0
  39. package/driver/mapping/model-batch-mapper.js +141 -0
  40. package/driver/mapping/model-mapper.js +315 -0
  41. package/driver/mapping/model-mapping-info.js +225 -0
  42. package/driver/mapping/object-selector.js +417 -0
  43. package/driver/mapping/q.js +156 -0
  44. package/driver/mapping/query-generator.js +556 -0
  45. package/driver/mapping/result-mapper.js +123 -0
  46. package/driver/mapping/result.js +139 -0
  47. package/driver/mapping/table-mappings.js +133 -0
  48. package/driver/mapping/tree.js +160 -0
  49. package/driver/metadata/aggregate.js +79 -0
  50. package/driver/metadata/client-state.js +119 -0
  51. package/driver/metadata/data-collection.js +182 -0
  52. package/driver/metadata/event-debouncer.js +174 -0
  53. package/driver/metadata/index.d.ts +276 -0
  54. package/driver/metadata/index.js +1156 -0
  55. package/driver/metadata/materialized-view.js +49 -0
  56. package/driver/metadata/schema-function.js +98 -0
  57. package/driver/metadata/schema-index.js +166 -0
  58. package/driver/metadata/schema-parser.js +1399 -0
  59. package/driver/metadata/table-metadata.js +77 -0
  60. package/driver/operation-state.js +206 -0
  61. package/driver/policies/address-resolution.js +145 -0
  62. package/driver/policies/index.d.ts +241 -0
  63. package/driver/policies/index.js +110 -0
  64. package/driver/policies/load-balancing.js +970 -0
  65. package/driver/policies/reconnection.js +166 -0
  66. package/driver/policies/retry.js +326 -0
  67. package/driver/policies/speculative-execution.js +150 -0
  68. package/driver/policies/timestamp-generation.js +176 -0
  69. package/driver/prepare-handler.js +347 -0
  70. package/driver/promise-utils.js +191 -0
  71. package/driver/readers.js +624 -0
  72. package/driver/request-execution.js +644 -0
  73. package/driver/request-handler.js +332 -0
  74. package/driver/requests.js +618 -0
  75. package/driver/stream-id-stack.js +209 -0
  76. package/driver/streams.js +745 -0
  77. package/driver/token.js +325 -0
  78. package/driver/tokenizer.js +631 -0
  79. package/driver/types/big-decimal.js +282 -0
  80. package/driver/types/duration.js +576 -0
  81. package/driver/types/index.d.ts +486 -0
  82. package/driver/types/index.js +733 -0
  83. package/driver/types/inet-address.js +262 -0
  84. package/driver/types/integer.js +818 -0
  85. package/driver/types/local-date.js +280 -0
  86. package/driver/types/local-time.js +299 -0
  87. package/driver/types/mutable-long.js +385 -0
  88. package/driver/types/protocol-version.js +391 -0
  89. package/driver/types/result-set.js +287 -0
  90. package/driver/types/result-stream.js +164 -0
  91. package/driver/types/row.js +85 -0
  92. package/driver/types/time-uuid.js +414 -0
  93. package/driver/types/tuple.js +103 -0
  94. package/driver/types/uuid.js +160 -0
  95. package/driver/types/vector.js +130 -0
  96. package/driver/types/version-number.js +153 -0
  97. package/driver/utils.js +1485 -0
  98. package/driver/writers.js +350 -0
  99. package/global.d.ts +1 -1
  100. package/global.d.ts.map +1 -1
  101. package/index.d.ts +6 -6
  102. package/index.d.ts.map +1 -1
  103. package/index.js +6 -6
  104. package/index.js.map +1 -1
  105. package/migrate/index.d.ts +1 -1
  106. package/migrate/index.d.ts.map +1 -1
  107. package/migrate/index.js +1 -1
  108. package/migrate/index.js.map +1 -1
  109. package/model/index.d.ts +6 -6
  110. package/model/index.d.ts.map +1 -1
  111. package/model/index.js +10 -10
  112. package/model/index.js.map +1 -1
  113. package/operations/countAll.d.ts +1 -1
  114. package/operations/countAll.d.ts.map +1 -1
  115. package/operations/delete.d.ts +3 -4
  116. package/operations/delete.d.ts.map +1 -1
  117. package/operations/delete.js +1 -1
  118. package/operations/delete.js.map +1 -1
  119. package/operations/find.d.ts +2 -2
  120. package/operations/find.d.ts.map +1 -1
  121. package/operations/find.js +1 -1
  122. package/operations/find.js.map +1 -1
  123. package/operations/findOne.d.ts +2 -2
  124. package/operations/findOne.d.ts.map +1 -1
  125. package/operations/findOne.js +1 -1
  126. package/operations/findOne.js.map +1 -1
  127. package/operations/insert.d.ts +3 -3
  128. package/operations/insert.d.ts.map +1 -1
  129. package/operations/insert.js +2 -2
  130. package/operations/insert.js.map +1 -1
  131. package/operations/sync.d.ts +1 -1
  132. package/operations/sync.d.ts.map +1 -1
  133. package/operations/sync.js +1 -1
  134. package/operations/sync.js.map +1 -1
  135. package/operations/tableExists.d.ts +1 -1
  136. package/operations/tableExists.d.ts.map +1 -1
  137. package/operations/update.d.ts +3 -3
  138. package/operations/update.d.ts.map +1 -1
  139. package/operations/update.js +2 -2
  140. package/operations/update.js.map +1 -1
  141. package/package.json +4 -12
  142. package/schema/index.d.ts +1 -1
  143. package/schema/index.d.ts.map +1 -1
  144. package/types.d.ts +4 -4
  145. package/types.d.ts.map +1 -1
  146. package/utils/queryParser.d.ts +1 -1
  147. package/utils/queryParser.d.ts.map +1 -1
  148. package/utils/queryParser.js +1 -1
  149. package/utils/queryParser.js.map +1 -1
  150. package/utils/typeChecker.d.ts +1 -1
  151. package/utils/typeChecker.d.ts.map +1 -1
  152. package/utils/typeChecker.js +1 -1
  153. package/utils/typeChecker.js.map +1 -1
@@ -0,0 +1,156 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import errors from "../errors.js"
20
+
21
+ /**
22
+ * Represents a CQL query operator, like >=, IN, <, ...
23
+ * @ignore
24
+ */
25
+ class QueryOperator {
26
+ /**
27
+ * Creates a new instance of <code>QueryOperator</code>.
28
+ * @param {String} key
29
+ * @param value
30
+ * @param [hasChildValues]
31
+ * @param [isInOperator]
32
+ */
33
+ constructor(key, value, hasChildValues, isInOperator) {
34
+ /**
35
+ * The CQL key representing the operator
36
+ * @type {string}
37
+ */
38
+ this.key = key
39
+
40
+ /**
41
+ * The value to be used as parameter.
42
+ */
43
+ this.value = value
44
+
45
+ /**
46
+ * Determines whether a query operator can have child values or operators (AND, OR)
47
+ */
48
+ this.hasChildValues = hasChildValues
49
+
50
+ /**
51
+ * Determines whether this instance represents CQL "IN" operator.
52
+ */
53
+ this.isInOperator = isInOperator
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Represents a CQL assignment operation, like col = col + x.
59
+ * @ignore
60
+ */
61
+ class QueryAssignment {
62
+ constructor(sign, value, inverted) {
63
+ /**
64
+ * Gets the sign of the assignment operation.
65
+ */
66
+ this.sign = sign
67
+
68
+ /**
69
+ * Gets the value to be assigned.
70
+ */
71
+ this.value = value
72
+
73
+ /**
74
+ * Determines whether the assignment should be inverted (prepends), e.g: col = x + col
75
+ * @type {boolean}
76
+ */
77
+ this.inverted = !!inverted
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Contains functions that represents operators in a query.
83
+ * @alias module:mapping~q
84
+ * @type {Object}
85
+ * @property {function} in_ Represents the CQL operator "IN".
86
+ * @property {function} gt Represents the CQL operator greater than ">".
87
+ * @property {function} gte Represents the CQL operator greater than or equals to ">=" .
88
+ * @property {function} lt Represents the CQL operator less than "<" .
89
+ * @property {function} lte Represents the CQL operator less than or equals to "<=" .
90
+ * @property {function} notEq Represents the CQL operator not equals to "!=" .
91
+ * @property {function} and When applied to a property, it represents two CQL conditions on the same column separated
92
+ * by the logical AND operator, e.g: "col1 >= x col < y"
93
+ * @property {function} incr Represents the CQL increment assignment used for counters, e.g: "col = col + x"
94
+ * @property {function} decr Represents the CQL decrement assignment used for counters, e.g: "col = col - x"
95
+ * @property {function} append Represents the CQL append assignment used for collections, e.g: "col = col + x"
96
+ * @property {function} prepend Represents the CQL prepend assignment used for lists, e.g: "col = x + col"
97
+ * @property {function} remove Represents the CQL remove assignment used for collections, e.g: "col = col - x"
98
+ */
99
+ const q = {
100
+ in_: function in_(arr) {
101
+ if (!Array.isArray(arr)) {
102
+ throw new errors.ArgumentError(
103
+ "IN operator supports only Array values",
104
+ )
105
+ }
106
+ return new QueryOperator("IN", arr, false, true)
107
+ },
108
+
109
+ gt: function gt(value) {
110
+ return new QueryOperator(">", value)
111
+ },
112
+
113
+ gte: function gte(value) {
114
+ return new QueryOperator(">=", value)
115
+ },
116
+
117
+ lt: function lt(value) {
118
+ return new QueryOperator("<", value)
119
+ },
120
+
121
+ lte: function lte(value) {
122
+ return new QueryOperator("<=", value)
123
+ },
124
+
125
+ notEq: function notEq(value) {
126
+ return new QueryOperator("!=", value)
127
+ },
128
+
129
+ and: function (condition1, condition2) {
130
+ return new QueryOperator("AND", [condition1, condition2], true)
131
+ },
132
+
133
+ incr: function incr(value) {
134
+ return new QueryAssignment("+", value)
135
+ },
136
+
137
+ decr: function decr(value) {
138
+ return new QueryAssignment("-", value)
139
+ },
140
+
141
+ append: function append(value) {
142
+ return new QueryAssignment("+", value)
143
+ },
144
+
145
+ prepend: function prepend(value) {
146
+ return new QueryAssignment("+", value, true)
147
+ },
148
+
149
+ remove: function remove(value) {
150
+ return new QueryAssignment("-", value)
151
+ },
152
+ }
153
+
154
+ export { q, QueryAssignment, QueryOperator }
155
+
156
+ export default { q, QueryAssignment, QueryOperator }
@@ -0,0 +1,556 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import vm from "vm"
20
+ import { QueryOperator, QueryAssignment } from "./q.js"
21
+ import types from "../types/index.js"
22
+ const dataTypes = types.dataTypes
23
+
24
+ const vmFileName = "gen-param-getter"
25
+
26
+ /**
27
+ * Provides methods to generate a query and parameter handlers.
28
+ * @ignore
29
+ */
30
+ class QueryGenerator {
31
+ /**
32
+ * Gets the SELECT query given the doc.
33
+ * @param {String} tableName
34
+ * @param {String} keyspace
35
+ * @param {Array} propertiesInfo
36
+ * @param {Array} fieldsInfo
37
+ * @param {Array} orderByColumns
38
+ * @param {Number|undefined} limit
39
+ * @return {string}
40
+ */
41
+ static getSelect(
42
+ tableName,
43
+ keyspace,
44
+ propertiesInfo,
45
+ fieldsInfo,
46
+ orderByColumns,
47
+ limit,
48
+ ) {
49
+ let query = "SELECT "
50
+ query +=
51
+ fieldsInfo.length > 0
52
+ ? fieldsInfo.map((p) => `"${p.columnName}"`).join(", ")
53
+ : "*"
54
+ query += ` FROM ${keyspace}.${tableName}`
55
+
56
+ if (propertiesInfo.length > 0) {
57
+ query += " WHERE "
58
+ query += QueryGenerator._getConditionWithOperators(propertiesInfo)
59
+ }
60
+
61
+ if (orderByColumns.length > 0) {
62
+ query += " ORDER BY "
63
+ query += orderByColumns
64
+ .map((order) => `"${order[0]}" ${order[1]}`)
65
+ .join(", ")
66
+ }
67
+
68
+ if (typeof limit === "number") {
69
+ query += " LIMIT ?"
70
+ }
71
+
72
+ return query
73
+ }
74
+
75
+ static selectParamsGetter(propertiesInfo, limit) {
76
+ let scriptText =
77
+ "(function getParametersSelect(doc, docInfo, mappingInfo) {\n"
78
+ scriptText += " return ["
79
+
80
+ scriptText += QueryGenerator._valueGetterExpression(propertiesInfo)
81
+
82
+ if (typeof limit === "number") {
83
+ if (propertiesInfo.length > 0) {
84
+ scriptText += ", "
85
+ }
86
+ scriptText += `docInfo['limit']`
87
+ }
88
+
89
+ // Finish return statement
90
+ scriptText += "];\n})"
91
+
92
+ const script = new vm.Script(scriptText, { filename: vmFileName })
93
+ return script.runInThisContext()
94
+ }
95
+
96
+ /**
97
+ * Gets the INSERT query and function to obtain the parameters, given the doc.
98
+ * @param {TableMetadata} table
99
+ * @param {String} keyspace
100
+ * @param {Array} propertiesInfo
101
+ * @param {Object} docInfo
102
+ * @param {Boolean|undefined} ifNotExists
103
+ * @return {{query: String, paramsGetter: Function, isIdempotent: Boolean}}
104
+ */
105
+ static getInsert(table, keyspace, propertiesInfo, docInfo, ifNotExists) {
106
+ const ttl = docInfo && docInfo.ttl
107
+
108
+ // Not all columns are contained in the table
109
+ const filteredPropertiesInfo = propertiesInfo.filter(
110
+ (pInfo) => table.columnsByName[pInfo.columnName] !== undefined,
111
+ )
112
+
113
+ return {
114
+ query: QueryGenerator._getInsertQuery(
115
+ table.name,
116
+ keyspace,
117
+ filteredPropertiesInfo,
118
+ ifNotExists,
119
+ ttl,
120
+ ),
121
+ paramsGetter: QueryGenerator._insertParamsGetter(
122
+ filteredPropertiesInfo,
123
+ docInfo,
124
+ ),
125
+ isIdempotent: !ifNotExists,
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Gets the query for an insert statement.
131
+ * @param {String} tableName
132
+ * @param {String} keyspace
133
+ * @param {Array} propertiesInfo
134
+ * @param {Boolean} ifNotExists
135
+ * @param {Number|undefined} ttl
136
+ * @return {String}
137
+ */
138
+ static _getInsertQuery(
139
+ tableName,
140
+ keyspace,
141
+ propertiesInfo,
142
+ ifNotExists,
143
+ ttl,
144
+ ) {
145
+ let query = `INSERT INTO ${keyspace}.${tableName} (`
146
+ query += propertiesInfo
147
+ .map((pInfo) => `"${pInfo.columnName}"`)
148
+ .join(", ")
149
+ query += ") VALUES ("
150
+ query += propertiesInfo.map(() => "?").join(", ")
151
+ query += ")"
152
+
153
+ if (ifNotExists === true) {
154
+ query += " IF NOT EXISTS"
155
+ }
156
+
157
+ if (typeof ttl === "number") {
158
+ query += " USING TTL ?"
159
+ }
160
+ return query
161
+ }
162
+
163
+ static _insertParamsGetter(propertiesInfo, docInfo) {
164
+ let scriptText =
165
+ "(function getParametersInsert(doc, docInfo, mappingInfo) {\n"
166
+ scriptText += " return ["
167
+
168
+ scriptText += QueryGenerator._valueGetterExpression(propertiesInfo)
169
+
170
+ if (docInfo && typeof docInfo.ttl === "number") {
171
+ scriptText += `, docInfo['ttl']`
172
+ }
173
+
174
+ // Finish return statement
175
+ scriptText += "];\n})"
176
+
177
+ const script = new vm.Script(scriptText, { filename: vmFileName })
178
+ return script.runInThisContext()
179
+ }
180
+
181
+ /**
182
+ * Gets the UPDATE query and function to obtain the parameters, given the doc.
183
+ * @param {TableMetadata} table
184
+ * @param {String} keyspace
185
+ * @param {Array} propertiesInfo
186
+ * @param {Object} docInfo
187
+ * @param {Array} when
188
+ * @param {Boolean|undefined} ifExists
189
+ * @return {{query: String, paramsGetter: Function, isIdempotent: Boolean, isCounter}}
190
+ */
191
+ static getUpdate(table, keyspace, propertiesInfo, docInfo, when, ifExists) {
192
+ const ttl = docInfo && docInfo.ttl
193
+ const primaryKeys = new Set(
194
+ table.partitionKeys.concat(table.clusteringKeys).map((c) => c.name),
195
+ )
196
+ let isIdempotent = true
197
+ let isCounter = false
198
+
199
+ // Not all columns are contained in the table
200
+ const filteredPropertiesInfo = propertiesInfo.filter((pInfo) => {
201
+ const column = table.columnsByName[pInfo.columnName]
202
+ if (column === undefined) {
203
+ return false
204
+ }
205
+
206
+ if (
207
+ column.type.code === dataTypes.list &&
208
+ pInfo.value instanceof QueryAssignment
209
+ ) {
210
+ // Its not idempotent when list append/prepend
211
+ isIdempotent = false
212
+ } else if (column.type.code === dataTypes.counter) {
213
+ // Any update on a counter table is not idempotent
214
+ isIdempotent = false
215
+ isCounter = true
216
+ }
217
+
218
+ return true
219
+ })
220
+
221
+ return {
222
+ query: QueryGenerator._getUpdateQuery(
223
+ table.name,
224
+ keyspace,
225
+ primaryKeys,
226
+ filteredPropertiesInfo,
227
+ when,
228
+ ifExists,
229
+ ttl,
230
+ ),
231
+ isIdempotent: isIdempotent && when.length === 0 && !ifExists,
232
+ paramsGetter: QueryGenerator._updateParamsGetter(
233
+ primaryKeys,
234
+ filteredPropertiesInfo,
235
+ when,
236
+ ttl,
237
+ ),
238
+ isCounter,
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Gets the query for an UPDATE statement.
244
+ * @param {String} tableName
245
+ * @param {String} keyspace
246
+ * @param {Set} primaryKeys
247
+ * @param {Array} propertiesInfo
248
+ * @param {Object} when
249
+ * @param {Boolean} ifExists
250
+ * @param {Number|undefined} ttl
251
+ */
252
+ static _getUpdateQuery(
253
+ tableName,
254
+ keyspace,
255
+ primaryKeys,
256
+ propertiesInfo,
257
+ when,
258
+ ifExists,
259
+ ttl,
260
+ ) {
261
+ let query = `UPDATE ${keyspace}.${tableName} `
262
+
263
+ if (typeof ttl === "number") {
264
+ query += "USING TTL ? "
265
+ }
266
+
267
+ query += "SET "
268
+
269
+ query += propertiesInfo
270
+ .filter((p) => !primaryKeys.has(p.columnName))
271
+ .map((p) => {
272
+ if (p.value instanceof QueryAssignment) {
273
+ if (p.value.inverted) {
274
+ // e.g: prepend "col1 = ? + col1"
275
+ return `"${p.columnName}" = ? ${p.value.sign} "${p.columnName}"`
276
+ }
277
+ // e.g: increment "col1 = col1 + ?"
278
+ return `"${p.columnName}" = "${p.columnName}" ${p.value.sign} ?`
279
+ }
280
+
281
+ return `"${p.columnName}" = ?`
282
+ })
283
+ .join(", ")
284
+
285
+ query += " WHERE "
286
+ query += propertiesInfo
287
+ .filter((p) => primaryKeys.has(p.columnName))
288
+ .map((p) => `"${p.columnName}" = ?`)
289
+ .join(" AND ")
290
+
291
+ if (ifExists === true) {
292
+ query += " IF EXISTS"
293
+ } else if (when.length > 0) {
294
+ query += " IF " + QueryGenerator._getConditionWithOperators(when)
295
+ }
296
+
297
+ return query
298
+ }
299
+
300
+ /**
301
+ * Returns a function to obtain the parameter values from a doc for an UPDATE statement.
302
+ * @param {Set} primaryKeys
303
+ * @param {Array} propertiesInfo
304
+ * @param {Array} when
305
+ * @param {Number|undefined} ttl
306
+ * @returns {Function}
307
+ */
308
+ static _updateParamsGetter(primaryKeys, propertiesInfo, when, ttl) {
309
+ let scriptText =
310
+ "(function getParametersUpdate(doc, docInfo, mappingInfo) {\n"
311
+ scriptText += " return ["
312
+
313
+ if (typeof ttl === "number") {
314
+ scriptText += `docInfo['ttl'], `
315
+ }
316
+
317
+ // Assignment clause
318
+ scriptText += QueryGenerator._assignmentGetterExpression(
319
+ propertiesInfo.filter((p) => !primaryKeys.has(p.columnName)),
320
+ )
321
+ scriptText += ", "
322
+
323
+ // Where clause
324
+ scriptText += QueryGenerator._valueGetterExpression(
325
+ propertiesInfo.filter((p) => primaryKeys.has(p.columnName)),
326
+ )
327
+
328
+ // Condition clause
329
+ if (when.length > 0) {
330
+ scriptText +=
331
+ ", " +
332
+ QueryGenerator._valueGetterExpression(when, "docInfo.when")
333
+ }
334
+
335
+ // Finish return statement
336
+ scriptText += "];\n})"
337
+
338
+ const script = new vm.Script(scriptText, { filename: vmFileName })
339
+ return script.runInThisContext()
340
+ }
341
+
342
+ /**
343
+ * Gets the DELETE query and function to obtain the parameters, given the doc.
344
+ * @param {TableMetadata} table
345
+ * @param {String} keyspace
346
+ * @param {Array} propertiesInfo
347
+ * @param {Object} docInfo
348
+ * @param {Array} when
349
+ * @param {Boolean|undefined} ifExists
350
+ * @return {{query: String, paramsGetter: Function, isIdempotent}}
351
+ */
352
+ static getDelete(table, keyspace, propertiesInfo, docInfo, when, ifExists) {
353
+ const deleteOnlyColumns = docInfo && docInfo.deleteOnlyColumns
354
+ const primaryKeys = new Set(
355
+ table.partitionKeys.concat(table.clusteringKeys).map((c) => c.name),
356
+ )
357
+
358
+ const filteredPropertiesInfo = propertiesInfo.filter(
359
+ (pInfo) => table.columnsByName[pInfo.columnName] !== undefined,
360
+ )
361
+
362
+ return {
363
+ query: QueryGenerator._getDeleteQuery(
364
+ table.name,
365
+ keyspace,
366
+ primaryKeys,
367
+ filteredPropertiesInfo,
368
+ when,
369
+ ifExists,
370
+ deleteOnlyColumns,
371
+ ),
372
+ paramsGetter: QueryGenerator._deleteParamsGetter(
373
+ primaryKeys,
374
+ filteredPropertiesInfo,
375
+ when,
376
+ ),
377
+ isIdempotent: when.length === 0 && !ifExists,
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Gets the query for an UPDATE statement.
383
+ * @param {String} tableName
384
+ * @param {String} keyspace
385
+ * @param {Set} primaryKeys
386
+ * @param {Array} propertiesInfo
387
+ * @param {Array} when
388
+ * @param {Boolean} ifExists
389
+ * @param {Boolean} deleteOnlyColumns
390
+ * @private
391
+ * @return {String}
392
+ */
393
+ static _getDeleteQuery(
394
+ tableName,
395
+ keyspace,
396
+ primaryKeys,
397
+ propertiesInfo,
398
+ when,
399
+ ifExists,
400
+ deleteOnlyColumns,
401
+ ) {
402
+ let query = "DELETE"
403
+
404
+ if (deleteOnlyColumns) {
405
+ const columnsToDelete = propertiesInfo
406
+ .filter((p) => !primaryKeys.has(p.columnName))
407
+ .map((p) => `"${p.columnName}"`)
408
+ .join(", ")
409
+
410
+ if (columnsToDelete !== "") {
411
+ query += " " + columnsToDelete
412
+ }
413
+ }
414
+
415
+ query += ` FROM ${keyspace}.${tableName} WHERE `
416
+ query += propertiesInfo
417
+ .filter((p) => primaryKeys.has(p.columnName))
418
+ .map((p) => `"${p.columnName}" = ?`)
419
+ .join(" AND ")
420
+
421
+ if (ifExists === true) {
422
+ query += " IF EXISTS"
423
+ } else if (when.length > 0) {
424
+ query += " IF " + QueryGenerator._getConditionWithOperators(when)
425
+ }
426
+
427
+ return query
428
+ }
429
+ /**
430
+ * Returns a function to obtain the parameter values from a doc for an UPDATE statement.
431
+ * @param {Set} primaryKeys
432
+ * @param {Array} propertiesInfo
433
+ * @param {Array} when
434
+ * @returns {Function}
435
+ */
436
+ static _deleteParamsGetter(primaryKeys, propertiesInfo, when) {
437
+ let scriptText =
438
+ "(function getParametersDelete(doc, docInfo, mappingInfo) {\n"
439
+ scriptText += " return ["
440
+
441
+ // Where clause
442
+ scriptText += QueryGenerator._valueGetterExpression(
443
+ propertiesInfo.filter((p) => primaryKeys.has(p.columnName)),
444
+ )
445
+
446
+ // Condition clause
447
+ if (when.length > 0) {
448
+ scriptText +=
449
+ ", " +
450
+ QueryGenerator._valueGetterExpression(when, "docInfo.when")
451
+ }
452
+
453
+ // Finish return statement
454
+ scriptText += "];\n})"
455
+
456
+ const script = new vm.Script(scriptText, { filename: vmFileName })
457
+ return script.runInThisContext()
458
+ }
459
+
460
+ /**
461
+ * Gets a string containing the doc properties to get.
462
+ * @param {Array} propertiesInfo
463
+ * @param {String} [objectName='doc']
464
+ * @return {string}
465
+ * @private
466
+ */
467
+ static _valueGetterExpression(propertiesInfo, objectName) {
468
+ objectName = objectName || "doc"
469
+
470
+ return propertiesInfo
471
+ .map((p) =>
472
+ QueryGenerator._valueGetterSingle(
473
+ `${objectName}['${p.propertyName}']`,
474
+ p.propertyName,
475
+ p.value,
476
+ p.fromModel,
477
+ ),
478
+ )
479
+ .join(", ")
480
+ }
481
+
482
+ static _valueGetterSingle(prefix, propName, value, fromModelFn) {
483
+ let valueGetter = prefix
484
+
485
+ if (value instanceof QueryOperator) {
486
+ if (value.hasChildValues) {
487
+ return (
488
+ `${QueryGenerator._valueGetterSingle(`${prefix}.value[0]`, propName, value.value[0], fromModelFn)}` +
489
+ `, ${QueryGenerator._valueGetterSingle(`${prefix}.value[1]`, propName, value.value[1], fromModelFn)}`
490
+ )
491
+ }
492
+
493
+ valueGetter = `${prefix}.value`
494
+
495
+ if (value.isInOperator && fromModelFn) {
496
+ // Transform each individual value
497
+ return `${valueGetter}.map(v => ${QueryGenerator._getMappingFunctionCall(propName, "v")})`
498
+ }
499
+ }
500
+
501
+ return !fromModelFn
502
+ ? valueGetter
503
+ : QueryGenerator._getMappingFunctionCall(propName, valueGetter)
504
+ }
505
+
506
+ /**
507
+ * Gets a string containing the doc properties to SET, considering QueryAssignment instances.
508
+ * @param {Array} propertiesInfo
509
+ * @param {String} [prefix='doc']
510
+ * @return {string}
511
+ * @private
512
+ */
513
+ static _assignmentGetterExpression(propertiesInfo, prefix) {
514
+ prefix = prefix || "doc"
515
+
516
+ return propertiesInfo
517
+ .map((p) => {
518
+ const valueGetter = `${prefix}['${p.propertyName}']${p.value instanceof QueryAssignment ? ".value" : ""}`
519
+ if (p.fromModel) {
520
+ return QueryGenerator._getMappingFunctionCall(
521
+ p.propertyName,
522
+ valueGetter,
523
+ )
524
+ }
525
+ return valueGetter
526
+ })
527
+ .join(", ")
528
+ }
529
+
530
+ static _getConditionWithOperators(propertiesInfo) {
531
+ return propertiesInfo
532
+ .map((p) =>
533
+ QueryGenerator._getSingleCondition(p.columnName, p.value),
534
+ )
535
+ .join(" AND ")
536
+ }
537
+
538
+ static _getMappingFunctionCall(propName, valueGetter) {
539
+ return `mappingInfo.getFromModelFn('${propName}')(${valueGetter})`
540
+ }
541
+
542
+ static _getSingleCondition(columnName, value) {
543
+ if (value instanceof QueryOperator) {
544
+ if (value.hasChildValues) {
545
+ return (
546
+ `${QueryGenerator._getSingleCondition(columnName, value.value[0])}` +
547
+ ` ${value.key} ${QueryGenerator._getSingleCondition(columnName, value.value[1])}`
548
+ )
549
+ }
550
+ return `"${columnName}" ${value.key} ?`
551
+ }
552
+ return `"${columnName}" = ?`
553
+ }
554
+ }
555
+
556
+ export default QueryGenerator