26 #include <boost/algorithm/string.hpp>
27 #include <boost/core/null_deleter.hpp>
28 #include <boost/filesystem.hpp>
29 #include <boost/function.hpp>
31 #include <rapidjson/document.h>
32 #include <rapidjson/stringbuffer.h>
33 #include <rapidjson/writer.h>
42 #include <type_traits>
77 #include "gen-cpp/CalciteServer.h"
85 #ifdef ENABLE_IMPORT_PARQUET
86 bool g_enable_legacy_parquet_import{
false};
95 using namespace std::string_literals;
99 const std::list<ColumnDescriptor>& columns)>;
104 const std::list<ColumnDescriptor>& columns)>;
113 executor->getSessionLock());
114 return executor->checkIsQuerySessionInterrupted(query_session, session_read_lock);
121 std::vector<int> table_chunk_key_prefix;
124 table_chunk_key_prefix = td->
fragmenter->getFragmentsForQuery().chunkKeyPrefix;
127 table_chunk_key_prefix.push_back(td->
tableId);
130 return table_chunk_key_prefix;
133 std::shared_ptr<Analyzer::Expr> NullLiteral::analyze(
137 return makeExpr<Analyzer::Constant>(
kNULLT,
true);
140 std::shared_ptr<Analyzer::Expr> StringLiteral::analyze(
144 return analyzeValue(*stringval_,
false);
147 std::shared_ptr<Analyzer::Expr> StringLiteral::analyzeValue(
const std::string& stringval,
152 d.
stringval =
new std::string(stringval);
153 return makeExpr<Analyzer::Constant>(ti,
false, d);
156 return makeExpr<Analyzer::Constant>(
kVARCHAR,
true);
159 std::shared_ptr<Analyzer::Expr> IntLiteral::analyze(
163 return analyzeValue(intval_);
166 std::shared_ptr<Analyzer::Expr> IntLiteral::analyzeValue(
const int64_t intval) {
169 if (intval >= INT16_MIN && intval <= INT16_MAX) {
172 }
else if (intval >= INT32_MIN && intval <= INT32_MAX) {
174 d.
intval = (int32_t)intval;
179 return makeExpr<Analyzer::Constant>(t,
false, d);
182 std::shared_ptr<Analyzer::Expr> FixedPtLiteral::analyze(
188 return makeExpr<Analyzer::Constant>(ti,
false, d);
191 std::shared_ptr<Analyzer::Expr> FixedPtLiteral::analyzeValue(
const int64_t numericval,
193 const int precision) {
199 return makeExpr<Analyzer::Constant>(ti,
false, d);
202 std::shared_ptr<Analyzer::Expr> FloatLiteral::analyze(
208 return makeExpr<Analyzer::Constant>(
kFLOAT,
false, d);
211 std::shared_ptr<Analyzer::Expr> DoubleLiteral::analyze(
217 return makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
220 std::shared_ptr<Analyzer::Expr> TimestampLiteral::analyze(
224 return get(timestampval_);
227 std::shared_ptr<Analyzer::Expr> TimestampLiteral::get(
const int64_t timestampval) {
230 return makeExpr<Analyzer::Constant>(
kTIMESTAMP,
false, d);
233 std::shared_ptr<Analyzer::Expr> UserLiteral::analyze(
238 return makeExpr<Analyzer::Constant>(
kTEXT,
false, d);
241 std::shared_ptr<Analyzer::Expr> UserLiteral::get(
const std::string& user) {
244 return makeExpr<Analyzer::Constant>(
kTEXT,
false, d);
247 std::shared_ptr<Analyzer::Expr> ArrayLiteral::analyze(
252 bool set_subtype =
true;
253 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
254 for (
auto& p : value_list_) {
255 auto e = p->analyze(catalog, query, allow_tlist_ref);
258 if (c !=
nullptr && c->get_is_null()) {
259 value_exprs.push_back(c);
265 }
else if (set_subtype) {
269 value_exprs.push_back(e);
271 std::shared_ptr<Analyzer::Expr>
result =
272 makeExpr<Analyzer::Constant>(ti,
false, value_exprs);
277 std::string str =
"{";
278 bool notfirst =
false;
279 for (
auto& p : value_list_) {
285 str += p->to_string();
291 std::shared_ptr<Analyzer::Expr> OperExpr::analyze(
295 auto left_expr = left_->analyze(catalog, query, allow_tlist_ref);
296 const auto& left_type = left_expr->get_type_info();
297 if (right_ ==
nullptr) {
298 return makeExpr<Analyzer::UOper>(
299 left_type, left_expr->get_contains_agg(), optype_, left_expr->decompress());
302 if (left_type.get_type() !=
kARRAY) {
303 throw std::runtime_error(left_->to_string() +
" is not of array type.");
305 auto right_expr = right_->analyze(catalog, query, allow_tlist_ref);
306 const auto& right_type = right_expr->get_type_info();
307 if (!right_type.is_integer()) {
308 throw std::runtime_error(right_->to_string() +
" is not of integer type.");
310 return makeExpr<Analyzer::BinOper>(
311 left_type.get_elem_type(),
false,
kARRAY_AT,
kONE, left_expr, right_expr);
313 auto right_expr = right_->analyze(catalog, query, allow_tlist_ref);
314 return normalize(optype_, opqualifier_, left_expr, right_expr);
318 const std::shared_ptr<Analyzer::Expr>& rhs_expr) {
319 if (dynamic_cast<Analyzer::Constant*>(rhs_expr.get())) {
323 std::set<int> lhs_rte_idx;
324 lhs_expr->collect_rte_idx(lhs_rte_idx);
325 CHECK(!lhs_rte_idx.empty());
326 std::set<int> rhs_rte_idx;
327 rhs_expr->collect_rte_idx(rhs_rte_idx);
328 CHECK(!rhs_rte_idx.empty());
329 return lhs_rte_idx.size() == 1UL && lhs_rte_idx == rhs_rte_idx;
334 const Executor* executor) {
341 CHECK_NE(lhs_dict_key, rhs_dict_key);
342 if (lhs_dict_key.isTransientDict()) {
343 return rhs_type_info;
345 if (rhs_dict_key.isTransientDict()) {
346 return lhs_type_info;
350 const auto lhs_sdp = executor->getStringDictionaryProxy(lhs_dict_key,
true);
351 const auto rhs_sdp = executor->getStringDictionaryProxy(rhs_dict_key,
true);
352 return lhs_sdp->entryCount() >= rhs_sdp->entryCount() ? lhs_type_info : rhs_type_info;
357 const Executor* executor) {
363 if (lhs_dict_key == rhs_dict_key ||
364 (lhs_dict_key.db_id == rhs_dict_key.db_id &&
366 return lhs_dict_key.
dict_id <= rhs_dict_key.dict_id ? lhs_type_info : rhs_type_info;
373 if (ret_ti.is_none_encoded_string()) {
380 std::shared_ptr<Analyzer::Expr> OperExpr::normalize(
383 std::shared_ptr<Analyzer::Expr> left_expr,
384 std::shared_ptr<Analyzer::Expr> right_expr,
385 const Executor* executor) {
386 if (left_expr->get_type_info().is_date_in_days() ||
387 right_expr->get_type_info().is_date_in_days()) {
389 left_expr = left_expr->decompress();
390 right_expr = right_expr->decompress();
392 const auto& left_type = left_expr->get_type_info();
393 auto right_type = right_expr->get_type_info();
396 CHECK(!std::dynamic_pointer_cast<Analyzer::Subquery>(right_expr));
397 if (right_type.get_type() !=
kARRAY) {
398 throw std::runtime_error(
399 "Existential or universal qualifiers can only be used in front of a subquery "
401 "expression of array type.");
403 right_type = right_type.get_elem_type();
408 optype, left_type, right_type, &new_left_type, &new_right_type);
409 if (result_type.is_timeinterval()) {
410 return makeExpr<Analyzer::BinOper>(
411 result_type,
false, optype, qual, left_expr, right_expr);
413 if (left_type != new_left_type) {
414 left_expr = left_expr->add_cast(new_left_type);
416 if (right_type != new_right_type) {
418 right_expr = right_expr->add_cast(new_right_type);
420 right_expr = right_expr->add_cast(new_right_type.
get_array_type());
427 throw std::runtime_error(
428 "Comparison operators are not yet supported for geospatial types.");
434 if (optype ==
kEQ || optype ==
kNE) {
446 auto& expr_to_cast = ti == new_left_type ? right_expr : left_expr;
449 expr_to_cast = expr_to_cast->add_cast(ti);
454 left_expr = left_expr->decompress();
455 right_expr = right_expr->decompress();
461 left_expr = left_expr->decompress();
462 right_expr = right_expr->decompress();
465 if (!(optype ==
kEQ || optype ==
kNE)) {
468 left_expr = left_expr->decompress();
469 right_expr = right_expr->decompress();
483 right_expr = right_expr->add_cast(ti);
491 left_expr = left_expr->add_cast(ti);
493 left_expr = left_expr->decompress();
494 right_expr = right_expr->decompress();
498 left_expr = left_expr->decompress();
499 right_expr = right_expr->decompress();
501 bool has_agg = (left_expr->get_contains_agg() || right_expr->get_contains_agg());
502 return makeExpr<Analyzer::BinOper>(
503 result_type, has_agg, optype, qual, left_expr, right_expr);
506 std::shared_ptr<Analyzer::Expr> SubqueryExpr::analyze(
510 throw std::runtime_error(
"Subqueries are not supported yet.");
514 std::shared_ptr<Analyzer::Expr> IsNullExpr::analyze(
518 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
526 std::shared_ptr<Analyzer::Expr> InSubquery::analyze(
530 throw std::runtime_error(
"Subqueries are not supported yet.");
534 std::shared_ptr<Analyzer::Expr> InValues::analyze(
538 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
541 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
542 for (
auto& p : value_list_) {
543 auto e = p->analyze(catalog, query, allow_tlist_ref);
544 if (ti != e->get_type_info()) {
545 if (ti.
is_string() && e->get_type_info().is_string()) {
548 }
else if (ti.
is_number() && e->get_type_info().is_number()) {
551 throw std::runtime_error(
"IN expressions must contain compatible types.");
555 value_exprs.push_back(e->add_cast(arg_expr->get_type_info()));
557 value_exprs.push_back(e);
561 arg_expr = arg_expr->decompress();
562 arg_expr = arg_expr->add_cast(ti);
563 std::list<std::shared_ptr<Analyzer::Expr>> cast_vals;
564 for (
auto p : value_exprs) {
565 cast_vals.push_back(p->add_cast(ti));
567 value_exprs.swap(cast_vals);
569 std::shared_ptr<Analyzer::Expr>
result =
570 makeExpr<Analyzer::InValues>(arg_expr, value_exprs);
577 std::shared_ptr<Analyzer::Expr> BetweenExpr::analyze(
581 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
582 auto lower_expr = lower_->analyze(catalog, query, allow_tlist_ref);
583 auto upper_expr = upper_->analyze(catalog, query, allow_tlist_ref);
586 arg_expr->get_type_info(),
587 lower_expr->get_type_info(),
591 makeExpr<Analyzer::BinOper>(
kBOOLEAN,
594 arg_expr->add_cast(new_left_type)->decompress(),
595 lower_expr->add_cast(new_right_type)->decompress());
597 arg_expr->get_type_info(),
598 lower_expr->get_type_info(),
601 auto upper_pred = makeExpr<Analyzer::BinOper>(
605 arg_expr->deep_copy()->add_cast(new_left_type)->decompress(),
606 upper_expr->add_cast(new_right_type)->decompress());
607 std::shared_ptr<Analyzer::Expr>
result =
615 std::shared_ptr<Analyzer::Expr> CharLengthExpr::analyze(
619 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
620 if (!arg_expr->get_type_info().is_string()) {
621 throw std::runtime_error(
622 "expression in char_length clause must be of a string type.");
624 std::shared_ptr<Analyzer::Expr>
result =
625 makeExpr<Analyzer::CharLengthExpr>(arg_expr->decompress(), calc_encoded_length_);
629 std::shared_ptr<Analyzer::Expr> CardinalityExpr::analyze(
633 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
634 if (!arg_expr->get_type_info().is_array()) {
635 throw std::runtime_error(
636 "expression in cardinality clause must be of an array type.");
638 std::shared_ptr<Analyzer::Expr>
result =
639 makeExpr<Analyzer::CardinalityExpr>(arg_expr->decompress());
643 void LikeExpr::check_like_expr(
const std::string& like_str,
char escape_char) {
644 if (like_str.back() == escape_char) {
645 throw std::runtime_error(
"LIKE pattern must not end with escape character.");
649 bool LikeExpr::test_is_simple_expr(
const std::string& like_str,
char escape_char) {
651 if (like_str.size() < 2 || like_str[0] !=
'%' || like_str[like_str.size() - 1] !=
'%') {
655 if (like_str[like_str.size() - 2] == escape_char &&
656 like_str[like_str.size() - 3] != escape_char) {
659 for (
size_t i = 1; i < like_str.size() - 1; i++) {
660 if (like_str[i] ==
'%' || like_str[i] ==
'_' || like_str[i] ==
'[' ||
661 like_str[i] ==
']') {
662 if (like_str[i - 1] != escape_char) {
670 void LikeExpr::erase_cntl_chars(std::string& like_str,
char escape_char) {
671 char prev_char =
'\0';
676 for (
char& cur_char : like_str) {
677 if (cur_char ==
'%' || cur_char == escape_char) {
678 if (prev_char != escape_char) {
679 prev_char = cur_char;
683 new_str.push_back(cur_char);
684 prev_char = cur_char;
689 std::shared_ptr<Analyzer::Expr> LikeExpr::analyze(
693 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
694 auto like_expr = like_string_->analyze(catalog, query, allow_tlist_ref);
695 auto escape_expr = escape_string_ ==
nullptr
697 : escape_string_->analyze(catalog, query, allow_tlist_ref);
698 return LikeExpr::get(arg_expr, like_expr, escape_expr, is_ilike_, is_not_);
701 std::shared_ptr<Analyzer::Expr> LikeExpr::get(std::shared_ptr<Analyzer::Expr> arg_expr,
702 std::shared_ptr<Analyzer::Expr> like_expr,
703 std::shared_ptr<Analyzer::Expr> escape_expr,
706 if (!arg_expr->get_type_info().is_string()) {
707 throw std::runtime_error(
"expression before LIKE must be of a string type.");
709 if (!like_expr->get_type_info().is_string()) {
710 throw std::runtime_error(
"expression after LIKE must be of a string type.");
712 char escape_char =
'\\';
713 if (escape_expr !=
nullptr) {
714 if (!escape_expr->get_type_info().is_string()) {
715 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
717 if (!escape_expr->get_type_info().is_string()) {
718 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
721 if (c !=
nullptr && c->get_constval().stringval->length() > 1) {
722 throw std::runtime_error(
"String after ESCAPE must have a single character.");
724 escape_char = (*c->get_constval().stringval)[0];
727 bool is_simple =
false;
731 std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
733 check_like_expr(pattern, escape_char);
734 is_simple = test_is_simple_expr(pattern, escape_char);
736 erase_cntl_chars(pattern, escape_char);
739 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::LikeExpr>(
740 arg_expr->decompress(), like_expr, escape_expr, is_ilike, is_simple);
747 void RegexpExpr::check_pattern_expr(
const std::string& pattern_str,
char escape_char) {
748 if (pattern_str.back() == escape_char) {
749 throw std::runtime_error(
"REGEXP pattern must not end with escape character.");
753 bool RegexpExpr::translate_to_like_pattern(std::string& pattern_str,
char escape_char) {
754 char prev_char =
'\0';
755 char prev_prev_char =
'\0';
756 std::string like_str;
757 for (
char& cur_char : pattern_str) {
758 if (prev_char == escape_char || isalnum(cur_char) || cur_char ==
' ' ||
760 like_str.push_back((cur_char ==
'.') ?
'_' : cur_char);
761 prev_prev_char = prev_char;
762 prev_char = cur_char;
765 if (prev_char ==
'.' && prev_prev_char != escape_char) {
766 if (cur_char ==
'*' || cur_char ==
'+') {
767 if (cur_char ==
'*') {
772 like_str.push_back(
'%');
773 prev_prev_char = prev_char;
774 prev_char = cur_char;
780 pattern_str = like_str;
784 std::shared_ptr<Analyzer::Expr> RegexpExpr::analyze(
788 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
789 auto pattern_expr = pattern_string_->analyze(catalog, query, allow_tlist_ref);
790 auto escape_expr = escape_string_ ==
nullptr
792 : escape_string_->analyze(catalog, query, allow_tlist_ref);
793 return RegexpExpr::get(arg_expr, pattern_expr, escape_expr, is_not_);
796 std::shared_ptr<Analyzer::Expr> RegexpExpr::get(
797 std::shared_ptr<Analyzer::Expr> arg_expr,
798 std::shared_ptr<Analyzer::Expr> pattern_expr,
799 std::shared_ptr<Analyzer::Expr> escape_expr,
801 if (!arg_expr->get_type_info().is_string()) {
802 throw std::runtime_error(
"expression before REGEXP must be of a string type.");
804 if (!pattern_expr->get_type_info().is_string()) {
805 throw std::runtime_error(
"expression after REGEXP must be of a string type.");
807 char escape_char =
'\\';
808 if (escape_expr !=
nullptr) {
809 if (!escape_expr->get_type_info().is_string()) {
810 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
812 if (!escape_expr->get_type_info().is_string()) {
813 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
816 if (c !=
nullptr && c->get_constval().stringval->length() > 1) {
817 throw std::runtime_error(
"String after ESCAPE must have a single character.");
819 escape_char = (*c->get_constval().stringval)[0];
820 if (escape_char !=
'\\') {
821 throw std::runtime_error(
"Only supporting '\\' escape character.");
827 if (translate_to_like_pattern(pattern, escape_char)) {
828 return LikeExpr::get(arg_expr, pattern_expr, escape_expr,
false, is_not);
831 std::shared_ptr<Analyzer::Expr>
result =
832 makeExpr<Analyzer::RegexpExpr>(arg_expr->decompress(), pattern_expr, escape_expr);
839 std::shared_ptr<Analyzer::Expr> LikelihoodExpr::analyze(
843 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
844 return LikelihoodExpr::get(arg_expr, likelihood_, is_not_);
847 std::shared_ptr<Analyzer::Expr> LikelihoodExpr::get(
848 std::shared_ptr<Analyzer::Expr> arg_expr,
851 if (!arg_expr->get_type_info().is_boolean()) {
852 throw std::runtime_error(
"likelihood expression expects boolean type.");
854 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::LikelihoodExpr>(
855 arg_expr->decompress(), is_not ? 1 - likelihood : likelihood);
859 std::shared_ptr<Analyzer::Expr> WidthBucketExpr::analyze(
863 auto target_value = target_value_->analyze(catalog, query, allow_tlist_ref);
864 auto lower_bound = lower_bound_->analyze(catalog, query, allow_tlist_ref);
865 auto upper_bound = upper_bound_->analyze(catalog, query, allow_tlist_ref);
866 auto partition_count = partition_count_->analyze(catalog, query, allow_tlist_ref);
870 std::shared_ptr<Analyzer::Expr> WidthBucketExpr::get(
871 std::shared_ptr<Analyzer::Expr> target_value,
874 std::shared_ptr<Analyzer::Expr> partition_count) {
875 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::WidthBucketExpr>(
880 std::shared_ptr<Analyzer::Expr> ExistsExpr::analyze(
884 throw std::runtime_error(
"Subqueries are not supported yet.");
888 std::shared_ptr<Analyzer::Expr> ColumnRef::analyze(
895 if (column_ ==
nullptr) {
896 throw std::runtime_error(
"invalid column name *.");
898 if (table_ !=
nullptr) {
901 throw std::runtime_error(
"range variable or table name " + *table_ +
907 throw std::runtime_error(
"Column name " + *column_ +
" does not exist.");
914 cd = rte->get_column_desc(catalog, *column_);
915 if (cd !=
nullptr && !found) {
918 table_id = rte->get_table_id();
919 }
else if (cd !=
nullptr && found) {
920 throw std::runtime_error(
"Column name " + *column_ +
" is ambiguous.");
924 if (cd ==
nullptr && allow_tlist_ref != TlistRefType::TLIST_NONE) {
929 std::shared_ptr<Analyzer::TargetEntry> tle;
931 if (*column_ == p->get_resname() && !found) {
935 }
else if (*column_ == p->get_resname() && found) {
936 throw std::runtime_error(
"Output alias " + *column_ +
" is ambiguous.");
941 if (dynamic_cast<Analyzer::Var*>(tle->get_expr())) {
947 if (allow_tlist_ref == TlistRefType::TLIST_COPY) {
948 return tle->get_expr()->deep_copy();
950 return makeExpr<Analyzer::Var>(
956 throw std::runtime_error(
"Column name " + *column_ +
" does not exist.");
959 return makeExpr<Analyzer::ColumnVar>(
965 std::shared_ptr<Analyzer::Expr> FunctionRef::analyze(
971 std::shared_ptr<Analyzer::Expr> arg_expr;
973 if (boost::iequals(*name_,
"count")) {
977 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
980 throw std::runtime_error(
981 "Strings must be dictionary-encoded in COUNT(DISTINCT).");
984 throw std::runtime_error(
"Only COUNT(DISTINCT) is supported on arrays.");
987 is_distinct = distinct_;
990 throw std::runtime_error(
"Cannot compute " + *name_ +
" with argument '*'.");
992 if (boost::iequals(*name_,
"min")) {
994 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
995 arg_expr = arg_expr->decompress();
996 result_type = arg_expr->get_type_info();
997 }
else if (boost::iequals(*name_,
"max")) {
999 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1000 arg_expr = arg_expr->decompress();
1001 result_type = arg_expr->get_type_info();
1002 }
else if (boost::iequals(*name_,
"avg")) {
1004 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1005 if (!arg_expr->get_type_info().is_number()) {
1006 throw std::runtime_error(
"Cannot compute AVG on non-number-type arguments.");
1008 arg_expr = arg_expr->decompress();
1010 }
else if (boost::iequals(*name_,
"sum")) {
1012 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1013 if (!arg_expr->get_type_info().is_number()) {
1014 throw std::runtime_error(
"Cannot compute SUM on non-number-type arguments.");
1016 arg_expr = arg_expr->decompress();
1018 : arg_expr->get_type_info();
1019 }
else if (boost::iequals(*name_,
"unnest")) {
1020 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1021 const SQLTypeInfo& arg_ti = arg_expr->get_type_info();
1023 throw std::runtime_error(arg_->to_string() +
" is not of array type.");
1027 throw std::runtime_error(
"invalid function name: " + *name_);
1029 if (arg_expr->get_type_info().is_string() ||
1030 arg_expr->get_type_info().get_type() ==
kARRAY) {
1031 throw std::runtime_error(
1032 "Only COUNT(DISTINCT ) aggregate is supported on strings and arrays.");
1037 return makeExpr<Analyzer::AggExpr>(
1038 result_type, agg_type, arg_expr,
is_distinct,
nullptr);
1041 std::shared_ptr<Analyzer::Expr> CastExpr::analyze(
1045 target_type_->check_type();
1046 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1048 target_type_->get_param1(),
1049 target_type_->get_param2(),
1050 arg_expr->get_type_info().get_notnull());
1051 if (arg_expr->get_type_info().get_type() != target_type_->get_type() &&
1053 arg_expr->decompress();
1055 return arg_expr->add_cast(ti);
1058 std::shared_ptr<Analyzer::Expr> CaseExpr::analyze(
1063 std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1065 for (
auto& p : when_then_list_) {
1066 auto e1 = p->get_expr1()->analyze(catalog, query, allow_tlist_ref);
1067 if (e1->get_type_info().get_type() !=
kBOOLEAN) {
1068 throw std::runtime_error(
"Only boolean expressions can be used after WHEN.");
1070 auto e2 = p->get_expr2()->analyze(catalog, query, allow_tlist_ref);
1071 expr_pair_list.emplace_back(e1, e2);
1074 else_expr_ ? else_expr_->analyze(catalog, query, allow_tlist_ref) :
nullptr;
1075 return normalize(expr_pair_list, else_e);
1082 if (*s ==
"t" || *s ==
"true" || *s ==
"T" || *s ==
"True") {
1084 }
else if (*s ==
"f" || *s ==
"false" || *s ==
"F" || *s ==
"False") {
1087 throw std::runtime_error(
"Invalid string for boolean " + *s);
1093 std::vector<std::string>& warnings,
1094 std::string& deferred_copy_from_partitions_) {
1095 if (!options_.empty()) {
1096 for (
auto& p : options_) {
1097 if (boost::iequals(*p->get_name(),
"max_reject")) {
1099 if (int_literal ==
nullptr) {
1100 throw std::runtime_error(
"max_reject option must be an integer.");
1103 }
else if (boost::iequals(*p->get_name(),
"max_import_batch_row_count")) {
1105 if (int_literal ==
nullptr) {
1106 throw std::runtime_error(
1107 "max_import_batch_row_count option must be an integer.");
1110 throw std::runtime_error(
1111 "max_import_batch_row_count option must be a positive integer (greater "
1115 }
else if (boost::iequals(*p->get_name(),
"buffer_size")) {
1117 if (int_literal ==
nullptr) {
1118 throw std::runtime_error(
"buffer_size option must be an integer.");
1121 }
else if (boost::iequals(*p->get_name(),
"threads")) {
1123 if (int_literal ==
nullptr) {
1124 throw std::runtime_error(
"Threads option must be an integer.");
1127 }
else if (boost::iequals(*p->get_name(),
"delimiter")) {
1130 if (str_literal ==
nullptr) {
1131 throw std::runtime_error(
"Delimiter option must be a string.");
1133 throw std::runtime_error(
"Delimiter must be a single character string.");
1136 }
else if (boost::iequals(*p->get_name(),
"nulls")) {
1139 if (str_literal ==
nullptr) {
1140 throw std::runtime_error(
"Nulls option must be a string.");
1143 }
else if (boost::iequals(*p->get_name(),
"header")) {
1146 if (str_literal ==
nullptr) {
1147 throw std::runtime_error(
"Header option must be a boolean.");
1152 #ifdef ENABLE_IMPORT_PARQUET
1153 }
else if (boost::iequals(*p->get_name(),
"parquet")) {
1154 warnings.emplace_back(
1155 "Deprecation Warning: COPY FROM WITH (parquet='true') is deprecated. Use "
1156 "WITH (source_type='parquet_file') instead.");
1159 if (str_literal ==
nullptr) {
1160 throw std::runtime_error(
"'parquet' option must be a boolean.");
1167 #endif // ENABLE_IMPORT_PARQUET
1168 }
else if (boost::iequals(*p->get_name(),
"s3_access_key")) {
1171 if (str_literal ==
nullptr) {
1172 throw std::runtime_error(
"Option s3_access_key must be a string.");
1175 }
else if (boost::iequals(*p->get_name(),
"s3_secret_key")) {
1178 if (str_literal ==
nullptr) {
1179 throw std::runtime_error(
"Option s3_secret_key must be a string.");
1182 }
else if (boost::iequals(*p->get_name(),
"s3_session_token")) {
1185 if (str_literal ==
nullptr) {
1186 throw std::runtime_error(
"Option s3_session_token must be a string.");
1189 }
else if (boost::iequals(*p->get_name(),
"s3_region")) {
1192 if (str_literal ==
nullptr) {
1193 throw std::runtime_error(
"Option s3_region must be a string.");
1196 }
else if (boost::iequals(*p->get_name(),
"s3_endpoint")) {
1199 if (str_literal ==
nullptr) {
1200 throw std::runtime_error(
"Option s3_endpoint must be a string.");
1203 }
else if (boost::iequals(*p->get_name(),
"s3_max_concurrent_downloads")) {
1205 if (int_literal ==
nullptr) {
1206 throw std::runtime_error(
1207 "'s3_max_concurrent_downloads' option must be an integer");
1209 const int s3_max_concurrent_downloads = int_literal->
get_intval();
1210 if (s3_max_concurrent_downloads > 0) {
1213 throw std::runtime_error(
1214 "Invalid value for 's3_max_concurrent_downloads' option (must be > 0): " +
1217 }
else if (boost::iequals(*p->get_name(),
"quote")) {
1220 if (str_literal ==
nullptr) {
1221 throw std::runtime_error(
"Quote option must be a string.");
1223 throw std::runtime_error(
"Quote must be a single character string.");
1226 }
else if (boost::iequals(*p->get_name(),
"escape")) {
1229 if (str_literal ==
nullptr) {
1230 throw std::runtime_error(
"Escape option must be a string.");
1232 throw std::runtime_error(
"Escape must be a single character string.");
1235 }
else if (boost::iequals(*p->get_name(),
"line_delimiter")) {
1238 if (str_literal ==
nullptr) {
1239 throw std::runtime_error(
"Line_delimiter option must be a string.");
1241 throw std::runtime_error(
"Line_delimiter must be a single character string.");
1244 }
else if (boost::iequals(*p->get_name(),
"quoted")) {
1247 if (str_literal ==
nullptr) {
1248 throw std::runtime_error(
"Quoted option must be a boolean.");
1251 }
else if (boost::iequals(*p->get_name(),
"plain_text")) {
1254 if (str_literal ==
nullptr) {
1255 throw std::runtime_error(
"plain_text option must be a boolean.");
1258 }
else if (boost::iequals(*p->get_name(),
"trim_spaces")) {
1261 if (str_literal ==
nullptr) {
1262 throw std::runtime_error(
"trim_spaces option must be a boolean.");
1265 }
else if (boost::iequals(*p->get_name(),
"array_marker")) {
1268 if (str_literal ==
nullptr) {
1269 throw std::runtime_error(
"Array Marker option must be a string.");
1271 throw std::runtime_error(
1272 "Array Marker option must be exactly two characters. Default is {}.");
1276 }
else if (boost::iequals(*p->get_name(),
"array_delimiter")) {
1279 if (str_literal ==
nullptr) {
1280 throw std::runtime_error(
"Array Delimiter option must be a string.");
1282 throw std::runtime_error(
"Array Delimiter must be a single character string.");
1285 }
else if (boost::iequals(*p->get_name(),
"lonlat")) {
1288 if (str_literal ==
nullptr) {
1289 throw std::runtime_error(
"Lonlat option must be a boolean.");
1292 }
else if (boost::iequals(*p->get_name(),
"geo")) {
1293 warnings.emplace_back(
1294 "Deprecation Warning: COPY FROM WITH (geo='true') is deprecated. Use WITH "
1295 "(source_type='geo_file') instead.");
1298 if (str_literal ==
nullptr) {
1299 throw std::runtime_error(
"'geo' option must be a boolean.");
1304 }
else if (boost::iequals(*p->get_name(),
"source_type")) {
1307 if (str_literal ==
nullptr) {
1308 throw std::runtime_error(
"'source_type' option must be a string.");
1311 if (boost::iequals(*s,
"delimited_file")) {
1313 }
else if (boost::iequals(*s,
"geo_file")) {
1315 #if ENABLE_IMPORT_PARQUET
1316 }
else if (boost::iequals(*s,
"parquet_file")) {
1319 }
else if (boost::iequals(*s,
"raster_file")) {
1321 }
else if (boost::iequals(*s,
"regex_parsed_file")) {
1324 throw std::runtime_error(
1325 "Invalid string for 'source_type' option (must be 'GEO_FILE', 'RASTER_FILE'"
1326 #
if ENABLE_IMPORT_PARQUET
1329 ", 'REGEX_PARSED_FILE'"
1330 " or 'DELIMITED_FILE'): " +
1333 }
else if (boost::iequals(*p->get_name(),
"geo_coords_type")) {
1336 if (str_literal ==
nullptr) {
1337 throw std::runtime_error(
"'geo_coords_type' option must be a string");
1340 if (boost::iequals(*s,
"geography")) {
1341 throw std::runtime_error(
1342 "GEOGRAPHY coords type not yet supported. Please use GEOMETRY.");
1344 }
else if (boost::iequals(*s,
"geometry")) {
1347 throw std::runtime_error(
1348 "Invalid string for 'geo_coords_type' option (must be 'GEOGRAPHY' or "
1352 }
else if (boost::iequals(*p->get_name(),
"raster_point_type")) {
1355 if (str_literal ==
nullptr) {
1356 throw std::runtime_error(
"'raster_point_type' option must be a string");
1359 if (boost::iequals(*s,
"none")) {
1361 }
else if (boost::iequals(*s,
"auto")) {
1363 }
else if (boost::iequals(*s,
"smallint")) {
1365 }
else if (boost::iequals(*s,
"int")) {
1367 }
else if (boost::iequals(*s,
"float")) {
1369 }
else if (boost::iequals(*s,
"double")) {
1371 }
else if (boost::iequals(*s,
"point")) {
1374 throw std::runtime_error(
1375 "Invalid string for 'raster_point_type' option (must be 'NONE', 'AUTO', "
1376 "'SMALLINT', 'INT', 'FLOAT', 'DOUBLE' or 'POINT'): " +
1379 }
else if (boost::iequals(*p->get_name(),
"raster_point_transform")) {
1382 if (str_literal ==
nullptr) {
1383 throw std::runtime_error(
"'raster_point_transform' option must be a string");
1386 if (boost::iequals(*s,
"none")) {
1388 }
else if (boost::iequals(*s,
"auto")) {
1390 }
else if (boost::iequals(*s,
"file")) {
1392 }
else if (boost::iequals(*s,
"world")) {
1396 throw std::runtime_error(
1397 "Invalid string for 'raster_point_transform' option (must be 'NONE', "
1398 "'AUTO', 'FILE' or 'WORLD'): " +
1401 }
else if (boost::iequals(*p->get_name(),
"raster_import_bands")) {
1404 if (str_literal ==
nullptr) {
1405 throw std::runtime_error(
"'raster_import_bands' option must be a string");
1407 const std::string* raster_import_bands = str_literal->
get_stringval();
1408 if (raster_import_bands) {
1411 throw std::runtime_error(
"Invalid value for 'raster_import_bands' option");
1413 }
else if (boost::iequals(*p->get_name(),
"raster_import_dimensions")) {
1416 if (str_literal ==
nullptr) {
1417 throw std::runtime_error(
"'raster_import_dimensions' option must be a string");
1419 const std::string* raster_import_dimensions = str_literal->
get_stringval();
1420 if (raster_import_dimensions) {
1423 throw std::runtime_error(
"Invalid value for 'raster_import_dimensions' option");
1425 }
else if (boost::iequals(*p->get_name(),
"geo_coords_encoding")) {
1428 if (str_literal ==
nullptr) {
1429 throw std::runtime_error(
"'geo_coords_encoding' option must be a string");
1432 if (boost::iequals(*s,
"none")) {
1435 }
else if (boost::iequals(*s,
"compressed(32)")) {
1439 throw std::runtime_error(
1440 "Invalid string for 'geo_coords_encoding' option (must be 'NONE' or "
1441 "'COMPRESSED(32)'): " +
1444 }
else if (boost::iequals(*p->get_name(),
"raster_scanlines_per_thread")) {
1446 if (int_literal ==
nullptr) {
1447 throw std::runtime_error(
1448 "'raster_scanlines_per_thread' option must be an integer");
1450 const int raster_scanlines_per_thread = int_literal->
get_intval();
1451 if (raster_scanlines_per_thread < 0) {
1452 throw std::runtime_error(
1453 "'raster_scanlines_per_thread' option must be >= 0, with 0 denoting auto "
1457 }
else if (boost::iequals(*p->get_name(),
"geo_coords_srid")) {
1459 if (int_literal ==
nullptr) {
1460 throw std::runtime_error(
"'geo_coords_srid' option must be an integer");
1463 if (srid == 4326 || srid == 3857 || srid == 900913) {
1466 throw std::runtime_error(
1467 "Invalid value for 'geo_coords_srid' option (must be 4326, 3857, or "
1471 }
else if (boost::iequals(*p->get_name(),
"geo_layer_name")) {
1474 if (str_literal ==
nullptr) {
1475 throw std::runtime_error(
"'geo_layer_name' option must be a string");
1477 const std::string* layer_name = str_literal->
get_stringval();
1481 throw std::runtime_error(
"Invalid value for 'geo_layer_name' option");
1483 }
else if (boost::iequals(*p->get_name(),
"partitions")) {
1484 const auto partitions =
1485 static_cast<const StringLiteral*
>(p->get_value())->get_stringval();
1487 const auto partitions_uc = boost::to_upper_copy<std::string>(*partitions);
1488 if (partitions_uc !=
"REPLICATED") {
1489 throw std::runtime_error(
1490 "Invalid value for 'partitions' option. Must be 'REPLICATED'.");
1492 deferred_copy_from_partitions_ = partitions_uc;
1493 }
else if (boost::iequals(*p->get_name(),
"geo_explode_collections")) {
1496 if (str_literal ==
nullptr) {
1497 throw std::runtime_error(
"geo_explode_collections option must be a boolean.");
1500 }
else if (boost::iequals(*p->get_name(),
"geo_validate_geometry")) {
1503 if (str_literal ==
nullptr) {
1504 throw std::runtime_error(
"geo_validate_geometry option must be a boolean.");
1512 throw std::runtime_error(
"GEOS geometry validation is not available.");
1515 }
else if (boost::iequals(*p->get_name(),
"source_srid")) {
1517 if (int_literal ==
nullptr) {
1518 throw std::runtime_error(
"'source_srid' option must be an integer");
1524 throw std::runtime_error(
1525 "'source_srid' option can only be used on csv/tsv files");
1527 }
else if (boost::iequals(*p->get_name(),
"regex_path_filter")) {
1530 if (str_literal ==
nullptr) {
1531 throw std::runtime_error(
"Option regex_path_filter must be a string.");
1535 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1536 }
else if (boost::iequals(*p->get_name(),
"file_sort_order_by")) {
1539 if (str_literal ==
nullptr) {
1540 throw std::runtime_error(
"Option file_sort_order_by must be a string.");
1544 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1545 }
else if (boost::iequals(*p->get_name(),
"file_sort_regex")) {
1548 if (str_literal ==
nullptr) {
1549 throw std::runtime_error(
"Option file_sort_regex must be a string.");
1553 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1554 }
else if (boost::iequals(*p->get_name(),
"raster_point_compute_angle")) {
1557 if (str_literal ==
nullptr) {
1558 throw std::runtime_error(
1559 "'raster_point_compute_angle' option must be a boolean.");
1564 }
else if (boost::iequals(*p->get_name(),
"raster_drop_if_all_null")) {
1567 if (str_literal ==
nullptr) {
1568 throw std::runtime_error(
"'raster_drop_if_all_null' option must be a boolean.");
1573 }
else if (boost::iequals(*p->get_name(),
"sql_order_by")) {
1574 if (
auto str_literal = dynamic_cast<const StringLiteral*>(p->get_value())) {
1575 copy_params.
sql_order_by = *str_literal->get_stringval();
1577 throw std::runtime_error(
"Option sql_order_by must be a string.");
1579 }
else if (boost::iequals(*p->get_name(),
"username")) {
1582 if (str_literal ==
nullptr) {
1583 throw std::runtime_error(
"Option username must be a string.");
1587 }
else if (boost::iequals(*p->get_name(),
"password")) {
1590 if (str_literal ==
nullptr) {
1591 throw std::runtime_error(
"Option password must be a string.");
1595 }
else if (boost::iequals(*p->get_name(),
"credential_string")) {
1598 if (str_literal ==
nullptr) {
1599 throw std::runtime_error(
"Option credential_string must be a string.");
1603 }
else if (boost::iequals(*p->get_name(),
"data_source_name")) {
1606 if (str_literal ==
nullptr) {
1607 throw std::runtime_error(
"Option data_source_name must be a string.");
1610 copy_params.
dsn = string_val;
1611 }
else if (boost::iequals(*p->get_name(),
"connection_string")) {
1614 if (str_literal ==
nullptr) {
1615 throw std::runtime_error(
"Option connection_string must be a string.");
1619 }
else if (boost::iequals(*p->get_name(),
"line_start_regex")) {
1622 if (str_literal ==
nullptr) {
1623 throw std::runtime_error(
"Option line_start_regex must be a string.");
1627 }
else if (boost::iequals(*p->get_name(),
"line_regex")) {
1630 if (str_literal ==
nullptr) {
1631 throw std::runtime_error(
"Option line_regex must be a string.");
1635 }
else if (boost::iequals(*p->get_name(),
"add_metadata_columns") &&
1639 if (str_literal ==
nullptr) {
1640 throw std::runtime_error(
"'add_metadata_columns' option must be a string.");
1644 throw std::runtime_error(
"Invalid option for COPY: " + *p->get_name());
1655 if (array_expr && array_expr->isNull()) {
1664 std::shared_ptr<Analyzer::Expr> CaseExpr::normalize(
1665 const std::list<std::pair<std::shared_ptr<Analyzer::Expr>,
1666 std::shared_ptr<Analyzer::Expr>>>& expr_pair_list,
1667 const std::shared_ptr<Analyzer::Expr> else_e_in,
1668 const Executor* executor) {
1670 bool has_agg =
false;
1681 for (
auto& p : expr_pair_list) {
1683 CHECK(e1->get_type_info().is_boolean());
1685 if (e2->get_contains_agg()) {
1688 const auto& e2_ti = e2->get_type_info();
1690 if (e2_ti.is_string() && !e2_ti.is_dict_encoded_string() && !col_var) {
1691 CHECK(e2_ti.is_none_encoded_string());
1692 none_encoded_literal_ti =
1704 e2->set_type_info(ti);
1705 }
else if (ti != e2_ti) {
1706 if (ti.
is_string() && e2_ti.is_string()) {
1710 }
else if (ti.
is_number() && e2_ti.is_number()) {
1712 }
else if (ti.
is_boolean() && e2_ti.is_boolean()) {
1715 throw std::runtime_error(
1716 "Expressions in THEN clause must be of the same or compatible types.");
1720 auto else_e = else_e_in;
1721 const auto& else_ti = else_e->get_type_info();
1724 if (else_e->get_contains_agg()) {
1727 if (else_ti.is_string() && !else_ti.is_dict_encoded_string() && !col_var) {
1728 CHECK(else_ti.is_none_encoded_string());
1729 none_encoded_literal_ti =
1738 else_e->set_type_info(ti);
1739 }
else if (ti != else_ti) {
1741 if (ti.
is_string() && else_ti.is_string()) {
1745 }
else if (ti.
is_number() && else_ti.is_number()) {
1747 }
else if (ti.
is_boolean() && else_ti.is_boolean()) {
1750 throw std::runtime_error(
1752 "Expressions in ELSE clause must be of the same or compatible types as "
1753 "those in the THEN clauses.");
1767 std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1768 cast_expr_pair_list;
1769 for (
auto p : expr_pair_list) {
1771 cast_expr_pair_list.emplace_back(p.first, p.second->add_cast(ti));
1773 if (else_e !=
nullptr) {
1774 else_e = else_e->add_cast(ti);
1779 else_e = makeExpr<Analyzer::Constant>(ti,
true, d);
1782 throw std::runtime_error(
1783 "Cannot deduce the type for case expressions, all branches null");
1786 auto case_expr = makeExpr<Analyzer::CaseExpr>(ti, has_agg, cast_expr_pair_list, else_e);
1791 std::string str(
"CASE ");
1792 for (
auto& p : when_then_list_) {
1793 str +=
"WHEN " + p->get_expr1()->to_string() +
" THEN " +
1794 p->get_expr2()->to_string() +
" ";
1796 if (else_expr_ !=
nullptr) {
1797 str +=
"ELSE " + else_expr_->to_string();
1805 left_->analyze(catalog, query);
1807 right_->analyze(catalog, *right_query);
1814 std::shared_ptr<Analyzer::Expr> p;
1815 if (having_clause_ !=
nullptr) {
1816 p = having_clause_->analyze(catalog, query, Expr::TlistRefType::TLIST_COPY);
1817 if (p->get_type_info().get_type() !=
kBOOLEAN) {
1818 throw std::runtime_error(
"Only boolean expressions can be in HAVING clause.");
1827 std::list<std::shared_ptr<Analyzer::Expr>> groupby;
1828 if (!groupby_clause_.empty()) {
1830 std::shared_ptr<Analyzer::Expr> gexpr;
1831 const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
1833 for (
auto& c : groupby_clause_) {
1835 if (dynamic_cast<Literal*>(c.get())) {
1838 throw std::runtime_error(
"Invalid literal in GROUP BY clause.");
1841 if (varno <= 0 || varno > static_cast<int>(tlist.size())) {
1842 throw std::runtime_error(
"Invalid ordinal number in GROUP BY clause.");
1844 if (tlist[varno - 1]->get_expr()->get_contains_agg()) {
1845 throw std::runtime_error(
1846 "Ordinal number in GROUP BY cannot reference an expression containing "
1850 gexpr = makeExpr<Analyzer::Var>(
1853 gexpr = c->analyze(catalog, query, Expr::TlistRefType::TLIST_REF);
1856 bool set_new_type =
false;
1859 set_new_type =
true;
1865 std::shared_ptr<Analyzer::Var> v;
1866 if (std::dynamic_pointer_cast<Analyzer::Var>(gexpr)) {
1868 int n = v->get_varno();
1869 gexpr = tlist[n - 1]->get_own_expr();
1871 if (cv !=
nullptr) {
1876 v->set_varno(gexpr_no);
1877 tlist[n - 1]->set_expr(v);
1881 groupby.push_back(new_e);
1883 v->set_type_info(new_e->get_type_info());
1886 groupby.push_back(gexpr);
1893 auto e = t->get_expr();
1894 e->check_group_by(groupby);
1902 if (where_clause_ ==
nullptr) {
1906 auto p = where_clause_->analyze(catalog, query, Expr::TlistRefType::TLIST_COPY);
1907 if (p->get_type_info().get_type() !=
kBOOLEAN) {
1908 throw std::runtime_error(
"Only boolean expressions can be in WHERE clause.");
1915 std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
1917 if (select_clause_.empty()) {
1921 rte->expand_star_in_targetlist(catalog, tlist, rte_idx++);
1924 for (
auto& p : select_clause_) {
1925 const Parser::Expr* select_expr = p->get_select_expr();
1927 if (
typeid(*select_expr) ==
typeid(
ColumnRef) &&
1928 dynamic_cast<const ColumnRef*>(select_expr)->get_column() ==
nullptr) {
1929 const std::string* range_var_name =
1930 dynamic_cast<const ColumnRef*
>(select_expr)->get_table();
1933 throw std::runtime_error(
"invalid range variable name: " + *range_var_name);
1938 auto e = select_expr->
analyze(catalog, query);
1939 std::string resname;
1941 if (p->get_alias() !=
nullptr) {
1942 resname = *p->get_alias();
1943 }
else if (std::dynamic_pointer_cast<Analyzer::ColumnVar>(e) &&
1944 !std::dynamic_pointer_cast<Analyzer::Var>(e)) {
1951 if (e->get_type_info().get_type() ==
kNULLT) {
1952 throw std::runtime_error(
1953 "Untyped NULL in SELECT clause. Use CAST to specify a type.");
1956 bool unnest = (o !=
nullptr && o->get_optype() ==
kUNNEST);
1957 auto tle = std::make_shared<Analyzer::TargetEntry>(resname, e, unnest);
1958 tlist.push_back(tle);
1967 for (
auto& p : from_clause_) {
1970 if (table_desc ==
nullptr) {
1971 throw std::runtime_error(
"Table " + *p->get_table_name() +
" does not exist.");
1973 std::string range_var;
1974 if (p->get_range_var() ==
nullptr) {
1975 range_var = *p->get_table_name();
1977 range_var = *p->get_range_var();
1987 analyze_from_clause(catalog, query);
1988 analyze_select_clause(catalog, query);
1989 analyze_where_clause(catalog, query);
1990 analyze_group_by(catalog, query);
1991 analyze_having_clause(catalog, query);
1998 boost::replace_all(s,
"\\\\t",
"\t");
1999 boost::replace_all(s,
"\\t",
"\t");
2000 boost::replace_all(s,
"\\\\n",
"\n");
2001 boost::replace_all(s,
"\\n",
"\n");
2007 std::regex e1(
"(\\\\x[0-9A-Fa-f][0-9A-Fa-f])");
2008 while (std::regex_search(s, m, e1)) {
2009 std::string original(m[0].first, m[0].second);
2010 std::string replacement;
2011 long val = strtol(original.substr(2, 2).c_str(), NULL, 16);
2012 replacement.push_back(val);
2013 boost::replace_all(s, original, replacement);
2017 std::regex e2(
"(\\\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f])");
2018 while (std::regex_search(s, m, e2)) {
2019 std::string original(m[0].first, m[0].second);
2020 std::string replacement;
2021 long val = strtol(original.substr(2, 4).c_str(), NULL, 16);
2022 replacement.push_back(val);
2023 boost::replace_all(s, original, replacement);
2030 std::list<std::unique_ptr<NameValueAssign>>& nameValueList,
2031 bool stringToNull =
false,
2032 bool stringToInteger =
false) {
2033 if (payload.HasMember(
"options") && payload[
"options"].IsObject()) {
2034 const auto& options = payload[
"options"];
2035 for (
auto itr = options.MemberBegin(); itr != options.MemberEnd(); ++itr) {
2036 auto option_name = std::make_unique<std::string>(itr->name.GetString());
2037 std::unique_ptr<Literal> literal_value;
2038 if (itr->value.IsString()) {
2039 std::string str = itr->value.GetString();
2040 if (stringToNull && str ==
"") {
2041 literal_value = std::make_unique<NullLiteral>();
2042 }
else if (stringToInteger && std::all_of(str.begin(), str.end(), ::isdigit)) {
2043 int iVal = std::stoi(str);
2044 literal_value = std::make_unique<IntLiteral>(iVal);
2048 auto unique_literal_string = std::make_unique<std::string>(
unescape(str));
2050 std::make_unique<StringLiteral>(unique_literal_string.release());
2052 }
else if (itr->value.IsInt() || itr->value.IsInt64()) {
2053 literal_value = std::make_unique<IntLiteral>(
json_i64(itr->value));
2054 }
else if (itr->value.IsDouble()) {
2055 literal_value = std::make_unique<DoubleLiteral>(
json_double(itr->value));
2056 }
else if (itr->value.IsNull()) {
2057 literal_value = std::make_unique<NullLiteral>();
2059 throw std::runtime_error(
"Unable to handle literal for " + *option_name);
2061 CHECK(literal_value);
2063 nameValueList.emplace_back(std::make_unique<NameValueAssign>(
2064 option_name.release(), literal_value.release()));
2075 throw std::runtime_error(
"OFFSET cannot be negative.");
2078 query_expr_->analyze(catalog, query);
2083 const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
2085 std::list<Analyzer::OrderEntry>* order_by =
new std::list<Analyzer::OrderEntry>();
2086 if (!orderby_clause_.empty()) {
2087 for (
auto& p : orderby_clause_) {
2088 int tle_no = p->get_colno();
2092 const std::string*
name = p->get_column()->get_column();
2095 for (
auto tle : tlist) {
2096 if (tle->get_resname() == *
name) {
2103 throw std::runtime_error(
"invalid name in order by: " + *name);
2106 order_by->push_back(
2112 for (
int i = 1; i <= static_cast<int>(tlist.size()); i++) {
2113 bool in_orderby =
false;
2114 std::for_each(order_by->begin(),
2117 in_orderby = in_orderby || (i == oe.tle_no);
2128 std::string str = select_expr_->to_string();
2129 if (alias_ !=
nullptr) {
2130 str +=
" AS " + *alias_;
2136 std::string str = *table_name_;
2137 if (range_var_ !=
nullptr) {
2138 str +=
" " + *range_var_;
2145 if (table_ ==
nullptr) {
2147 }
else if (column_ ==
nullptr) {
2148 str = *table_ +
".*";
2150 str = *table_ +
"." + *column_;
2156 std::string op_str[] = {
2157 "=",
"===",
"<>",
"<",
">",
"<=",
">=",
" AND ",
" OR ",
"NOT",
"-",
"+",
"*",
"/"};
2160 str =
"-(" + left_->to_string() +
")";
2161 }
else if (optype_ ==
kNOT) {
2162 str =
"NOT (" + left_->to_string() +
")";
2164 str = left_->to_string() +
"[" + right_->to_string() +
"]";
2165 }
else if (optype_ ==
kUNNEST) {
2166 str =
"UNNEST(" + left_->to_string() +
")";
2167 }
else if (optype_ ==
kIN) {
2168 str =
"(" + left_->to_string() +
" IN " + right_->to_string() +
")";
2170 str =
"(" + left_->to_string() + op_str[optype_] + right_->to_string() +
")";
2176 std::string str = arg_->to_string();
2186 return "EXISTS (" + query_->to_string() +
")";
2192 str += query_->to_string();
2198 std::string str = arg_->to_string();
2200 str +=
" IS NOT NULL";
2209 str += subquery_->to_string();
2215 bool notfirst =
false;
2216 for (
auto& p : value_list_) {
2222 str += p->to_string();
2229 std::string str = arg_->to_string();
2231 str +=
" NOT BETWEEN ";
2235 str += lower_->to_string() +
" AND " + upper_->to_string();
2241 if (calc_encoded_length_) {
2242 str =
"CHAR_LENGTH (" + arg_->to_string() +
")";
2244 str =
"LENGTH (" + arg_->to_string() +
")";
2250 std::string str =
"CARDINALITY(" + arg_->to_string() +
")";
2255 std::string str = arg_->to_string();
2257 str +=
" NOT LIKE ";
2261 str += like_string_->to_string();
2262 if (escape_string_ !=
nullptr) {
2263 str +=
" ESCAPE " + escape_string_->to_string();
2269 std::string str = arg_->to_string();
2271 str +=
" NOT REGEXP ";
2275 str += pattern_string_->to_string();
2276 if (escape_string_ !=
nullptr) {
2277 str +=
" ESCAPE " + escape_string_->to_string();
2283 std::string str =
" WIDTH_BUCKET ";
2284 str += target_value_->to_string();
2286 str += lower_bound_->to_string();
2288 str += upper_bound_->to_string();
2290 str += partition_count_->to_string();
2296 std::string str =
" LIKELIHOOD ";
2297 str += arg_->to_string();
2299 str += boost::lexical_cast<std::string>(is_not_ ? 1.0 - likelihood_ : likelihood_);
2304 std::string str = *name_ +
"(";
2308 if (arg_ ==
nullptr) {
2311 str += arg_->to_string() +
")";
2317 std::string query_str =
"SELECT ";
2319 query_str +=
"DISTINCT ";
2321 if (select_clause_.empty()) {
2324 bool notfirst =
false;
2325 for (
auto& p : select_clause_) {
2331 query_str += p->to_string();
2334 query_str +=
" FROM ";
2335 bool notfirst =
false;
2336 for (
auto& p : from_clause_) {
2342 query_str += p->to_string();
2344 if (where_clause_) {
2345 query_str +=
" WHERE " + where_clause_->to_string();
2347 if (!groupby_clause_.empty()) {
2348 query_str +=
" GROUP BY ";
2349 bool notfirst =
false;
2350 for (
auto& p : groupby_clause_) {
2356 query_str += p->to_string();
2359 if (having_clause_) {
2360 query_str +=
" HAVING " + having_clause_->to_string();
2370 if (td ==
nullptr) {
2371 throw std::runtime_error(
"Table " + *table_ +
" does not exist.");
2374 throw std::runtime_error(
"Insert to views is not supported yet.");
2378 std::list<int> result_col_list;
2379 if (column_list_.empty()) {
2380 const std::list<const ColumnDescriptor*> all_cols =
2382 for (
auto cd : all_cols) {
2383 result_col_list.push_back(cd->columnId);
2386 for (
auto& c : column_list_) {
2388 if (cd ==
nullptr) {
2389 throw std::runtime_error(
"Column " + *c +
" does not exist.");
2391 result_col_list.push_back(cd->
columnId);
2393 if (col_ti.get_physical_cols() > 0) {
2395 for (
auto i = 1; i <= col_ti.get_physical_cols(); i++) {
2398 if (pcd ==
nullptr) {
2399 throw std::runtime_error(
"Column " + *c +
"'s metadata is incomplete.");
2401 result_col_list.push_back(pcd->
columnId);
2411 CHECK(literal.IsObject());
2412 CHECK(literal.HasMember(
"literal"));
2413 CHECK(literal.HasMember(
"type"));
2415 if (type ==
"NULL") {
2417 }
else if (type ==
"CHAR" || type ==
"BOOLEAN") {
2418 auto* val =
new std::string(
json_str(literal[
"literal"]));
2420 }
else if (type ==
"DECIMAL") {
2421 CHECK(literal.HasMember(
"scale"));
2422 CHECK(literal.HasMember(
"precision"));
2423 auto scale =
json_i64(literal[
"scale"]);
2424 auto precision =
json_i64(literal[
"precision"]);
2426 auto int_val = std::stol(
json_str(literal[
"literal"]));
2429 auto dbl_val = std::stod(
json_str(literal[
"literal"]));
2432 auto* val =
new std::string(
json_str(literal[
"literal"]));
2435 }
else if (type ==
"DOUBLE") {
2436 auto dbl_val = std::stod(
json_str(literal[
"literal"]));
2439 CHECK(
false) <<
"Unexpected calcite data type: " <<
type;
2445 CHECK(array.IsArray());
2446 auto json_elements = array.GetArray();
2447 auto* elements =
new std::list<Expr*>();
2448 for (
const auto& e : json_elements) {
2456 const rapidjson::Value& payload)
2458 CHECK(payload.HasMember(
"name"));
2459 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
2461 if (payload.HasMember(
"columns")) {
2462 CHECK(payload[
"columns"].IsArray());
2463 for (
auto& column : payload[
"columns"].GetArray()) {
2465 column_list_.emplace_back(std::make_unique<std::string>(s));
2469 CHECK(payload.HasMember(
"values") && payload[
"values"].IsArray());
2470 auto tuples = payload[
"values"].GetArray();
2471 if (tuples.Empty()) {
2472 throw std::runtime_error(
"Values statement cannot be empty");
2475 int column_offset = 0;
2477 for (
const auto& json_tuple : tuples) {
2478 auto values_list = std::make_unique<ValuesList>();
2479 CHECK(json_tuple.IsArray());
2480 auto tuple = json_tuple.GetArray();
2482 for (
const auto& value : tuple) {
2483 CHECK(value.IsObject());
2484 if (value.HasMember(
"array")) {
2493 }
catch (std::out_of_range
const& e) {
2497 auto target_col_iter = cds.begin();
2498 std::advance(target_col_iter, column_offset);
2499 auto* cd = *target_col_iter;
2501 auto const col_identifier = td->tableName +
"." + cd->columnName;
2502 throw std::runtime_error(
2503 "Detected an out-of-range exception when inserting a value into column \"" +
2504 col_identifier +
"\"");
2511 size_t list_size =
values_lists_[0]->get_value_list().size();
2514 throw std::runtime_error(
2515 "Numbers of columns and values don't match for the "
2520 const std::list<const ColumnDescriptor*> non_phys_cols =
2522 if (non_phys_cols.size() != list_size) {
2523 throw std::runtime_error(
2524 "Number of columns in table does not match the list of values given in the "
2528 std::vector<const ColumnDescriptor*> cds;
2538 const auto& values_list =
values_lists_[i]->get_value_list();
2539 if (values_list.size() != list_size) {
2540 throw std::runtime_error(
2541 "Insert values lists should be of the same size. Expected: " +
2544 auto& query_values_list = query_values_lists[i];
2546 for (
auto& v : values_list) {
2547 auto e = v->analyze(catalog, query);
2548 const auto* cd = cds[cds_id];
2549 const auto& col_ti = cd->columnType;
2550 if (col_ti.get_notnull()) {
2552 if (c !=
nullptr && c->get_is_null()) {
2553 throw std::runtime_error(
"Cannot insert NULL into column " + cd->columnName);
2556 e = e->add_cast(col_ti);
2560 if (col_ti.get_physical_cols() > 0) {
2561 CHECK(cd->columnType.is_geometry());
2565 if (uoper && uoper->get_optype() ==
kCAST) {
2570 std::string* geo_string{
nullptr};
2572 is_null = c->get_is_null();
2574 geo_string = c->get_constval().stringval;
2577 if (!is_null && !geo_string) {
2578 throw std::runtime_error(
"Expecting a WKT or WKB hex string for column " +
2581 std::vector<double> coords;
2582 std::vector<double> bounds;
2583 std::vector<int> ring_sizes;
2584 std::vector<int> poly_rings;
2587 const bool validate_with_geos_if_available =
false;
2595 validate_with_geos_if_available)) {
2596 throw std::runtime_error(
"Cannot read geometry to insert into column " +
2599 if (coords.empty()) {
2604 throw std::runtime_error(
2605 "Imported geometry doesn't match the type of column " + cd->columnName);
2609 if (cd->columnType.get_type() ==
kPOINT) {
2610 if (!coords.empty()) {
2611 throw std::runtime_error(
2612 "NULL POINT with unexpected coordinates in column " + cd->columnName);
2622 const auto* cd_coords = cds[cds_id];
2625 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2626 if (!is_null || cd->columnType.get_type() ==
kPOINT) {
2628 for (
auto cc : compressed_coords) {
2631 auto e = makeExpr<Analyzer::Constant>(
kTINYINT,
false, d);
2632 value_exprs.push_back(e);
2637 makeExpr<Analyzer::Constant>(cd_coords->columnType, is_null, value_exprs),
2642 cd->columnType.get_type() ==
kPOLYGON ||
2645 const auto* cd_ring_sizes = cds[cds_id];
2646 CHECK(cd_ring_sizes);
2648 CHECK_EQ(cd_ring_sizes->columnType.get_subtype(),
kINT);
2649 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2651 for (
auto c : ring_sizes) {
2654 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
2655 value_exprs.push_back(e);
2660 makeExpr<Analyzer::Constant>(
2661 cd_ring_sizes->columnType, is_null, value_exprs),
2667 const auto* cd_poly_rings = cds[cds_id];
2668 CHECK(cd_poly_rings);
2670 CHECK_EQ(cd_poly_rings->columnType.get_subtype(),
kINT);
2671 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2673 for (
auto c : poly_rings) {
2676 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
2677 value_exprs.push_back(e);
2682 makeExpr<Analyzer::Constant>(
2683 cd_poly_rings->columnType, is_null, value_exprs),
2692 cd->columnType.get_type() ==
kPOLYGON ||
2694 const auto* cd_bounds = cds[cds_id];
2698 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2700 for (
auto b : bounds) {
2703 auto e = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
2704 value_exprs.push_back(e);
2709 makeExpr<Analyzer::Constant>(cd_bounds->columnType, is_null, value_exprs),
2719 bool read_only_mode) {
2720 if (read_only_mode) {
2721 throw std::runtime_error(
"INSERT values invalid in read only mode.");
2725 const auto td_with_lock =
2731 throw std::runtime_error(
"User has no insert privileges on " + *
table_ +
".");
2737 const auto insert_data_lock =
2743 auto td = td_with_lock();
2746 throw std::runtime_error(
"Singleton inserts on views is not supported.");
2754 leafs_connector_ = std::make_unique<Fragmenter_Namespace::LocalInsertConnector>();
2758 ra_executor.executeSimpleInsert(query, insert_data_loader, session);
2762 }
catch (std::exception& e) {
2763 LOG(
ERROR) <<
"An error occurred during insert rollback attempt. Table id: "
2764 << td->tableId <<
", Error: " << e.what();
2768 if (!td->isTemporaryTable()) {
2775 throw std::runtime_error(
"UPDATE statement not supported yet.");
2780 throw std::runtime_error(
"DELETE statement not supported yet.");
2787 if (!col_ti.is_integer() && !col_ti.is_time() &&
2788 !(col_ti.is_string() && col_ti.get_compression() ==
kENCODING_DICT)) {
2789 throw std::runtime_error(
"Cannot shard on type " + col_ti.get_type_name() +
2790 ", encoding " + col_ti.get_compression_name());
2795 const std::list<ColumnDescriptor>& columns) {
2797 for (
const auto& cd : columns) {
2798 if (cd.columnName == name) {
2803 if (cd.columnType.is_geometry()) {
2804 index += cd.columnType.get_physical_cols();
2812 const std::list<ColumnDescriptor>& columns) {
2814 for (
const auto& cd : columns) {
2815 if (boost::to_upper_copy<std::string>(cd.columnName) == name) {
2819 if (cd.columnType.is_geometry()) {
2820 index += cd.columnType.get_physical_cols();
2828 const std::string& field_name,
2829 const std::string& field_value,
2830 rapidjson::Document& document) {
2831 rapidjson::Value field_name_json_str;
2832 field_name_json_str.SetString(
2833 field_name.c_str(), field_name.size(), document.GetAllocator());
2834 rapidjson::Value field_value_json_str;
2835 field_value_json_str.SetString(
2836 field_value.c_str(), field_value.size(), document.GetAllocator());
2837 obj.AddMember(field_name_json_str, field_value_json_str, document.GetAllocator());
2842 const std::vector<SharedDictionaryDef>& shared_dict_defs) {
2843 rapidjson::Document document;
2844 auto& allocator = document.GetAllocator();
2845 rapidjson::Value arr(rapidjson::kArrayType);
2846 if (shard_key_def) {
2847 rapidjson::Value shard_key_obj(rapidjson::kObjectType);
2850 arr.PushBack(shard_key_obj, allocator);
2852 for (
const auto& shared_dict_def : shared_dict_defs) {
2853 rapidjson::Value shared_dict_obj(rapidjson::kObjectType);
2855 set_string_field(shared_dict_obj,
"name", shared_dict_def.get_column(), document);
2857 shared_dict_obj,
"foreign_table", shared_dict_def.get_foreign_table(), document);
2860 shared_dict_def.get_foreign_column(),
2862 arr.PushBack(shared_dict_obj, allocator);
2864 rapidjson::StringBuffer buffer;
2865 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
2867 return buffer.GetString();
2870 template <
typename LITERAL_TYPE,
2871 typename ASSIGNMENT,
2875 VALIDATE validate = VALIDATE()) {
2876 const auto val = validate(p);
2883 auto assignment = [&td](
const auto val) { td.storageType = val; };
2884 return get_property_value<StringLiteral, decltype(assignment), CaseSensitiveValidate>(
2891 return get_property_value<IntLiteral>(p, [&td](
const auto val) {
2899 return get_property_value<IntLiteral>(
2900 p, [&df_td](
const auto val) { df_td.maxFragRows = val; });
2906 return get_property_value<IntLiteral>(p,
2907 [&td](
const auto val) { td.maxChunkSize = val; });
2914 return get_property_value<IntLiteral>(
2915 p, [&df_td](
const auto val) { df_td.maxChunkSize = val; });
2921 return get_property_value<StringLiteral>(p, [&df_td](
const auto val) {
2922 if (val.size() != 1) {
2923 throw std::runtime_error(
"Length of DELIMITER must be equal to 1.");
2925 df_td.delimiter = val;
2932 return get_property_value<StringLiteral>(p, [&df_td](
const auto val) {
2933 if (val ==
"FALSE") {
2934 df_td.hasHeader =
false;
2935 }
else if (val ==
"TRUE") {
2936 df_td.hasHeader =
true;
2938 throw std::runtime_error(
"Option HEADER support only 'true' or 'false' values.");
2946 return get_property_value<IntLiteral>(p, [&td](
const auto val) {
2948 if (val < min_page_size) {
2949 throw std::runtime_error(
"page_size cannot be less than " +
2952 td.fragPageSize = val;
2958 return get_property_value<IntLiteral>(p, [&td](
const auto val) { td.maxRows = val; });
2964 return get_property_value<IntLiteral>(
2965 p, [&df_td](
const auto val) { df_td.skipRows = val; });
2971 return get_property_value<StringLiteral>(p, [&td](
const auto partitions_uc) {
2972 if (partitions_uc !=
"SHARDED" && partitions_uc !=
"REPLICATED") {
2973 throw std::runtime_error(
"PARTITIONS must be SHARDED or REPLICATED");
2975 if (td.shardedColumnId != 0 && partitions_uc ==
"REPLICATED") {
2976 throw std::runtime_error(
2977 "A table cannot be sharded and replicated at the same time");
2979 td.partitions = partitions_uc;
2985 if (!td.shardedColumnId) {
2986 throw std::runtime_error(
"SHARD KEY must be defined.");
2988 return get_property_value<IntLiteral>(p, [&td](
const auto shard_count) {
2990 throw std::runtime_error(
2991 "SHARD_COUNT must be a multiple of the number of leaves in the cluster.");
2993 td.nShards = g_leaf_count ? shard_count / g_leaf_count : shard_count;
2994 if (!td.shardedColumnId && !td.nShards) {
2995 throw std::runtime_error(
2996 "Must specify the number of shards through the SHARD_COUNT option");
3004 return get_property_value<StringLiteral>(p, [&td](
const auto vacuum_uc) {
3005 if (vacuum_uc !=
"IMMEDIATE" && vacuum_uc !=
"DELAYED") {
3006 throw std::runtime_error(
"VACUUM must be IMMEDIATE or DELAYED");
3008 td.hasDeletedCol = boost::iequals(vacuum_uc,
"IMMEDIATE") ?
false :
true;
3015 return get_property_value<StringLiteral>(p, [&td, &columns](
const auto sort_upper) {
3017 if (!td.sortedColumnId) {
3018 throw std::runtime_error(
"Specified sort column " + sort_upper +
" doesn't exist");
3026 auto assignment = [&td](
const auto val) {
3027 td.maxRollbackEpochs =
3032 return get_property_value<IntLiteral, decltype(assignment), PositiveOrZeroValidate>(
3049 const std::unique_ptr<NameValueAssign>& p,
3050 const std::list<ColumnDescriptor>& columns) {
3051 const auto it = tableDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3052 if (it == tableDefFuncMap.end()) {
3053 throw std::runtime_error(
3054 "Invalid CREATE TABLE option " + *p->get_name() +
3055 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, PAGE_SIZE, MAX_ROLLBACK_EPOCHS, "
3057 "PARTITIONS, SHARD_COUNT, VACUUM, SORT_COLUMN, STORAGE_TYPE.");
3059 return it->second(td, p.get(), columns);
3063 const std::unique_ptr<NameValueAssign>& p,
3064 const std::list<ColumnDescriptor>& columns) {
3065 const auto it = tableDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3066 if (it == tableDefFuncMap.end()) {
3067 throw std::runtime_error(
3068 "Invalid CREATE TABLE AS option " + *p->get_name() +
3069 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, PAGE_SIZE, MAX_ROLLBACK_EPOCHS, "
3071 "PARTITIONS, SHARD_COUNT, VACUUM, SORT_COLUMN, STORAGE_TYPE, "
3072 "USE_SHARED_DICTIONARIES or FORCE_GEO_COMPRESSION.");
3074 return it->second(td, p.get(), columns);
3085 const std::unique_ptr<NameValueAssign>& p,
3086 const std::list<ColumnDescriptor>& columns) {
3088 dataframeDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3089 if (it == dataframeDefFuncMap.end()) {
3090 throw std::runtime_error(
3091 "Invalid CREATE DATAFRAME option " + *p->get_name() +
3092 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, SKIP_ROWS, DELIMITER or HEADER.");
3094 return it->second(df_td, p.get(), columns);
3098 std::string element_name,
3099 std::string& table_name,
3100 std::list<std::unique_ptr<TableElement>>& table_element_list) {
3101 const auto elements = payload[element_name].GetArray();
3102 for (
const auto& element : elements) {
3103 CHECK(element.IsObject());
3104 CHECK(element.HasMember(
"type"));
3105 if (
json_str(element[
"type"]) ==
"SQL_COLUMN_DECLARATION") {
3107 table_element_list.emplace_back(std::move(col_def));
3108 }
else if (
json_str(element[
"type"]) ==
"SQL_COLUMN_CONSTRAINT") {
3109 CHECK(element.HasMember(
"name"));
3110 if (
json_str(element[
"name"]) ==
"SHARD_KEY") {
3111 CHECK(element.HasMember(
"columns"));
3112 CHECK(element[
"columns"].IsArray());
3113 const auto& columns = element[
"columns"].GetArray();
3114 if (columns.Size() != size_t(1)) {
3115 throw std::runtime_error(
"Only one shard column is currently supported.");
3117 auto shard_key_def = std::make_unique<ShardKeyDef>(
json_str(columns[0]));
3118 table_element_list.emplace_back(std::move(shard_key_def));
3119 }
else if (
json_str(element[
"name"]) ==
"SHARED_DICT") {
3120 CHECK(element.HasMember(
"columns"));
3121 CHECK(element[
"columns"].IsArray());
3122 const auto& columns = element[
"columns"].GetArray();
3123 if (columns.Size() != size_t(1)) {
3124 throw std::runtime_error(
3125 R
"(Only one column per shared dictionary entry is currently supported. Use multiple SHARED DICT statements to share dictionaries from multiple columns.)");
3127 CHECK(element.HasMember("references") && element[
"references"].IsObject());
3128 const auto& references = element[
"references"].GetObject();
3129 std::string references_table_name;
3130 if (references.HasMember(
"table")) {
3131 references_table_name =
json_str(references[
"table"]);
3133 references_table_name = table_name;
3135 CHECK(references.HasMember(
"column"));
3137 auto shared_dict_def = std::make_unique<SharedDictionaryDef>(
3138 json_str(columns[0]), references_table_name,
json_str(references[
"column"]));
3139 table_element_list.emplace_back(std::move(shared_dict_def));
3142 LOG(
FATAL) <<
"Unsupported type for SQL_COLUMN_CONSTRAINT: "
3146 LOG(
FATAL) <<
"Unsupported element type for CREATE TABLE: "
3147 << element[
"type"].GetString();
3154 CHECK(element.HasMember(
"name"));
3155 auto col_name = std::make_unique<std::string>(
json_str(element[
"name"]));
3156 CHECK(element.HasMember(
"sqltype"));
3162 if (element.HasMember(
"precision")) {
3163 precision =
json_i64(element[
"precision"]);
3165 if (element.HasMember(
"scale")) {
3166 scale =
json_i64(element[
"scale"]);
3169 std::optional<int64_t> array_size;
3170 if (element.HasMember(
"arraySize")) {
3172 array_size =
json_i64(element[
"arraySize"]);
3174 std::unique_ptr<SQLType> sql_type;
3175 if (element.HasMember(
"subtype")) {
3176 CHECK(element.HasMember(
"coordinateSystem"));
3179 std::make_unique<SQLType>(subtype_sql_types,
3180 static_cast<int>(sql_types),
3181 static_cast<int>(
json_i64(element[
"coordinateSystem"])),
3183 }
else if (precision > 0 && scale > 0) {
3184 sql_type = std::make_unique<SQLType>(sql_types,
3187 array_size.has_value(),
3188 array_size ? *array_size : -1);
3189 }
else if (precision > 0) {
3190 sql_type = std::make_unique<SQLType>(sql_types,
3193 array_size.has_value(),
3194 array_size ? *array_size : -1);
3196 sql_type = std::make_unique<SQLType>(sql_types,
3197 array_size.has_value(),
3198 array_size ? *array_size : -1);
3202 CHECK(element.HasMember(
"nullable"));
3203 const auto nullable =
json_bool(element[
"nullable"]);
3204 std::unique_ptr<ColumnConstraintDef> constraint_def;
3206 if (element.HasMember(
"default") && !element[
"default"].IsNull()) {
3207 std::string* defaultval =
new std::string(
json_str(element[
"default"]));
3208 boost::algorithm::trim_if(*defaultval, boost::is_any_of(
" \"'`"));
3212 constraint_def = std::make_unique<ColumnConstraintDef>(!nullable,
3216 std::unique_ptr<CompressDef> compress_def;
3217 if (element.HasMember(
"encodingType") && !element[
"encodingType"].IsNull()) {
3218 std::string encoding_type =
json_str(element[
"encodingType"]);
3219 CHECK(element.HasMember(
"encodingSize"));
3220 auto encoding_name = std::make_unique<std::string>(
json_str(element[
"encodingType"]));
3221 compress_def = std::make_unique<CompressDef>(encoding_name.release(),
3222 json_i64(element[
"encodingSize"]));
3224 return std::make_unique<ColumnDef>(col_name.release(),
3226 compress_def ? compress_def.release() :
nullptr,
3227 constraint_def ? constraint_def.release() :
nullptr);
3231 const rapidjson::Value& payload) {
3232 std::list<ColumnDef> table_element_list;
3233 CHECK(payload[payload_key].IsArray());
3235 const auto elements = payload[payload_key].GetArray();
3236 for (
const auto& element : elements) {
3237 CHECK(element.IsObject());
3238 CHECK(element.HasMember(
"type"));
3239 if (
json_str(element[
"type"]) ==
"SQL_COLUMN_DECLARATION") {
3241 table_element_list.emplace_back(std::move(*col_def));
3243 LOG(
FATAL) <<
"Unsupported element type for ALTER TABLE: "
3244 << element[
"type"].GetString();
3247 return table_element_list;
3251 CHECK(payload.HasMember(
"name"));
3252 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
3253 CHECK(payload.HasMember(
"elements"));
3254 CHECK(payload[
"elements"].IsArray());
3257 if (payload.HasMember(
"temporary")) {
3262 if (payload.HasMember(
"ifNotExists")) {
3273 std::list<ColumnDescriptor>& columns,
3274 std::vector<SharedDictionaryDef>& shared_dict_defs) {
3275 std::unordered_set<std::string> uc_col_names;
3279 if (dynamic_cast<SharedDictionaryDef*>(e.get())) {
3282 this, shared_dict_def, columns, shared_dict_defs, catalog);
3283 shared_dict_defs.push_back(*shared_dict_def);
3286 if (dynamic_cast<ShardKeyDef*>(e.get())) {
3287 if (shard_key_def) {
3288 throw std::runtime_error(
"Specified more than one shard key");
3290 shard_key_def =
static_cast<const ShardKeyDef*
>(e.get());
3293 if (!dynamic_cast<ColumnDef*>(e.get())) {
3294 throw std::runtime_error(
"Table constraints are not supported yet.");
3301 columns.push_back(cd);
3306 if (shard_key_def) {
3309 throw std::runtime_error(
"Specified shard column " + shard_key_def->get_column() +
3324 throw std::runtime_error(
"SHARD_COUNT needs to be specified with SHARD_KEY.");
3330 bool read_only_mode) {
3331 if (read_only_mode) {
3332 throw std::runtime_error(
"CREATE TABLE invalid in read only mode.");
3344 throw std::runtime_error(
"Table " + *
table_ +
3345 " will not be created. User has no create privileges.");
3353 std::list<ColumnDescriptor> columns;
3354 std::vector<SharedDictionaryDef> shared_dict_defs;
3359 catalog.createShardedTable(td, columns, shared_dict_defs);
3367 CHECK(payload.HasMember(
"name"));
3368 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
3370 CHECK(payload.HasMember(
"elementList"));
3373 CHECK(payload.HasMember(
"filePath"));
3374 std::string fs =
json_str(payload[
"filePath"]);
3376 boost::algorithm::trim_if(fs, boost::is_any_of(
" \"'`"));
3377 filename_ = std::make_unique<std::string>(fs);
3383 bool read_only_mode) {
3384 if (read_only_mode) {
3385 throw std::runtime_error(
"CREATE DATAFRAME invalid in read only mode.");
3394 throw std::runtime_error(
"Table " + *
table_ +
3395 " will not be created. User has no create privileges.");
3398 if (catalog.getMetadataForTable(*
table_) !=
nullptr) {
3399 throw std::runtime_error(
"Table " + *
table_ +
" already exists.");
3402 std::list<ColumnDescriptor> columns;
3403 std::vector<SharedDictionaryDef> shared_dict_defs;
3405 std::unordered_set<std::string> uc_col_names;
3407 if (dynamic_cast<SharedDictionaryDef*>(e.get())) {
3410 this, shared_dict_def, columns, shared_dict_defs, catalog);
3411 shared_dict_defs.push_back(*shared_dict_def);
3414 if (!dynamic_cast<ColumnDef*>(e.get())) {
3415 throw std::runtime_error(
"Table constraints are not supported yet.");
3420 const auto uc_col_name = boost::to_upper_copy<std::string>(cd.
columnName);
3421 const auto it_ok = uc_col_names.insert(uc_col_name);
3422 if (!it_ok.second) {
3423 throw std::runtime_error(
"Column '" + cd.
columnName +
"' defined more than once");
3426 columns.push_back(cd);
3448 catalog.createShardedTable(df_td, columns, shared_dict_defs);
3457 throw std::runtime_error(
"Cannot create model. ML functions are disabled.");
3459 CHECK(payload.HasMember(
"name"));
3460 const std::string model_type_str =
json_str(payload[
"type"]);
3464 if (payload.HasMember(
"replace")) {
3469 if (payload.HasMember(
"ifNotExists")) {
3473 CHECK(payload.HasMember(
"query"));
3475 std::regex newline_re(
"\\n");
3476 std::regex backtick_re(
"`");
3477 select_query_ = std::regex_replace(select_query_, newline_re,
" ");
3478 select_query_ = std::regex_replace(select_query_, backtick_re,
"");
3486 const std::vector<std::string>& features,
3487 const std::string& training_query,
3488 const double data_split_train_fraction,
3489 const double data_split_eval_fraction,
3490 const std::vector<int64_t>& feature_permutations) {
3492 rapidjson::Document doc;
3496 rapidjson::Value predicted_value;
3497 predicted_value.SetString(predicted.c_str(), predicted.length(), doc.GetAllocator());
3498 doc.AddMember(
"predicted", predicted_value, doc.GetAllocator());
3500 rapidjson::Value features_array(rapidjson::kArrayType);
3501 for (
const auto& feature : features) {
3502 rapidjson::Value feature_value;
3503 feature_value.SetString(feature.c_str(), feature.length(), doc.GetAllocator());
3504 features_array.PushBack(feature_value, doc.GetAllocator());
3506 doc.AddMember(
"features", features_array, doc.GetAllocator());
3508 rapidjson::Value training_query_value;
3509 training_query_value.SetString(
3510 training_query.c_str(), training_query.length(), doc.GetAllocator());
3511 doc.AddMember(
"training_query", training_query_value, doc.GetAllocator());
3513 rapidjson::Value data_split_train_fraction_key(
"data_split_train_fraction",
3514 doc.GetAllocator());
3516 rapidjson::Value data_split_train_fraction_value(data_split_train_fraction);
3519 data_split_train_fraction_key, data_split_train_fraction_value, doc.GetAllocator());
3521 rapidjson::Value data_split_eval_fraction_key(
"data_split_eval_fraction",
3522 doc.GetAllocator());
3524 rapidjson::Value data_split_eval_fraction_value(data_split_eval_fraction);
3527 data_split_eval_fraction_key, data_split_eval_fraction_value, doc.GetAllocator());
3529 rapidjson::Value feature_permutations_array(rapidjson::kArrayType);
3530 for (
const auto& feature_permutation : feature_permutations) {
3531 rapidjson::Value feature_permutation_value;
3532 feature_permutation_value.SetInt64(feature_permutation);
3533 feature_permutations_array.PushBack(feature_permutation_value, doc.GetAllocator());
3535 doc.AddMember(
"feature_permutations", feature_permutations_array, doc.GetAllocator());
3538 rapidjson::StringBuffer buffer;
3539 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
3542 return buffer.GetString();
3553 std::ostringstream error_oss;
3555 throw std::runtime_error(error_oss.str());
3564 bool train_fraction_specified =
false;
3565 bool eval_fraction_specified =
false;
3567 const auto key = boost::to_lower_copy<std::string>(*p->get_name());
3568 if (key ==
"train_fraction" || key ==
"data_split_train_fraction") {
3569 if (train_fraction_specified) {
3570 throw std::runtime_error(
3571 "Error parsing DATA_SPLIT_TRAIN_FRACTION value. "
3572 "Expected only one value.");
3576 if (fp_literal !=
nullptr) {
3578 if (data_split_train_fraction_ <= 0.0 || data_split_train_fraction_ > 1.0) {
3579 throw std::runtime_error(
3580 "Error parsing DATA_SPLIT_TRAIN_FRACTION value. "
3581 "Expected value between 0.0 and 1.0.");
3584 throw std::runtime_error(
3585 "Error parsing DATA_SPLIT_TRAIN_FRACTION value. "
3586 "Expected floating point value betwen 0.0 and 1.0.");
3588 train_fraction_specified =
true;
3591 if (key ==
"eval_fraction" || key ==
"data_split_eval_fraction") {
3592 if (eval_fraction_specified) {
3593 throw std::runtime_error(
3594 "Error parsing DATA_SPLIT_EVAL_FRACTION value. "
3595 "Expected only one value.");
3599 if (fp_literal !=
nullptr) {
3601 if (data_split_eval_fraction_ < 0.0 || data_split_eval_fraction_ >= 1.0) {
3602 throw std::runtime_error(
3603 "Error parsing DATA_SPLIT_EVAL_FRACTION value. "
3604 "Expected value between 0.0 and 1.0.");
3607 throw std::runtime_error(
3608 "Error parsing DATA_SPLIT_EVAL_FRACTION value. "
3609 "Expected floating point value betwen 0.0 and 1.0.");
3611 eval_fraction_specified =
true;
3620 if (str_literal !=
nullptr) {
3622 << boost::to_lower_copy<std::string>(*str_literal->
get_stringval())
3627 if (int_literal !=
nullptr) {
3632 if (fp_literal !=
nullptr) {
3636 throw std::runtime_error(
"Error parsing value.");
3654 throw std::runtime_error(
3655 "Error parsing DATA_SPLIT_TRAIN_FRACTION and DATA_SPLIT_EVAL_FRACTION values. "
3656 "Expected sum of values to be less than or equal to 1.0.");
3660 const std::shared_ptr<Catalog_Namespace::SessionInfo> session_ptr) {
3665 auto validate_result = local_connector.
query(
3666 validate_query_state->createQueryStateProxy(),
select_query_, {},
true,
false);
3668 auto column_descriptors_for_model_create =
3671 std::vector<size_t> categorical_feature_idxs;
3672 std::vector<size_t> numeric_feature_idxs;
3673 bool numeric_feature_seen =
false;
3674 bool all_categorical_features_placed_first =
true;
3677 (model_has_predicted_var ? 1 : 0));
3678 bool is_predicted = model_has_predicted_var ?
true :
false;
3679 size_t feature_idx = 0;
3680 for (
auto& cd : column_descriptors_for_model_create) {
3683 if (cd.columnName.rfind(
"EXPR$", 0) == 0) {
3684 throw std::runtime_error(
3685 "All projected expressions (i.e. col * 2) that are not column references (i.e. "
3686 "col) must be aliased.");
3690 if (!cd.columnType.is_number()) {
3691 throw std::runtime_error(
3692 "Numeric predicted column expression should be first argument to CREATE "
3695 is_predicted =
false;
3697 if (cd.columnType.is_number()) {
3698 numeric_feature_idxs.emplace_back(feature_idx);
3699 numeric_feature_seen =
true;
3700 }
else if (cd.columnType.is_string()) {
3701 categorical_feature_idxs.emplace_back(feature_idx);
3702 if (numeric_feature_seen) {
3703 all_categorical_features_placed_first =
false;
3706 throw std::runtime_error(
"Feature column expression should be numeric or TEXT.");
3713 if (!all_categorical_features_placed_first) {
3714 std::ostringstream modified_query_oss;
3715 modified_query_oss <<
"SELECT ";
3716 if (model_has_predicted_var) {
3719 for (
auto categorical_feature_idx : categorical_feature_idxs) {
3723 for (
auto numeric_feature_idx : numeric_feature_idxs) {
3726 if (numeric_feature_idx != numeric_feature_idxs.back()) {
3727 modified_query_oss <<
", ";
3730 modified_query_oss <<
" FROM (" << modified_select_query <<
")";
3731 modified_select_query = modified_query_oss.str();
3735 std::ostringstream modified_query_oss;
3736 if (all_categorical_features_placed_first) {
3737 modified_query_oss <<
"SELECT * FROM (" << modified_select_query <<
")";
3739 modified_query_oss << modified_select_query;
3742 modified_select_query = modified_query_oss.str();
3744 return modified_select_query;
3756 auto session_copy = session;
3757 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
3758 &session_copy, boost::null_deleter());
3773 const auto model_metadata =
3785 options_oss_ <<
"model_metadata => '" << model_metadata <<
"'";
3791 std::ostringstream model_query_oss;
3792 model_query_oss <<
"SELECT * FROM TABLE(" << model_train_func <<
"(model_name=>'"
3793 <<
get_model_name() <<
"', data=>CURSOR(" << modified_select_query
3795 model_query_oss <<
", " << options_str;
3796 model_query_oss <<
"))";
3798 std::string wrapped_model_query = model_query_oss.str();
3802 local_connector.
query(
3803 query_state->createQueryStateProxy(), wrapped_model_query, {},
false);
3807 bool read_only_mode) {
3808 if (read_only_mode) {
3809 throw std::runtime_error(
"CREATE MODEL invalid in read only mode.");
3814 }
catch (std::exception& e) {
3815 std::ostringstream error_oss;
3826 auto get_error_substring = [](
const std::string& message) -> std::string {
3827 size_t colon_position = std::string::npos;
3828 for (
int i = 0; i < 3; ++i) {
3829 colon_position = message.find(
':', colon_position + 1);
3830 if (colon_position == std::string::npos) {
3835 if (colon_position + 2 >= message.length()) {
3838 return message.substr(colon_position + 2);
3841 const auto error_substr = get_error_substring(e.what());
3843 error_oss <<
"Could not create model " <<
model_name_ <<
". " << error_substr;
3844 throw std::runtime_error(error_oss.str());
3849 CHECK(payload.HasMember(
"modelName"));
3853 if (payload.HasMember(
"ifExists")) {
3859 bool read_only_mode) {
3860 if (read_only_mode) {
3861 throw std::runtime_error(
"DROP MODEL invalid in read only mode.");
3865 }
catch (std::runtime_error& e) {
3874 const std::string select_stmt,
3875 std::vector<TargetMetaInfo>& targets,
3876 bool validate_only =
false,
3877 std::vector<size_t> outer_fragment_indices = {},
3878 bool allow_interrupt =
false) {
3880 auto& catalog = session->getCatalog();
3884 const auto device_type = session->get_executor_device_type();
3888 auto calcite_mgr = catalog.getCalciteMgr();
3892 const auto calciteQueryParsingOption =
3893 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true,
false);
3894 const auto calciteOptimizationOption = calcite_mgr->getCalciteOptimizationOption(
3899 const auto query_ra = calcite_mgr
3900 ->process(query_state_proxy,
3902 calciteQueryParsingOption,
3903 calciteOptimizationOption)
3906 executor.get(), query_ra, query_state_proxy->shared_from_this());
3929 std::numeric_limits<size_t>::max(),
3931 outer_fragment_indices};
3940 result = ra_executor.executeRelAlgQuery(co, eo,
false,
false,
nullptr);
3941 targets =
result.getTargetsMeta();
3947 std::string& sql_query_string) {
3949 auto& catalog = session->getCatalog();
3953 const auto device_type = session->get_executor_device_type();
3957 auto calcite_mgr = catalog.getCalciteMgr();
3961 const auto calciteQueryParsingOption =
3962 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true,
false);
3963 const auto calciteOptimizationOption = calcite_mgr->getCalciteOptimizationOption(
3968 const auto query_ra = calcite_mgr
3969 ->process(query_state_proxy,
3971 calciteQueryParsingOption,
3972 calciteOptimizationOption)
3993 return ra_executor.getOuterFragmentCount(co, eo);
3997 std::string& sql_query_string,
3998 std::vector<size_t> outer_frag_indices,
4000 bool allow_interrupt) {
4002 std::string pg_shimmed_select_query =
pg_shim(sql_query_string);
4004 std::vector<TargetMetaInfo> target_metainfos;
4007 auto query_session = session ? session->get_session_id() :
"";
4009 if (allow_interrupt && !validate_only && !query_session.empty()) {
4010 executor->enrollQuerySession(query_session,
4012 query_submitted_time,
4014 QuerySessionStatus::QueryStatus::PENDING_EXECUTOR);
4028 std::string& sql_query_string,
4029 std::vector<size_t> outer_frag_indices,
4030 bool allow_interrupt) {
4032 query_state_proxy, sql_query_string, outer_frag_indices,
false, allow_interrupt);
4039 std::list<ColumnDescriptor> column_descriptors;
4040 std::list<ColumnDescriptor> column_descriptors_for_create;
4042 int rowid_suffix = 0;
4043 for (
const auto& target_metainfo : result.
targets_meta) {
4045 cd.
columnName = target_metainfo.get_resname();
4049 cd.
columnType = target_metainfo.get_physical_type_info();
4069 column_descriptors_for_create.push_back(cd_for_create);
4070 column_descriptors.push_back(cd);
4074 return column_descriptors_for_create;
4077 return column_descriptors;
4081 const rapidjson::Value& payload) {
4082 CHECK(payload.HasMember(
"name"));
4085 CHECK(payload.HasMember(
"query"));
4088 boost::replace_all(select_query_,
"\n",
" ");
4089 select_query_ =
"(" + select_query_ +
")";
4091 if (payload.HasMember(
"columns")) {
4092 CHECK(payload[
"columns"].IsArray());
4093 for (
auto& column : payload[
"columns"].GetArray()) {
4095 column_list_.emplace_back(std::unique_ptr<std::string>(
new std::string(s)));
4102 bool validate_table,
4105 auto& catalog = session->getCatalog();
4107 bool populate_table =
false;
4110 populate_table =
true;
4114 populate_table =
true;
4118 auto get_target_column_descriptors = [
this, &catalog](
const TableDescriptor* td) {
4119 std::vector<const ColumnDescriptor*> target_column_descriptors;
4121 auto list = catalog.getAllColumnMetadataForTable(td->
tableId,
false,
false,
false);
4122 target_column_descriptors = {std::begin(list), std::end(list)};
4126 if (cd ==
nullptr) {
4127 throw std::runtime_error(
"Column " + *c +
" does not exist.");
4129 target_column_descriptors.push_back(cd);
4133 return target_column_descriptors;
4138 if (validate_table) {
4141 throw std::runtime_error(
"Table " +
table_name_ +
" does not exist.");
4144 throw std::runtime_error(
"Insert to views is not supported yet.");
4150 throw std::runtime_error(
"User has no insert privileges on " +
table_name_ +
".");
4159 std::vector<const ColumnDescriptor*> target_column_descriptors =
4160 get_target_column_descriptors(td);
4162 if (source_column_descriptors.size() != target_column_descriptors.size()) {
4163 throw std::runtime_error(
"The number of source and target columns does not match.");
4166 for (
int i = 0; i < source_column_descriptors.size(); i++) {
4168 &(*std::next(source_column_descriptors.begin(), i));
4172 auto type_cannot_be_cast = [](
const auto& col_type) {
4173 return (col_type.is_time() || col_type.is_geometry() || col_type.is_array() ||
4174 col_type.is_boolean());
4177 if (type_cannot_be_cast(source_cd->
columnType) ||
4178 type_cannot_be_cast(target_cd->
columnType)) {
4179 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4181 "' and target '" + target_cd->
columnName +
" " +
4183 "' column types do not match.");
4188 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4190 "' and target '" + target_cd->
columnName +
" " +
4192 "' array column element types do not match.");
4197 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4199 "' and target '" + target_cd->
columnName +
" " +
4201 "' column types do not match.");
4215 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4217 "' and target '" + target_cd->
columnName +
" " +
4219 "' decimal columns scales do not match.");
4225 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4227 "' and target '" + target_cd->
columnName +
" " +
4229 "' column types do not match.");
4233 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4235 "' and target '" + target_cd->
columnName +
" " +
4237 "' columns string encodings do not match.");
4244 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4246 "' and target '" + target_cd->
columnName +
" " +
4248 "' timestamp column precisions do not match.");
4257 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
4259 "' and target '" + target_cd->
columnName +
" " +
4261 "' column encoding sizes do not match.");
4266 if (!populate_table) {
4270 int64_t total_row_count = 0;
4271 int64_t total_source_query_time_ms = 0;
4272 int64_t total_target_value_translate_time_ms = 0;
4273 int64_t total_data_load_time_ms = 0;
4276 auto target_column_descriptors = get_target_column_descriptors(td);
4277 auto outer_frag_count =
4280 size_t outer_frag_end = outer_frag_count == 0 ? 1 : outer_frag_count;
4281 auto query_session = session ? session->get_session_id() :
"";
4283 std::string work_type_str = for_CTAS ?
"CTAS" :
"ITAS";
4285 for (
size_t outer_frag_idx = 0; outer_frag_idx < outer_frag_end; outer_frag_idx++) {
4286 std::vector<size_t> allowed_outer_fragment_indices;
4288 if (outer_frag_count) {
4289 allowed_outer_fragment_indices.push_back(outer_frag_idx);
4293 std::vector<AggregatedResult> query_results =
4296 allowed_outer_fragment_indices,
4298 total_source_query_time_ms +=
timer_stop(query_clock_begin);
4301 auto query_str =
"INSERT_DATA for " + work_type_str;
4306 executor->enrollQuerySession(query_session,
4310 QuerySessionStatus::QueryStatus::RUNNING_IMPORTER);
4317 executor->clearQuerySessionStatus(query_session,
start_time);
4321 for (
auto&
res : query_results) {
4323 throw std::runtime_error(
4324 "Query execution has been interrupted while performing " + work_type_str);
4326 auto& result_rows =
res.rs;
4328 const auto num_rows = result_rows->rowCount();
4330 if (0 == num_rows) {
4334 total_row_count += num_rows;
4339 const size_t rows_per_block =
4340 std::max(std::min(num_rows / leaf_count,
size_t(64 * 1024)),
size_t(1));
4342 std::vector<std::unique_ptr<TargetValueConverter>> value_converters;
4346 const int num_worker_threads = std::thread::hardware_concurrency();
4348 std::vector<size_t> thread_start_idx(num_worker_threads),
4349 thread_end_idx(num_worker_threads);
4350 bool can_go_parallel = !result_rows->isTruncated() && rows_per_block > 20000;
4352 std::atomic<size_t> crt_row_idx{0};
4354 auto do_work = [&result_rows, &value_converters, &crt_row_idx](
4356 const size_t block_end,
4357 const size_t num_cols,
4359 bool& stop_convert) {
4360 const auto result_row = result_rows->getRowAtNoTranslations(idx);
4361 if (!result_row.empty()) {
4362 size_t target_row = crt_row_idx.fetch_add(1);
4363 if (target_row >= block_end) {
4364 stop_convert =
true;
4367 for (
unsigned int col = 0; col < num_cols; col++) {
4368 const auto& mapd_variant = result_row[col];
4369 value_converters[col]->convertToColumnarFormat(target_row, &mapd_variant);
4374 auto convert_function = [&thread_start_idx,
4380 &do_work](
const int thread_id,
const size_t block_end) {
4381 const int num_cols = value_converters.size();
4382 const size_t start = thread_start_idx[
thread_id];
4383 const size_t end = thread_end_idx[
thread_id];
4385 bool stop_convert =
false;
4387 size_t local_idx = 0;
4388 for (idx = start; idx < end; ++idx, ++local_idx) {
4389 if (
UNLIKELY((local_idx & 0xFFFF) == 0 &&
4391 throw std::runtime_error(
4392 "Query execution has been interrupted while performing " +
4395 do_work(idx, block_end, num_cols, thread_id, stop_convert);
4401 for (idx = start; idx < end; ++idx) {
4402 do_work(idx, block_end, num_cols, thread_id, stop_convert);
4411 auto single_threaded_value_converter =
4412 [&crt_row_idx, &value_converters, &result_rows](
const size_t idx,
4413 const size_t block_end,
4414 const size_t num_cols,
4415 bool& stop_convert) {
4416 size_t target_row = crt_row_idx.fetch_add(1);
4417 if (target_row >= block_end) {
4418 stop_convert =
true;
4421 const auto result_row = result_rows->getNextRow(
false,
false);
4422 CHECK(!result_row.empty());
4423 for (
unsigned int col = 0; col < num_cols; col++) {
4424 const auto& mapd_variant = result_row[col];
4425 value_converters[col]->convertToColumnarFormat(target_row, &mapd_variant);
4429 auto single_threaded_convert_function = [&value_converters,
4435 &single_threaded_value_converter](
4437 const size_t block_end) {
4438 const int num_cols = value_converters.size();
4439 const size_t start = thread_start_idx[
thread_id];
4440 const size_t end = thread_end_idx[
thread_id];
4442 bool stop_convert =
false;
4444 size_t local_idx = 0;
4445 for (idx = start; idx < end; ++idx, ++local_idx) {
4446 if (
UNLIKELY((local_idx & 0xFFFF) == 0 &&
4448 throw std::runtime_error(
4449 "Query execution has been interrupted while performing " +
4452 single_threaded_value_converter(idx, block_end, num_cols, stop_convert);
4458 for (idx = start; idx < end; ++idx) {
4459 single_threaded_value_converter(idx, end, num_cols, stop_convert);
4468 if (can_go_parallel) {
4469 const size_t entry_count = result_rows->entryCount();
4473 stride = (entry_count + num_worker_threads - 1) / num_worker_threads;
4474 i < num_worker_threads && start_entry < entry_count;
4475 ++i, start_entry += stride) {
4476 const auto end_entry = std::min(start_entry + stride, entry_count);
4477 thread_start_idx[i] = start_entry;
4478 thread_end_idx[i] = end_entry;
4481 thread_start_idx[0] = 0;
4482 thread_end_idx[0] = result_rows->entryCount();
4485 for (
size_t block_start = 0; block_start < num_rows;
4486 block_start += rows_per_block) {
4487 const auto num_rows_this_itr = block_start + rows_per_block < num_rows
4489 : num_rows - block_start;
4491 value_converters.clear();
4493 for (
const auto targetDescriptor : target_column_descriptors) {
4494 auto sourceDataMetaInfo =
res.targets_meta[colNum++];
4500 targetDescriptor->columnType,
4501 !targetDescriptor->columnType.get_notnull(),
4502 result_rows->getRowSetMemOwner()->getLiteralStringDictProxy(),
4504 sourceDataMetaInfo.get_type_info().is_dict_encoded_string()
4505 ? executor->getStringDictionaryProxy(
4506 sourceDataMetaInfo.get_type_info().getStringDictKey(),
4507 result_rows->getRowSetMemOwner(),
4510 auto converter = factory.
create(param);
4511 value_converters.push_back(std::move(converter));
4515 if (can_go_parallel) {
4516 std::vector<std::future<void>> worker_threads;
4517 for (
int i = 0; i < num_worker_threads; ++i) {
4518 worker_threads.push_back(
4522 for (
auto& child : worker_threads) {
4525 for (
auto& child : worker_threads) {
4530 single_threaded_convert_function(0, num_rows_this_itr);
4534 auto finalizer_func =
4535 [](std::unique_ptr<TargetValueConverter>::pointer targetValueConverter) {
4536 targetValueConverter->finalizeDataBlocksForInsertData();
4539 std::vector<std::future<void>> worker_threads;
4540 for (
auto& converterPtr : value_converters) {
4541 worker_threads.push_back(
4545 for (
auto& child : worker_threads) {
4548 for (
auto& child : worker_threads) {
4553 insert_data.
databaseId = catalog.getCurrentDB().dbId;
4556 insert_data.
numRows = num_rows_this_itr;
4558 for (
int col_idx = 0; col_idx < target_column_descriptors.size(); col_idx++) {
4561 throw std::runtime_error(
4562 "Query execution has been interrupted while performing " +
4565 value_converters[col_idx]->addDataBlocksToInsertData(insert_data);
4567 total_target_value_translate_time_ms +=
timer_stop(translate_clock_begin);
4570 auto data_memory_holder =
4572 insertDataLoader.
insertData(*session, insert_data);
4573 total_data_load_time_ms +=
timer_stop(data_load_clock_begin);
4580 }
catch (std::exception& e) {
4581 LOG(
ERROR) <<
"An error occurred during ITAS rollback attempt. Table id: "
4582 << td->
tableId <<
", Error: " << e.what();
4587 int64_t total_time_ms = total_source_query_time_ms +
4588 total_target_value_translate_time_ms + total_data_load_time_ms;
4590 VLOG(1) <<
"CTAS/ITAS " << total_row_count <<
" rows loaded in " << total_time_ms
4591 <<
"ms (outer_frag_count=" << outer_frag_count
4592 <<
", query_time=" << total_source_query_time_ms
4593 <<
"ms, translation_time=" << total_target_value_translate_time_ms
4594 <<
"ms, data_load_time=" << total_data_load_time_ms
4597 if (!is_temporary) {
4606 const auto table_id = catalog->getTableId(table[0]);
4607 if (!table_id.has_value()) {
4608 throw std::runtime_error{
"Table \"" + table[0] +
4609 "\" does not exist in catalog: " + table[1] +
"."};
4611 return {catalog->getDatabaseId(), table_id.value()};
4615 const std::string& insert_table_db_name,
4616 const std::string& query_str,
4618 const std::optional<std::string>& insert_table_name = {}) {
4620 auto& calcite_mgr = sys_catalog.getCalciteMgr();
4621 const auto calciteQueryParsingOption =
4622 calcite_mgr.getCalciteQueryParsingOption(
true,
false,
true,
false);
4623 const auto calciteOptimizationOption = calcite_mgr.getCalciteOptimizationOption(
4625 const auto result = calcite_mgr.process(query_state_proxy,
4627 calciteQueryParsingOption,
4628 calciteOptimizationOption);
4631 auto comparator = [](
const std::vector<std::string>& table_1,
4632 const std::vector<std::string>& table_2) {
4635 std::set<std::vector<std::string>, decltype(comparator)>
tables(comparator);
4636 for (
auto& tab :
result.resolved_accessed_objects.tables_selected_from) {
4639 if (insert_table_name.has_value()) {
4641 std::vector<std::string>{insert_table_name.value(), insert_table_db_name});
4644 for (
const auto& table :
tables) {
4645 const auto catalog = sys_catalog.getCatalog(table[1]);
4650 *catalog, table[0])));
4651 if (insert_table_name.has_value() && table[0] == insert_table_name.value() &&
4652 table[1] == insert_table_db_name) {
4656 catalog->getDatabaseId(), (*locks.back())())));
4661 catalog->getDatabaseId(), (*locks.back())())));
4669 bool read_only_mode) {
4670 if (read_only_mode) {
4671 throw std::runtime_error(
"INSERT INTO TABLE invalid in read only mode.");
4673 auto session_copy = session;
4674 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
4675 &session_copy, boost::null_deleter());
4677 auto stdlog =
STDLOG(query_state);
4678 auto& catalog = session_ptr->getCatalog();
4682 if (catalog.getMetadataForTable(
table_name_) ==
nullptr) {
4683 throw std::runtime_error(
"ITAS failed: table " +
table_name_ +
" does not exist.");
4693 populateData(query_state->createQueryStateProxy(), td,
true,
false);
4701 if (payload.HasMember(
"temporary")) {
4707 if (payload.HasMember(
"ifNotExists")) {
4717 bool read_only_mode) {
4718 if (read_only_mode) {
4719 throw std::runtime_error(
"CREATE TABLE invalid in read only mode.");
4721 auto session_copy = session;
4722 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
4723 &session_copy, boost::null_deleter());
4725 auto stdlog =
STDLOG(query_state);
4730 std::set<std::string> select_tables;
4737 throw std::runtime_error(
"CTAS failed. Table " +
table_name_ +
4738 " will not be created. User has no create privileges.");
4741 if (catalog.getMetadataForTable(
table_name_) !=
nullptr) {
4746 " already exists and no data was loaded.");
4752 auto validate_result = local_connector.
query(
4753 query_state->createQueryStateProxy(),
select_query_, {},
true,
false);
4755 auto column_descriptors_for_create =
4759 for (
auto& cd : column_descriptors_for_create) {
4760 if (cd.columnType.is_decimal() &&
4762 throw std::runtime_error(cd.columnName +
": Precision too high, max " +
4769 cd.columnType.setUsesFlatBuffer(
false);
4775 td.
nColumns = column_descriptors_for_create.size();
4790 bool use_shared_dictionaries =
true;
4791 bool force_geo_compression =
true;
4795 if (boost::to_lower_copy<std::string>(*p->get_name()) ==
4796 "use_shared_dictionaries") {
4799 if (
nullptr == literal) {
4800 throw std::runtime_error(
4801 "USE_SHARED_DICTIONARIES must be a string parameter");
4803 std::string val = boost::to_lower_copy<std::string>(*literal->
get_stringval());
4804 use_shared_dictionaries = val ==
"true" || val ==
"1" || val ==
"t";
4805 }
else if (boost::to_lower_copy<std::string>(*p->get_name()) ==
4806 "force_geo_compression") {
4809 if (
nullptr == literal) {
4810 throw std::runtime_error(
"FORCE_GEO_COMPRESSION must be a string parameter");
4812 std::string val = boost::to_lower_copy<std::string>(*literal->
get_stringval());
4813 force_geo_compression = val ==
"true" || val ==
"1" || val ==
"t";
4820 std::vector<SharedDictionaryDef> sharedDictionaryRefs;
4822 if (use_shared_dictionaries) {
4823 const auto source_column_descriptors =
4825 const auto mapping = catalog.getDictionaryToColumnMapping();
4827 for (
auto& source_cd : source_column_descriptors) {
4828 const auto& ti = source_cd.columnType;
4829 if (ti.is_string()) {
4831 int dict_id = ti.get_comp_param();
4832 auto it = mapping.find(dict_id);
4833 if (mapping.end() != it) {
4834 const auto targetColumn = it->second;
4836 catalog.getMetadataForTable(targetColumn->tableId,
false);
4838 LOG(
INFO) <<
"CTAS: sharing text dictionary on column "
4839 << source_cd.columnName <<
" with " << targetTable->tableName
4840 <<
"." << targetColumn->columnName;
4841 sharedDictionaryRefs.emplace_back(
4842 source_cd.columnName, targetTable->tableName, targetColumn->columnName);
4849 if (force_geo_compression) {
4850 for (
auto& cd_for_create : column_descriptors_for_create) {
4851 auto& ti = cd_for_create.columnType;
4852 if (ti.is_geometry() && ti.get_output_srid() == 4326) {
4855 ti.set_comp_param(32);
4863 catalog.createTable(td, column_descriptors_for_create, sharedDictionaryRefs,
true);
4878 populateData(query_state->createQueryStateProxy(), td,
false,
true);
4883 catalog.dropTable(created_td);
4891 CHECK(payload.HasMember(
"tableName"));
4892 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4895 if (payload.HasMember(
"ifExists")) {
4896 if_exists_ =
json_bool(payload[
"ifExists"]);
4901 bool read_only_mode) {
4902 if (read_only_mode) {
4903 throw std::runtime_error(
"DROP TABLE invalid in read only mode.");
4911 std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
4914 std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
4916 catalog, *
table_,
false));
4917 td = (*td_with_lock)();
4918 }
catch (
const std::runtime_error& e) {
4927 CHECK(td_with_lock);
4932 throw std::runtime_error(
"Table " + *
table_ +
4933 " will not be dropped. User has no proper privileges.");
4939 auto table_data_read_lock =
4944 auto table_data_write_lock =
4946 catalog.dropTable(td);
4950 CHECK(payload.HasMember(
"tableName"));
4951 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4955 bool read_only_mode) {
4956 if (read_only_mode) {
4957 throw std::runtime_error(
"TRUNCATE TABLE invalid in read only mode.");
4961 const auto td_with_lock =
4964 const auto td = td_with_lock();
4966 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
4970 std::vector<DBObject> privObjects;
4974 privObjects.push_back(dbObject);
4976 throw std::runtime_error(
"Table " + *
table_ +
" will not be truncated. User " +
4978 " has no proper privileges.");
4982 throw std::runtime_error(*
table_ +
" is a view. Cannot Truncate.");
4988 auto table_data_read_lock =
4993 auto table_data_write_lock =
4995 catalog.truncateTable(td);
4999 CHECK(payload.HasMember(
"tableName"));
5000 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
5010 std::vector<DBObject> privObjects;
5014 privObjects.push_back(dbObject);
5021 bool read_only_mode) {
5022 if (read_only_mode) {
5023 throw std::runtime_error(
"OPTIMIZE TABLE invalid in read only mode.");
5029 const auto td_with_lock =
5032 const auto td = td_with_lock();
5035 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5039 throw std::runtime_error(
"OPTIMIZE TABLE command is not supported on views.");
5053 bool repair_type(std::list<std::unique_ptr<NameValueAssign>>& options) {
5054 for (
const auto& opt : options) {
5055 if (boost::iequals(*opt->get_name(),
"REPAIR_TYPE")) {
5057 static_cast<const StringLiteral*
>(opt->get_value())->get_stringval();
5062 throw std::runtime_error(
"REPAIR_TYPE must be REMOVE.");
5065 throw std::runtime_error(
"The only VALIDATE WITH options is REPAIR_TYPE.");
5074 throw std::runtime_error(
"Validation Type is required for VALIDATE command.");
5076 std::list<std::unique_ptr<NameValueAssign>> options;
5078 for (
const auto e : *with_opts) {
5079 options.emplace_back(e);
5088 CHECK(payload.HasMember(
"type"));
5089 type_ = std::make_unique<std::string>(
json_str(payload[
"type"]));
5091 std::list<std::unique_ptr<NameValueAssign>> options;
5103 std::vector<DBObject> privObjects;
5107 privObjects.push_back(dbObject);
5109 throw std::runtime_error(
"Current user does not have the privilege to alter table: " +
5115 CHECK(payload.HasMember(
"name"));
5117 CHECK(payload.HasMember(
"newName"));
5122 bool read_only_mode) {
5123 if (read_only_mode) {
5124 throw std::runtime_error(
"RENAME TABLE invalid in read only mode.");
5127 throw std::runtime_error(
"Only a super user can rename users.");
5132 throw std::runtime_error(
"User " + *
username_ +
" does not exist.");
5139 CHECK(payload.HasMember(
"name"));
5141 CHECK(payload.HasMember(
"newName"));
5146 bool read_only_mode) {
5147 if (read_only_mode) {
5148 throw std::runtime_error(
"RENAME DATABASE invalid in read only mode.");
5156 throw std::runtime_error(
"Database " + *
database_name_ +
" does not exist.");
5161 throw std::runtime_error(
"Only a super user or the owner can rename the database.");
5168 CHECK(payload.HasMember(
"tableNames"));
5169 CHECK(payload[
"tableNames"].IsArray());
5170 const auto elements = payload[
"tableNames"].GetArray();
5171 for (
const auto& element : elements) {
5172 CHECK(element.HasMember(
"name"));
5173 CHECK(element.HasMember(
"newName"));
5175 new std::string(
json_str(element[
"newName"])));
5184 std::list<std::pair<std::string, std::string>> tableNames) {
5185 for (
auto item : tableNames) {
5187 new std::string(item.second));
5202 std::time_t
result = std::time(
nullptr);
5207 sMap[oldName] = newName;
5212 std::string tableName) {
5213 if (sMap.find(tableName) != sMap.end()) {
5217 return sMap[tableName];
5222 sMap[tableName] = tableName;
5239 for (
auto it : sMap) {
5240 if ((it.second) !=
EMPTY_NAME && (it.first) != (it.second)) {
5241 throw std::runtime_error(
5242 "Error: Attempted to overwrite and lose data in table: \'" + (it.first) +
"\'");
5251 throw std::runtime_error(td->
tableName +
" is a foreign table. " +
5252 "Use ALTER FOREIGN TABLE.");
5258 bool read_only_mode) {
5259 if (read_only_mode) {
5260 throw std::runtime_error(
"RENAME TABLE invalid in read only mode.");
5268 std::vector<std::pair<std::string, std::string>> names;
5273 std::string curTableName = *(item.first);
5274 std::string newTableName = *(item.second);
5281 std::string altCurTableName =
loadTable(catalog, tableSubtituteMap, curTableName);
5282 std::string altNewTableName =
loadTable(catalog, tableSubtituteMap, newTableName);
5284 if (altCurTableName != curTableName && altCurTableName !=
EMPTY_NAME) {
5286 recordRename(tableSubtituteMap, curTableName, curTableName);
5297 if (
hasData(tableSubtituteMap, altCurTableName)) {
5298 const TableDescriptor* td = catalog.getMetadataForTable(altCurTableName);
5306 if (
hasData(tableSubtituteMap, altNewTableName)) {
5311 recordRename(tableSubtituteMap, altNewTableName, tmpNewTableName);
5312 recordRename(tableSubtituteMap, tmpNewTableName, tmpNewTableName);
5313 names.emplace_back(altNewTableName, tmpNewTableName);
5314 names.emplace_back(altCurTableName, altNewTableName);
5318 recordRename(tableSubtituteMap, altNewTableName, altNewTableName);
5319 names.emplace_back(altCurTableName, altNewTableName);
5322 throw std::runtime_error(
"Source table \'" + curTableName +
"\' does not exist.");
5327 catalog.renameTables(names);
5330 while (!tablesToRename_.empty()) {
5331 tablesToRename_.pop_front();
5338 if (cc ==
nullptr) {
5343 std::string default_value;
5344 const std::string* default_value_ptr =
nullptr;
5347 auto defaultsp =
dynamic_cast<const StringLiteral*
>(def_val_literal);
5349 defaultsp ? *defaultsp->
get_stringval() : def_val_literal->to_string();
5354 std::regex array_re(R
"(^ARRAY\s*\[(.*)\]$)", std::regex_constants::icase);
5355 default_value = std::regex_replace(default_value, array_re, "{$1}");
5356 boost::erase_all(default_value,
"\'");
5358 default_value_ptr = &default_value;
5377 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5380 throw std::runtime_error(
"Adding columns to a view is not supported.");
5384 throw std::runtime_error(
5385 "Adding columns to temporary tables is not yet supported.");
5395 for (
const auto& coldef :
coldefs_) {
5396 auto& new_column_name = *coldef->get_column_name();
5397 if (catalog.getMetadataForColumn(td->
tableId, new_column_name) !=
nullptr) {
5398 throw std::runtime_error(
"Column " + new_column_name +
" already exists.");
5404 bool read_only_mode) {
5405 if (read_only_mode) {
5406 throw std::runtime_error(
"ADD COLUMN invalid in read only mode.");
5411 const auto td_with_lock =
5414 const auto td = td_with_lock();
5419 if (std::dynamic_pointer_c