1576 lines
63 KiB
C++
1576 lines
63 KiB
C++
/* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with MySQL.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <cstddef>
|
|
|
|
#include "plugin/x/src/expr_generator.h"
|
|
#include "unittest/gunit/xplugin/xpl/message_helpers.h"
|
|
#include "unittest/gunit/xplugin/xpl/mysqlx_pb_wrapper.h"
|
|
|
|
namespace xpl {
|
|
namespace test {
|
|
|
|
const char *const EMPTY_SCHEMA = "";
|
|
const char *const EMPTY = "";
|
|
enum { DM_DOCUMENT = 0, DM_TABLE = 1 };
|
|
|
|
using Octets = Scalar::Octets;
|
|
|
|
TEST(xpl_expr_generator, literal_uint) {
|
|
EXPECT_EQ("0", generate_expression(Scalar(static_cast<unsigned>(0)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("1234567890",
|
|
generate_expression(Scalar(static_cast<unsigned>(1234567890)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_NE("-1234567890",
|
|
generate_expression(Scalar(static_cast<unsigned>(-1234567890)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_sint) {
|
|
EXPECT_EQ("0", generate_expression(Scalar(0), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("1234567890",
|
|
generate_expression(Scalar(1234567890), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("-1234567890",
|
|
generate_expression(Scalar(-1234567890), EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_null) {
|
|
EXPECT_EQ("NULL", generate_expression(Scalar(Scalar::Null()), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_octets) {
|
|
EXPECT_EQ("'\\\"test1\\\" \t \\'test2\\''",
|
|
generate_expression(Scalar("\"test1\" \t 'test2'"), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_string) {
|
|
EXPECT_EQ("'\\\"test1\\\" \t \\'test2\\''",
|
|
generate_expression(Scalar(Scalar::String("\"test1\" \t 'test2'")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_double) {
|
|
EXPECT_EQ("1234567890.123456", generate_expression(Scalar(1234567890.123456),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.substr(0, 17));
|
|
EXPECT_EQ(
|
|
"-1234567890.123456",
|
|
generate_expression(Scalar(-1234567890.123456), EMPTY_SCHEMA, DM_TABLE)
|
|
.substr(0, 18));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_float) {
|
|
EXPECT_EQ("1234.12",
|
|
generate_expression(Scalar(1234.123f), EMPTY_SCHEMA, DM_TABLE)
|
|
.substr(0, 8));
|
|
EXPECT_EQ("-1234.12",
|
|
generate_expression(Scalar(-1234.123f), EMPTY_SCHEMA, DM_TABLE)
|
|
.substr(0, 9));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, literal_bool) {
|
|
EXPECT_EQ("TRUE", generate_expression(Scalar(true), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("FALSE",
|
|
generate_expression(Scalar(false), EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, invalid_operator) {
|
|
EXPECT_THROW(generate_expression(Operator("some invalid operator"),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, nullary_operators) {
|
|
EXPECT_EQ("*", generate_expression(Operator("*"), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("*", generate_expression(Operator("*"), EMPTY_SCHEMA, DM_DOCUMENT));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, unary_operators) {
|
|
EXPECT_EQ("(NOT TRUE)",
|
|
generate_expression(Operator("not", true), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(+TRUE)", generate_expression(Operator("sign_plus", true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(-TRUE)", generate_expression(Operator("sign_minus", true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(!TRUE)",
|
|
generate_expression(Operator("!", true), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(generate_expression(Operator("!"), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("!", true, true), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, binary_operators) {
|
|
EXPECT_EQ("(TRUE AND TRUE)", generate_expression(Operator("&&", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE OR TRUE)", generate_expression(Operator("||", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE XOR TRUE)", generate_expression(Operator("xor", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE = TRUE)", generate_expression(Operator("==", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE != TRUE)", generate_expression(Operator("!=", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE >= TRUE)", generate_expression(Operator(">=", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE > TRUE)", generate_expression(Operator(">", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE <= TRUE)", generate_expression(Operator("<=", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE < TRUE)", generate_expression(Operator("<", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE & TRUE)", generate_expression(Operator("&", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE | TRUE)", generate_expression(Operator("|", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE ^ TRUE)", generate_expression(Operator("^", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE << TRUE)", generate_expression(Operator("<<", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE >> TRUE)", generate_expression(Operator(">>", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE + TRUE)", generate_expression(Operator("+", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE - TRUE)", generate_expression(Operator("-", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE * TRUE)", generate_expression(Operator("*", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE / TRUE)", generate_expression(Operator("/", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(4 DIV 2)",
|
|
generate_expression(Operator("div", 4, 2), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE % TRUE)", generate_expression(Operator("%", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE IS TRUE)", generate_expression(Operator("is", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(TRUE IS NOT TRUE)",
|
|
generate_expression(Operator("is_not", true, true), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("(TRUE REGEXP TRUE)",
|
|
generate_expression(Operator("regexp", true, true), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("(TRUE NOT REGEXP TRUE)",
|
|
generate_expression(Operator("not_regexp", true, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(generate_expression(Operator("+"), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(generate_expression(Operator("+", true), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(generate_expression(Operator("+", true, true, true),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, identifier) {
|
|
EXPECT_EQ("` schema \"'`.` table \"'`",
|
|
generate_expression(Identifier(" table \"'"), " schema \"'", true));
|
|
EXPECT_EQ("` schema \"'`.` table \"'`",
|
|
generate_expression(Identifier(" table \"'", " schema \"'"),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, variable) {
|
|
// EXPECT_EQ("@`'variable``\"`",
|
|
// generate_expression(Expr(Variable("'variable`\""))));
|
|
EXPECT_THROW(generate_expression(Expr(Variable("'variable`\"")), EMPTY_SCHEMA,
|
|
DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, column_identifier) {
|
|
Document_path doc_path{"docpath \"'"};
|
|
|
|
EXPECT_EQ("`column ``\"'`",
|
|
generate_expression(Column_identifier("column `\"'"), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("`table ``\"'`.`column ``\"'`",
|
|
generate_expression(Column_identifier("column `\"'", "table `\"'"),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("`schema ``\"'`.`table ``\"'`.`column ``\"'`",
|
|
generate_expression(
|
|
Column_identifier("column `\"'", "table `\"'", "schema `\"'"),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"JSON_EXTRACT(doc,'$.\\\"docpath \\\\\\\"\\'\\\"')",
|
|
generate_expression(Column_identifier(doc_path, EMPTY, EMPTY, EMPTY),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("JSON_EXTRACT(`\"'`` column`,'$.\\\"docpath \\\\\\\"\\'\\\"')",
|
|
generate_expression(
|
|
Column_identifier(doc_path, "\"'` column", EMPTY, EMPTY),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"JSON_EXTRACT(`\"'`` table`.`\"'`` column`,'$.\\\"docpath "
|
|
"\\\\\\\"\\'\\\"')",
|
|
generate_expression(
|
|
Column_identifier(doc_path, "\"'` column", "\"'` table", EMPTY),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"JSON_EXTRACT(`\"'`` schema`.`\"'`` table`."
|
|
"`\"'`` column`,'$.\\\"docpath \\\\\\\"\\'\\\"')",
|
|
generate_expression(Column_identifier(doc_path, "\"'` column",
|
|
"\"'` table", "\"'` schema"),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(generate_expression(Column_identifier(EMPTY, "table"),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(generate_expression(Column_identifier("column", EMPTY, "schema"),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, column_identifier_doc_id) {
|
|
Column_identifier ident(Document_path{"_id"});
|
|
ASSERT_EQ("JSON_EXTRACT(doc,'$._id')",
|
|
generate_expression(ident, EMPTY_SCHEMA, DM_TABLE));
|
|
ASSERT_EQ("JSON_EXTRACT(doc,'$._id')",
|
|
generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, column_identifier_doc_id_names) {
|
|
Column_identifier ident(Document_path{"_id"}, "field", "table", "schema");
|
|
ASSERT_EQ("JSON_EXTRACT(`schema`.`table`.`field`,'$._id')",
|
|
generate_expression(ident, EMPTY_SCHEMA, DM_TABLE));
|
|
ASSERT_EQ("JSON_EXTRACT(`schema`.`table`.`field`,'$._id')",
|
|
generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, column_identifier_no_column) {
|
|
Column_identifier ident(EMPTY, "table");
|
|
ASSERT_THROW(generate_expression(ident, EMPTY_SCHEMA, DM_DOCUMENT),
|
|
Expression_generator::Error);
|
|
|
|
ASSERT_THROW(generate_expression(ident, EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
|
|
Column_identifier ident2(Document_path{"member"}, EMPTY, "table", EMPTY);
|
|
ASSERT_EQ("JSON_EXTRACT(`table`.doc,'$.member')",
|
|
generate_expression(ident2, EMPTY_SCHEMA, DM_DOCUMENT));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, interval_expression) {
|
|
EXPECT_EQ("DATE_ADD(FALSE, INTERVAL TRUE MICROSECOND)",
|
|
generate_expression(
|
|
Operator("date_add", false, true, Octets{"MICROSECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE SECOND)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"SECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE MINUTE)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"MINUTE"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE HOUR)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"HOUR"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE DAY)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"DAY"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE WEEK)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"WEEK"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE MONTH)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"MONTH"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE QUARTER)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"QUARTER"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE YEAR)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"YEAR"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE SECOND_MICROSECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"SECOND_MICROSECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE MINUTE_MICROSECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"MINUTE_MICROSECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE MINUTE_SECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"MINUTE_SECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE HOUR_MICROSECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"HOUR_MICROSECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE HOUR_SECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"HOUR_SECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE HOUR_MINUTE)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"HOUR_MINUTE"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE DAY_MICROSECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"DAY_MICROSECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE DAY_SECOND)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"DAY_SECOND"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE DAY_MINUTE)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"DAY_MINUTE"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ(
|
|
"DATE_SUB(FALSE, INTERVAL TRUE DAY_HOUR)",
|
|
generate_expression(Operator("date_sub", false, true, Octets{"DAY_HOUR"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("DATE_SUB(FALSE, INTERVAL TRUE YEAR_MONTH)",
|
|
generate_expression(
|
|
Operator("date_sub", false, true, Octets{"YEAR_MONTH"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("date_sub", false, true, "invalid unit"),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("date_sub", false, true, true, true),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, in_expression) {
|
|
EXPECT_EQ(
|
|
"(FALSE IN (TRUE))",
|
|
generate_expression(Operator("in", false, true), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(FALSE NOT IN (TRUE))",
|
|
generate_expression(Operator("not_in", false, true), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("(FALSE IN (TRUE,FALSE))",
|
|
generate_expression(Operator("in", false, true, false),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_EQ("(FALSE NOT IN (TRUE,FALSE))",
|
|
generate_expression(Operator("not_in", false, true, false),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("in", false), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, between_expression) {
|
|
EXPECT_EQ("(2 BETWEEN 1 AND 3)",
|
|
generate_expression(Operator("between", 2, 1, 3), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("(2 NOT BETWEEN 1 AND 3)",
|
|
generate_expression(Operator("not_between", 2, 1, 3), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("between", 0, 0), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(generate_expression(Operator("between", 0, 0, 0, 0),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, like_expression) {
|
|
EXPECT_EQ("(TRUE LIKE FALSE)",
|
|
generate_expression(Operator("like", true, false), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("(TRUE NOT LIKE FALSE)",
|
|
generate_expression(Operator("not_like", true, false), EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
EXPECT_EQ("(TRUE LIKE FALSE ESCAPE TRUE)",
|
|
generate_expression(Operator("like", true, false, true),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("like", true), EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
EXPECT_THROW(generate_expression(Operator("like", true, true, true, true),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
std::invalid_argument);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, complex_expressions) {
|
|
EXPECT_EQ("(`schema`.`ident``` NOT LIKE 'string\\'' ESCAPE 'x')",
|
|
generate_expression(
|
|
Expr(Operator("not_like", Column_identifier("ident`", "schema"),
|
|
"string'", "x")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
|
|
EXPECT_EQ("((1 * 2) % (3 / 4))",
|
|
generate_expression(
|
|
Expr(Operator("%", Operator("*", 1, 2), Operator("/", 3, 4))),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
|
|
EXPECT_EQ("(`schema`.func(5,FALSE) IN (1,(+2),(-(7 - 0))))",
|
|
generate_expression(
|
|
Expr(Operator(
|
|
"in", Function_call(Identifier("func", "schema"), 5, false),
|
|
1, Operator("sign_plus", 2),
|
|
Operator("sign_minus", Operator("-", 7, 0)))),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_root) {
|
|
EXPECT_EQ("'$'", generate_expression(Document_path(Document_path()),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_empty_member) {
|
|
EXPECT_THROW(
|
|
generate_expression(Document_path{EMPTY, "name"}, EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_empty_member_opposite) {
|
|
EXPECT_THROW(
|
|
generate_expression(Document_path{"name", EMPTY}, EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_array) {
|
|
Document_path path;
|
|
EXPECT_EQ("'$.name[42]'", generate_expression(Document_path{"name", 42},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_root_array) {
|
|
Document_path path;
|
|
EXPECT_EQ("'$[42]'",
|
|
generate_expression(Document_path{42}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_member_asterisk) {
|
|
EXPECT_EQ(
|
|
"'$.name.*'",
|
|
generate_expression(
|
|
Document_path{"name", Document_path_item::Base::MEMBER_ASTERISK},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_root_asterisk) {
|
|
EXPECT_EQ("'$.*'",
|
|
generate_expression(
|
|
Document_path{Document_path_item::Base::MEMBER_ASTERISK},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_double_asterisk) {
|
|
EXPECT_EQ(
|
|
"'$.name**'",
|
|
generate_expression(
|
|
Document_path{"name", Document_path_item::Base::DOUBLE_ASTERISK},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_array_index) {
|
|
EXPECT_EQ("'$.name[42]'", generate_expression(Document_path{"name", 42},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_root_array_index) {
|
|
EXPECT_EQ("'$[42]'",
|
|
generate_expression(Document_path{42}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_array_index_asterisk) {
|
|
EXPECT_STREQ(
|
|
"'$.name[*]'",
|
|
generate_expression(
|
|
Document_path{"name", Document_path_item::Base::ARRAY_INDEX_ASTERISK},
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_root_array_index_asterisk) {
|
|
EXPECT_STREQ(
|
|
"'$[*]'",
|
|
generate_expression(
|
|
Document_path{Document_path_item::Base::ARRAY_INDEX_ASTERISK},
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, document_path_root_double_asterisk) {
|
|
EXPECT_EQ("'$**'",
|
|
generate_expression(
|
|
Document_path{Document_path_item::Base::DOUBLE_ASTERISK},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_not_found) {
|
|
EXPECT_THROW(generate_expression(Expr(Placeholder{10}), Expression_list(),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_found) {
|
|
EXPECT_EQ("2", generate_expression(Expr(Placeholder{0}), Expression_list{2},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_opearator_one_arg) {
|
|
EXPECT_EQ("(1 + 2)",
|
|
generate_expression(Operator("+", 1, Placeholder{0}),
|
|
Expression_list{2}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_opearator_two_args) {
|
|
EXPECT_EQ("(1 + 2)",
|
|
generate_expression(Operator("+", Placeholder{1}, Placeholder{0}),
|
|
Expression_list{2, 1}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_function) {
|
|
EXPECT_EQ(
|
|
"xschema.bar(42,'foo')",
|
|
generate_expression(Function_call("bar", Placeholder{0}, Placeholder{1}),
|
|
Expression_list{42, "foo"}, "xschema", true));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_function_and_operator) {
|
|
EXPECT_EQ(
|
|
"(xschema.bar(42,'foo') > 42)",
|
|
generate_expression(
|
|
Operator(">", Function_call("bar", Placeholder{0}, Placeholder{1}),
|
|
Placeholder{0}),
|
|
Expression_list{42, "foo"}, "xschema", true));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, placeholder_operator_null) {
|
|
EXPECT_EQ("(`bar` IS NOT NULL)",
|
|
generate_expression(
|
|
Operator("is_not", Column_identifier("bar"), Placeholder{0}),
|
|
Expression_list{Scalar::Null()}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_missing_param) {
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("cast", 42), EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_empty_type) {
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("cast", 42), EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_invalid_target_type) {
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("cast", 42, 44), EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_undefinied) {
|
|
EXPECT_THROW(generate_expression(Operator("cast", 42, Octets("UNDEFINIED")),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_expr_to_json) {
|
|
EXPECT_EQ(
|
|
"CAST(`foo`.`bar` AS JSON)",
|
|
generate_expression(
|
|
Operator("cast", Column_identifier("bar", "foo"), Octets{"JSON"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_signed) {
|
|
EXPECT_EQ("CAST(42 AS SIGNED)",
|
|
generate_expression(Operator("cast", 42, Octets{"SIGNED"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_signed_integer) {
|
|
EXPECT_EQ("CAST(42 AS SIGNED INTEGER)",
|
|
generate_expression(Operator("cast", 42, Octets{"SIGNED INTEGER"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_unsigned) {
|
|
EXPECT_EQ("CAST(42 AS UNSIGNED)",
|
|
generate_expression(Operator("cast", 42, Octets{"UNSIGNED"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_unsigned_integer) {
|
|
EXPECT_EQ(
|
|
"CAST(42 AS UNSIGNED INTEGER)",
|
|
generate_expression(Operator("cast", 42, Octets{"UNSIGNED INTEGER"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_char) {
|
|
EXPECT_EQ("CAST('one' AS CHAR)",
|
|
generate_expression(Operator("cast", "one", Octets{"CHAR"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_multichar) {
|
|
EXPECT_EQ("CAST('one' AS CHAR(42))",
|
|
generate_expression(Operator("cast", "one", Octets{"CHAR(42)"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_binary) {
|
|
EXPECT_EQ("CAST('one' AS BINARY)",
|
|
generate_expression(Operator("cast", "one", Octets{"BINARY"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_binary_lowercase) {
|
|
EXPECT_EQ("CAST('one' AS binary)",
|
|
generate_expression(Operator("cast", "one", Octets("binary")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_precision_binary) {
|
|
EXPECT_EQ("CAST('one' AS BINARY(44))",
|
|
generate_expression(Operator("cast", "one", Octets("BINARY(44)")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_decimal) {
|
|
EXPECT_EQ("CAST(3.141593 AS DECIMAL)",
|
|
generate_expression(Operator("cast", 3.141593, Octets("DECIMAL")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_precision_decimal) {
|
|
EXPECT_EQ(
|
|
"CAST(3.141593 AS DECIMAL(4))",
|
|
generate_expression(Operator("cast", 3.141593, Octets("DECIMAL(4)")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_precision_scale_decimal) {
|
|
EXPECT_EQ(
|
|
"CAST(3.141593 AS DECIMAL(4,2))",
|
|
generate_expression(Operator("cast", 3.141593, Octets("DECIMAL(4,2)")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_time) {
|
|
EXPECT_EQ("CAST('3:14' AS TIME)",
|
|
generate_expression(Operator("cast", "3:14", Octets("TIME")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_date) {
|
|
EXPECT_EQ("CAST('2015.08.10' AS DATE)",
|
|
generate_expression(Operator("cast", "2015.08.10", Octets("DATE")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_scalar_to_datetime) {
|
|
EXPECT_EQ("CAST('2015.08.10T3:14' AS DATETIME)",
|
|
generate_expression(
|
|
Operator("cast", "2015.08.10T3:14", Octets("DATETIME")),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cast_placeholder_to_json) {
|
|
Expression_generator::Prep_stmt_placeholder_list ids;
|
|
EXPECT_EQ(
|
|
"CAST(? AS JSON)",
|
|
generate_expression(Operator("cast", Placeholder(0), Octets("JSON")),
|
|
EMPTY_SCHEMA, DM_TABLE, &ids));
|
|
EXPECT_EQ(1, ids.size());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_empty) {
|
|
EXPECT_EQ("JSON_OBJECT()",
|
|
generate_expression(Object(), EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_empty_key) {
|
|
EXPECT_THROW(generate_expression(Object{{"", 1}}, EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_empty_value) {
|
|
EXPECT_THROW(
|
|
generate_expression(Object("first", nullptr), EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_one_scalar) {
|
|
EXPECT_EQ("JSON_OBJECT('first',1)",
|
|
generate_expression(Object{{"first", 1}}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_two_scalars) {
|
|
EXPECT_EQ("JSON_OBJECT('first',1,'second','two')",
|
|
generate_expression(Object{{"first", 1}, {"second", "two"}},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_object) {
|
|
EXPECT_EQ("JSON_OBJECT('second',JSON_OBJECT('first',1))",
|
|
generate_expression(Object{{"second", Object{{"first", 1}}}},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_as_expr) {
|
|
EXPECT_EQ("JSON_OBJECT('first',1)",
|
|
generate_expression(Object{{"first", 1}}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_operator) {
|
|
EXPECT_EQ("JSON_OBJECT('sum',(1 + 2))",
|
|
generate_expression(Object{{"sum", Operator("+", 1, 2)}},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_function) {
|
|
EXPECT_EQ("JSON_OBJECT('result',foo('bar'))",
|
|
generate_expression(Object{{"result", Function_call("foo", "bar")}},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_array) {
|
|
EXPECT_EQ("JSON_OBJECT('tab',JSON_ARRAY(1,2))",
|
|
generate_expression(Object{{"tab", Array{1, 2}}}, EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_in_function) {
|
|
EXPECT_EQ("foo(JSON_OBJECT('first',1))",
|
|
generate_expression(Function_call("foo", Object{{"first", 1}}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, object_real_example) {
|
|
EXPECT_EQ(
|
|
"JSON_OBJECT('name',concat("
|
|
"JSON_UNQUOTE(JSON_EXTRACT(doc,'$.first_name')),' ',"
|
|
"JSON_UNQUOTE(JSON_EXTRACT(doc,'$.last_name'))),'number',(1 + 1))",
|
|
generate_expression(
|
|
Object{{"name",
|
|
Function_call(
|
|
"concat", Column_identifier(Document_path{"first_name"}),
|
|
" ", Column_identifier(Document_path{"last_name"}))},
|
|
{"number", Operator("+", 1, 1)}},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_empty) {
|
|
EXPECT_EQ("JSON_ARRAY()",
|
|
generate_expression(Array(), EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_one_scalar) {
|
|
EXPECT_EQ("JSON_ARRAY(1)",
|
|
generate_expression(Array{1}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_two_scalars) {
|
|
EXPECT_EQ("JSON_ARRAY(1,'two')",
|
|
generate_expression(Array{1, "two"}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_as_expr) {
|
|
EXPECT_EQ("JSON_ARRAY(1)",
|
|
generate_expression(Expr(Array{1}), EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_array) {
|
|
EXPECT_EQ(
|
|
"JSON_ARRAY('one',JSON_ARRAY(1,2))",
|
|
generate_expression(Array{"one", Array{1, 2}}, EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_object) {
|
|
EXPECT_EQ("JSON_ARRAY(JSON_OBJECT('first',1),'two')",
|
|
generate_expression(Array{Object{{"first", 1}}, "two"},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_operator) {
|
|
EXPECT_EQ("JSON_ARRAY((1 + 2),'two')",
|
|
generate_expression(Array{Operator("+", 1, 2), "two"}, EMPTY_SCHEMA,
|
|
DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_function) {
|
|
EXPECT_EQ("JSON_ARRAY(foo('bar'),'two')",
|
|
generate_expression(Array{Function_call("foo", "bar"), "two"},
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_in_function) {
|
|
EXPECT_EQ("fun(JSON_ARRAY('foo','bar'))",
|
|
generate_expression(Function_call("fun", Array{"foo", "bar"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_in_operator) {
|
|
EXPECT_STREQ("JSON_CONTAINS(JSON_ARRAY(1,2),CAST(1 AS JSON))",
|
|
generate_expression(Operator("in", 1, Array{1, 2}), EMPTY_SCHEMA,
|
|
DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_not_in_operator) {
|
|
EXPECT_EQ("NOT JSON_CONTAINS(JSON_ARRAY(1,2),CAST(1 AS JSON))",
|
|
generate_expression(Operator("not_in", 1, Array{1, 2}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_in_operator_string) {
|
|
EXPECT_EQ("JSON_CONTAINS(JSON_ARRAY('foo','bar'),JSON_QUOTE('foo'))",
|
|
generate_expression(Operator("in", "foo", Array{"foo", "bar"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, array_not_in_operator_string) {
|
|
EXPECT_EQ("NOT JSON_CONTAINS(JSON_ARRAY('foo','bar'),JSON_QUOTE('foo'))",
|
|
generate_expression(Operator("not_in", "foo", Array{"foo", "bar"}),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, default_operator) {
|
|
EXPECT_EQ("DEFAULT",
|
|
generate_expression(Operator("default"), EMPTY_SCHEMA, DM_TABLE));
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("default", 42), EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, scalar_octets_plain) {
|
|
EXPECT_EQ("'ABC'", generate_expression(
|
|
Scalar(Octets("ABC", Octets::Content_type::k_plain)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, scalar_octets_geometry) {
|
|
EXPECT_EQ("ST_GEOMETRYFROMWKB('010')",
|
|
generate_expression(
|
|
Scalar(Octets("010", Octets::Content_type::k_geometry)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, scalar_octets_json) {
|
|
EXPECT_EQ("CAST('{\\\"a\\\":42}' AS JSON)",
|
|
generate_expression(
|
|
Scalar(Octets("{\"a\":42}", Octets::Content_type::k_json)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, scalar_octets_xml) {
|
|
EXPECT_EQ("'<a>bbb</a>'",
|
|
generate_expression(
|
|
Scalar(Octets("<a>bbb</a>", Octets::Content_type::k_xml)),
|
|
EMPTY_SCHEMA, DM_TABLE));
|
|
}
|
|
|
|
TEST(xpl_expr_generator, scalar_octets_unknown) {
|
|
EXPECT_THROW(
|
|
generate_expression(
|
|
Scalar(Octets("foo", static_cast<Octets::Content_type>(666))),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_literals) {
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST(1 AS JSON),CAST(2 AS JSON))",
|
|
generate_expression(Operator("cont_in", 2, 1), EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST(1.2 AS JSON),CAST(2.1 AS JSON))",
|
|
generate_expression(Operator("cont_in", 2.1, 1.2), EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ("JSON_CONTAINS(CAST(FALSE AS JSON),CAST(TRUE AS JSON))",
|
|
generate_expression(Operator("cont_in", true, false),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST('null' AS JSON),CAST('null' AS JSON))",
|
|
generate_expression(Operator("cont_in", Scalar::Null(), Scalar::Null()),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ("JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
|
|
generate_expression(Operator("cont_in", Scalar::String("black"),
|
|
Scalar::String("white")),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
|
|
generate_expression(
|
|
Operator("cont_in", Octets("black", Octets::Content_type::k_plain),
|
|
Octets("white", Octets::Content_type::k_plain)),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
|
|
"CAST('{\\\"black\\\":1}' AS JSON))",
|
|
generate_expression(
|
|
Operator("cont_in",
|
|
Octets("{\"black\":1}", Octets::Content_type::k_json),
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_QUOTE('<a>white</a>'),JSON_QUOTE('<a>black</a>'))",
|
|
generate_expression(
|
|
Operator("cont_in",
|
|
Octets("<a>black</a>", Octets::Content_type::k_xml),
|
|
Octets("<a>white</a>", Octets::Content_type::k_xml)),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_QUOTE(ST_GEOMETRYFROMWKB('101')),"
|
|
"JSON_QUOTE(ST_GEOMETRYFROMWKB('010')))",
|
|
generate_expression(
|
|
Operator("cont_in", Octets("010", Octets::Content_type::k_geometry),
|
|
Octets("101", Octets::Content_type::k_geometry)),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_arrays) {
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_ARRAY(3,4),JSON_ARRAY(1,2))",
|
|
generate_expression(Operator("cont_in", Array{1, 2}, Array{3, 4}),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_ARRAY(3,FALSE,'white'),JSON_ARRAY(1,TRUE,'black'))",
|
|
generate_expression(Operator("cont_in", Array{1, true, "black"},
|
|
Array{3, false, "white"}),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)),"
|
|
"JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)))",
|
|
generate_expression(
|
|
Operator(
|
|
"cont_in",
|
|
Array{Octets("{\"black\":1}", Octets::Content_type::k_json)},
|
|
Array{Octets("{\"white\":2}", Octets::Content_type::k_json)}),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_objects) {
|
|
EXPECT_STREQ("JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('first',1))",
|
|
generate_expression(Operator("cont_in", Object{{"first", 1}},
|
|
Object{{"second", 2}}),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)),"
|
|
"JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)))",
|
|
generate_expression(
|
|
Operator("cont_in",
|
|
Object{{"first", Octets("{\"black\":1}",
|
|
Octets::Content_type::k_json)}},
|
|
Object{{"second", Octets("{\"white\":2}",
|
|
Octets::Content_type::k_json)}}),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_operators) {
|
|
Operator plus("+", 1, 2), minus("-", 2, 1);
|
|
EXPECT_THROW(generate_expression(Operator("cont_in", plus, minus),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
EXPECT_STREQ("JSON_CONTAINS(CAST((2 - 1) AS JSON),CAST((1 + 2) AS JSON))",
|
|
generate_expression(
|
|
Operator("cont_in", Operator("cast", plus, Octets{"JSON"}),
|
|
Operator("cast", minus, Octets{"JSON"})),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_THROW(
|
|
generate_expression(
|
|
Operator("cont_in", plus, Operator("cast", minus, Octets("JSON"))),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
EXPECT_THROW(
|
|
generate_expression(
|
|
Operator("cont_in", Operator("cast", plus, Octets("JSON")), minus),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
EXPECT_THROW(generate_expression(
|
|
Operator("cont_in", Operator("cast", plus, Octets("SIGNED")),
|
|
Operator("cast", minus, Octets("JSON"))),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
EXPECT_THROW(generate_expression(
|
|
Operator("cont_in", Operator("cast", plus, Octets("JSON")),
|
|
Operator("cast", minus, Octets("SIGNED"))),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_functions) {
|
|
Function_call concat("concat", "foo", "bar");
|
|
EXPECT_THROW(generate_expression(Operator("cont_in", concat, concat),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(json_quote(concat('foo','bar')),"
|
|
"json_quote(concat('foo','bar')))",
|
|
generate_expression(
|
|
Operator("cont_in", Function_call("json_quote", concat),
|
|
Function_call("json_quote", concat)),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_THROW(
|
|
generate_expression(
|
|
Operator("cont_in", concat, Function_call("json_quote", concat)),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
EXPECT_THROW(
|
|
generate_expression(
|
|
Operator("cont_in", Function_call("json_quote", concat), concat),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_placeholders) {
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST(2 AS JSON),CAST(1 AS JSON))",
|
|
generate_expression(Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
Expression_list({1, 2}), EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ("JSON_CONTAINS(JSON_QUOTE('bar'),JSON_QUOTE('foo'))",
|
|
generate_expression(
|
|
Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
Expression_list({"foo", "bar"}), EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
|
|
"CAST('{\\\"black\\\":1}' AS JSON))",
|
|
generate_expression(
|
|
Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
Expression_list(
|
|
{Octets("{\"black\":1}", Octets::Content_type::k_json),
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)}),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
EXPECT_THROW(
|
|
generate_expression(Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
|
|
Expression_generator::Prep_stmt_placeholder_list ids;
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST(? AS JSON),CAST(? AS JSON))",
|
|
generate_expression(Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
EMPTY_SCHEMA, DM_TABLE, &ids)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, cont_in_expression_identifier) {
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(CAST(42 AS JSON),"
|
|
"JSON_EXTRACT(`schema`.`table`.`field`,'$.member'))",
|
|
generate_expression(
|
|
Operator("cont_in",
|
|
Column_identifier(Document_path{"member"}, "field", "table",
|
|
"schema"),
|
|
42),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(JSON_EXTRACT(`schema`.`table`.`field`,'$.member'),"
|
|
"CAST(42 AS JSON))",
|
|
generate_expression(
|
|
Operator("cont_in", 42,
|
|
Column_identifier(Document_path{"member"}, "field", "table",
|
|
"schema")),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
|
|
EXPECT_STREQ(
|
|
"JSON_CONTAINS(`schema`.`table`.`field`,"
|
|
"CAST(42 AS JSON))",
|
|
generate_expression(
|
|
Operator("cont_in", 42,
|
|
Column_identifier("field", "table", "schema")),
|
|
EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, any_scalar) {
|
|
EXPECT_STREQ("42",
|
|
generate_expression(Any(42), EMPTY_SCHEMA, DM_TABLE).c_str());
|
|
}
|
|
|
|
TEST(xpl_expr_generator, any_object) {
|
|
EXPECT_THROW(generate_expression(Any(Any::Object{{"name", Any(42)}}),
|
|
EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
TEST(xpl_expr_generator, any_array) {
|
|
EXPECT_THROW(
|
|
generate_expression(Any(Any::Array{"name", 42}), EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error);
|
|
}
|
|
|
|
struct Param_function_call {
|
|
std::string expect;
|
|
Function_call func;
|
|
std::string schema;
|
|
};
|
|
|
|
class Function_call_test : public testing::TestWithParam<Param_function_call> {
|
|
};
|
|
|
|
TEST_P(Function_call_test, function_call) {
|
|
const Param_function_call ¶m = GetParam();
|
|
EXPECT_STREQ(param.expect.c_str(),
|
|
generate_expression(param.func, param.schema, DM_TABLE).c_str());
|
|
}
|
|
|
|
Param_function_call function_call_param[] = {
|
|
{"func()", Function_call("func"), EMPTY_SCHEMA},
|
|
{"schema.func()", Function_call("func"), "schema"},
|
|
{"schema.func(FALSE,5)", Function_call("func", false, 5), "schema"},
|
|
{"concat(FALSE,5)", Function_call("concat", false, 5), "schema"},
|
|
{"CONCAT(FALSE,5)", Function_call("CONCAT", false, 5), "schema"},
|
|
{"CONCAT(FALSE,5)", Function_call("CONCAT", false, 5), EMPTY_SCHEMA},
|
|
{"ASCII('string')", Function_call("ASCII", "string"), EMPTY_SCHEMA},
|
|
{"ASCII(`column`)", Function_call("ASCII", Column_identifier("column")),
|
|
EMPTY_SCHEMA},
|
|
{"ASCII(JSON_UNQUOTE(JSON_EXTRACT(doc,'$.path')))",
|
|
Function_call("ASCII", Column_identifier(Document_path{"path"})),
|
|
EMPTY_SCHEMA},
|
|
{"ABS(42)", Function_call("ABS", 42), EMPTY_SCHEMA},
|
|
{"ABS(`column`)", Function_call("ABS", Column_identifier("column")),
|
|
EMPTY_SCHEMA},
|
|
{"ABS(JSON_UNQUOTE(JSON_EXTRACT(doc,'$.path')))",
|
|
Function_call("ABS", Column_identifier(Document_path{"path"})),
|
|
EMPTY_SCHEMA},
|
|
{"JSON_TYPE(42)", Function_call("JSON_TYPE", 42), EMPTY_SCHEMA},
|
|
{"JSON_TYPE(`column`)",
|
|
Function_call("JSON_TYPE", Column_identifier("column")), EMPTY_SCHEMA},
|
|
{"JSON_TYPE(JSON_EXTRACT(doc,'$.path'))",
|
|
Function_call("JSON_TYPE", Column_identifier(Document_path{"path"})),
|
|
EMPTY_SCHEMA},
|
|
{"JSON_KEYS('{\\\"a\\\":42}')", Function_call("JSON_KEYS", "{\"a\":42}"),
|
|
EMPTY_SCHEMA},
|
|
{"JSON_KEYS(`column`)",
|
|
Function_call("JSON_KEYS", Column_identifier("column")), EMPTY_SCHEMA},
|
|
{"JSON_KEYS(JSON_EXTRACT(doc,'$.path'))",
|
|
Function_call("JSON_KEYS", Column_identifier(Document_path{"path"})),
|
|
EMPTY_SCHEMA}};
|
|
|
|
INSTANTIATE_TEST_CASE_P(xpl_expr_generator_function_call, Function_call_test,
|
|
testing::ValuesIn(function_call_param));
|
|
|
|
struct Param_placeholders {
|
|
std::string expect;
|
|
Expression_generator::Prep_stmt_placeholder_list expect_ids;
|
|
Expression_list args;
|
|
Array expr;
|
|
};
|
|
|
|
class Placeholders_test : public testing::TestWithParam<Param_placeholders> {};
|
|
|
|
TEST_P(Placeholders_test, placeholders) {
|
|
const Param_placeholders ¶m = GetParam();
|
|
Query_string_builder qb;
|
|
Expression_generator gen(&qb, param.args, EMPTY_SCHEMA, DM_TABLE);
|
|
Expression_generator::Prep_stmt_placeholder_list ids;
|
|
gen.set_prep_stmt_placeholder_list(&ids);
|
|
gen.feed(param.expr);
|
|
|
|
EXPECT_STREQ(param.expect.c_str(), qb.get().c_str());
|
|
EXPECT_EQ(param.expect_ids, ids);
|
|
}
|
|
|
|
#define PH Placeholder
|
|
|
|
Param_placeholders placeholders_param[] = {
|
|
{"JSON_ARRAY(?)", {0}, {}, {PH{0}}},
|
|
{"JSON_ARRAY('a')", {}, {"a"}, {PH{0}}},
|
|
{"JSON_ARRAY(?)", {0}, {"a"}, {PH{1}}},
|
|
{"JSON_ARRAY(?,?)", {0, 0}, {}, {PH{0}, PH{0}}},
|
|
{"JSON_ARRAY(?,?)", {1, 0}, {}, {PH{1}, PH{0}}},
|
|
{"JSON_ARRAY('a',?)", {0}, {"a"}, {PH{0}, PH{1}}},
|
|
{"JSON_ARRAY(?,'a')", {0}, {"a"}, {PH{1}, PH{0}}},
|
|
{"JSON_ARRAY('a','b')", {}, {"a", "b"}, {PH{0}, PH{1}}},
|
|
{"JSON_ARRAY('a','b','a')", {}, {"a", "b"}, {PH{0}, PH{1}, PH{0}}},
|
|
{"JSON_ARRAY('a','b',?)", {0}, {"a", "b"}, {PH{0}, PH{1}, PH{2}}},
|
|
{"JSON_ARRAY('a',?,'b')", {0}, {"a", "b"}, {PH{0}, PH{2}, PH{1}}},
|
|
{"JSON_ARRAY(?,'a','b')", {0}, {"a", "b"}, {PH{2}, PH{0}, PH{1}}},
|
|
{"JSON_ARRAY(?,'a',?,'b',?)",
|
|
{0, 0, 0},
|
|
{"a", "b"},
|
|
{PH{2}, PH{0}, PH{2}, PH{1}, PH{2}}},
|
|
{"JSON_ARRAY(?,'a',?,'b',?)",
|
|
{0, 1, 0},
|
|
{"a", "b"},
|
|
{PH{2}, PH{0}, PH{3}, PH{1}, PH{2}}},
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(xpl_expr_generator_placeholders, Placeholders_test,
|
|
testing::ValuesIn(placeholders_param));
|
|
|
|
struct Param_operator_pass {
|
|
std::string expect;
|
|
Operator operator_;
|
|
Expression_list args;
|
|
};
|
|
|
|
class Operator_pass_test : public testing::TestWithParam<Param_operator_pass> {
|
|
};
|
|
|
|
TEST_P(Operator_pass_test, operator_pass) {
|
|
const auto ¶m = GetParam();
|
|
EXPECT_STREQ(
|
|
param.expect.c_str(),
|
|
generate_expression(param.operator_, param.args, EMPTY_SCHEMA, DM_TABLE)
|
|
.c_str());
|
|
}
|
|
|
|
Param_operator_pass cont_in_pass_param[] = {
|
|
// literals
|
|
{"JSON_CONTAINS(CAST(1 AS JSON),CAST(2 AS JSON))",
|
|
Operator("cont_in", 2, 1),
|
|
{}},
|
|
{"JSON_CONTAINS(CAST(1.2 AS JSON),CAST(2.1 AS JSON))",
|
|
Operator("cont_in", 2.1, 1.2),
|
|
{}},
|
|
{"JSON_CONTAINS(CAST(FALSE AS JSON),CAST(TRUE AS JSON))",
|
|
Operator("cont_in", true, false),
|
|
{}},
|
|
{"JSON_CONTAINS(CAST('null' AS JSON),CAST('null' AS JSON))",
|
|
Operator("cont_in", Scalar::Null(), Scalar::Null()),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
|
|
Operator("cont_in", Scalar::String("black"), Scalar::String("white")),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_QUOTE('white'),JSON_QUOTE('black'))",
|
|
Operator("cont_in", Octets("black", Octets::Content_type::k_plain),
|
|
Octets("white", Octets::Content_type::k_plain)),
|
|
{}},
|
|
{"JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
|
|
"CAST('{\\\"black\\\":1}' AS JSON))",
|
|
Operator("cont_in", Octets("{\"black\":1}", Octets::Content_type::k_json),
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_QUOTE('<a>white</a>'),JSON_QUOTE('<a>black</a>'))",
|
|
Operator("cont_in", Octets("<a>black</a>", Octets::Content_type::k_xml),
|
|
Octets("<a>white</a>", Octets::Content_type::k_xml)),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_QUOTE(ST_GEOMETRYFROMWKB('101')),"
|
|
"JSON_QUOTE(ST_GEOMETRYFROMWKB('010')))",
|
|
Operator("cont_in", Octets("010", Octets::Content_type::k_geometry),
|
|
Octets("101", Octets::Content_type::k_geometry)),
|
|
{}},
|
|
// arrays
|
|
{"JSON_CONTAINS(JSON_ARRAY(3,4),JSON_ARRAY(1,2))",
|
|
Operator("cont_in", Array{1, 2}, Array{3, 4}),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_ARRAY(3,FALSE,'white'),JSON_ARRAY(1,TRUE,'black'))",
|
|
Operator("cont_in", Array{1, true, "black"}, Array{3, false, "white"}),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)),"
|
|
"JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)))",
|
|
Operator("cont_in",
|
|
Array{Octets("{\"black\":1}", Octets::Content_type::k_json)},
|
|
Array{Octets("{\"white\":2}", Octets::Content_type::k_json)}),
|
|
{}},
|
|
// objects
|
|
{"JSON_CONTAINS(JSON_OBJECT('second',2),JSON_OBJECT('first',1))",
|
|
Operator("cont_in", Object{{"first", 1}}, Object{{"second", 2}}),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)),"
|
|
"JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)))",
|
|
Operator("cont_in",
|
|
Object{{"first",
|
|
Octets("{\"black\":1}", Octets::Content_type::k_json)}},
|
|
Object{{"second",
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)}}),
|
|
{}},
|
|
{"JSON_CONTAINS(CAST((2 - 1) AS JSON),CAST((1 + 2) AS JSON))",
|
|
Operator("cont_in", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
|
|
Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
|
|
{}},
|
|
// functions
|
|
{"JSON_CONTAINS(json_quote(concat('foo','bar')),"
|
|
"json_quote(concat('foo','bar')))",
|
|
Operator(
|
|
"cont_in",
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar")),
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar"))),
|
|
{}},
|
|
// placeholders
|
|
{"JSON_CONTAINS(CAST(2 AS JSON),CAST(1 AS JSON))",
|
|
Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
{1, 2}},
|
|
{"JSON_CONTAINS(JSON_QUOTE('bar'),JSON_QUOTE('foo'))",
|
|
Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
{"foo", "bar"}},
|
|
{"JSON_CONTAINS(CAST('{\\\"white\\\":2}' AS JSON),"
|
|
"CAST('{\\\"black\\\":1}' AS JSON))",
|
|
Operator("cont_in", Placeholder(0), Placeholder(1)),
|
|
{Octets("{\"black\":1}", Octets::Content_type::k_json),
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)}},
|
|
// identifier
|
|
{"JSON_CONTAINS(CAST(42 AS JSON),"
|
|
"JSON_EXTRACT(`schema`.`table`.`field`,'$.member'))",
|
|
Operator(
|
|
"cont_in",
|
|
Column_identifier(Document_path{"member"}, "field", "table", "schema"),
|
|
42),
|
|
{}},
|
|
{"JSON_CONTAINS(JSON_EXTRACT(`schema`.`table`.`field`,'$.member'),"
|
|
"CAST(42 AS JSON))",
|
|
Operator("cont_in", 42,
|
|
Column_identifier(Document_path{"member"}, "field", "table",
|
|
"schema")),
|
|
{}},
|
|
{"JSON_CONTAINS(`schema`.`table`.`field`,CAST(42 AS JSON))",
|
|
Operator("cont_in", 42, Column_identifier("field", "table", "schema")),
|
|
{}},
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(xpl_expr_generator_cont_in_pass, Operator_pass_test,
|
|
testing::ValuesIn(cont_in_pass_param));
|
|
|
|
struct Param_operator_fail {
|
|
Operator operator_;
|
|
Expression_list args;
|
|
};
|
|
|
|
class Operator_fail_test : public testing::TestWithParam<Param_operator_fail> {
|
|
};
|
|
|
|
TEST_P(Operator_fail_test, operator_fail) {
|
|
const auto ¶m = GetParam();
|
|
EXPECT_THROW(
|
|
generate_expression(param.operator_, param.args, EMPTY_SCHEMA, DM_TABLE),
|
|
Expression_generator::Error)
|
|
<< "Should throw for: " << msg_to_string(param.operator_.base());
|
|
}
|
|
|
|
Param_operator_fail cont_in_fail_param[] = {
|
|
// literals
|
|
// arrays
|
|
// objects
|
|
// operators
|
|
{Operator("cont_in", Operator("+", 1, 2), Operator("-", 2, 1)), {}},
|
|
{Operator("cont_in", Operator("+", 1, 2),
|
|
Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
|
|
{}},
|
|
{Operator("cont_in", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
|
|
Operator("-", 2, 1)),
|
|
{}},
|
|
{Operator("cont_in",
|
|
Operator("cast", Operator("+", 1, 2), Octets("SIGNED")),
|
|
Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
|
|
{}},
|
|
{Operator("cont_in", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
|
|
Operator("cast", Operator("-", 2, 1), Octets("SIGNED"))),
|
|
{}},
|
|
// functions
|
|
{Operator("cont_in", Function_call("concat", "foo", "bar"),
|
|
Function_call("concat", "foo", "bar")),
|
|
{}},
|
|
{Operator(
|
|
"cont_in", Function_call("concat", "foo", "bar"),
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar"))),
|
|
{}},
|
|
{Operator(
|
|
"cont_in",
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar")),
|
|
Function_call("concat", "foo", "bar")),
|
|
{}},
|
|
// placeholders
|
|
{Operator("cont_in", Placeholder(0), Placeholder(1)), {}},
|
|
// identifier
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(xpl_expr_generator_cont_in_fail, Operator_fail_test,
|
|
testing::ValuesIn(cont_in_fail_param));
|
|
|
|
Param_operator_pass overlaps_pass_param[] = {
|
|
// literals
|
|
{"JSON_OVERLAPS(CAST(2 AS JSON),CAST(1 AS JSON))",
|
|
Operator("overlaps", 2, 1),
|
|
{}},
|
|
{"JSON_OVERLAPS(CAST(2.1 AS JSON),CAST(1.2 AS JSON))",
|
|
Operator("overlaps", 2.1, 1.2),
|
|
{}},
|
|
{"JSON_OVERLAPS(CAST(TRUE AS JSON),CAST(FALSE AS JSON))",
|
|
Operator("overlaps", true, false),
|
|
{}},
|
|
{"JSON_OVERLAPS(CAST('null' AS JSON),CAST('null' AS JSON))",
|
|
Operator("overlaps", Scalar::Null(), Scalar::Null()),
|
|
{}},
|
|
{"JSON_OVERLAPS(JSON_QUOTE('black'),JSON_QUOTE('white'))",
|
|
Operator("overlaps", Scalar::String("black"), Scalar::String("white")),
|
|
{}},
|
|
{"JSON_OVERLAPS(JSON_QUOTE('black'),JSON_QUOTE('white'))",
|
|
Operator("overlaps", Octets("black", Octets::Content_type::k_plain),
|
|
Octets("white", Octets::Content_type::k_plain)),
|
|
{}},
|
|
{"JSON_OVERLAPS("
|
|
"CAST('{\\\"black\\\":1}' AS JSON),CAST('{\\\"white\\\":2}' AS JSON))",
|
|
Operator("overlaps", Octets("{\"black\":1}", Octets::Content_type::k_json),
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)),
|
|
{}},
|
|
{"JSON_OVERLAPS(JSON_QUOTE('<a>black</a>'),JSON_QUOTE('<a>white</a>'))",
|
|
Operator("overlaps", Octets("<a>black</a>", Octets::Content_type::k_xml),
|
|
Octets("<a>white</a>", Octets::Content_type::k_xml)),
|
|
{}},
|
|
{"JSON_OVERLAPS("
|
|
"JSON_QUOTE(ST_GEOMETRYFROMWKB('010')),"
|
|
"JSON_QUOTE(ST_GEOMETRYFROMWKB('101')))",
|
|
Operator("overlaps", Octets("010", Octets::Content_type::k_geometry),
|
|
Octets("101", Octets::Content_type::k_geometry)),
|
|
{}},
|
|
// arrays
|
|
{"JSON_OVERLAPS(JSON_ARRAY(1,2),JSON_ARRAY(3,4))",
|
|
Operator("overlaps", Array{1, 2}, Array{3, 4}),
|
|
{}},
|
|
{"JSON_OVERLAPS(JSON_ARRAY(1,TRUE,'black'),JSON_ARRAY(3,FALSE,'white'))",
|
|
Operator("overlaps", Array{1, true, "black"}, Array{3, false, "white"}),
|
|
{}},
|
|
{"JSON_OVERLAPS("
|
|
"JSON_ARRAY(CAST('{\\\"black\\\":1}' AS JSON)),"
|
|
"JSON_ARRAY(CAST('{\\\"white\\\":2}' AS JSON)))",
|
|
Operator("overlaps",
|
|
Array{Octets("{\"black\":1}", Octets::Content_type::k_json)},
|
|
Array{Octets("{\"white\":2}", Octets::Content_type::k_json)}),
|
|
{}},
|
|
// objects
|
|
{"JSON_OVERLAPS(JSON_OBJECT('first',1),JSON_OBJECT('second',2))",
|
|
Operator("overlaps", Object{{"first", 1}}, Object{{"second", 2}}),
|
|
{}},
|
|
{"JSON_OVERLAPS("
|
|
"JSON_OBJECT('first',CAST('{\\\"black\\\":1}' AS JSON)),"
|
|
"JSON_OBJECT('second',CAST('{\\\"white\\\":2}' AS JSON)))",
|
|
Operator("overlaps",
|
|
Object{{"first",
|
|
Octets("{\"black\":1}", Octets::Content_type::k_json)}},
|
|
Object{{"second",
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)}}),
|
|
{}},
|
|
{"JSON_OVERLAPS(CAST((1 + 2) AS JSON),CAST((2 - 1) AS JSON))",
|
|
Operator("overlaps", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
|
|
Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
|
|
{}},
|
|
// functions
|
|
{"JSON_OVERLAPS("
|
|
"json_quote(concat('foo','bar')),"
|
|
"json_quote(concat('foo','bar')))",
|
|
Operator(
|
|
"overlaps",
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar")),
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar"))),
|
|
{}},
|
|
// placeholders
|
|
{"JSON_OVERLAPS(CAST(1 AS JSON),CAST(2 AS JSON))",
|
|
Operator("overlaps", Placeholder(0), Placeholder(1)),
|
|
{1, 2}},
|
|
{"JSON_OVERLAPS(JSON_QUOTE('foo'),JSON_QUOTE('bar'))",
|
|
Operator("overlaps", Placeholder(0), Placeholder(1)),
|
|
{"foo", "bar"}},
|
|
{"JSON_OVERLAPS("
|
|
"CAST('{\\\"black\\\":1}' AS JSON),"
|
|
"CAST('{\\\"white\\\":2}' AS JSON))",
|
|
Operator("overlaps", Placeholder(0), Placeholder(1)),
|
|
{Octets("{\"black\":1}", Octets::Content_type::k_json),
|
|
Octets("{\"white\":2}", Octets::Content_type::k_json)}},
|
|
// identifier
|
|
{"JSON_OVERLAPS("
|
|
"JSON_EXTRACT(`schema`.`table`.`field`,'$.member'),"
|
|
"CAST(42 AS JSON))",
|
|
Operator(
|
|
"overlaps",
|
|
Column_identifier(Document_path{"member"}, "field", "table", "schema"),
|
|
42),
|
|
{}},
|
|
{"JSON_OVERLAPS("
|
|
"CAST(42 AS JSON),"
|
|
"JSON_EXTRACT(`schema`.`table`.`field`,'$.member'))",
|
|
Operator("overlaps", 42,
|
|
Column_identifier(Document_path{"member"}, "field", "table",
|
|
"schema")),
|
|
{}},
|
|
{"JSON_OVERLAPS("
|
|
"CAST(42 AS JSON),"
|
|
"`schema`.`table`.`field`)",
|
|
Operator("overlaps", 42, Column_identifier("field", "table", "schema")),
|
|
{}},
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(xpl_expr_generator_overlaps_pass, Operator_pass_test,
|
|
testing::ValuesIn(overlaps_pass_param));
|
|
|
|
Param_operator_fail overlaps_fail_param[] = {
|
|
// literals
|
|
// arrays
|
|
// objects
|
|
// operators
|
|
{Operator("overlaps", Operator("+", 1, 2), Operator("-", 2, 1)), {}},
|
|
{Operator("overlaps", Operator("+", 1, 2),
|
|
Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
|
|
{}},
|
|
{Operator("overlaps", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
|
|
Operator("-", 2, 1)),
|
|
{}},
|
|
{Operator("overlaps",
|
|
Operator("cast", Operator("+", 1, 2), Octets("SIGNED")),
|
|
Operator("cast", Operator("-", 2, 1), Octets("JSON"))),
|
|
{}},
|
|
{Operator("overlaps", Operator("cast", Operator("+", 1, 2), Octets("JSON")),
|
|
Operator("cast", Operator("-", 2, 1), Octets("SIGNED"))),
|
|
{}},
|
|
// functions
|
|
{Operator("overlaps", Function_call("concat", "foo", "bar"),
|
|
Function_call("concat", "foo", "bar")),
|
|
{}},
|
|
{Operator(
|
|
"overlaps", Function_call("concat", "foo", "bar"),
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar"))),
|
|
{}},
|
|
{Operator(
|
|
"overlaps",
|
|
Function_call("json_quote", Function_call("concat", "foo", "bar")),
|
|
Function_call("concat", "foo", "bar")),
|
|
{}},
|
|
// placeholders
|
|
{Operator("overlaps", Placeholder(0), Placeholder(1)), {}},
|
|
// identifier
|
|
};
|
|
|
|
INSTANTIATE_TEST_CASE_P(xpl_expr_generator_overlaps_fail, Operator_fail_test,
|
|
testing::ValuesIn(overlaps_fail_param));
|
|
|
|
} // namespace test
|
|
} // namespace xpl
|