1 /* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include <gtest/gtest.h>
24 #include <cstddef>
25
26 #include "plugin/x/src/expr_generator.h"
27 #include "unittest/gunit/xplugin/xpl/message_helpers.h"
28 #include "unittest/gunit/xplugin/xpl/mysqlx_pb_wrapper.h"
29
30 namespace xpl {
31 namespace test {
32
33 const char *const EMPTY_SCHEMA = "";
34 const char *const EMPTY = "";
35 enum { DM_DOCUMENT = 0, DM_TABLE = 1 };
36
37 using Octets = Scalar::Octets;
38
TEST(xpl_expr_generator,literal_uint)39 TEST(xpl_expr_generator, literal_uint) {
40 EXPECT_EQ("0", generate_expression(Scalar(static_cast<unsigned>(0)),
41 EMPTY_SCHEMA, DM_TABLE));
42 EXPECT_EQ("1234567890",
43 generate_expression(Scalar(static_cast<unsigned>(1234567890)),
44 EMPTY_SCHEMA, DM_TABLE));
45 EXPECT_NE("-1234567890",
46 generate_expression(Scalar(static_cast<unsigned>(-1234567890)),
47 EMPTY_SCHEMA, DM_TABLE));
48 }
49
TEST(xpl_expr_generator,literal_sint)50 TEST(xpl_expr_generator, literal_sint) {
51 EXPECT_EQ("0", generate_expression(Scalar(0), EMPTY_SCHEMA, DM_TABLE));
52 EXPECT_EQ("1234567890",
53 generate_expression(Scalar(1234567890), EMPTY_SCHEMA, DM_TABLE));
54 EXPECT_EQ("-1234567890",
55 generate_expression(Scalar(-1234567890), EMPTY_SCHEMA, DM_TABLE));
56 }
57
TEST(xpl_expr_generator,literal_null)58 TEST(xpl_expr_generator, literal_null) {
59 EXPECT_EQ("NULL", generate_expression(Scalar(Scalar::Null()), EMPTY_SCHEMA,
60 DM_TABLE));
61 }
62
TEST(xpl_expr_generator,literal_octets)63 TEST(xpl_expr_generator, literal_octets) {
64 EXPECT_EQ("'\\\"test1\\\" \t \\'test2\\''",
65 generate_expression(Scalar("\"test1\" \t 'test2'"), EMPTY_SCHEMA,
66 DM_TABLE));
67 }
68
TEST(xpl_expr_generator,literal_string)69 TEST(xpl_expr_generator, literal_string) {
70 EXPECT_EQ("'\\\"test1\\\" \t \\'test2\\''",
71 generate_expression(Scalar(Scalar::String("\"test1\" \t 'test2'")),
72 EMPTY_SCHEMA, DM_TABLE));
73 }
74
TEST(xpl_expr_generator,literal_double)75 TEST(xpl_expr_generator, literal_double) {
76 EXPECT_EQ("1234567890.123456", generate_expression(Scalar(1234567890.123456),
77 EMPTY_SCHEMA, DM_TABLE)
78 .substr(0, 17));
79 EXPECT_EQ(
80 "-1234567890.123456",
81 generate_expression(Scalar(-1234567890.123456), EMPTY_SCHEMA, DM_TABLE)
82 .substr(0, 18));
83 }
84
TEST(xpl_expr_generator,literal_float)85 TEST(xpl_expr_generator, literal_float) {
86 EXPECT_EQ("1234.12",
87 generate_expression(Scalar(1234.123f), EMPTY_SCHEMA, DM_TABLE)
88 .substr(0, 8));
89 EXPECT_EQ("-1234.12",
90 generate_expression(Scalar(-1234.123f), EMPTY_SCHEMA, DM_TABLE)
91 .substr(0, 9));
92 }
93
TEST(xpl_expr_generator,literal_bool)94 TEST(xpl_expr_generator, literal_bool) {
95 EXPECT_EQ("TRUE", generate_expression(Scalar(true), EMPTY_SCHEMA, DM_TABLE));
96 EXPECT_EQ("FALSE",
97 generate_expression(Scalar(false), EMPTY_SCHEMA, DM_TABLE));
98 }
99
TEST(xpl_expr_generator,invalid_operator)100 TEST(xpl_expr_generator, invalid_operator) {
101 EXPECT_THROW(generate_expression(Operator("some invalid operator"),
102 EMPTY_SCHEMA, DM_TABLE),
103 std::invalid_argument);
104 }
105
TEST(xpl_expr_generator,nullary_operators)106 TEST(xpl_expr_generator, nullary_operators) {
107 EXPECT_EQ("*", generate_expression(Operator("*"), EMPTY_SCHEMA, DM_TABLE));
108 EXPECT_EQ("*", generate_expression(Operator("*"), EMPTY_SCHEMA, DM_DOCUMENT));
109 }
110
TEST(xpl_expr_generator,unary_operators)111 TEST(xpl_expr_generator, unary_operators) {
112 EXPECT_EQ("(NOT TRUE)",
113 generate_expression(Operator("not", true), EMPTY_SCHEMA, DM_TABLE));
114 EXPECT_EQ("(+TRUE)", generate_expression(Operator("sign_plus", true),
115 EMPTY_SCHEMA, DM_TABLE));
116 EXPECT_EQ("(-TRUE)", generate_expression(Operator("sign_minus", true),
117 EMPTY_SCHEMA, DM_TABLE));
118 EXPECT_EQ("(!TRUE)",
119 generate_expression(Operator("!", true), EMPTY_SCHEMA, DM_TABLE));
120 EXPECT_THROW(generate_expression(Operator("!"), EMPTY_SCHEMA, DM_TABLE),
121 std::invalid_argument);
122 EXPECT_THROW(
123 generate_expression(Operator("!", true, true), EMPTY_SCHEMA, DM_TABLE),
124 std::invalid_argument);
125 }
126
TEST(xpl_expr_generator,binary_operators)127 TEST(xpl_expr_generator, binary_operators) {
128 EXPECT_EQ("(TRUE AND TRUE)", generate_expression(Operator("&&", true, true),
129 EMPTY_SCHEMA, DM_TABLE));
130 EXPECT_EQ("(TRUE OR TRUE)", generate_expression(Operator("||", true, true),
131 EMPTY_SCHEMA, DM_TABLE));
132 EXPECT_EQ("(TRUE XOR TRUE)", generate_expression(Operator("xor", true, true),
133 EMPTY_SCHEMA, DM_TABLE));
134 EXPECT_EQ("(TRUE = TRUE)", generate_expression(Operator("==", true, true),
135 EMPTY_SCHEMA, DM_TABLE));
136 EXPECT_EQ("(TRUE != TRUE)", generate_expression(Operator("!=", true, true),
137 EMPTY_SCHEMA, DM_TABLE));
138 EXPECT_EQ("(TRUE >= TRUE)", generate_expression(Operator(">=", true, true),
139 EMPTY_SCHEMA, DM_TABLE));
140 EXPECT_EQ("(TRUE > TRUE)", generate_expression(Operator(">", true, true),
141 EMPTY_SCHEMA, DM_TABLE));
142 EXPECT_EQ("(TRUE <= TRUE)", generate_expression(Operator("<=", true, true),
143 EMPTY_SCHEMA, DM_TABLE));
144 EXPECT_EQ("(TRUE < TRUE)", generate_expression(Operator("<", true, true),
145 EMPTY_SCHEMA, DM_TABLE));
146 EXPECT_EQ("(TRUE & TRUE)", generate_expression(Operator("&", true, true),
147 EMPTY_SCHEMA, DM_TABLE));
148 EXPECT_EQ("(TRUE | TRUE)", generate_expression(Operator("|", true, true),
149 EMPTY_SCHEMA, DM_TABLE));
150 EXPECT_EQ("(TRUE ^ TRUE)", generate_expression(Operator("^", true, true),
151 EMPTY_SCHEMA, DM_TABLE));
152 EXPECT_EQ("(TRUE << TRUE)", generate_expression(Operator("<<", true, true),
153 EMPTY_SCHEMA, DM_TABLE));
154 EXPECT_EQ("(TRUE >> TRUE)", generate_expression(Operator(">>", true, true),
155 EMPTY_SCHEMA, DM_TABLE));
156 EXPECT_EQ("(TRUE + TRUE)", generate_expression(Operator("+", true, true),
157 EMPTY_SCHEMA, DM_TABLE));
158 EXPECT_EQ("(TRUE - TRUE)", generate_expression(Operator("-", true, true),
159 EMPTY_SCHEMA, DM_TABLE));
160 EXPECT_EQ("(TRUE * TRUE)", generate_expression(Operator("*", true, true),
161 EMPTY_SCHEMA, DM_TABLE));
162 EXPECT_EQ("(TRUE / TRUE)", generate_expression(Operator("/", true, true),
163 EMPTY_SCHEMA, DM_TABLE));
164 EXPECT_EQ("(4 DIV 2)",
165 generate_expression(Operator("div", 4, 2), EMPTY_SCHEMA, DM_TABLE));
166 EXPECT_EQ("(TRUE % TRUE)", generate_expression(Operator("%", true, true),
167 EMPTY_SCHEMA, DM_TABLE));
168 EXPECT_EQ("(TRUE IS TRUE)", generate_expression(Operator("is", true, true),
169 EMPTY_SCHEMA, DM_TABLE));
170 EXPECT_EQ("(TRUE IS NOT TRUE)",
171 generate_expression(Operator("is_not", true, true), EMPTY_SCHEMA,
172 DM_TABLE));
173 EXPECT_EQ("(TRUE REGEXP TRUE)",
174 generate_expression(Operator("regexp", true, true), EMPTY_SCHEMA,
175 DM_TABLE));
176 EXPECT_EQ("(TRUE NOT REGEXP TRUE)",
177 generate_expression(Operator("not_regexp", true, true),
178 EMPTY_SCHEMA, DM_TABLE));
179 EXPECT_THROW(generate_expression(Operator("+"), EMPTY_SCHEMA, DM_TABLE),
180 std::invalid_argument);
181 EXPECT_THROW(generate_expression(Operator("+", true), EMPTY_SCHEMA, DM_TABLE),
182 std::invalid_argument);
183 EXPECT_THROW(generate_expression(Operator("+", true, true, true),
184 EMPTY_SCHEMA, DM_TABLE),
185 std::invalid_argument);
186 }
187
TEST(xpl_expr_generator,identifier)188 TEST(xpl_expr_generator, identifier) {
189 EXPECT_EQ("` schema \"'`.` table \"'`",
190 generate_expression(Identifier(" table \"'"), " schema \"'", true));
191 EXPECT_EQ("` schema \"'`.` table \"'`",
192 generate_expression(Identifier(" table \"'", " schema \"'"),
193 EMPTY_SCHEMA, DM_TABLE));
194 }
195
TEST(xpl_expr_generator,variable)196 TEST(xpl_expr_generator, variable) {
197 // EXPECT_EQ("@`'variable``\"`",
198 // generate_expression(Expr(Variable("'variable`\""))));
199 EXPECT_THROW(generate_expression(Expr(Variable("'variable`\"")), EMPTY_SCHEMA,
200 DM_TABLE),
201 Expression_generator::Error);
202 }
203
TEST(xpl_expr_generator,column_identifier)204 TEST(xpl_expr_generator, column_identifier) {
205 Document_path doc_path{"docpath \"'"};
206
207 EXPECT_EQ("`column ``\"'`",
208 generate_expression(Column_identifier("column `\"'"), EMPTY_SCHEMA,
209 DM_TABLE));
210 EXPECT_EQ("`table ``\"'`.`column ``\"'`",
211 generate_expression(Column_identifier("column `\"'", "table `\"'"),
212 EMPTY_SCHEMA, DM_TABLE));
213 EXPECT_EQ("`schema ``\"'`.`table ``\"'`.`column ``\"'`",
214 generate_expression(
215 Column_identifier("column `\"'", "table `\"'", "schema `\"'"),
216 EMPTY_SCHEMA, DM_TABLE));
217 EXPECT_EQ(
218 "JSON_EXTRACT(doc,'$.\\\"docpath \\\\\\\"\\'\\\"')",
219 generate_expression(Column_identifier(doc_path, EMPTY, EMPTY, EMPTY),
220 EMPTY_SCHEMA, DM_TABLE));
221 EXPECT_EQ("JSON_EXTRACT(`\"'`` column`,'$.\\\"docpath \\\\\\\"\\'\\\"')",
222 generate_expression(
223 Column_identifier(doc_path, "\"'` column", EMPTY, EMPTY),
224 EMPTY_SCHEMA, DM_TABLE));
225 EXPECT_EQ(
226 "JSON_EXTRACT(`\"'`` table`.`\"'`` column`,'$.\\\"docpath "
227 "\\\\\\\"\\'\\\"')",
228 generate_expression(
229 Column_identifier(doc_path, "\"'` column", "\"'` table", EMPTY),
230 EMPTY_SCHEMA, DM_TABLE));
231 EXPECT_EQ(
232 "JSON_EXTRACT(`\"'`` schema`.`\"'`` table`."
233 "`\"'`` column`,'$.\\\"docpath \\\\\\\"\\'\\\"')",
234 generate_expression(Column_identifier(doc_path, "\"'` column",
235 "\"'` table", "\"'` schema"),
236 EMPTY_SCHEMA, DM_TABLE));
237 EXPECT_THROW(generate_expression(Column_identifier(EMPTY, "table"),
238 EMPTY_SCHEMA, DM_TABLE),
239 std::invalid_argument);
240 EXPECT_THROW(generate_expression(Column_identifier("column", EMPTY, "schema"),
241 EMPTY_SCHEMA, DM_TABLE),
242 std::invalid_argument);
243 }
244
TEST(xpl_expr_generator,column_identifier_empty)245 TEST(xpl_expr_generator, column_identifier_empty) {
246 Column_identifier ident{EMPTY, EMPTY, EMPTY};
247 EXPECT_EQ("JSON_EXTRACT(doc,'$')",
248 generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT));
249 EXPECT_THROW(generate_expression(ident, EMPTY_SCHEMA, DM_TABLE),
250 std::invalid_argument);
251 }
252
TEST(xpl_expr_generator,column_identifier_doc_id)253 TEST(xpl_expr_generator, column_identifier_doc_id) {
254 Column_identifier ident(Document_path{"_id"});
255 ASSERT_EQ("JSON_EXTRACT(doc,'$._id')",
256 generate_expression(ident, EMPTY_SCHEMA, DM_TABLE));
257 ASSERT_EQ("JSON_EXTRACT(doc,'$._id')",
258 generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT));
259 }
260
TEST(xpl_expr_generator,column_identifier_doc_id_names)261 TEST(xpl_expr_generator, column_identifier_doc_id_names) {
262 Column_identifier ident(Document_path{"_id"}, "field", "table", "schema");
263 ASSERT_EQ("JSON_EXTRACT(`schema`.`table`.`field`,'$._id')",
264 generate_expression(ident, EMPTY_SCHEMA, DM_TABLE));
265 ASSERT_EQ("JSON_EXTRACT(`schema`.`table`.`field`,'$._id')",
266 generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT));
267 }
268
TEST(xpl_expr_generator,column_identifier_no_column)269 TEST(xpl_expr_generator, column_identifier_no_column) {
270 Column_identifier ident(EMPTY, "table");
271 ASSERT_THROW(generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT),
272 Expression_generator::Error);
273
274 ASSERT_THROW(generate_expression(ident, EMPTY_SCHEMA, DM_TABLE),
275 Expression_generator::Error);
276
277 Column_identifier ident2(Document_path{"member"}, EMPTY, "table", EMPTY);
278 ASSERT_EQ("JSON_EXTRACT(`table`.doc,'$.member')",
279 generate_expression(ident2, EMPTY_SCHEMA, DM_DOCUMENT));
280 }
281
TEST(xpl_expr_generator,interval_expression)282 TEST(xpl_expr_generator, interval_expression) {
283 EXPECT_EQ("DATE_ADD(FALSE, INTERVAL TRUE MICROSECOND)",
284 generate_expression(
285 Operator("date_add", false, true, Octets{"MICROSECOND"}),
286 EMPTY_SCHEMA, DM_TABLE));
287 EXPECT_EQ(
288 "DATE_SUB(FALSE, INTERVAL TRUE SECOND)",
289 generate_expression(Operator("date_sub", false, true, Octets{"SECOND"}),
290 EMPTY_SCHEMA, DM_TABLE));
291 EXPECT_EQ(
292 "DATE_SUB(FALSE, INTERVAL TRUE MINUTE)",
293 generate_expression(Operator("date_sub", false, true, Octets{"MINUTE"}),
294 EMPTY_SCHEMA, DM_TABLE));
295 EXPECT_EQ(
296 "DATE_SUB(FALSE, INTERVAL TRUE HOUR)",
297 generate_expression(Operator("date_sub", false, true, Octets{"HOUR"}),
298 EMPTY_SCHEMA, DM_TABLE));
299 EXPECT_EQ(
300 "DATE_SUB(FALSE, INTERVAL TRUE DAY)",
301 generate_expression(Operator("date_sub", false, true, Octets{"DAY"}),
302 EMPTY_SCHEMA, DM_TABLE));
303 EXPECT_EQ(
304 "DATE_SUB(FALSE, INTERVAL TRUE WEEK)",
305 generate_expression(Operator("date_sub", false, true, Octets{"WEEK"}),
306 EMPTY_SCHEMA, DM_TABLE));
307 EXPECT_EQ(
308 "DATE_SUB(FALSE, INTERVAL TRUE MONTH)",
309 generate_expression(Operator("date_sub", false, true, Octets{"MONTH"}),
310 EMPTY_SCHEMA, DM_TABLE));
311 EXPECT_EQ(
312 "DATE_SUB(FALSE, INTERVAL TRUE QUARTER)",
313 generate_expression(Operator("date_sub", false, true, Octets{"QUARTER"}),
314 EMPTY_SCHEMA, DM_TABLE));
315 EXPECT_EQ(
316 "DATE_SUB(FALSE, INTERVAL TRUE YEAR)",
317 generate_expression(Operator("date_sub", false, true, Octets{"YEAR"}),
318 EMPTY_SCHEMA, DM_TABLE));
319 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE SECOND_MICROSECOND)",
320 generate_expression(
321 Operator("date_sub", false, true, Octets{"SECOND_MICROSECOND"}),
322 EMPTY_SCHEMA, DM_TABLE));
323 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE MINUTE_MICROSECOND)",
324 generate_expression(
325 Operator("date_sub", false, true, Octets{"MINUTE_MICROSECOND"}),
326 EMPTY_SCHEMA, DM_TABLE));
327 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE MINUTE_SECOND)",
328 generate_expression(
329 Operator("date_sub", false, true, Octets{"MINUTE_SECOND"}),
330 EMPTY_SCHEMA, DM_TABLE));
331 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE HOUR_MICROSECOND)",
332 generate_expression(
333 Operator("date_sub", false, true, Octets{"HOUR_MICROSECOND"}),
334 EMPTY_SCHEMA, DM_TABLE));
335 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE HOUR_SECOND)",
336 generate_expression(
337 Operator("date_sub", false, true, Octets{"HOUR_SECOND"}),
338 EMPTY_SCHEMA, DM_TABLE));
339 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE HOUR_MINUTE)",
340 generate_expression(
341 Operator("date_sub", false, true, Octets{"HOUR_MINUTE"}),
342 EMPTY_SCHEMA, DM_TABLE));
343 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE DAY_MICROSECOND)",
344 generate_expression(
345 Operator("date_sub", false, true, Octets{"DAY_MICROSECOND"}),
346 EMPTY_SCHEMA, DM_TABLE));
347 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE DAY_SECOND)",
348 generate_expression(
349 Operator("date_sub", false, true, Octets{"DAY_SECOND"}),
350 EMPTY_SCHEMA, DM_TABLE));
351 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE DAY_MINUTE)",
352 generate_expression(
353 Operator("date_sub", false, true, Octets{"DAY_MINUTE"}),
354 EMPTY_SCHEMA, DM_TABLE));
355 EXPECT_EQ(
356 "DATE_SUB(FALSE, INTERVAL TRUE DAY_HOUR)",
357 generate_expression(Operator("date_sub", false, true, Octets{"DAY_HOUR"}),
358 EMPTY_SCHEMA, DM_TABLE));
359 EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE YEAR_MONTH)",
360 generate_expression(
361 Operator("date_sub", false, true, Octets{"YEAR_MONTH"}),
362 EMPTY_SCHEMA, DM_TABLE));
363 EXPECT_THROW(
364 generate_expression(Operator("date_sub", false, true, "invalid unit"),
365 EMPTY_SCHEMA, DM_TABLE),
366 std::invalid_argument);
367 EXPECT_THROW(
368 generate_expression(Operator("date_sub", false, true, true, true),
369 EMPTY_SCHEMA, DM_TABLE),
370 std::invalid_argument);
371 }
372
TEST(xpl_expr_generator,in_expression)373 TEST(xpl_expr_generator, in_expression) {
374 EXPECT_EQ(
375 "(FALSE IN (TRUE))",
376 generate_expression(Operator("in", false, true), EMPTY_SCHEMA, DM_TABLE));
377 EXPECT_EQ("(FALSE NOT IN (TRUE))",
378 generate_expression(Operator("not_in", false, true), EMPTY_SCHEMA,
379 DM_TABLE));
380 EXPECT_EQ("(FALSE IN (TRUE,FALSE))",
381 generate_expression(Operator("in", false, true, false),
382 EMPTY_SCHEMA, DM_TABLE));
383 EXPECT_EQ("(FALSE NOT IN (TRUE,FALSE))",
384 generate_expression(Operator("not_in", false, true, false),
385 EMPTY_SCHEMA, DM_TABLE));
386 EXPECT_THROW(
387 generate_expression(Operator("in", false), EMPTY_SCHEMA, DM_TABLE),
388 std::invalid_argument);
389 }
390
TEST(xpl_expr_generator,between_expression)391 TEST(xpl_expr_generator, between_expression) {
392 EXPECT_EQ("(2 BETWEEN 1 AND 3)",
393 generate_expression(Operator("between", 2, 1, 3), EMPTY_SCHEMA,
394 DM_TABLE));
395 EXPECT_EQ("(2 NOT BETWEEN 1 AND 3)",
396 generate_expression(Operator("not_between", 2, 1, 3), EMPTY_SCHEMA,
397 DM_TABLE));
398 EXPECT_THROW(
399 generate_expression(Operator("between", 0, 0), EMPTY_SCHEMA, DM_TABLE),
400 std::invalid_argument);
401 EXPECT_THROW(generate_expression(Operator("between", 0, 0, 0, 0),
402 EMPTY_SCHEMA, DM_TABLE),
403 std::invalid_argument);
404 }
405
TEST(xpl_expr_generator,like_expression)406 TEST(xpl_expr_generator, like_expression) {
407 EXPECT_EQ("(TRUE LIKE FALSE)",
408 generate_expression(Operator("like", true, false), EMPTY_SCHEMA,
409 DM_TABLE));
410 EXPECT_EQ("(TRUE NOT LIKE FALSE)",
411 generate_expression(Operator("not_like", true, false), EMPTY_SCHEMA,
412 DM_TABLE));
413 EXPECT_EQ("(TRUE LIKE FALSE ESCAPE TRUE)",
414 generate_expression(Operator("like", true, false, true),
415 EMPTY_SCHEMA, DM_TABLE));
416 EXPECT_THROW(
417 generate_expression(Operator("like", true), EMPTY_SCHEMA, DM_TABLE),
418 std::invalid_argument);
419 EXPECT_THROW(generate_expression(Operator("like", true, true, true, true),
420 EMPTY_SCHEMA, DM_TABLE),
421 std::invalid_argument);
422 }
423
TEST(xpl_expr_generator,complex_expressions)424 TEST(xpl_expr_generator, complex_expressions) {
425 EXPECT_EQ("(`schema`.`ident``` NOT LIKE 'string\\'' ESCAPE 'x')",
426 generate_expression(
427 Expr(Operator("not_like", Column_identifier("ident`", "schema"),
428 "string'", "x")),
429 EMPTY_SCHEMA, DM_TABLE));
430
431 EXPECT_EQ("((1 * 2) % (3 / 4))",
432 generate_expression(
433 Expr(Operator("%", Operator("*", 1, 2), Operator("/", 3, 4))),
434 EMPTY_SCHEMA, DM_TABLE));
435
436 EXPECT_EQ("(`schema`.func(5,FALSE) IN (1,(+2),(-(7 - 0))))",
437 generate_expression(
438 Expr(Operator(
439 "in", Function_call(Identifier("func", "schema"), 5, false),
440 1, Operator("sign_plus", 2),
441 Operator("sign_minus", Operator("-", 7, 0)))),
442 EMPTY_SCHEMA, DM_TABLE));
443 }
444
TEST(xpl_expr_generator,document_path_root)445 TEST(xpl_expr_generator, document_path_root) {
446 EXPECT_EQ("'$'", generate_expression(Document_path(Document_path()),
447 EMPTY_SCHEMA, DM_TABLE));
448 }
449
TEST(xpl_expr_generator,document_path_empty_member)450 TEST(xpl_expr_generator, document_path_empty_member) {
451 EXPECT_THROW(
452 generate_expression(Document_path{EMPTY, "name"}, EMPTY_SCHEMA, DM_TABLE),
453 Expression_generator::Error);
454 }
455
TEST(xpl_expr_generator,document_path_empty_member_opposite)456 TEST(xpl_expr_generator, document_path_empty_member_opposite) {
457 EXPECT_THROW(
458 generate_expression(Document_path{"name", EMPTY}, EMPTY_SCHEMA, DM_TABLE),
459 Expression_generator::Error);
460 }
461
TEST(xpl_expr_generator,document_path_array)462 TEST(xpl_expr_generator, document_path_array) {
463 Document_path path;
464 EXPECT_EQ("'$.name[42]'", generate_expression(Document_path{"name", 42},
465 EMPTY_SCHEMA, DM_TABLE));
466 }
467
TEST(xpl_expr_generator,document_path_root_array)468 TEST(xpl_expr_generator, document_path_root_array) {
469 Document_path path;
470 EXPECT_EQ("'$[42]'",
471 generate_expression(Document_path{42}, EMPTY_SCHEMA, DM_TABLE));
472 }
473
TEST(xpl_expr_generator,document_path_member_asterisk)474 TEST(xpl_expr_generator, document_path_member_asterisk) {
475 EXPECT_EQ(
476 "'$.name.*'",
477 generate_expression(
478 Document_path{"name", Document_path_item::Base::MEMBER_ASTERISK},
479 EMPTY_SCHEMA, DM_TABLE));
480 }
481
TEST(xpl_expr_generator,document_path_root_asterisk)482 TEST(xpl_expr_generator, document_path_root_asterisk) {
483 EXPECT_EQ("'$.*'",
484 generate_expression(
485 Document_path{Document_path_item::Base::MEMBER_ASTERISK},
486 EMPTY_SCHEMA, DM_TABLE));
487 }
488
TEST(xpl_expr_generator,document_path_double_asterisk)489 TEST(xpl_expr_generator, document_path_double_asterisk) {
490 EXPECT_EQ(
491 "'$.name**'",
492 generate_expression(
493 Document_path{"name", Document_path_item::Base::DOUBLE_ASTERISK},
494 EMPTY_SCHEMA, DM_TABLE));
495 }
496
TEST(xpl_expr_generator,document_path_array_index)497 TEST(xpl_expr_generator, document_path_array_index) {
498 EXPECT_EQ("'$.name[42]'", generate_expression(Document_path{"name", 42},
499 EMPTY_SCHEMA, DM_TABLE));
500 }
501
TEST(xpl_expr_generator,document_path_root_array_index)502 TEST(xpl_expr_generator, document_path_root_array_index) {
503 EXPECT_EQ("'$[42]'",
504 generate_expression(Document_path{42}, EMPTY_SCHEMA, DM_TABLE));
505 }
506
TEST(xpl_expr_generator,document_path_array_index_asterisk)507 TEST(xpl_expr_generator, document_path_array_index_asterisk) {
508 EXPECT_STREQ(
509 "'$.name[*]'",
510 generate_expression(
511 Document_path{"name", Document_path_item::Base::ARRAY_INDEX_ASTERISK},
512 EMPTY_SCHEMA, DM_TABLE)
513 .c_str());
514 }
515
TEST(xpl_expr_generator,document_path_root_array_index_asterisk)516 TEST(xpl_expr_generator, document_path_root_array_index_asterisk) {
517 EXPECT_STREQ(
518 "'$[*]'",
519 generate_expression(
520 Document_path{Document_path_item::Base::ARRAY_INDEX_ASTERISK},
521 EMPTY_SCHEMA, DM_TABLE)
522 .c_str());
523 }
524
TEST(xpl_expr_generator,document_path_root_double_asterisk)525 TEST(xpl_expr_generator, document_path_root_double_asterisk) {
526 EXPECT_EQ("'$**'",
527 generate_expression(
528 Document_path{Document_path_item::Base::DOUBLE_ASTERISK},
529 EMPTY_SCHEMA, DM_TABLE));
530 }
531
TEST(xpl_expr_generator,placeholder_not_found)532 TEST(xpl_expr_generator, placeholder_not_found) {
533 EXPECT_THROW(generate_expression(Expr(Placeholder{10}), Expression_list(),
534 EMPTY_SCHEMA, DM_TABLE),
535 Expression_generator::Error);
536 }
537
TEST(xpl_expr_generator,placeholder_found)538 TEST(xpl_expr_generator, placeholder_found) {
539 EXPECT_EQ("2", generate_expression(Expr(Placeholder{0}), Expression_list{2},
540 EMPTY_SCHEMA, DM_TABLE));
541 }
542
TEST(xpl_expr_generator,placeholder_opearator_one_arg)543 TEST(xpl_expr_generator, placeholder_opearator_one_arg) {
544 EXPECT_EQ("(1 + 2)",
545 generate_expression(Operator("+", 1, Placeholder{0}),
546 Expression_list{2}, EMPTY_SCHEMA, DM_TABLE));
547 }
548
TEST(xpl_expr_generator,placeholder_opearator_two_args)549 TEST(xpl_expr_generator, placeholder_opearator_two_args) {
550 EXPECT_EQ("(1 + 2)",
551 generate_expression(Operator("+", Placeholder{1}, Placeholder{0}),
552 Expression_list{2, 1}, EMPTY_SCHEMA, DM_TABLE));
553 }
554
TEST(xpl_expr_generator,placeholder_function)555 TEST(xpl_expr_generator, placeholder_function) {
556 EXPECT_EQ(
557 "xschema.bar(42,'foo')",
558 generate_expression(Function_call("bar", Placeholder{0}, Placeholder{1}),
559 Expression_list{42, "foo"}, "xschema", true));
560 }
561
TEST(xpl_expr_generator,placeholder_function_and_operator)562 TEST(xpl_expr_generator, placeholder_function_and_operator) {
563 EXPECT_EQ(
564 "(xschema.bar(42,'foo') > 42)",
565 generate_expression(
566 Operator(">", Function_call("bar", Placeholder{0}, Placeholder{1}),
567 Placeholder{0}),
568 Expression_list{42, "foo"}, "xschema", true));
569 }
570
TEST(xpl_expr_generator,placeholder_operator_null)571 TEST(xpl_expr_generator, placeholder_operator_null) {
572 EXPECT_EQ("(`bar` IS NOT NULL)",
573 generate_expression(
574 Operator("is_not", Column_identifier("bar"), Placeholder{0}),
575 Expression_list{Scalar::Null()}, EMPTY_SCHEMA, DM_TABLE));
576 }
577
TEST(xpl_expr_generator,cast_missing_param)578 TEST(xpl_expr_generator, cast_missing_param) {
579 EXPECT_THROW(
580 generate_expression(Operator("cast", 42), EMPTY_SCHEMA, DM_TABLE),
581 Expression_generator::Error);
582 }
583
TEST(xpl_expr_generator,cast_empty_type)584 TEST(xpl_expr_generator, cast_empty_type) {
585 EXPECT_THROW(
586 generate_expression(Operator("cast", 42), EMPTY_SCHEMA, DM_TABLE),
587 Expression_generator::Error);
588 }
589
TEST(xpl_expr_generator,cast_invalid_target_type)590 TEST(xpl_expr_generator, cast_invalid_target_type) {
591 EXPECT_THROW(
592 generate_expression(Operator("cast", 42, 44), EMPTY_SCHEMA, DM_TABLE),
593 Expression_generator::Error);
594 }
595
TEST(xpl_expr_generator,cast_scalar_to_undefinied)596 TEST(xpl_expr_generator, cast_scalar_to_undefinied) {
597 EXPECT_THROW(generate_expression(Operator("cast", 42, Octets("UNDEFINIED")),
598 EMPTY_SCHEMA, DM_TABLE),
599 Expression_generator::Error);
600 }
601
TEST(xpl_expr_generator,cast_expr_to_json)602 TEST(xpl_expr_generator, cast_expr_to_json) {
603 EXPECT_EQ(
604 "CAST(`foo`.`bar` AS JSON)",
605 generate_expression(
606 Operator("cast", Column_identifier("bar", "foo"), Octets{"JSON"}),
607 EMPTY_SCHEMA, DM_TABLE));
608 }
609
TEST(xpl_expr_generator,cast_scalar_to_signed)610 TEST(xpl_expr_generator, cast_scalar_to_signed) {
611 EXPECT_EQ("CAST(42 AS SIGNED)",
612 generate_expression(Operator("cast", 42, Octets{"SIGNED"}),
613 EMPTY_SCHEMA, DM_TABLE));
614 }
615
TEST(xpl_expr_generator,cast_scalar_to_signed_integer)616 TEST(xpl_expr_generator, cast_scalar_to_signed_integer) {
617 EXPECT_EQ("CAST(42 AS SIGNED INTEGER)",
618 generate_expression(Operator("cast", 42, Octets{"SIGNED INTEGER"}),
619 EMPTY_SCHEMA, DM_TABLE));
620 }
621
TEST(xpl_expr_generator,cast_scalar_to_unsigned)622 TEST(xpl_expr_generator, cast_scalar_to_unsigned) {
623 EXPECT_EQ("CAST(42 AS UNSIGNED)",
624 generate_expression(Operator("cast", 42, Octets{"UNSIGNED"}),
625 EMPTY_SCHEMA, DM_TABLE));
626 }
627
TEST(xpl_expr_generator,cast_scalar_to_unsigned_integer)628 TEST(xpl_expr_generator, cast_scalar_to_unsigned_integer) {
629 EXPECT_EQ(
630 "CAST(42 AS UNSIGNED INTEGER)",
631 generate_expression(Operator("cast", 42, Octets{"UNSIGNED INTEGER"}),
632 EMPTY_SCHEMA, DM_TABLE));
633 }
634
TEST(xpl_expr_generator,cast_scalar_to_char)635 TEST(xpl_expr_generator, cast_scalar_to_char) {
636 EXPECT_EQ("CAST('one' AS CHAR)",
637 generate_expression(Operator("cast", "one", Octets{"CHAR"}),
638 EMPTY_SCHEMA, DM_TABLE));
639 }
640
TEST(xpl_expr_generator,cast_scalar_to_multichar)641 TEST(xpl_expr_generator, cast_scalar_to_multichar) {
642 EXPECT_EQ("CAST('one' AS CHAR(42))",
643 generate_expression(Operator("cast", "one", Octets{"CHAR(42)"}),
644 EMPTY_SCHEMA, DM_TABLE));
645 }
646
TEST(xpl_expr_generator,cast_scalar_to_binary)647 TEST(xpl_expr_generator, cast_scalar_to_binary) {
648 EXPECT_EQ("CAST('one' AS BINARY)",
649 generate_expression(Operator("cast", "one", Octets{"BINARY"}),
650 EMPTY_SCHEMA, DM_TABLE));
651 }
652
TEST(xpl_expr_generator,cast_scalar_to_binary_lowercase)653 TEST(xpl_expr_generator, cast_scalar_to_binary_lowercase) {
654 EXPECT_EQ("CAST('one' AS binary)",
655 generate_expression(Operator("cast", "one", Octets("binary")),
656 EMPTY_SCHEMA, DM_TABLE));
657 }
658
TEST(xpl_expr_generator,cast_scalar_to_precision_binary)659 TEST(xpl_expr_generator, cast_scalar_to_precision_binary) {
660 EXPECT_EQ("CAST('one' AS BINARY(44))",
661 generate_expression(Operator("cast", "one", Octets("BINARY(44)")),
662 EMPTY_SCHEMA, DM_TABLE));
663 }
664
TEST(xpl_expr_generator,cast_scalar_to_decimal)665 TEST(xpl_expr_generator, cast_scalar_to_decimal) {
666 EXPECT_EQ("CAST(3.141593 AS DECIMAL)",
667 generate_expression(Operator("cast", 3.141593, Octets("DECIMAL")),
668 EMPTY_SCHEMA, DM_TABLE));
669 }
670
TEST(xpl_expr_generator,cast_scalar_to_precision_decimal)671 TEST(xpl_expr_generator, cast_scalar_to_precision_decimal) {
672 EXPECT_EQ(
673 "CAST(3.141593 AS DECIMAL(4))",
674 generate_expression(Operator("cast", 3.141593, Octets("DECIMAL(4)")),
675 EMPTY_SCHEMA, DM_TABLE));
676 }
677
TEST(xpl_expr_generator,cast_scalar_to_precision_scale_decimal)678 TEST(xpl_expr_generator, cast_scalar_to_precision_scale_decimal) {
679 EXPECT_EQ(
680 "CAST(3.141593 AS DECIMAL(4,2))",
681 generate_expression(Operator("cast", 3.141593, Octets("DECIMAL(4,2)")),
682 EMPTY_SCHEMA, DM_TABLE));
683 }
684
TEST(xpl_expr_generator,cast_scalar_to_time)685 TEST(xpl_expr_generator, cast_scalar_to_time) {
686 EXPECT_EQ("CAST('3:14' AS TIME)",
687 generate_expression(Operator("cast", "3:14", Octets("TIME")),
688 EMPTY_SCHEMA, DM_TABLE));
689 }
690
TEST(xpl_expr_generator,cast_scalar_to_date)691 TEST(xpl_expr_generator, cast_scalar_to_date) {
692 EXPECT_EQ("CAST('2015.08.10' AS DATE)",
693 generate_expression(Operator("cast", "2015.08.10", Octets("DATE")),
694 EMPTY_SCHEMA, DM_TABLE));
695 }
696
TEST(xpl_expr_generator,cast_scalar_to_datetime)697 TEST(xpl_expr_generator, cast_scalar_to_datetime) {
698 EXPECT_EQ("CAST('2015.08.10T3:14' AS DATETIME)",
699 generate_expression(
700 Operator("cast", "2015.08.10T3:14", Octets("DATETIME")),
701 EMPTY_SCHEMA, DM_TABLE));
702 }
703
TEST(xpl_expr_generator,cast_placeholder_to_json)704 TEST(xpl_expr_generator, cast_placeholder_to_json) {
705 Expression_generator::Prep_stmt_placeholder_list ids;
706 EXPECT_EQ(
707 "CAST(? AS JSON)",
708 generate_expression(Operator("cast", Placeholder(0), Octets("JSON")),
709 EMPTY_SCHEMA, DM_TABLE, &ids));
710 EXPECT_EQ(1, ids.size());
711 }
712
TEST(xpl_expr_generator,object_empty)713 TEST(xpl_expr_generator, object_empty) {
714 EXPECT_EQ("JSON_OBJECT()",
715 generate_expression(Object(), EMPTY_SCHEMA, DM_TABLE));
716 }
717
TEST(xpl_expr_generator,object_empty_key)718 TEST(xpl_expr_generator, object_empty_key) {
719 EXPECT_THROW(generate_expression(Object{{"", 1}}, EMPTY_SCHEMA, DM_TABLE),
720 Expression_generator::Error);
721 }
722
TEST(xpl_expr_generator,object_empty_value)723 TEST(xpl_expr_generator, object_empty_value) {
724 EXPECT_THROW(
725 generate_expression(Object("first", nullptr), EMPTY_SCHEMA, DM_TABLE),
726 Expression_generator::Error);
727 }
728
TEST(xpl_expr_generator,object_one_scalar)729 TEST(xpl_expr_generator, object_one_scalar) {
730 EXPECT_EQ("JSON_OBJECT('first',1)",
731 generate_expression(Object{{"first", 1}}, EMPTY_SCHEMA, DM_TABLE));
732 }
733
TEST(xpl_expr_generator,object_two_scalars)734 TEST(xpl_expr_generator, object_two_scalars) {
735 EXPECT_EQ("JSON_OBJECT('first',1,'second','two')",
736 generate_expression(Object{{"first", 1}, {"second", "two"}},
737 EMPTY_SCHEMA, DM_TABLE));
738 }
739
TEST(xpl_expr_generator,object_object)740 TEST(xpl_expr_generator, object_object) {
741 EXPECT_EQ("JSON_OBJECT('second',JSON_OBJECT('first',1))",
742 generate_expression(Object{{"second", Object{{"first", 1}}}},
743 EMPTY_SCHEMA, DM_TABLE));
744 }
745
TEST(xpl_expr_generator,object_as_expr)746 TEST(xpl_expr_generator, object_as_expr) {
747 EXPECT_EQ("JSON_OBJECT('first',1)",
748 generate_expression(Object{{"first", 1}}, EMPTY_SCHEMA, DM_TABLE));
749 }
750
TEST(xpl_expr_generator,object_operator)751 TEST(xpl_expr_generator, object_operator) {
752 EXPECT_EQ("JSON_OBJECT('sum',(1 + 2))",
753 generate_expression(Object{{"sum", Operator("+", 1, 2)}},
754 EMPTY_SCHEMA, DM_TABLE));
755 }
756
TEST(xpl_expr_generator,object_function)757 TEST(xpl_expr_generator, object_function) {
758 EXPECT_EQ("JSON_OBJECT('result',foo('bar'))",
759 generate_expression(Object{{"result", Function_call("foo", "bar")}},
760 EMPTY_SCHEMA, DM_TABLE));
761 }
762
TEST(xpl_expr_generator,object_array)763 TEST(xpl_expr_generator, object_array) {
764 EXPECT_EQ("JSON_OBJECT('tab',JSON_ARRAY(1,2))",
765 generate_expression(Object{{"tab", Array{1, 2}}}, EMPTY_SCHEMA,
766 DM_TABLE));
767 }
768
TEST(xpl_expr_generator,object_in_function)769 TEST(xpl_expr_generator, object_in_function) {
770 EXPECT_EQ("foo(JSON_OBJECT('first',1))",
771 generate_expression(Function_call("foo", Object{{"first", 1}}),
772 EMPTY_SCHEMA, DM_TABLE));
773 }
774
TEST(xpl_expr_generator,object_real_example)775 TEST(xpl_expr_generator, object_real_example) {
776 EXPECT_EQ(
777 "JSON_OBJECT('name',concat("
778 "JSON_UNQUOTE(JSON_EXTRACT(doc,'$.first_name')),' ',"
779 "JSON_UNQUOTE(JSON_EXTRACT(doc,'$.last_name'))),'number',(1 + 1))",
780 generate_expression(
781 Object{{"name",
782 Function_call(
783 "concat", Column_identifier(Document_path{"first_name"}),
784 " ", Column_identifier(Document_path{"last_name"}))},
785 {"number", Operator("+", 1, 1)}},
786 EMPTY_SCHEMA, DM_TABLE));
787 }
788
TEST(xpl_expr_generator,array_empty)789 TEST(xpl_expr_generator, array_empty) {
790 EXPECT_EQ("JSON_ARRAY()",
791 generate_expression(Array(), EMPTY_SCHEMA, DM_TABLE));
792 }
793
TEST(xpl_expr_generator,array_one_scalar)794 TEST(xpl_expr_generator, array_one_scalar) {
795 EXPECT_EQ("JSON_ARRAY(1)",
796 generate_expression(Array{1}, EMPTY_SCHEMA, DM_TABLE));
797 }
798
TEST(xpl_expr_generator,array_two_scalars)799 TEST(xpl_expr_generator, array_two_scalars) {
800 EXPECT_EQ("JSON_ARRAY(1,'two')",
801 generate_expression(Array{1, "two"}, EMPTY_SCHEMA, DM_TABLE));
802 }
803
TEST(xpl_expr_generator,array_as_expr)804 TEST(xpl_expr_generator, array_as_expr) {
805 EXPECT_EQ("JSON_ARRAY(1)",
806 generate_expression(Expr(Array{1}), EMPTY_SCHEMA, DM_TABLE));
807 }
808
TEST(xpl_expr_generator,array_array)809 TEST(xpl_expr_generator, array_array) {
810 EXPECT_EQ(
811 "JSON_ARRAY('one',JSON_ARRAY(1,2))",
812 generate_expression(Array{"one", Array{1, 2}}, EMPTY_SCHEMA, DM_TABLE));
813 }
814
TEST(xpl_expr_generator,array_object)815 TEST(xpl_expr_generator, array_object) {
816 EXPECT_EQ("JSON_ARRAY(JSON_OBJECT('first',1),'two')",
817 generate_expression(Array{Object{{"first", 1}}, "two"},
818 EMPTY_SCHEMA, DM_TABLE));
819 }
820
TEST(xpl_expr_generator,array_operator)821 TEST(xpl_expr_generator, array_operator) {
822 EXPECT_EQ("JSON_ARRAY((1 + 2),'two')",
823 generate_expression(Array{Operator("+", 1, 2), "two"}, EMPTY_SCHEMA,
824 DM_TABLE));
825 }
826
TEST(xpl_expr_generator,array_function)827 TEST(xpl_expr_generator, array_function) {
828 EXPECT_EQ("JSON_ARRAY(foo('bar'),'two')",
829 generate_expression(Array{Function_call("foo", "bar"), "two"},
830 EMPTY_SCHEMA, DM_TABLE));
831 }
832
TEST(xpl_expr_generator,array_in_function)833 TEST(xpl_expr_generator, array_in_function) {
834 EXPECT_EQ("fun(JSON_ARRAY('foo','bar'))",
835 generate_expression(Function_call("fun", Array{"foo", "bar"}),
836 EMPTY_SCHEMA, DM_TABLE));
837 }
838
TEST(xpl_expr_generator,array_in_operator)839 TEST(xpl_expr_generator, array_in_operator) {
840 EXPECT_STREQ("JSON_CONTAINS(JSON_ARRAY(1,2),CAST(1 AS JSON))",
841 generate_expression(Operator("in", 1, Array{1, 2}), EMPTY_SCHEMA,
842 DM_TABLE)
843 .c_str());
844 }
845
TEST(xpl_expr_generator,array_not_in_operator)846 TEST(xpl_expr_generator, array_not_in_operator) {
847 EXPECT_EQ("NOT JSON_CONTAINS(JSON_ARRAY(1,2),CAST(1 AS JSON))",
848 generate_expression(Operator("not_in", 1, Array{1, 2}),
849 EMPTY_SCHEMA, DM_TABLE));
850 }
851
TEST(xpl_expr_generator,array_in_operator_string)852 TEST(xpl_expr_generator, array_in_operator_string) {
853 EXPECT_EQ("JSON_CONTAINS(JSON_ARRAY('foo','bar'),JSON_QUOTE('foo'))",
854 generate_expression(Operator("in", "foo", Array{"foo", "bar"}),
855 EMPTY_SCHEMA, DM_TABLE));
856 }
857
TEST(xpl_expr_generator,array_not_in_operator_string)858 TEST(xpl_expr_generator, array_not_in_operator_string) {
859 EXPECT_EQ("NOT JSON_CONTAINS(JSON_ARRAY('foo','bar'),JSON_QUOTE('foo'))",
860 generate_expression(Operator("not_in", "foo", Array{"foo", "bar"}),
861 EMPTY_SCHEMA, DM_TABLE));
862 }
863
TEST(xpl_expr_generator,default_operator)864 TEST(xpl_expr_generator, default_operator) {
865 EXPECT_EQ("DEFAULT",
866 generate_expression(Operator("default"), EMPTY_SCHEMA, DM_TABLE));
867 EXPECT_THROW(
868 generate_expression(Operator("default", 42), EMPTY_SCHEMA, DM_TABLE),
869 Expression_generator::Error);
870 }
871
TEST(xpl_expr_generator,scalar_octets_plain)872 TEST(xpl_expr_generator, scalar_octets_plain) {
873 EXPECT_EQ("'ABC'", generate_expression(
874 Scalar(Octets("ABC", Octets::Content_type::k_plain)),
875 EMPTY_SCHEMA, DM_TABLE));
876 }
877
TEST(xpl_expr_generator,scalar_octets_geometry)878 TEST(xpl_expr_generator, scalar_octets_geometry) {
879 EXPECT_EQ("ST_GEOMETRYFROMWKB('010')",
880 generate_expression(
881 Scalar(Octets("010", Octets::Content_type::k_geometry)),
882 EMPTY_SCHEMA, DM_TABLE));
883 }
884
TEST(xpl_expr_generator,scalar_octets_json)885 TEST(xpl_expr_generator, scalar_octets_json) {
886 EXPECT_EQ("CAST('{\\\"a\\\":42}' AS JSON)",
887 generate_expression(
888 Scalar(Octets("{\"a\":42}", Octets::Content_type::k_json)),
889 EMPTY_SCHEMA, DM_TABLE));
890 }
891
TEST(xpl_expr_generator,scalar_octets_xml)892 TEST(xpl_expr_generator, scalar_octets_xml) {
893 EXPECT_EQ("'<a>bbb</a>'",
894 generate_expression(
895 Scalar(Octets("<a>bbb</a>", Octets::Content_type::k_xml)),
896 EMPTY_SCHEMA, DM_TABLE));
897 }
898
TEST(xpl_expr_generator,scalar_octets_unknown)899 TEST(xpl_expr_generator, scalar_octets_unknown) {
900 EXPECT_THROW(
901 generate_expression(
902 Scalar(Octets("foo", static_cast<Octets::Content_type>(666))),
903 EMPTY_SCHEMA, DM_TABLE),
904 Expression_generator::Error);
905 }
906
TEST(xpl_expr_generator,cont_in_expression_literals)907 TEST(xpl_expr_generator, cont_in_expression_literals) {
908 EXPECT_STREQ(
909 "JSON_CONTAINS(CAST(1 AS JSON),CAST(2 AS JSON))",
910 generate_expression(Operator("cont_in", 2, 1), EMPTY_SCHEMA, DM_TABLE)
911 .c_str());
912 EXPECT_STREQ(
913 "JSON_CONTAINS(CAST(1.2 AS JSON),CAST(2.1 AS JSON))",
914 generate_expression(Operator("cont_in", 2.1, 1.2), EMPTY_SCHEMA, DM_TABLE)
915 .c_str());
916 EXPECT_STREQ("JSON_CONTAINS(CAST(FALSE AS JSON),CAST(TRUE AS JSON))",
917 generate_expression(Operator("cont_in", true, false),
918 EMPTY_SCHEMA, DM_TABLE)
919 .c_str());
920 EXPECT_STREQ(
921 "JSON_CONTAINS(CAST('null' AS JSON),CAST('null' AS JSON))",
922 generate_expression(Operator("cont_in", Scalar::Null(), Scalar::Null()),
923 EMPTY_SCHEMA, DM_TABLE)
924 .c_str());
925 EXPECT_STREQ("JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
926 generate_expression(Operator("cont_in", Scalar::String("black"),
927 Scalar::String("white")),
928 EMPTY_SCHEMA, DM_TABLE)
929 .c_str());
930 EXPECT_STREQ(
931 "JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
932 generate_expression(
933 Operator("cont_in", Octets("black", Octets::Content_type::k_plain),
934 Octets("white", Octets::Content_type::k_plain)),
935 EMPTY_SCHEMA, DM_TABLE)
936 .c_str());
937 EXPECT_STREQ(
938 "JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
939 "CAST('{\\\"black\\\":1}' AS JSON))",
940 generate_expression(
941 Operator("cont_in",
942 Octets("{\"black\":1}", Octets::Content_type::k_json),
943 Octets("{\"white\":2}", Octets::Content_type::k_json)),
944 EMPTY_SCHEMA, DM_TABLE)
945 .c_str());
946 EXPECT_STREQ(
947 "JSON_CONTAINS(JSON_QUOTE('<a>white</a>'),JSON_QUOTE('<a>black</a>'))",
948 generate_expression(
949 Operator("cont_in",
950 Octets("<a>black</a>", Octets::Content_type::k_xml),
951 Octets("<a>white</a>", Octets::Content_type::k_xml)),
952 EMPTY_SCHEMA, DM_TABLE)
953 .c_str());
954 EXPECT_STREQ(
955 "JSON_CONTAINS(JSON_QUOTE(ST_GEOMETRYFROMWKB('101')),"
956 "JSON_QUOTE(ST_GEOMETRYFROMWKB('010')))",
957 generate_expression(
958 Operator("cont_in", Octets("010", Octets::Content_type::k_geometry),
959 Octets("101", Octets::Content_type::k_geometry)),
960 EMPTY_SCHEMA, DM_TABLE)
961 .c_str());
962 }
963
TEST(xpl_expr_generator,cont_in_expression_arrays)964 TEST(xpl_expr_generator, cont_in_expression_arrays) {
965 EXPECT_STREQ(
966 "JSON_CONTAINS(JSON_ARRAY(3,4),JSON_ARRAY(1,2))",
967 generate_expression(Operator("cont_in", Array{1, 2}, Array{3, 4}),
968 EMPTY_SCHEMA, DM_TABLE)
969 .c_str());
970 EXPECT_STREQ(
971 "JSON_CONTAINS(JSON_ARRAY(3,FALSE,'white'),JSON_ARRAY(1,TRUE,'black'))",
972 generate_expression(Operator("cont_in", Array{1, true, "black"},
973 Array{3, false, "white"}),
974 EMPTY_SCHEMA, DM_TABLE)
975 .c_str());
976 EXPECT_STREQ(
977 "JSON_CONTAINS(JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)),"
978 "JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)))",
979 generate_expression(
980 Operator(
981 "cont_in",
982 Array{Octets("{\"black\":1}", Octets::Content_type::k_json)},
983 Array{Octets("{\"white\":2}", Octets::Content_type::k_json)}),
984 EMPTY_SCHEMA, DM_TABLE)
985 .c_str());
986 }
987
TEST(xpl_expr_generator,cont_in_expression_objects)988 TEST(xpl_expr_generator, cont_in_expression_objects) {
989 EXPECT_STREQ("JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('first',1))",
990 generate_expression(Operator("cont_in", Object{{"first", 1}},
991 Object{{"second", 2}}),
992 EMPTY_SCHEMA, DM_TABLE)
993 .c_str());
994 EXPECT_STREQ(
995 "JSON_CONTAINS(JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)),"
996 "JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)))",
997 generate_expression(
998 Operator("cont_in",
999 Object{{"first", Octets("{\"black\":1}",
1000 Octets::Content_type::k_json)}},
1001 Object{{"second", Octets("{\"white\":2}",
1002 Octets::Content_type::k_json)}}),
1003 EMPTY_SCHEMA, DM_TABLE)
1004 .c_str());
1005 }
1006
TEST(xpl_expr_generator,cont_in_expression_operators)1007 TEST(xpl_expr_generator, cont_in_expression_operators) {
1008 Operator plus("+", 1, 2), minus("-", 2, 1);
1009 EXPECT_THROW(generate_expression(Operator("cont_in", plus, minus),
1010 EMPTY_SCHEMA, DM_TABLE),
1011 Expression_generator::Error);
1012 EXPECT_STREQ("JSON_CONTAINS(CAST((2 - 1) AS JSON),CAST((1 + 2) AS JSON))",
1013 generate_expression(
1014 Operator("cont_in", Operator("cast", plus, Octets{"JSON"}),
1015 Operator("cast", minus, Octets{"JSON"})),
1016 EMPTY_SCHEMA, DM_TABLE)
1017 .c_str());
1018 EXPECT_THROW(
1019 generate_expression(
1020 Operator("cont_in", plus, Operator("cast", minus, Octets("JSON"))),
1021 EMPTY_SCHEMA, DM_TABLE),
1022 Expression_generator::Error);
1023 EXPECT_THROW(
1024 generate_expression(
1025 Operator("cont_in", Operator("cast", plus, Octets("JSON")), minus),
1026 EMPTY_SCHEMA, DM_TABLE),
1027 Expression_generator::Error);
1028 EXPECT_THROW(generate_expression(
1029 Operator("cont_in", Operator("cast", plus, Octets("SIGNED")),
1030 Operator("cast", minus, Octets("JSON"))),
1031 EMPTY_SCHEMA, DM_TABLE),
1032 Expression_generator::Error);
1033 EXPECT_THROW(generate_expression(
1034 Operator("cont_in", Operator("cast", plus, Octets("JSON")),
1035 Operator("cast", minus, Octets("SIGNED"))),
1036 EMPTY_SCHEMA, DM_TABLE),
1037 Expression_generator::Error);
1038 }
1039
TEST(xpl_expr_generator,cont_in_expression_functions)1040 TEST(xpl_expr_generator, cont_in_expression_functions) {
1041 Function_call concat("concat", "foo", "bar");
1042 EXPECT_THROW(generate_expression(Operator("cont_in", concat, concat),
1043 EMPTY_SCHEMA, DM_TABLE),
1044 Expression_generator::Error);
1045 EXPECT_STREQ(
1046 "JSON_CONTAINS(json_quote(concat('foo','bar')),"
1047 "json_quote(concat('foo','bar')))",
1048 generate_expression(
1049 Operator("cont_in", Function_call("json_quote", concat),
1050 Function_call("json_quote", concat)),
1051 EMPTY_SCHEMA, DM_TABLE)
1052 .c_str());
1053 EXPECT_THROW(
1054 generate_expression(
1055 Operator("cont_in", concat, Function_call("json_quote", concat)),
1056 EMPTY_SCHEMA, DM_TABLE),
1057 Expression_generator::Error);
1058 EXPECT_THROW(
1059 generate_expression(
1060 Operator("cont_in", Function_call("json_quote", concat), concat),
1061 EMPTY_SCHEMA, DM_TABLE),
1062 Expression_generator::Error);
1063 }
1064
TEST(xpl_expr_generator,cont_in_expression_placeholders)1065 TEST(xpl_expr_generator, cont_in_expression_placeholders) {
1066 EXPECT_STREQ(
1067 "JSON_CONTAINS(CAST(2 AS JSON),CAST(1 AS JSON))",
1068 generate_expression(Operator("cont_in", Placeholder(0), Placeholder(1)),
1069 Expression_list({1, 2}), EMPTY_SCHEMA, DM_TABLE)
1070 .c_str());
1071 EXPECT_STREQ("JSON_CONTAINS(JSON_QUOTE('bar'),JSON_QUOTE('foo'))",
1072 generate_expression(
1073 Operator("cont_in", Placeholder(0), Placeholder(1)),
1074 Expression_list({"foo", "bar"}), EMPTY_SCHEMA, DM_TABLE)
1075 .c_str());
1076 EXPECT_STREQ(
1077 "JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
1078 "CAST('{\\\"black\\\":1}' AS JSON))",
1079 generate_expression(
1080 Operator("cont_in", Placeholder(0), Placeholder(1)),
1081 Expression_list(
1082 {Octets("{\"black\":1}", Octets::Content_type::k_json),
1083 Octets("{\"white\":2}", Octets::Content_type::k_json)}),
1084 EMPTY_SCHEMA, DM_TABLE)
1085 .c_str());
1086 EXPECT_THROW(
1087 generate_expression(Operator("cont_in", Placeholder(0), Placeholder(1)),
1088 EMPTY_SCHEMA, DM_TABLE),
1089 Expression_generator::Error);
1090
1091 Expression_generator::Prep_stmt_placeholder_list ids;
1092 EXPECT_STREQ(
1093 "JSON_CONTAINS(CAST(? AS JSON),CAST(? AS JSON))",
1094 generate_expression(Operator("cont_in", Placeholder(0), Placeholder(1)),
1095 EMPTY_SCHEMA, DM_TABLE, &ids)
1096 .c_str());
1097 }
1098
TEST(xpl_expr_generator,cont_in_expression_identifier)1099 TEST(xpl_expr_generator, cont_in_expression_identifier) {
1100 EXPECT_STREQ(
1101 "JSON_CONTAINS(CAST(42 AS JSON),"
1102 "JSON_EXTRACT(`schema`.`table`.`field`,'$.member'))",
1103 generate_expression(
1104 Operator("cont_in",
1105 Column_identifier(Document_path{"member"}, "field", "table",
1106 "schema"),
1107 42),
1108 EMPTY_SCHEMA, DM_TABLE)
1109 .c_str());
1110
1111 EXPECT_STREQ(
1112 "JSON_CONTAINS(JSON_EXTRACT(`schema`.`table`.`field`,'$.member'),"
1113 "CAST(42 AS JSON))",
1114 generate_expression(
1115 Operator("cont_in", 42,
1116 Column_identifier(Document_path{"member"}, "field", "table",
1117 "schema")),
1118 EMPTY_SCHEMA, DM_TABLE)
1119 .c_str());
1120
1121 EXPECT_STREQ(
1122 "JSON_CONTAINS(`schema`.`table`.`field`,"
1123 "CAST(42 AS JSON))",
1124 generate_expression(
1125 Operator("cont_in", 42,
1126 Column_identifier("field", "table", "schema")),
1127 EMPTY_SCHEMA, DM_TABLE)
1128 .c_str());
1129 }
1130
TEST(xpl_expr_generator,any_scalar)1131 TEST(xpl_expr_generator, any_scalar) {
1132 EXPECT_STREQ("42",
1133 generate_expression(Any(42), EMPTY_SCHEMA, DM_TABLE).c_str());
1134 }
1135
TEST(xpl_expr_generator,any_object)1136 TEST(xpl_expr_generator, any_object) {
1137 EXPECT_STREQ("JSON_OBJECT('name',42)",
1138 generate_expression(Any(Any::Object{{"name", Any(42)}}),
1139 EMPTY_SCHEMA, DM_TABLE)
1140 .c_str());
1141 }
1142
TEST(xpl_expr_generator,any_array)1143 TEST(xpl_expr_generator, any_array) {
1144 EXPECT_STREQ(
1145 "JSON_ARRAY('name',42)",
1146 generate_expression(Any(Any::Array{"name", 42}), EMPTY_SCHEMA, DM_TABLE)
1147 .c_str());
1148 }
1149
1150 struct Param_function_call {
1151 std::string expect;
1152 Function_call func;
1153 std::string schema;
1154 };
1155
1156 class Function_call_test : public testing::TestWithParam<Param_function_call> {
1157 };
1158
TEST_P(Function_call_test,function_call)1159 TEST_P(Function_call_test, function_call) {
1160 const Param_function_call ¶m = GetParam();
1161 EXPECT_STREQ(param.expect.c_str(),
1162 generate_expression(param.func, param.schema, DM_TABLE).c_str());
1163 }
1164
1165 Param_function_call function_call_param[] = {
1166 {"func()", Function_call("func"), EMPTY_SCHEMA},
1167 {"schema.func()", Function_call("func"), "schema"},
1168 {"schema.func(FALSE,5)", Function_call("func", false, 5), "schema"},
1169 {"concat(FALSE,5)", Function_call("concat", false, 5), "schema"},
1170 {"CONCAT(FALSE,5)", Function_call("CONCAT", false, 5), "schema"},
1171 {"CONCAT(FALSE,5)", Function_call("CONCAT", false, 5), EMPTY_SCHEMA},
1172 {"ASCII('string')", Function_call("ASCII", "string"), EMPTY_SCHEMA},
1173 {"ASCII(`column`)", Function_call("ASCII", Column_identifier("column")),
1174 EMPTY_SCHEMA},
1175 {"ASCII(JSON_UNQUOTE(JSON_EXTRACT(doc,'$.path')))",
1176 Function_call("ASCII", Column_identifier(Document_path{"path"})),
1177 EMPTY_SCHEMA},
1178 {"ABS(42)", Function_call("ABS", 42), EMPTY_SCHEMA},
1179 {"ABS(`column`)", Function_call("ABS", Column_identifier("column")),
1180 EMPTY_SCHEMA},
1181 {"ABS(JSON_UNQUOTE(JSON_EXTRACT(doc,'$.path')))",
1182 Function_call("ABS", Column_identifier(Document_path{"path"})),
1183 EMPTY_SCHEMA},
1184 {"JSON_TYPE(42)", Function_call("JSON_TYPE", 42), EMPTY_SCHEMA},
1185 {"JSON_TYPE(`column`)",
1186 Function_call("JSON_TYPE", Column_identifier("column")), EMPTY_SCHEMA},
1187 {"JSON_TYPE(JSON_EXTRACT(doc,'$.path'))",
1188 Function_call("JSON_TYPE", Column_identifier(Document_path{"path"})),
1189 EMPTY_SCHEMA},
1190 {"JSON_KEYS('{\\\"a\\\":42}')", Function_call("JSON_KEYS", "{\"a\":42}"),
1191 EMPTY_SCHEMA},
1192 {"JSON_KEYS(`column`)",
1193 Function_call("JSON_KEYS", Column_identifier("column")), EMPTY_SCHEMA},
1194 {"JSON_KEYS(JSON_EXTRACT(doc,'$.path'))",
1195 Function_call("JSON_KEYS", Column_identifier(Document_path{"path"})),
1196 EMPTY_SCHEMA}};
1197
1198 INSTANTIATE_TEST_CASE_P(xpl_expr_generator_function_call, Function_call_test,
1199 testing::ValuesIn(function_call_param));
1200
1201 struct Param_placeholders {
1202 std::string expect;
1203 Expression_generator::Prep_stmt_placeholder_list expect_ids;
1204 Expression_list args;
1205 Array expr;
1206 };
1207
1208 class Placeholders_test : public testing::TestWithParam<Param_placeholders> {};
1209
TEST_P(Placeholders_test,placeholders)1210 TEST_P(Placeholders_test, placeholders) {
1211 const Param_placeholders ¶m = GetParam();
1212 Query_string_builder qb;
1213 Expression_generator gen(&qb, param.args, EMPTY_SCHEMA, DM_TABLE);
1214 Expression_generator::Prep_stmt_placeholder_list ids;
1215 gen.set_prep_stmt_placeholder_list(&ids);
1216 gen.feed(param.expr);
1217
1218 EXPECT_STREQ(param.expect.c_str(), qb.get().c_str());
1219 EXPECT_EQ(param.expect_ids, ids);
1220 }
1221
1222 #define PH Placeholder
1223
1224 Param_placeholders placeholders_param[] = {
1225 {"JSON_ARRAY(?)", {0}, {}, {PH{0}}},
1226 {"JSON_ARRAY('a')", {}, {"a"}, {PH{0}}},
1227 {"JSON_ARRAY(?)", {0}, {"a"}, {PH{1}}},
1228 {"JSON_ARRAY(?,?)", {0, 0}, {}, {PH{0}, PH{0}}},
1229 {"JSON_ARRAY(?,?)", {1, 0}, {}, {PH{1}, PH{0}}},
1230 {"JSON_ARRAY('a',?)", {0}, {"a"}, {PH{0}, PH{1}}},
1231 {"JSON_ARRAY(?,'a')", {0}, {"a"}, {PH{1}, PH{0}}},
1232 {"JSON_ARRAY('a','b')", {}, {"a", "b"}, {PH{0}, PH{1}}},
1233 {"JSON_ARRAY('a','b','a')", {}, {"a", "b"}, {PH{0}, PH{1}, PH{0}}},
1234 {"JSON_ARRAY('a','b',?)", {0}, {"a", "b"}, {PH{0}, PH{1}, PH{2}}},
1235 {"JSON_ARRAY('a',?,'b')", {0}, {"a", "b"}, {PH{0}, PH{2}, PH{1}}},
1236 {"JSON_ARRAY(?,'a','b')", {0}, {"a", "b"}, {PH{2}, PH{0}, PH{1}}},
1237 {"JSON_ARRAY(?,'a',?,'b',?)",
1238 {0, 0, 0},
1239 {"a", "b"},
1240 {PH{2}, PH{0}, PH{2}, PH{1}, PH{2}}},
1241 {"JSON_ARRAY(?,'a',?,'b',?)",
1242 {0, 1, 0},
1243 {"a", "b"},
1244 {PH{2}, PH{0}, PH{3}, PH{1}, PH{2}}},
1245 };
1246
1247 INSTANTIATE_TEST_CASE_P(xpl_expr_generator_placeholders, Placeholders_test,
1248 testing::ValuesIn(placeholders_param));
1249
1250 struct Param_operator_pass {
1251 std::string expect;
1252 Operator operator_;
1253 Expression_list args;
1254 };
1255
1256 class Operator_pass_test : public testing::TestWithParam<Param_operator_pass> {
1257 };
1258
TEST_P(Operator_pass_test,operator_pass)1259 TEST_P(Operator_pass_test, operator_pass) {
1260 const auto ¶m = GetParam();
1261 EXPECT_STREQ(
1262 param.expect.c_str(),
1263 generate_expression(param.operator_, param.args, EMPTY_SCHEMA, DM_TABLE)
1264 .c_str());
1265 }
1266
1267 Param_operator_pass cont_in_pass_param[] = {
1268 // literals
1269 {"JSON_CONTAINS(CAST(1 AS JSON),CAST(2 AS JSON))",
1270 Operator("cont_in", 2, 1),
1271 {}},
1272 {"JSON_CONTAINS(CAST(1.2 AS JSON),CAST(2.1 AS JSON))",
1273 Operator("cont_in", 2.1, 1.2),
1274 {}},
1275 {"JSON_CONTAINS(CAST(FALSE AS JSON),CAST(TRUE AS JSON))",
1276 Operator("cont_in", true, false),
1277 {}},
1278 {"JSON_CONTAINS(CAST('null' AS JSON),CAST('null' AS JSON))",
1279 Operator("cont_in", Scalar::Null(), Scalar::Null()),
1280 {}},
1281 {"JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
1282 Operator("cont_in", Scalar::String("black"), Scalar::String("white")),
1283 {}},
1284 {"JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
1285 Operator("cont_in", Octets("black", Octets::Content_type::k_plain),
1286 Octets("white", Octets::Content_type::k_plain)),
1287 {}},
1288 {"JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
1289 "CAST('{\\\"black\\\":1}' AS JSON))",
1290 Operator("cont_in", Octets("{\"black\":1}", Octets::Content_type::k_json),
1291 Octets("{\"white\":2}", Octets::Content_type::k_json)),
1292 {}},
1293 {"JSON_CONTAINS(JSON_QUOTE('<a>white</a>'),JSON_QUOTE('<a>black</a>'))",
1294 Operator("cont_in", Octets("<a>black</a>", Octets::Content_type::k_xml),
1295 Octets("<a>white</a>", Octets::Content_type::k_xml)),
1296 {}},
1297 {"JSON_CONTAINS(JSON_QUOTE(ST_GEOMETRYFROMWKB('101')),"
1298 "JSON_QUOTE(ST_GEOMETRYFROMWKB('010')))",
1299 Operator("cont_in", Octets("010", Octets::Content_type::k_geometry),
1300 Octets("101", Octets::Content_type::k_geometry)),
1301 {}},
1302 // arrays
1303 {"JSON_CONTAINS(JSON_ARRAY(3,4),JSON_ARRAY(1,2))",
1304 Operator("cont_in", Array{1, 2}, Array{3, 4}),
1305 {}},
1306 {"JSON_CONTAINS(JSON_ARRAY(3,FALSE,'white'),JSON_ARRAY(1,TRUE,'black'))",
1307 Operator("cont_in", Array{1, true, "black"}, Array{3, false, "white"}),
1308 {}},
1309 {"JSON_CONTAINS(JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)),"
1310 "JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)))",
1311 Operator("cont_in",
1312 Array{Octets("{\"black\":1}", Octets::Content_type::k_json)},
1313 Array{Octets("{\"white\":2}", Octets::Content_type::k_json)}),
1314 {}},
1315 // objects
1316 {"JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('first',1))",
1317 Operator("cont_in", Object{{"first", 1}}, Object{{"second", 2}}),
1318 {}},
1319 {"JSON_CONTAINS(JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)),"
1320 "JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)))",
1321 Operator("cont_in",
1322 Object{{"first",
1323 Octets("{\"black\":1}", Octets::Content_type::k_json)}},
1324 Object{{"second",
1325 Octets("{\"white\":2}", Octets::Content_type::k_json)}}),
1326 {}},
1327 {"JSON_CONTAINS(CAST((2 - 1) AS JSON),CAST((1 + 2) AS JSON))",
1328 Operator("cont_in", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
1329 Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
1330 {}},
1331 // functions
1332 {"JSON_CONTAINS(json_quote(concat('foo','bar')),"
1333 "json_quote(concat('foo','bar')))",
1334 Operator(
1335 "cont_in",
1336 Function_call("json_quote", Function_call("concat", "foo", "bar")),
1337 Function_call("json_quote", Function_call("concat", "foo", "bar"))),
1338 {}},
1339 // placeholders
1340 {"JSON_CONTAINS(CAST(2 AS JSON),CAST(1 AS JSON))",
1341 Operator("cont_in", Placeholder(0), Placeholder(1)),
1342 {1, 2}},
1343 {"JSON_CONTAINS(JSON_QUOTE('bar'),JSON_QUOTE('foo'))",
1344 Operator("cont_in", Placeholder(0), Placeholder(1)),
1345 {"foo", "bar"}},
1346 {"JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
1347 "CAST('{\\\"black\\\":1}' AS JSON))",
1348 Operator("cont_in", Placeholder(0), Placeholder(1)),
1349 {Octets("{\"black\":1}", Octets::Content_type::k_json),
1350 Octets("{\"white\":2}", Octets::Content_type::k_json)}},
1351 // identifier
1352 {"JSON_CONTAINS(CAST(42 AS JSON),"
1353 "JSON_EXTRACT(`schema`.`table`.`field`,'$.member'))",
1354 Operator(
1355 "cont_in",
1356 Column_identifier(Document_path{"member"}, "field", "table", "schema"),
1357 42),
1358 {}},
1359 {"JSON_CONTAINS(JSON_EXTRACT(`schema`.`table`.`field`,'$.member'),"
1360 "CAST(42 AS JSON))",
1361 Operator("cont_in", 42,
1362 Column_identifier(Document_path{"member"}, "field", "table",
1363 "schema")),
1364 {}},
1365 {"JSON_CONTAINS(`schema`.`table`.`field`,CAST(42 AS JSON))",
1366 Operator("cont_in", 42, Column_identifier("field", "table", "schema")),
1367 {}},
1368 };
1369
1370 INSTANTIATE_TEST_CASE_P(xpl_expr_generator_cont_in_pass, Operator_pass_test,
1371 testing::ValuesIn(cont_in_pass_param));
1372
1373 struct Param_operator_fail {
1374 Operator operator_;
1375 Expression_list args;
1376 };
1377
1378 class Operator_fail_test : public testing::TestWithParam<Param_operator_fail> {
1379 };
1380
TEST_P(Operator_fail_test,operator_fail)1381 TEST_P(Operator_fail_test, operator_fail) {
1382 const auto ¶m = GetParam();
1383 EXPECT_THROW(
1384 generate_expression(param.operator_, param.args, EMPTY_SCHEMA, DM_TABLE),
1385 Expression_generator::Error)
1386 << "Should throw for: " << msg_to_string(param.operator_.base());
1387 }
1388
1389 Param_operator_fail cont_in_fail_param[] = {
1390 // literals
1391 // arrays
1392 // objects
1393 // operators
1394 {Operator("cont_in", Operator("+", 1, 2), Operator("-", 2, 1)), {}},
1395 {Operator("cont_in", Operator("+", 1, 2),
1396 Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
1397 {}},
1398 {Operator("cont_in", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
1399 Operator("-", 2, 1)),
1400 {}},
1401 {Operator("cont_in",
1402 Operator("cast", Operator("+", 1, 2), Octets("SIGNED")),
1403 Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
1404 {}},
1405 {Operator("cont_in", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
1406 Operator("cast", Operator("-", 2, 1), Octets("SIGNED"))),
1407 {}},
1408 // functions
1409 {Operator("cont_in", Function_call("concat", "foo", "bar"),
1410 Function_call("concat", "foo", "bar")),
1411 {}},
1412 {Operator(
1413 "cont_in", Function_call("concat", "foo", "bar"),
1414 Function_call("json_quote", Function_call("concat", "foo", "bar"))),
1415 {}},
1416 {Operator(
1417 "cont_in",
1418 Function_call("json_quote", Function_call("concat", "foo", "bar")),
1419 Function_call("concat", "foo", "bar")),
1420 {}},
1421 // placeholders
1422 {Operator("cont_in", Placeholder(0), Placeholder(1)), {}},
1423 // identifier
1424 };
1425
1426 INSTANTIATE_TEST_CASE_P(xpl_expr_generator_cont_in_fail, Operator_fail_test,
1427 testing::ValuesIn(cont_in_fail_param));
1428
1429 Param_operator_pass overlaps_pass_param[] = {
1430 // literals
1431 {"JSON_OVERLAPS(CAST(2 AS JSON),CAST(1 AS JSON))",
1432 Operator("overlaps", 2, 1),
1433 {}},
1434 {"JSON_OVERLAPS(CAST(2.1 AS JSON),CAST(1.2 AS JSON))",
1435 Operator("overlaps", 2.1, 1.2),
1436 {}},
1437 {"JSON_OVERLAPS(CAST(TRUE AS JSON),CAST(FALSE AS JSON))",
1438 Operator("overlaps", true, false),
1439 {}},
1440 {"JSON_OVERLAPS(CAST('null' AS JSON),CAST('null' AS JSON))",
1441 Operator("overlaps", Scalar::Null(), Scalar::Null()),
1442 {}},
1443 {"JSON_OVERLAPS(JSON_QUOTE('black'),JSON_QUOTE('white'))",
1444 Operator("overlaps", Scalar::String("black"), Scalar::String("white")),
1445 {}},
1446 {"JSON_OVERLAPS(JSON_QUOTE('black'),JSON_QUOTE('white'))",
1447 Operator("overlaps", Octets("black", Octets::Content_type::k_plain),
1448 Octets("white", Octets::Content_type::k_plain)),
1449 {}},
1450 {"JSON_OVERLAPS("
1451 "CAST('{\\\"black\\\":1}' AS JSON),CAST('{\\\"white\\\":2}' AS JSON))",
1452 Operator("overlaps", Octets("{\"black\":1}", Octets::Content_type::k_json),
1453 Octets("{\"white\":2}", Octets::Content_type::k_json)),
1454 {}},
1455 {"JSON_OVERLAPS(JSON_QUOTE('<a>black</a>'),JSON_QUOTE('<a>white</a>'))",
1456 Operator("overlaps", Octets("<a>black</a>", Octets::Content_type::k_xml),
1457 Octets("<a>white</a>", Octets::Content_type::k_xml)),
1458 {}},
1459 {"JSON_OVERLAPS("
1460 "JSON_QUOTE(ST_GEOMETRYFROMWKB('010')),"
1461 "JSON_QUOTE(ST_GEOMETRYFROMWKB('101')))",
1462 Operator("overlaps", Octets("010", Octets::Content_type::k_geometry),
1463 Octets("101", Octets::Content_type::k_geometry)),
1464 {}},
1465 // arrays
1466 {"JSON_OVERLAPS(JSON_ARRAY(1,2),JSON_ARRAY(3,4))",
1467 Operator("overlaps", Array{1, 2}, Array{3, 4}),
1468 {}},
1469 {"JSON_OVERLAPS(JSON_ARRAY(1,TRUE,'black'),JSON_ARRAY(3,FALSE,'white'))",
1470 Operator("overlaps", Array{1, true, "black"}, Array{3, false, "white"}),
1471 {}},
1472 {"JSON_OVERLAPS("
1473 "JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)),"
1474 "JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)))",
1475 Operator("overlaps",
1476 Array{Octets("{\"black\":1}", Octets::Content_type::k_json)},
1477 Array{Octets("{\"white\":2}", Octets::Content_type::k_json)}),
1478 {}},
1479 // objects
1480 {"JSON_OVERLAPS(JSON_OBJECT('first',1),JSON_OBJECT('second',2))",
1481 Operator("overlaps", Object{{"first", 1}}, Object{{"second", 2}}),
1482 {}},
1483 {"JSON_OVERLAPS("
1484 "JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)),"
1485 "JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)))",
1486 Operator("overlaps",
1487 Object{{"first",
1488 Octets("{\"black\":1}", Octets::Content_type::k_json)}},
1489 Object{{"second",
1490 Octets("{\"white\":2}", Octets::Content_type::k_json)}}),
1491 {}},
1492 {"JSON_OVERLAPS(CAST((1 + 2) AS JSON),CAST((2 - 1) AS JSON))",
1493 Operator("overlaps", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
1494 Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
1495 {}},
1496 // functions
1497 {"JSON_OVERLAPS("
1498 "json_quote(concat('foo','bar')),"
1499 "json_quote(concat('foo','bar')))",
1500 Operator(
1501 "overlaps",
1502 Function_call("json_quote", Function_call("concat", "foo", "bar")),
1503 Function_call("json_quote", Function_call("concat", "foo", "bar"))),
1504 {}},
1505 // placeholders
1506 {"JSON_OVERLAPS(CAST(1 AS JSON),CAST(2 AS JSON))",
1507 Operator("overlaps", Placeholder(0), Placeholder(1)),
1508 {1, 2}},
1509 {"JSON_OVERLAPS(JSON_QUOTE('foo'),JSON_QUOTE('bar'))",
1510 Operator("overlaps", Placeholder(0), Placeholder(1)),
1511 {"foo", "bar"}},
1512 {"JSON_OVERLAPS("
1513 "CAST('{\\\"black\\\":1}' AS JSON),"
1514 "CAST('{\\\"white\\\":2}' AS JSON))",
1515 Operator("overlaps", Placeholder(0), Placeholder(1)),
1516 {Octets("{\"black\":1}", Octets::Content_type::k_json),
1517 Octets("{\"white\":2}", Octets::Content_type::k_json)}},
1518 // identifier
1519 {"JSON_OVERLAPS("
1520 "JSON_EXTRACT(`schema`.`table`.`field`,'$.member'),"
1521 "CAST(42 AS JSON))",
1522 Operator(
1523 "overlaps",
1524 Column_identifier(Document_path{"member"}, "field", "table", "schema"),
1525 42),
1526 {}},
1527 {"JSON_OVERLAPS("
1528 "CAST(42 AS JSON),"
1529 "JSON_EXTRACT(`schema`.`table`.`field`,'$.member'))",
1530 Operator("overlaps", 42,
1531 Column_identifier(Document_path{"member"}, "field", "table",
1532 "schema")),
1533 {}},
1534 {"JSON_OVERLAPS("
1535 "CAST(42 AS JSON),"
1536 "`schema`.`table`.`field`)",
1537 Operator("overlaps", 42, Column_identifier("field", "table", "schema")),
1538 {}},
1539 };
1540
1541 INSTANTIATE_TEST_CASE_P(xpl_expr_generator_overlaps_pass, Operator_pass_test,
1542 testing::ValuesIn(overlaps_pass_param));
1543
1544 Param_operator_fail overlaps_fail_param[] = {
1545 // literals
1546 // arrays
1547 // objects
1548 // operators
1549 {Operator("overlaps", Operator("+", 1, 2), Operator("-", 2, 1)), {}},
1550 {Operator("overlaps", Operator("+", 1, 2),
1551 Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
1552 {}},
1553 {Operator("overlaps", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
1554 Operator("-", 2, 1)),
1555 {}},
1556 {Operator("overlaps",
1557 Operator("cast", Operator("+", 1, 2), Octets("SIGNED")),
1558 Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
1559 {}},
1560 {Operator("overlaps", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
1561 Operator("cast", Operator("-", 2, 1), Octets("SIGNED"))),
1562 {}},
1563 // functions
1564 {Operator("overlaps", Function_call("concat", "foo", "bar"),
1565 Function_call("concat", "foo", "bar")),
1566 {}},
1567 {Operator(
1568 "overlaps", Function_call("concat", "foo", "bar"),
1569 Function_call("json_quote", Function_call("concat", "foo", "bar"))),
1570 {}},
1571 {Operator(
1572 "overlaps",
1573 Function_call("json_quote", Function_call("concat", "foo", "bar")),
1574 Function_call("concat", "foo", "bar")),
1575 {}},
1576 // placeholders
1577 {Operator("overlaps", Placeholder(0), Placeholder(1)), {}},
1578 // identifier
1579 };
1580
1581 INSTANTIATE_TEST_CASE_P(xpl_expr_generator_overlaps_fail, Operator_fail_test,
1582 testing::ValuesIn(overlaps_fail_param));
1583
1584 } // namespace test
1585 } // namespace xpl
1586