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 &param = 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 &param = 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 &param = 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 &param = 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