Skip to content

Commit 0d8129f

Browse files
authored
Escape column names with quotes (#391)
1 parent d528a2d commit 0d8129f

File tree

3 files changed

+50
-50
lines changed

3 files changed

+50
-50
lines changed

lib/mapping/query-generator.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class QueryGenerator {
4242
*/
4343
static getSelect(tableName, keyspace, propertiesInfo, fieldsInfo, orderByColumns, limit) {
4444
let query = 'SELECT ';
45-
query += fieldsInfo.length > 0 ? fieldsInfo.map(p => p.columnName).join(', ') : '*';
45+
query += fieldsInfo.length > 0 ? fieldsInfo.map(p => `"${p.columnName}"`).join(', ') : '*';
4646
query += ` FROM ${keyspace}.${tableName}`;
4747

4848
if (propertiesInfo.length > 0) {
@@ -52,7 +52,7 @@ class QueryGenerator {
5252

5353
if (orderByColumns.length > 0) {
5454
query += ' ORDER BY ';
55-
query += orderByColumns.map(order => order[0] + ' ' + order[1]).join(', ');
55+
query += orderByColumns.map(order => `"${order[0]}" ${order[1]}`).join(', ');
5656
}
5757

5858
if (typeof limit === 'number') {
@@ -116,7 +116,7 @@ class QueryGenerator {
116116
*/
117117
static _getInsertQuery(tableName, keyspace, propertiesInfo, ifNotExists, ttl) {
118118
let query = `INSERT INTO ${keyspace}.${tableName} (`;
119-
query += propertiesInfo.map(pInfo => pInfo.columnName).join(', ');
119+
query += propertiesInfo.map(pInfo => `"${pInfo.columnName}"`).join(', ');
120120
query += ') VALUES (';
121121
query += propertiesInfo.map(() => '?').join(', ');
122122
query += ')';
@@ -217,18 +217,18 @@ class QueryGenerator {
217217
if (p.value instanceof QueryAssignment) {
218218
if (p.value.inverted) {
219219
// e.g: prepend "col1 = ? + col1"
220-
return `${p.columnName} = ? ${p.value.sign} ${p.columnName}`;
220+
return `"${p.columnName}" = ? ${p.value.sign} "${p.columnName}"`;
221221
}
222222
// e.g: increment "col1 = col1 + ?"
223-
return `${p.columnName} = ${p.columnName} ${p.value.sign} ?`;
223+
return `"${p.columnName}" = "${p.columnName}" ${p.value.sign} ?`;
224224
}
225225

226-
return p.columnName + ' = ?';
226+
return `"${p.columnName}" = ?`;
227227
})
228228
.join(', ');
229229

230230
query += ' WHERE ';
231-
query += propertiesInfo.filter(p => primaryKeys.has(p.columnName)).map(p => p.columnName + ' = ?').join(' AND ');
231+
query += propertiesInfo.filter(p => primaryKeys.has(p.columnName)).map(p => `"${p.columnName}" = ?`).join(' AND ');
232232

233233
if (ifExists === true) {
234234
query += ' IF EXISTS';
@@ -318,7 +318,7 @@ class QueryGenerator {
318318

319319
if (deleteOnlyColumns) {
320320
const columnsToDelete = propertiesInfo.filter(p => !primaryKeys.has(p.columnName))
321-
.map(p => p.columnName)
321+
.map(p => `"${p.columnName}"`)
322322
.join(', ');
323323

324324
if (columnsToDelete !== '') {
@@ -327,7 +327,7 @@ class QueryGenerator {
327327
}
328328

329329
query += ` FROM ${keyspace}.${tableName} WHERE `;
330-
query += propertiesInfo.filter(p => primaryKeys.has(p.columnName)).map(p => p.columnName + ' = ?').join(' AND ');
330+
query += propertiesInfo.filter(p => primaryKeys.has(p.columnName)).map(p => `"${p.columnName}" = ?`).join(' AND ');
331331

332332
if (ifExists === true) {
333333
query += ' IF EXISTS';
@@ -437,9 +437,9 @@ class QueryGenerator {
437437
return `${QueryGenerator._getSingleCondition(columnName, value.value[0])}` +
438438
` ${value.key} ${QueryGenerator._getSingleCondition(columnName, value.value[1])}`;
439439
}
440-
return `${columnName} ${value.key} ?`;
440+
return `"${columnName}" ${value.key} ?`;
441441
}
442-
return `${columnName} = ?`;
442+
return `"${columnName}" = ?`;
443443
}
444444
}
445445

test/unit/mapping/model-mapper-mutation-tests.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('ModelMapper', () => {
3636
.then(() => {
3737
assert.strictEqual(clientInfo.executions.length, 1);
3838
const execution = clientInfo.executions[0];
39-
assert.strictEqual(execution.query, 'INSERT INTO ks1.table1 (id2, id1) VALUES (?, ?)');
39+
assert.strictEqual(execution.query, 'INSERT INTO ks1.table1 ("id2", "id1") VALUES (?, ?)');
4040
assert.deepStrictEqual(execution.params, Object.keys(doc).map(key => doc[key]));
4141
helper.assertProperties(execution.options, { prepare: true, isIdempotent: true });
4242
});
@@ -46,7 +46,7 @@ describe('ModelMapper', () => {
4646
{
4747
doc: { id2: 'value2' , id1: 'value1', name: 'name1' },
4848
docInfo: { ifNotExists: true },
49-
query: 'INSERT INTO ks1.table1 (id2, id1, name) VALUES (?, ?, ?) IF NOT EXISTS',
49+
query: 'INSERT INTO ks1.table1 ("id2", "id1", "name") VALUES (?, ?, ?) IF NOT EXISTS',
5050
params: [ 'value2', 'value1', 'name1' ],
5151
isIdempotent: false
5252
}
@@ -56,7 +56,7 @@ describe('ModelMapper', () => {
5656
{
5757
doc: { id2: 'value2' , id1: 'value1', name: 'name1' },
5858
docInfo: { ttl: 1000 },
59-
query: 'INSERT INTO ks1.table1 (id2, id1, name) VALUES (?, ?, ?) USING TTL ?',
59+
query: 'INSERT INTO ks1.table1 ("id2", "id1", "name") VALUES (?, ?, ?) USING TTL ?',
6060
params: [ 'value2', 'value1', 'name1', 1000 ]
6161
}
6262
]));
@@ -137,7 +137,7 @@ describe('ModelMapper', () => {
137137
items: [
138138
{
139139
doc: { id1: 'value_id1', id2: 'value_id2', name: { prop1: 1, prop2: 'two' } },
140-
query: 'INSERT INTO ks1.table1 (id1, id2, name) VALUES (?, ?, ?)',
140+
query: 'INSERT INTO ks1.table1 ("id1", "id2", "name") VALUES (?, ?, ?)',
141141
params: [ 'value_id1', 'value_id2', '{"prop1":1,"prop2":"two"}']
142142
}
143143
]
@@ -150,7 +150,7 @@ describe('ModelMapper', () => {
150150
it('should retrieve the table that apply and make a single execution', () => testQueries('update', [
151151
{
152152
doc: { id2: 'value2' , id1: 'value1', name: 'name1' },
153-
query: 'UPDATE ks1.table1 SET name = ? WHERE id2 = ? AND id1 = ?',
153+
query: 'UPDATE ks1.table1 SET "name" = ? WHERE "id2" = ? AND "id1" = ?',
154154
params: ['name1', 'value2', 'value1'],
155155
isIdempotent: true
156156
}]));
@@ -159,20 +159,20 @@ describe('ModelMapper', () => {
159159
{
160160
doc: {id2: 'value2', id1: 'value1', name: 'name1'},
161161
docInfo: {when: {name: 'previous name'}},
162-
query: 'UPDATE ks1.table1 SET name = ? WHERE id2 = ? AND id1 = ? IF name = ?',
162+
query: 'UPDATE ks1.table1 SET "name" = ? WHERE "id2" = ? AND "id1" = ? IF "name" = ?',
163163
params: ['name1', 'value2', 'value1', 'previous name'],
164164
isIdempotent: false
165165
}]));
166166

167167
it('should append/prepend to a list', () => testQueries('update', [
168168
{
169169
doc: { id2: 'value2' , id1: 'value1', name: 'name1', list1: q.append(['a', 'b']) },
170-
query: 'UPDATE ks1.table1 SET name = ?, list1 = list1 + ? WHERE id2 = ? AND id1 = ?',
170+
query: 'UPDATE ks1.table1 SET "name" = ?, "list1" = "list1" + ? WHERE "id2" = ? AND "id1" = ?',
171171
params: ['name1', ['a', 'b'], 'value2', 'value1'],
172172
isIdempotent: false
173173
}, {
174174
doc: { id2: 'value2' , id1: 'value1', name: 'name1', list1: q.prepend(['a', 'b']) },
175-
query: 'UPDATE ks1.table1 SET name = ?, list1 = ? + list1 WHERE id2 = ? AND id1 = ?',
175+
query: 'UPDATE ks1.table1 SET "name" = ?, "list1" = ? + "list1" WHERE "id2" = ? AND "id1" = ?',
176176
params: ['name1', ['a', 'b'], 'value2', 'value1'],
177177
isIdempotent: false
178178
}]));
@@ -183,10 +183,10 @@ describe('ModelMapper', () => {
183183
const items = [
184184
{
185185
doc: { id2: 'value2' , id1: 'value1', c1: q.incr(10) },
186-
query: 'UPDATE ks1.table1 SET c1 = c1 + ? WHERE id2 = ? AND id1 = ?'
186+
query: 'UPDATE ks1.table1 SET "c1" = "c1" + ? WHERE "id2" = ? AND "id1" = ?'
187187
}, {
188188
doc: { id2: 'another id 2' , id1: 'another id 1', c1: q.decr(10) },
189-
query: 'UPDATE ks1.table1 SET c1 = c1 - ? WHERE id2 = ? AND id1 = ?'
189+
query: 'UPDATE ks1.table1 SET "c1" = "c1" - ? WHERE "id2" = ? AND "id1" = ?'
190190
}];
191191

192192
return Promise.all(items.map((item, index) => modelMapper.update(item.doc).then(() => {
@@ -226,15 +226,15 @@ describe('ModelMapper', () => {
226226
{
227227
doc: { id2: 'value2', id1: 'value1', name: 'name1', description: 'description1' },
228228
docInfo: { fields: [ 'id1', 'id2', 'description' ] },
229-
query: 'UPDATE ks1.table1 SET description = ? WHERE id1 = ? AND id2 = ?',
229+
query: 'UPDATE ks1.table1 SET "description" = ? WHERE "id1" = ? AND "id2" = ?',
230230
params: ['description1', 'value1', 'value2']
231231
}]));
232232

233233
it('should set TTL', () => testQueries('update', [
234234
{
235235
doc: { id1: 'value_id1', id2: 'value_id2', name: 'value_name1' },
236236
docInfo: { ttl: 360 },
237-
query: 'UPDATE ks1.table1 USING TTL ? SET name = ? WHERE id1 = ? AND id2 = ?',
237+
query: 'UPDATE ks1.table1 USING TTL ? SET "name" = ? WHERE "id1" = ? AND "id2" = ?',
238238
params: [ 360, 'value_name1', 'value_id1', 'value_id2' ]
239239
}
240240
]));
@@ -253,13 +253,13 @@ describe('ModelMapper', () => {
253253
items: [
254254
{
255255
doc: { id1: 'value_id1', id2: 'value_id2', name: { prop1: 1, prop2: 'two' } },
256-
query: 'UPDATE ks1.table1 SET name = ? WHERE id1 = ? AND id2 = ?',
256+
query: 'UPDATE ks1.table1 SET "name" = ? WHERE "id1" = ? AND "id2" = ?',
257257
params: [ '{"prop1":1,"prop2":"two"}', 'value_id1', 'value_id2_suffix' ]
258258
},
259259
{
260260
doc: { id1: 'value_id1', id2: 'value_id2', description: 'my description' },
261261
docInfo: { when: { name: { a: 'a', b: 2 } } },
262-
query: 'UPDATE ks1.table1 SET description = ? WHERE id1 = ? AND id2 = ? IF name = ?',
262+
query: 'UPDATE ks1.table1 SET "description" = ? WHERE "id1" = ? AND "id2" = ? IF "name" = ?',
263263
params: [ 'my description', 'value_id1', 'value_id2_suffix', '{"a":"a","b":2}' ],
264264
isIdempotent: false
265265
}
@@ -294,24 +294,24 @@ describe('ModelMapper', () => {
294294
it('should generate the query, params and set the idempotency', () => testQueries('remove', [
295295
{
296296
doc: { id1: 'x', 'id2': 'y' },
297-
query: 'DELETE FROM ks1.table1 WHERE id1 = ? AND id2 = ?',
297+
query: 'DELETE FROM ks1.table1 WHERE "id1" = ? AND "id2" = ?',
298298
params: [ 'x', 'y' ]
299299
}, {
300300
doc: { id1: 'x', 'id2': 'y' },
301301
docInfo: { when: { name: 'a' }},
302-
query: 'DELETE FROM ks1.table1 WHERE id1 = ? AND id2 = ? IF name = ?',
302+
query: 'DELETE FROM ks1.table1 WHERE "id1" = ? AND "id2" = ? IF "name" = ?',
303303
params: [ 'x', 'y', 'a' ],
304304
isIdempotent: false
305305
}, {
306306
doc: { id1: 'x', 'id2': 'y' },
307307
docInfo: { ifExists: true },
308-
query: 'DELETE FROM ks1.table1 WHERE id1 = ? AND id2 = ? IF EXISTS',
308+
query: 'DELETE FROM ks1.table1 WHERE "id1" = ? AND "id2" = ? IF EXISTS',
309309
params: [ 'x', 'y' ],
310310
isIdempotent: false
311311
}, {
312312
doc: { id1: 'x', 'id2': 'y' },
313313
docInfo: { fields: [ 'id1', 'id2', 'name' ], deleteOnlyColumns: true },
314-
query: 'DELETE name FROM ks1.table1 WHERE id1 = ? AND id2 = ?',
314+
query: 'DELETE "name" FROM ks1.table1 WHERE "id1" = ? AND "id2" = ?',
315315
params: [ 'x', 'y' ]
316316
}
317317
]));
@@ -330,13 +330,13 @@ describe('ModelMapper', () => {
330330
items: [
331331
{
332332
doc: { id1: 'value_id1', id2: 'value_id2' },
333-
query: 'DELETE FROM ks1.table1 WHERE id1 = ? AND id2 = ?',
333+
query: 'DELETE FROM ks1.table1 WHERE "id1" = ? AND "id2" = ?',
334334
params: [ 'value_id1', 'value_id2_suffix' ]
335335
},
336336
{
337337
doc: { id1: 'value_id1', id2: 'value_id2' },
338338
docInfo: { when: { name: { a: 1 } }},
339-
query: 'DELETE FROM ks1.table1 WHERE id1 = ? AND id2 = ? IF name = ?',
339+
query: 'DELETE FROM ks1.table1 WHERE "id1" = ? AND "id2" = ? IF "name" = ?',
340340
params: [ 'value_id1', 'value_id2_suffix', '{"a":1}' ],
341341
isIdempotent: false
342342
},

test/unit/mapping/model-mapper-select-tests.js

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,30 @@ describe('ModelMapper', () => {
3232
{
3333
doc: { id1: 'value1', id2: q.gte('e') },
3434
docInfo: { limit: 100 },
35-
query: 'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 >= ? LIMIT ?',
35+
query: 'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ? LIMIT ?',
3636
params: [ 'value1', 'e', 100 ]
3737
}]));
3838

3939
it('should support fields to specify the selection columns', () => testQueries('find', [
4040
{
4141
doc: { id1: 'value1', id2: q.gte('e') },
4242
docInfo: { fields: ['name', 'description', 'locationType'] },
43-
query: 'SELECT name, description, location_type FROM ks1.table1 WHERE id1 = ? AND id2 >= ?',
43+
query: 'SELECT "name", "description", "location_type" FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ?',
4444
params: [ 'value1', 'e' ]
4545
}]));
4646

4747
it('should support relational operators, orderBy, limit and fields', () => testQueries('find', [
4848
{
4949
doc: {id1: 'value1', id2: q.gte('m')},
50-
query: 'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 >= ?',
50+
query: 'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ?',
5151
params: ['value1', 'm']
5252
}, {
5353
doc: {id1: 'value1', id2: q.and(q.gte('a'), q.lt('z'))},
54-
query: 'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 >= ? AND id2 < ?',
54+
query: 'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ? AND "id2" < ?',
5555
params: ['value1', 'a', 'z']
5656
}, {
5757
doc: {id1: 'value1', id2: q.and(q.gte('a'), q.and(q.gte('e'), q.lt('z')))},
58-
query: 'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 >= ? AND id2 >= ? AND id2 < ?',
58+
query: 'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ? AND "id2" >= ? AND "id2" < ?',
5959
params: ['value1', 'a', 'e', 'z']
6060
}]));
6161

@@ -64,19 +64,19 @@ describe('ModelMapper', () => {
6464
doc: { id1: 'value2' },
6565
docInfo: { orderBy: {'id2': 'desc' }},
6666
query:
67-
'SELECT * FROM ks1.table1 WHERE id1 = ? ORDER BY id2 DESC',
67+
'SELECT * FROM ks1.table1 WHERE "id1" = ? ORDER BY "id2" DESC',
6868
params: [ 'value2' ]
6969
}, {
7070
doc: { id1: 'value3' },
7171
docInfo: { orderBy: {'id2': 'asc' }},
7272
query:
73-
'SELECT * FROM ks1.table1 WHERE id1 = ? ORDER BY id2 ASC',
73+
'SELECT * FROM ks1.table1 WHERE "id1" = ? ORDER BY "id2" ASC',
7474
params: [ 'value3' ]
7575
}, {
7676
doc: { id1: 'value1', id2: q.gte('e') },
7777
docInfo: { fields: ['name'], limit: 20, orderBy: {'id2': 'asc' }},
7878
query:
79-
'SELECT name FROM ks1.table1 WHERE id1 = ? AND id2 >= ? ORDER BY id2 ASC LIMIT ?',
79+
'SELECT "name" FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ? ORDER BY "id2" ASC LIMIT ?',
8080
params: [ 'value1', 'e', 20 ]
8181
}]));
8282

@@ -85,7 +85,7 @@ describe('ModelMapper', () => {
8585
doc: { id1: 'value2' },
8686
docInfo: { orderBy: {'id2': 'asc' }},
8787
query:
88-
'SELECT * FROM ks1.table1 WHERE id1 = ? ORDER BY id2 ASC',
88+
'SELECT * FROM ks1.table1 WHERE "id1" = ? ORDER BY "id2" ASC',
8989
params: [ 'value2' ]
9090
}]));
9191

@@ -108,19 +108,19 @@ describe('ModelMapper', () => {
108108
{
109109
doc: { id1: 'value_id1', id2: 'value_id2' },
110110
query:
111-
'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 = ?',
111+
'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" = ?',
112112
params: [ 'value_id1', 'value_id2' + suffix ]
113113
},
114114
{
115115
doc: { id1: 'value_id1', id2: q.gt('value_id2') },
116116
query:
117-
'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 > ?',
117+
'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" > ?',
118118
params: [ 'value_id1', 'value_id2' + suffix ]
119119
},
120120
{
121121
doc: { id1: 'value_id1', id2: q.and(q.gte('a'), q.lt('z')) },
122122
query:
123-
'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 >= ? AND id2 < ?',
123+
'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" >= ? AND "id2" < ?',
124124
params: [ 'value_id1', 'a' + suffix, 'z' + suffix ]
125125
}
126126
]
@@ -141,7 +141,7 @@ describe('ModelMapper', () => {
141141
{
142142
doc: { id1: 'value_id1', id2: q.in_(['first', 'second']) },
143143
query:
144-
'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 IN ?',
144+
'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" IN ?',
145145
params: [ 'value_id1', ['first_mapped_value', 'second_mapped_value'] ]
146146
}
147147
]
@@ -191,7 +191,7 @@ describe('ModelMapper', () => {
191191

192192
return modelMapper.find({ id1: 'x', id2: 'y'}).then(() => {
193193
const execution = clientInfo.executions[0];
194-
assert.strictEqual(execution.query, 'SELECT * FROM ks1.table1 WHERE id1 = ? AND id2 = ?');
194+
assert.strictEqual(execution.query, 'SELECT * FROM ks1.table1 WHERE "id1" = ? AND "id2" = ?');
195195
});
196196
});
197197

@@ -203,7 +203,7 @@ describe('ModelMapper', () => {
203203

204204
return modelMapper.find({ id1: 'x', id2: 'y'}).then(() => {
205205
const execution = clientInfo.executions[0];
206-
assert.strictEqual(execution.query, 'SELECT * FROM ks1.NoTableSpecified WHERE id1 = ? AND id2 = ?');
206+
assert.strictEqual(execution.query, 'SELECT * FROM ks1.NoTableSpecified WHERE "id1" = ? AND "id2" = ?');
207207
});
208208
});
209209

@@ -234,11 +234,11 @@ describe('ModelMapper', () => {
234234
.then(() => {
235235
[
236236
// Selected "table2" for the first query
237-
'SELECT * FROM ks1.table2 WHERE id1 = ? ORDER BY id3 ASC',
237+
'SELECT * FROM ks1.table2 WHERE "id1" = ? ORDER BY "id3" ASC',
238238
// Selected "table1" for the second query
239-
'SELECT * FROM ks1.table1 WHERE id1 = ? ORDER BY id2 DESC, id3 DESC',
239+
'SELECT * FROM ks1.table1 WHERE "id1" = ? ORDER BY "id2" DESC, "id3" DESC',
240240
// Selected "table1" for the third query
241-
'SELECT * FROM ks1.table1 WHERE id1 = ? ORDER BY id2 ASC'
241+
'SELECT * FROM ks1.table1 WHERE "id1" = ? ORDER BY "id2" ASC'
242242
].forEach((query, index) => {
243243
assert.strictEqual(clientInfo.executions[index].query, query);
244244
assert.deepStrictEqual(clientInfo.executions[index].params, [ 'a' ]);
@@ -279,7 +279,7 @@ describe('ModelMapper', () => {
279279
it('should support fields to specify the selection columns', () => testQueries('findAll', [
280280
{
281281
docInfo: { fields: ['name', 'description', 'locationType'] },
282-
query: 'SELECT name, description, location_type FROM ks1.table1',
282+
query: 'SELECT "name", "description", "location_type" FROM ks1.table1',
283283
params: []
284284
}]));
285285
});

0 commit comments

Comments
 (0)