25 #include <boost/algorithm/string.hpp>
26 #include <boost/core/null_deleter.hpp>
27 #include <boost/filesystem.hpp>
28 #include <boost/function.hpp>
30 #include <rapidjson/document.h>
31 #include <rapidjson/stringbuffer.h>
32 #include <rapidjson/writer.h>
41 #include <type_traits>
75 #include "gen-cpp/CalciteServer.h"
83 #ifdef ENABLE_IMPORT_PARQUET
84 bool g_enable_legacy_parquet_import{
false};
91 using namespace std::string_literals;
95 const std::list<ColumnDescriptor>& columns)>;
100 const std::list<ColumnDescriptor>& columns)>;
109 executor->getSessionLock());
110 return executor->checkIsQuerySessionInterrupted(query_session, session_read_lock);
117 std::vector<int> table_chunk_key_prefix;
120 table_chunk_key_prefix = td->
fragmenter->getFragmentsForQuery().chunkKeyPrefix;
123 table_chunk_key_prefix.push_back(td->
tableId);
126 return table_chunk_key_prefix;
129 std::shared_ptr<Analyzer::Expr> NullLiteral::analyze(
133 return makeExpr<Analyzer::Constant>(
kNULLT,
true);
136 std::shared_ptr<Analyzer::Expr> StringLiteral::analyze(
140 return analyzeValue(*stringval_,
false);
143 std::shared_ptr<Analyzer::Expr> StringLiteral::analyzeValue(
const std::string& stringval,
148 d.
stringval =
new std::string(stringval);
149 return makeExpr<Analyzer::Constant>(ti,
false, d);
152 return makeExpr<Analyzer::Constant>(
kVARCHAR,
true);
155 std::shared_ptr<Analyzer::Expr> IntLiteral::analyze(
159 return analyzeValue(intval_);
162 std::shared_ptr<Analyzer::Expr> IntLiteral::analyzeValue(
const int64_t intval) {
165 if (intval >= INT16_MIN && intval <= INT16_MAX) {
168 }
else if (intval >= INT32_MIN && intval <= INT32_MAX) {
170 d.
intval = (int32_t)intval;
175 return makeExpr<Analyzer::Constant>(t,
false, d);
178 std::shared_ptr<Analyzer::Expr> FixedPtLiteral::analyze(
184 return makeExpr<Analyzer::Constant>(ti,
false, d);
187 std::shared_ptr<Analyzer::Expr> FixedPtLiteral::analyzeValue(
const int64_t numericval,
189 const int precision) {
195 return makeExpr<Analyzer::Constant>(ti,
false, d);
198 std::shared_ptr<Analyzer::Expr> FloatLiteral::analyze(
204 return makeExpr<Analyzer::Constant>(
kFLOAT,
false, d);
207 std::shared_ptr<Analyzer::Expr> DoubleLiteral::analyze(
213 return makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
216 std::shared_ptr<Analyzer::Expr> TimestampLiteral::analyze(
220 return get(timestampval_);
223 std::shared_ptr<Analyzer::Expr> TimestampLiteral::get(
const int64_t timestampval) {
226 return makeExpr<Analyzer::Constant>(
kTIMESTAMP,
false, d);
229 std::shared_ptr<Analyzer::Expr> UserLiteral::analyze(
234 return makeExpr<Analyzer::Constant>(
kTEXT,
false, d);
237 std::shared_ptr<Analyzer::Expr> UserLiteral::get(
const std::string& user) {
240 return makeExpr<Analyzer::Constant>(
kTEXT,
false, d);
243 std::shared_ptr<Analyzer::Expr> ArrayLiteral::analyze(
248 bool set_subtype =
true;
249 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
250 for (
auto& p : value_list_) {
251 auto e = p->analyze(catalog, query, allow_tlist_ref);
254 if (c !=
nullptr && c->get_is_null()) {
255 value_exprs.push_back(c);
261 }
else if (set_subtype) {
265 value_exprs.push_back(e);
267 std::shared_ptr<Analyzer::Expr>
result =
268 makeExpr<Analyzer::Constant>(ti,
false, value_exprs);
273 std::string str =
"{";
274 bool notfirst =
false;
275 for (
auto& p : value_list_) {
281 str += p->to_string();
287 std::shared_ptr<Analyzer::Expr> OperExpr::analyze(
291 auto left_expr = left_->analyze(catalog, query, allow_tlist_ref);
292 const auto& left_type = left_expr->get_type_info();
293 if (right_ ==
nullptr) {
294 return makeExpr<Analyzer::UOper>(
295 left_type, left_expr->get_contains_agg(), optype_, left_expr->decompress());
298 if (left_type.get_type() !=
kARRAY) {
299 throw std::runtime_error(left_->to_string() +
" is not of array type.");
301 auto right_expr = right_->analyze(catalog, query, allow_tlist_ref);
302 const auto& right_type = right_expr->get_type_info();
303 if (!right_type.is_integer()) {
304 throw std::runtime_error(right_->to_string() +
" is not of integer type.");
306 return makeExpr<Analyzer::BinOper>(
307 left_type.get_elem_type(),
false,
kARRAY_AT,
kONE, left_expr, right_expr);
309 auto right_expr = right_->analyze(catalog, query, allow_tlist_ref);
310 return normalize(optype_, opqualifier_, left_expr, right_expr);
314 const std::shared_ptr<Analyzer::Expr>& rhs_expr) {
315 std::set<int> lhs_rte_idx;
316 lhs_expr->collect_rte_idx(lhs_rte_idx);
317 CHECK(!lhs_rte_idx.empty());
318 std::set<int> rhs_rte_idx;
319 rhs_expr->collect_rte_idx(rhs_rte_idx);
320 CHECK(!rhs_rte_idx.empty());
321 return lhs_rte_idx.size() == 1UL && lhs_rte_idx == rhs_rte_idx;
326 const Executor* executor) {
333 CHECK_NE(lhs_dict_key, rhs_dict_key);
334 if (lhs_dict_key.isTransientDict()) {
335 return rhs_type_info;
337 if (rhs_dict_key.isTransientDict()) {
338 return lhs_type_info;
342 const auto lhs_sdp = executor->getStringDictionaryProxy(lhs_dict_key,
true);
343 const auto rhs_sdp = executor->getStringDictionaryProxy(rhs_dict_key,
true);
344 return lhs_sdp->entryCount() >= rhs_sdp->entryCount() ? lhs_type_info : rhs_type_info;
349 const Executor* executor) {
355 if (lhs_dict_key == rhs_dict_key ||
356 (lhs_dict_key.db_id == rhs_dict_key.db_id &&
358 return lhs_dict_key.
dict_id <= rhs_dict_key.dict_id ? lhs_type_info : rhs_type_info;
365 if (ret_ti.is_none_encoded_string()) {
372 std::shared_ptr<Analyzer::Expr> OperExpr::normalize(
375 std::shared_ptr<Analyzer::Expr> left_expr,
376 std::shared_ptr<Analyzer::Expr> right_expr,
377 const Executor* executor) {
378 if (left_expr->get_type_info().is_date_in_days() ||
379 right_expr->get_type_info().is_date_in_days()) {
381 left_expr = left_expr->decompress();
382 right_expr = right_expr->decompress();
384 const auto& left_type = left_expr->get_type_info();
385 auto right_type = right_expr->get_type_info();
388 CHECK(!std::dynamic_pointer_cast<Analyzer::Subquery>(right_expr));
389 if (right_type.get_type() !=
kARRAY) {
390 throw std::runtime_error(
391 "Existential or universal qualifiers can only be used in front of a subquery "
393 "expression of array type.");
395 right_type = right_type.get_elem_type();
400 optype, left_type, right_type, &new_left_type, &new_right_type);
401 if (result_type.is_timeinterval()) {
402 return makeExpr<Analyzer::BinOper>(
403 result_type,
false, optype, qual, left_expr, right_expr);
405 if (left_type != new_left_type) {
406 left_expr = left_expr->add_cast(new_left_type);
408 if (right_type != new_right_type) {
410 right_expr = right_expr->add_cast(new_right_type);
412 right_expr = right_expr->add_cast(new_right_type.
get_array_type());
419 throw std::runtime_error(
420 "Comparison operators are not yet supported for geospatial types.");
426 if (optype ==
kEQ || optype ==
kNE) {
432 const bool should_translate_strings =
434 if (should_translate_strings && (optype ==
kEQ || optype ==
kNE)) {
440 auto& expr_to_cast = ti == new_left_type ? right_expr : left_expr;
443 expr_to_cast = expr_to_cast->add_cast(ti);
448 left_expr = left_expr->decompress();
449 right_expr = right_expr->decompress();
455 left_expr = left_expr->decompress();
456 right_expr = right_expr->decompress();
459 if (!(optype ==
kEQ || optype ==
kNE)) {
462 left_expr = left_expr->decompress();
463 right_expr = right_expr->decompress();
477 right_expr = right_expr->add_cast(ti);
485 left_expr = left_expr->add_cast(ti);
487 left_expr = left_expr->decompress();
488 right_expr = right_expr->decompress();
492 left_expr = left_expr->decompress();
493 right_expr = right_expr->decompress();
495 bool has_agg = (left_expr->get_contains_agg() || right_expr->get_contains_agg());
496 return makeExpr<Analyzer::BinOper>(
497 result_type, has_agg, optype, qual, left_expr, right_expr);
500 std::shared_ptr<Analyzer::Expr> SubqueryExpr::analyze(
504 throw std::runtime_error(
"Subqueries are not supported yet.");
508 std::shared_ptr<Analyzer::Expr> IsNullExpr::analyze(
512 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
520 std::shared_ptr<Analyzer::Expr> InSubquery::analyze(
524 throw std::runtime_error(
"Subqueries are not supported yet.");
528 std::shared_ptr<Analyzer::Expr> InValues::analyze(
532 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
535 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
536 for (
auto& p : value_list_) {
537 auto e = p->analyze(catalog, query, allow_tlist_ref);
538 if (ti != e->get_type_info()) {
539 if (ti.
is_string() && e->get_type_info().is_string()) {
542 }
else if (ti.
is_number() && e->get_type_info().is_number()) {
545 throw std::runtime_error(
"IN expressions must contain compatible types.");
549 value_exprs.push_back(e->add_cast(arg_expr->get_type_info()));
551 value_exprs.push_back(e);
555 arg_expr = arg_expr->decompress();
556 arg_expr = arg_expr->add_cast(ti);
557 std::list<std::shared_ptr<Analyzer::Expr>> cast_vals;
558 for (
auto p : value_exprs) {
559 cast_vals.push_back(p->add_cast(ti));
561 value_exprs.swap(cast_vals);
563 std::shared_ptr<Analyzer::Expr>
result =
564 makeExpr<Analyzer::InValues>(arg_expr, value_exprs);
571 std::shared_ptr<Analyzer::Expr> BetweenExpr::analyze(
575 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
576 auto lower_expr = lower_->analyze(catalog, query, allow_tlist_ref);
577 auto upper_expr = upper_->analyze(catalog, query, allow_tlist_ref);
580 arg_expr->get_type_info(),
581 lower_expr->get_type_info(),
585 makeExpr<Analyzer::BinOper>(
kBOOLEAN,
588 arg_expr->add_cast(new_left_type)->decompress(),
589 lower_expr->add_cast(new_right_type)->decompress());
591 arg_expr->get_type_info(),
592 lower_expr->get_type_info(),
595 auto upper_pred = makeExpr<Analyzer::BinOper>(
599 arg_expr->deep_copy()->add_cast(new_left_type)->decompress(),
600 upper_expr->add_cast(new_right_type)->decompress());
601 std::shared_ptr<Analyzer::Expr>
result =
609 std::shared_ptr<Analyzer::Expr> CharLengthExpr::analyze(
613 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
614 if (!arg_expr->get_type_info().is_string()) {
615 throw std::runtime_error(
616 "expression in char_length clause must be of a string type.");
618 std::shared_ptr<Analyzer::Expr>
result =
619 makeExpr<Analyzer::CharLengthExpr>(arg_expr->decompress(), calc_encoded_length_);
623 std::shared_ptr<Analyzer::Expr> CardinalityExpr::analyze(
627 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
628 if (!arg_expr->get_type_info().is_array()) {
629 throw std::runtime_error(
630 "expression in cardinality clause must be of an array type.");
632 std::shared_ptr<Analyzer::Expr>
result =
633 makeExpr<Analyzer::CardinalityExpr>(arg_expr->decompress());
637 void LikeExpr::check_like_expr(
const std::string& like_str,
char escape_char) {
638 if (like_str.back() == escape_char) {
639 throw std::runtime_error(
"LIKE pattern must not end with escape character.");
643 bool LikeExpr::test_is_simple_expr(
const std::string& like_str,
char escape_char) {
645 if (like_str.size() < 2 || like_str[0] !=
'%' || like_str[like_str.size() - 1] !=
'%') {
649 if (like_str[like_str.size() - 2] == escape_char &&
650 like_str[like_str.size() - 3] != escape_char) {
653 for (
size_t i = 1; i < like_str.size() - 1; i++) {
654 if (like_str[i] ==
'%' || like_str[i] ==
'_' || like_str[i] ==
'[' ||
655 like_str[i] ==
']') {
656 if (like_str[i - 1] != escape_char) {
664 void LikeExpr::erase_cntl_chars(std::string& like_str,
char escape_char) {
665 char prev_char =
'\0';
670 for (
char& cur_char : like_str) {
671 if (cur_char ==
'%' || cur_char == escape_char) {
672 if (prev_char != escape_char) {
673 prev_char = cur_char;
677 new_str.push_back(cur_char);
678 prev_char = cur_char;
683 std::shared_ptr<Analyzer::Expr> LikeExpr::analyze(
687 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
688 auto like_expr = like_string_->analyze(catalog, query, allow_tlist_ref);
689 auto escape_expr = escape_string_ ==
nullptr
691 : escape_string_->analyze(catalog, query, allow_tlist_ref);
692 return LikeExpr::get(arg_expr, like_expr, escape_expr, is_ilike_, is_not_);
695 std::shared_ptr<Analyzer::Expr> LikeExpr::get(std::shared_ptr<Analyzer::Expr> arg_expr,
696 std::shared_ptr<Analyzer::Expr> like_expr,
697 std::shared_ptr<Analyzer::Expr> escape_expr,
700 if (!arg_expr->get_type_info().is_string()) {
701 throw std::runtime_error(
"expression before LIKE must be of a string type.");
703 if (!like_expr->get_type_info().is_string()) {
704 throw std::runtime_error(
"expression after LIKE must be of a string type.");
706 char escape_char =
'\\';
707 if (escape_expr !=
nullptr) {
708 if (!escape_expr->get_type_info().is_string()) {
709 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
711 if (!escape_expr->get_type_info().is_string()) {
712 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
715 if (c !=
nullptr && c->get_constval().stringval->length() > 1) {
716 throw std::runtime_error(
"String after ESCAPE must have a single character.");
718 escape_char = (*c->get_constval().stringval)[0];
721 bool is_simple =
false;
725 std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
727 check_like_expr(pattern, escape_char);
728 is_simple = test_is_simple_expr(pattern, escape_char);
730 erase_cntl_chars(pattern, escape_char);
733 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::LikeExpr>(
734 arg_expr->decompress(), like_expr, escape_expr, is_ilike, is_simple);
741 void RegexpExpr::check_pattern_expr(
const std::string& pattern_str,
char escape_char) {
742 if (pattern_str.back() == escape_char) {
743 throw std::runtime_error(
"REGEXP pattern must not end with escape character.");
747 bool RegexpExpr::translate_to_like_pattern(std::string& pattern_str,
char escape_char) {
748 char prev_char =
'\0';
749 char prev_prev_char =
'\0';
750 std::string like_str;
751 for (
char& cur_char : pattern_str) {
752 if (prev_char == escape_char || isalnum(cur_char) || cur_char ==
' ' ||
754 like_str.push_back((cur_char ==
'.') ?
'_' : cur_char);
755 prev_prev_char = prev_char;
756 prev_char = cur_char;
759 if (prev_char ==
'.' && prev_prev_char != escape_char) {
760 if (cur_char ==
'*' || cur_char ==
'+') {
761 if (cur_char ==
'*') {
766 like_str.push_back(
'%');
767 prev_prev_char = prev_char;
768 prev_char = cur_char;
774 pattern_str = like_str;
778 std::shared_ptr<Analyzer::Expr> RegexpExpr::analyze(
782 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
783 auto pattern_expr = pattern_string_->analyze(catalog, query, allow_tlist_ref);
784 auto escape_expr = escape_string_ ==
nullptr
786 : escape_string_->analyze(catalog, query, allow_tlist_ref);
787 return RegexpExpr::get(arg_expr, pattern_expr, escape_expr, is_not_);
790 std::shared_ptr<Analyzer::Expr> RegexpExpr::get(
791 std::shared_ptr<Analyzer::Expr> arg_expr,
792 std::shared_ptr<Analyzer::Expr> pattern_expr,
793 std::shared_ptr<Analyzer::Expr> escape_expr,
795 if (!arg_expr->get_type_info().is_string()) {
796 throw std::runtime_error(
"expression before REGEXP must be of a string type.");
798 if (!pattern_expr->get_type_info().is_string()) {
799 throw std::runtime_error(
"expression after REGEXP must be of a string type.");
801 char escape_char =
'\\';
802 if (escape_expr !=
nullptr) {
803 if (!escape_expr->get_type_info().is_string()) {
804 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
806 if (!escape_expr->get_type_info().is_string()) {
807 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
810 if (c !=
nullptr && c->get_constval().stringval->length() > 1) {
811 throw std::runtime_error(
"String after ESCAPE must have a single character.");
813 escape_char = (*c->get_constval().stringval)[0];
814 if (escape_char !=
'\\') {
815 throw std::runtime_error(
"Only supporting '\\' escape character.");
821 if (translate_to_like_pattern(pattern, escape_char)) {
822 return LikeExpr::get(arg_expr, pattern_expr, escape_expr,
false, is_not);
825 std::shared_ptr<Analyzer::Expr>
result =
826 makeExpr<Analyzer::RegexpExpr>(arg_expr->decompress(), pattern_expr, escape_expr);
833 std::shared_ptr<Analyzer::Expr> LikelihoodExpr::analyze(
837 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
838 return LikelihoodExpr::get(arg_expr, likelihood_, is_not_);
841 std::shared_ptr<Analyzer::Expr> LikelihoodExpr::get(
842 std::shared_ptr<Analyzer::Expr> arg_expr,
845 if (!arg_expr->get_type_info().is_boolean()) {
846 throw std::runtime_error(
"likelihood expression expects boolean type.");
848 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::LikelihoodExpr>(
849 arg_expr->decompress(), is_not ? 1 - likelihood : likelihood);
853 std::shared_ptr<Analyzer::Expr> WidthBucketExpr::analyze(
857 auto target_value = target_value_->analyze(catalog, query, allow_tlist_ref);
858 auto lower_bound = lower_bound_->analyze(catalog, query, allow_tlist_ref);
859 auto upper_bound = upper_bound_->analyze(catalog, query, allow_tlist_ref);
860 auto partition_count = partition_count_->analyze(catalog, query, allow_tlist_ref);
864 std::shared_ptr<Analyzer::Expr> WidthBucketExpr::get(
865 std::shared_ptr<Analyzer::Expr> target_value,
868 std::shared_ptr<Analyzer::Expr> partition_count) {
869 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::WidthBucketExpr>(
874 std::shared_ptr<Analyzer::Expr> ExistsExpr::analyze(
878 throw std::runtime_error(
"Subqueries are not supported yet.");
882 std::shared_ptr<Analyzer::Expr> ColumnRef::analyze(
889 if (column_ ==
nullptr) {
890 throw std::runtime_error(
"invalid column name *.");
892 if (table_ !=
nullptr) {
895 throw std::runtime_error(
"range variable or table name " + *table_ +
901 throw std::runtime_error(
"Column name " + *column_ +
" does not exist.");
908 cd = rte->get_column_desc(catalog, *column_);
909 if (cd !=
nullptr && !found) {
912 table_id = rte->get_table_id();
913 }
else if (cd !=
nullptr && found) {
914 throw std::runtime_error(
"Column name " + *column_ +
" is ambiguous.");
918 if (cd ==
nullptr && allow_tlist_ref != TlistRefType::TLIST_NONE) {
923 std::shared_ptr<Analyzer::TargetEntry> tle;
925 if (*column_ == p->get_resname() && !found) {
929 }
else if (*column_ == p->get_resname() && found) {
930 throw std::runtime_error(
"Output alias " + *column_ +
" is ambiguous.");
935 if (dynamic_cast<Analyzer::Var*>(tle->get_expr())) {
941 if (allow_tlist_ref == TlistRefType::TLIST_COPY) {
942 return tle->get_expr()->deep_copy();
944 return makeExpr<Analyzer::Var>(
950 throw std::runtime_error(
"Column name " + *column_ +
" does not exist.");
953 return makeExpr<Analyzer::ColumnVar>(
959 std::shared_ptr<Analyzer::Expr> FunctionRef::analyze(
965 std::shared_ptr<Analyzer::Expr> arg_expr;
967 if (boost::iequals(*name_,
"count")) {
971 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
974 throw std::runtime_error(
975 "Strings must be dictionary-encoded in COUNT(DISTINCT).");
978 throw std::runtime_error(
"Only COUNT(DISTINCT) is supported on arrays.");
981 is_distinct = distinct_;
984 throw std::runtime_error(
"Cannot compute " + *name_ +
" with argument '*'.");
986 if (boost::iequals(*name_,
"min")) {
988 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
989 arg_expr = arg_expr->decompress();
990 result_type = arg_expr->get_type_info();
991 }
else if (boost::iequals(*name_,
"max")) {
993 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
994 arg_expr = arg_expr->decompress();
995 result_type = arg_expr->get_type_info();
996 }
else if (boost::iequals(*name_,
"avg")) {
998 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
999 if (!arg_expr->get_type_info().is_number()) {
1000 throw std::runtime_error(
"Cannot compute AVG on non-number-type arguments.");
1002 arg_expr = arg_expr->decompress();
1004 }
else if (boost::iequals(*name_,
"sum")) {
1006 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1007 if (!arg_expr->get_type_info().is_number()) {
1008 throw std::runtime_error(
"Cannot compute SUM on non-number-type arguments.");
1010 arg_expr = arg_expr->decompress();
1012 : arg_expr->get_type_info();
1013 }
else if (boost::iequals(*name_,
"unnest")) {
1014 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1015 const SQLTypeInfo& arg_ti = arg_expr->get_type_info();
1017 throw std::runtime_error(arg_->to_string() +
" is not of array type.");
1021 throw std::runtime_error(
"invalid function name: " + *name_);
1023 if (arg_expr->get_type_info().is_string() ||
1024 arg_expr->get_type_info().get_type() ==
kARRAY) {
1025 throw std::runtime_error(
1026 "Only COUNT(DISTINCT ) aggregate is supported on strings and arrays.");
1031 return makeExpr<Analyzer::AggExpr>(
1032 result_type, agg_type, arg_expr,
is_distinct,
nullptr);
1035 std::shared_ptr<Analyzer::Expr> CastExpr::analyze(
1039 target_type_->check_type();
1040 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1042 target_type_->get_param1(),
1043 target_type_->get_param2(),
1044 arg_expr->get_type_info().get_notnull());
1045 if (arg_expr->get_type_info().get_type() != target_type_->get_type() &&
1047 arg_expr->decompress();
1049 return arg_expr->add_cast(ti);
1052 std::shared_ptr<Analyzer::Expr> CaseExpr::analyze(
1057 std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1059 for (
auto& p : when_then_list_) {
1060 auto e1 = p->get_expr1()->analyze(catalog, query, allow_tlist_ref);
1061 if (e1->get_type_info().get_type() !=
kBOOLEAN) {
1062 throw std::runtime_error(
"Only boolean expressions can be used after WHEN.");
1064 auto e2 = p->get_expr2()->analyze(catalog, query, allow_tlist_ref);
1065 expr_pair_list.emplace_back(e1, e2);
1068 else_expr_ ? else_expr_->analyze(catalog, query, allow_tlist_ref) :
nullptr;
1069 return normalize(expr_pair_list, else_e);
1076 if (*s ==
"t" || *s ==
"true" || *s ==
"T" || *s ==
"True") {
1078 }
else if (*s ==
"f" || *s ==
"false" || *s ==
"F" || *s ==
"False") {
1081 throw std::runtime_error(
"Invalid string for boolean " + *s);
1087 std::vector<std::string>& warnings,
1088 std::string& deferred_copy_from_partitions_) {
1089 if (!options_.empty()) {
1090 for (
auto& p : options_) {
1091 if (boost::iequals(*p->get_name(),
"max_reject")) {
1093 if (int_literal ==
nullptr) {
1094 throw std::runtime_error(
"max_reject option must be an integer.");
1097 }
else if (boost::iequals(*p->get_name(),
"max_import_batch_row_count")) {
1099 if (int_literal ==
nullptr) {
1100 throw std::runtime_error(
1101 "max_import_batch_row_count option must be an integer.");
1104 throw std::runtime_error(
1105 "max_import_batch_row_count option must be a positive integer (greater "
1109 }
else if (boost::iequals(*p->get_name(),
"buffer_size")) {
1111 if (int_literal ==
nullptr) {
1112 throw std::runtime_error(
"buffer_size option must be an integer.");
1115 }
else if (boost::iequals(*p->get_name(),
"threads")) {
1117 if (int_literal ==
nullptr) {
1118 throw std::runtime_error(
"Threads option must be an integer.");
1121 }
else if (boost::iequals(*p->get_name(),
"delimiter")) {
1124 if (str_literal ==
nullptr) {
1125 throw std::runtime_error(
"Delimiter option must be a string.");
1127 throw std::runtime_error(
"Delimiter must be a single character string.");
1130 }
else if (boost::iequals(*p->get_name(),
"nulls")) {
1133 if (str_literal ==
nullptr) {
1134 throw std::runtime_error(
"Nulls option must be a string.");
1137 }
else if (boost::iequals(*p->get_name(),
"header")) {
1140 if (str_literal ==
nullptr) {
1141 throw std::runtime_error(
"Header option must be a boolean.");
1146 #ifdef ENABLE_IMPORT_PARQUET
1147 }
else if (boost::iequals(*p->get_name(),
"parquet")) {
1149 "Deprecation Warning: COPY FROM WITH (parquet='true') is deprecated. Use "
1150 "WITH (source_type='parquet_file') instead.");
1153 if (str_literal ==
nullptr) {
1154 throw std::runtime_error(
"'parquet' option must be a boolean.");
1161 #endif // ENABLE_IMPORT_PARQUET
1162 }
else if (boost::iequals(*p->get_name(),
"s3_access_key")) {
1165 if (str_literal ==
nullptr) {
1166 throw std::runtime_error(
"Option s3_access_key must be a string.");
1169 }
else if (boost::iequals(*p->get_name(),
"s3_secret_key")) {
1172 if (str_literal ==
nullptr) {
1173 throw std::runtime_error(
"Option s3_secret_key must be a string.");
1176 }
else if (boost::iequals(*p->get_name(),
"s3_session_token")) {
1179 if (str_literal ==
nullptr) {
1180 throw std::runtime_error(
"Option s3_session_token must be a string.");
1183 }
else if (boost::iequals(*p->get_name(),
"s3_region")) {
1186 if (str_literal ==
nullptr) {
1187 throw std::runtime_error(
"Option s3_region must be a string.");
1190 }
else if (boost::iequals(*p->get_name(),
"s3_endpoint")) {
1193 if (str_literal ==
nullptr) {
1194 throw std::runtime_error(
"Option s3_endpoint must be a string.");
1197 }
else if (boost::iequals(*p->get_name(),
"s3_max_concurrent_downloads")) {
1199 if (int_literal ==
nullptr) {
1200 throw std::runtime_error(
1201 "'s3_max_concurrent_downloads' option must be an integer");
1203 const int s3_max_concurrent_downloads = int_literal->
get_intval();
1204 if (s3_max_concurrent_downloads > 0) {
1207 throw std::runtime_error(
1208 "Invalid value for 's3_max_concurrent_downloads' option (must be > 0): " +
1211 }
else if (boost::iequals(*p->get_name(),
"quote")) {
1214 if (str_literal ==
nullptr) {
1215 throw std::runtime_error(
"Quote option must be a string.");
1217 throw std::runtime_error(
"Quote must be a single character string.");
1220 }
else if (boost::iequals(*p->get_name(),
"escape")) {
1223 if (str_literal ==
nullptr) {
1224 throw std::runtime_error(
"Escape option must be a string.");
1226 throw std::runtime_error(
"Escape must be a single character string.");
1229 }
else if (boost::iequals(*p->get_name(),
"line_delimiter")) {
1232 if (str_literal ==
nullptr) {
1233 throw std::runtime_error(
"Line_delimiter option must be a string.");
1235 throw std::runtime_error(
"Line_delimiter must be a single character string.");
1238 }
else if (boost::iequals(*p->get_name(),
"quoted")) {
1241 if (str_literal ==
nullptr) {
1242 throw std::runtime_error(
"Quoted option must be a boolean.");
1245 }
else if (boost::iequals(*p->get_name(),
"plain_text")) {
1248 if (str_literal ==
nullptr) {
1249 throw std::runtime_error(
"plain_text option must be a boolean.");
1252 }
else if (boost::iequals(*p->get_name(),
"trim_spaces")) {
1255 if (str_literal ==
nullptr) {
1256 throw std::runtime_error(
"trim_spaces option must be a boolean.");
1259 }
else if (boost::iequals(*p->get_name(),
"array_marker")) {
1262 if (str_literal ==
nullptr) {
1263 throw std::runtime_error(
"Array Marker option must be a string.");
1265 throw std::runtime_error(
1266 "Array Marker option must be exactly two characters. Default is {}.");
1270 }
else if (boost::iequals(*p->get_name(),
"array_delimiter")) {
1273 if (str_literal ==
nullptr) {
1274 throw std::runtime_error(
"Array Delimiter option must be a string.");
1276 throw std::runtime_error(
"Array Delimiter must be a single character string.");
1279 }
else if (boost::iequals(*p->get_name(),
"lonlat")) {
1282 if (str_literal ==
nullptr) {
1283 throw std::runtime_error(
"Lonlat option must be a boolean.");
1286 }
else if (boost::iequals(*p->get_name(),
"geo")) {
1288 "Deprecation Warning: COPY FROM WITH (geo='true') is deprecated. Use WITH "
1289 "(source_type='geo_file') instead.");
1292 if (str_literal ==
nullptr) {
1293 throw std::runtime_error(
"'geo' option must be a boolean.");
1298 }
else if (boost::iequals(*p->get_name(),
"source_type")) {
1301 if (str_literal ==
nullptr) {
1302 throw std::runtime_error(
"'source_type' option must be a string.");
1305 if (boost::iequals(*s,
"delimited_file")) {
1307 }
else if (boost::iequals(*s,
"geo_file")) {
1309 #if ENABLE_IMPORT_PARQUET
1310 }
else if (boost::iequals(*s,
"parquet_file")) {
1313 }
else if (boost::iequals(*s,
"raster_file")) {
1315 }
else if (boost::iequals(*s,
"regex_parsed_file")) {
1318 throw std::runtime_error(
1319 "Invalid string for 'source_type' option (must be 'GEO_FILE', 'RASTER_FILE'"
1320 #
if ENABLE_IMPORT_PARQUET
1323 ", 'REGEX_PARSED_FILE'"
1324 " or 'DELIMITED_FILE'): " +
1327 }
else if (boost::iequals(*p->get_name(),
"geo_coords_type")) {
1330 if (str_literal ==
nullptr) {
1331 throw std::runtime_error(
"'geo_coords_type' option must be a string");
1334 if (boost::iequals(*s,
"geography")) {
1335 throw std::runtime_error(
1336 "GEOGRAPHY coords type not yet supported. Please use GEOMETRY.");
1338 }
else if (boost::iequals(*s,
"geometry")) {
1341 throw std::runtime_error(
1342 "Invalid string for 'geo_coords_type' option (must be 'GEOGRAPHY' or "
1346 }
else if (boost::iequals(*p->get_name(),
"raster_point_type")) {
1349 if (str_literal ==
nullptr) {
1350 throw std::runtime_error(
"'raster_point_type' option must be a string");
1353 if (boost::iequals(*s,
"none")) {
1355 }
else if (boost::iequals(*s,
"auto")) {
1357 }
else if (boost::iequals(*s,
"smallint")) {
1359 }
else if (boost::iequals(*s,
"int")) {
1361 }
else if (boost::iequals(*s,
"float")) {
1363 }
else if (boost::iequals(*s,
"double")) {
1365 }
else if (boost::iequals(*s,
"point")) {
1368 throw std::runtime_error(
1369 "Invalid string for 'raster_point_type' option (must be 'NONE', 'AUTO', "
1370 "'SMALLINT', 'INT', 'FLOAT', 'DOUBLE' or 'POINT'): " +
1373 }
else if (boost::iequals(*p->get_name(),
"raster_point_transform")) {
1376 if (str_literal ==
nullptr) {
1377 throw std::runtime_error(
"'raster_point_transform' option must be a string");
1380 if (boost::iequals(*s,
"none")) {
1382 }
else if (boost::iequals(*s,
"auto")) {
1384 }
else if (boost::iequals(*s,
"file")) {
1386 }
else if (boost::iequals(*s,
"world")) {
1390 throw std::runtime_error(
1391 "Invalid string for 'raster_point_transform' option (must be 'NONE', "
1392 "'AUTO', 'FILE' or 'WORLD'): " +
1395 }
else if (boost::iequals(*p->get_name(),
"raster_import_bands")) {
1398 if (str_literal ==
nullptr) {
1399 throw std::runtime_error(
"'raster_import_bands' option must be a string");
1401 const std::string* raster_import_bands = str_literal->
get_stringval();
1402 if (raster_import_bands) {
1405 throw std::runtime_error(
"Invalid value for 'raster_import_bands' option");
1407 }
else if (boost::iequals(*p->get_name(),
"raster_import_dimensions")) {
1410 if (str_literal ==
nullptr) {
1411 throw std::runtime_error(
"'raster_import_dimensions' option must be a string");
1413 const std::string* raster_import_dimensions = str_literal->
get_stringval();
1414 if (raster_import_dimensions) {
1417 throw std::runtime_error(
"Invalid value for 'raster_import_dimensions' option");
1419 }
else if (boost::iequals(*p->get_name(),
"geo_coords_encoding")) {
1422 if (str_literal ==
nullptr) {
1423 throw std::runtime_error(
"'geo_coords_encoding' option must be a string");
1426 if (boost::iequals(*s,
"none")) {
1429 }
else if (boost::iequals(*s,
"compressed(32)")) {
1433 throw std::runtime_error(
1434 "Invalid string for 'geo_coords_encoding' option (must be 'NONE' or "
1435 "'COMPRESSED(32)'): " +
1438 }
else if (boost::iequals(*p->get_name(),
"raster_scanlines_per_thread")) {
1440 if (int_literal ==
nullptr) {
1441 throw std::runtime_error(
1442 "'raster_scanlines_per_thread' option must be an integer");
1444 const int raster_scanlines_per_thread = int_literal->
get_intval();
1445 if (raster_scanlines_per_thread < 0) {
1446 throw std::runtime_error(
1447 "'raster_scanlines_per_thread' option must be >= 0, with 0 denoting auto "
1451 }
else if (boost::iequals(*p->get_name(),
"geo_coords_srid")) {
1453 if (int_literal ==
nullptr) {
1454 throw std::runtime_error(
"'geo_coords_srid' option must be an integer");
1457 if (srid == 4326 || srid == 3857 || srid == 900913) {
1460 throw std::runtime_error(
1461 "Invalid value for 'geo_coords_srid' option (must be 4326, 3857, or "
1465 }
else if (boost::iequals(*p->get_name(),
"geo_layer_name")) {
1468 if (str_literal ==
nullptr) {
1469 throw std::runtime_error(
"'geo_layer_name' option must be a string");
1471 const std::string* layer_name = str_literal->
get_stringval();
1475 throw std::runtime_error(
"Invalid value for 'geo_layer_name' option");
1477 }
else if (boost::iequals(*p->get_name(),
"partitions")) {
1478 const auto partitions =
1479 static_cast<const StringLiteral*
>(p->get_value())->get_stringval();
1481 const auto partitions_uc = boost::to_upper_copy<std::string>(*partitions);
1482 if (partitions_uc !=
"REPLICATED") {
1483 throw std::runtime_error(
1484 "Invalid value for 'partitions' option. Must be 'REPLICATED'.");
1486 deferred_copy_from_partitions_ = partitions_uc;
1487 }
else if (boost::iequals(*p->get_name(),
"geo_assign_render_groups")) {
1490 if (str_literal ==
nullptr) {
1491 throw std::runtime_error(
"geo_assign_render_groups option must be a boolean.");
1494 }
else if (boost::iequals(*p->get_name(),
"geo_explode_collections")) {
1497 if (str_literal ==
nullptr) {
1498 throw std::runtime_error(
"geo_explode_collections option must be a boolean.");
1501 }
else if (boost::iequals(*p->get_name(),
"source_srid")) {
1503 if (int_literal ==
nullptr) {
1504 throw std::runtime_error(
"'source_srid' option must be an integer");
1510 throw std::runtime_error(
1511 "'source_srid' option can only be used on csv/tsv files");
1513 }
else if (boost::iequals(*p->get_name(),
"regex_path_filter")) {
1516 if (str_literal ==
nullptr) {
1517 throw std::runtime_error(
"Option regex_path_filter must be a string.");
1521 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1522 }
else if (boost::iequals(*p->get_name(),
"file_sort_order_by")) {
1525 if (str_literal ==
nullptr) {
1526 throw std::runtime_error(
"Option file_sort_order_by must be a string.");
1530 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1531 }
else if (boost::iequals(*p->get_name(),
"file_sort_regex")) {
1534 if (str_literal ==
nullptr) {
1535 throw std::runtime_error(
"Option file_sort_regex must be a string.");
1539 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1540 }
else if (boost::iequals(*p->get_name(),
"raster_point_compute_angle")) {
1543 if (str_literal ==
nullptr) {
1544 throw std::runtime_error(
1545 "'raster_point_compute_angle' option must be a boolean.");
1550 }
else if (boost::iequals(*p->get_name(),
"sql_order_by")) {
1551 if (
auto str_literal = dynamic_cast<const StringLiteral*>(p->get_value())) {
1552 copy_params.
sql_order_by = *str_literal->get_stringval();
1554 throw std::runtime_error(
"Option sql_order_by must be a string.");
1556 }
else if (boost::iequals(*p->get_name(),
"username")) {
1559 if (str_literal ==
nullptr) {
1560 throw std::runtime_error(
"Option username must be a string.");
1564 }
else if (boost::iequals(*p->get_name(),
"password")) {
1567 if (str_literal ==
nullptr) {
1568 throw std::runtime_error(
"Option password must be a string.");
1572 }
else if (boost::iequals(*p->get_name(),
"credential_string")) {
1575 if (str_literal ==
nullptr) {
1576 throw std::runtime_error(
"Option credential_string must be a string.");
1580 }
else if (boost::iequals(*p->get_name(),
"data_source_name")) {
1583 if (str_literal ==
nullptr) {
1584 throw std::runtime_error(
"Option data_source_name must be a string.");
1587 copy_params.
dsn = string_val;
1588 }
else if (boost::iequals(*p->get_name(),
"connection_string")) {
1591 if (str_literal ==
nullptr) {
1592 throw std::runtime_error(
"Option connection_string must be a string.");
1596 }
else if (boost::iequals(*p->get_name(),
"line_start_regex")) {
1599 if (str_literal ==
nullptr) {
1600 throw std::runtime_error(
"Option line_start_regex must be a string.");
1604 }
else if (boost::iequals(*p->get_name(),
"line_regex")) {
1607 if (str_literal ==
nullptr) {
1608 throw std::runtime_error(
"Option line_regex must be a string.");
1612 }
else if (boost::iequals(*p->get_name(),
"add_metadata_columns") &&
1616 if (str_literal ==
nullptr) {
1617 throw std::runtime_error(
"'add_metadata_columns' option must be a string.");
1621 throw std::runtime_error(
"Invalid option for COPY: " + *p->get_name());
1637 std::shared_ptr<Analyzer::Expr> CaseExpr::normalize(
1638 const std::list<std::pair<std::shared_ptr<Analyzer::Expr>,
1639 std::shared_ptr<Analyzer::Expr>>>& expr_pair_list,
1640 const std::shared_ptr<Analyzer::Expr> else_e_in,
1641 const Executor* executor) {
1643 bool has_agg =
false;
1654 for (
auto& p : expr_pair_list) {
1656 CHECK(e1->get_type_info().is_boolean());
1658 if (e2->get_contains_agg()) {
1661 const auto& e2_ti = e2->get_type_info();
1663 if (e2_ti.is_string() && !e2_ti.is_dict_encoded_string() && !col_var) {
1664 CHECK(e2_ti.is_none_encoded_string());
1665 none_encoded_literal_ti =
1673 }
else if (e2_ti.get_type() ==
kNULLT) {
1675 e2->set_type_info(ti);
1676 }
else if (ti != e2_ti) {
1677 if (ti.
is_string() && e2_ti.is_string()) {
1681 }
else if (ti.
is_number() && e2_ti.is_number()) {
1683 }
else if (ti.
is_boolean() && e2_ti.is_boolean()) {
1686 throw std::runtime_error(
1687 "Expressions in THEN clause must be of the same or compatible types.");
1691 auto else_e = else_e_in;
1692 const auto& else_ti = else_e->get_type_info();
1695 if (else_e->get_contains_agg()) {
1698 if (else_ti.is_string() && !else_ti.is_dict_encoded_string() && !col_var) {
1699 CHECK(else_ti.is_none_encoded_string());
1700 none_encoded_literal_ti =
1709 else_e->set_type_info(ti);
1710 }
else if (ti != else_ti) {
1712 if (ti.
is_string() && else_ti.is_string()) {
1716 }
else if (ti.
is_number() && else_ti.is_number()) {
1718 }
else if (ti.
is_boolean() && else_ti.is_boolean()) {
1721 throw std::runtime_error(
1723 "Expressions in ELSE clause must be of the same or compatible types as "
1724 "those in the THEN clauses.");
1738 std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1739 cast_expr_pair_list;
1740 for (
auto p : expr_pair_list) {
1742 cast_expr_pair_list.emplace_back(p.first, p.second->add_cast(ti));
1744 if (else_e !=
nullptr) {
1745 else_e = else_e->add_cast(ti);
1750 else_e = makeExpr<Analyzer::Constant>(ti,
true, d);
1753 throw std::runtime_error(
1754 "Cannot deduce the type for case expressions, all branches null");
1757 auto case_expr = makeExpr<Analyzer::CaseExpr>(ti, has_agg, cast_expr_pair_list, else_e);
1762 std::string str(
"CASE ");
1763 for (
auto& p : when_then_list_) {
1764 str +=
"WHEN " + p->get_expr1()->to_string() +
" THEN " +
1765 p->get_expr2()->to_string() +
" ";
1767 if (else_expr_ !=
nullptr) {
1768 str +=
"ELSE " + else_expr_->to_string();
1776 left_->analyze(catalog, query);
1778 right_->analyze(catalog, *right_query);
1785 std::shared_ptr<Analyzer::Expr> p;
1786 if (having_clause_ !=
nullptr) {
1787 p = having_clause_->analyze(catalog, query, Expr::TlistRefType::TLIST_COPY);
1788 if (p->get_type_info().get_type() !=
kBOOLEAN) {
1789 throw std::runtime_error(
"Only boolean expressions can be in HAVING clause.");
1798 std::list<std::shared_ptr<Analyzer::Expr>> groupby;
1799 if (!groupby_clause_.empty()) {
1801 std::shared_ptr<Analyzer::Expr> gexpr;
1802 const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
1804 for (
auto& c : groupby_clause_) {
1806 if (dynamic_cast<Literal*>(c.get())) {
1809 throw std::runtime_error(
"Invalid literal in GROUP BY clause.");
1812 if (varno <= 0 || varno > static_cast<int>(tlist.size())) {
1813 throw std::runtime_error(
"Invalid ordinal number in GROUP BY clause.");
1815 if (tlist[varno - 1]->get_expr()->get_contains_agg()) {
1816 throw std::runtime_error(
1817 "Ordinal number in GROUP BY cannot reference an expression containing "
1821 gexpr = makeExpr<Analyzer::Var>(
1824 gexpr = c->analyze(catalog, query, Expr::TlistRefType::TLIST_REF);
1827 bool set_new_type =
false;
1830 set_new_type =
true;
1835 std::shared_ptr<Analyzer::Var> v;
1836 if (std::dynamic_pointer_cast<Analyzer::Var>(gexpr)) {
1838 int n = v->get_varno();
1839 gexpr = tlist[n - 1]->get_own_expr();
1841 if (cv !=
nullptr) {
1846 v->set_varno(gexpr_no);
1847 tlist[n - 1]->set_expr(v);
1851 groupby.push_back(new_e);
1853 v->set_type_info(new_e->get_type_info());
1856 groupby.push_back(gexpr);
1863 auto e = t->get_expr();
1864 e->check_group_by(groupby);
1872 if (where_clause_ ==
nullptr) {
1876 auto p = where_clause_->analyze(catalog, query, Expr::TlistRefType::TLIST_COPY);
1877 if (p->get_type_info().get_type() !=
kBOOLEAN) {
1878 throw std::runtime_error(
"Only boolean expressions can be in WHERE clause.");
1885 std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
1887 if (select_clause_.empty()) {
1891 rte->expand_star_in_targetlist(catalog, tlist, rte_idx++);
1894 for (
auto& p : select_clause_) {
1895 const Parser::Expr* select_expr = p->get_select_expr();
1897 if (
typeid(*select_expr) ==
typeid(
ColumnRef) &&
1898 dynamic_cast<const ColumnRef*>(select_expr)->get_column() ==
nullptr) {
1899 const std::string* range_var_name =
1900 dynamic_cast<const ColumnRef*
>(select_expr)->get_table();
1903 throw std::runtime_error(
"invalid range variable name: " + *range_var_name);
1908 auto e = select_expr->
analyze(catalog, query);
1909 std::string resname;
1911 if (p->get_alias() !=
nullptr) {
1912 resname = *p->get_alias();
1913 }
else if (std::dynamic_pointer_cast<Analyzer::ColumnVar>(e) &&
1914 !std::dynamic_pointer_cast<Analyzer::Var>(e)) {
1921 if (e->get_type_info().get_type() ==
kNULLT) {
1922 throw std::runtime_error(
1923 "Untyped NULL in SELECT clause. Use CAST to specify a type.");
1926 bool unnest = (o !=
nullptr && o->get_optype() ==
kUNNEST);
1927 auto tle = std::make_shared<Analyzer::TargetEntry>(resname, e, unnest);
1928 tlist.push_back(tle);
1937 for (
auto& p : from_clause_) {
1940 if (table_desc ==
nullptr) {
1941 throw std::runtime_error(
"Table " + *p->get_table_name() +
" does not exist.");
1943 std::string range_var;
1944 if (p->get_range_var() ==
nullptr) {
1945 range_var = *p->get_table_name();
1947 range_var = *p->get_range_var();
1957 analyze_from_clause(catalog, query);
1958 analyze_select_clause(catalog, query);
1959 analyze_where_clause(catalog, query);
1960 analyze_group_by(catalog, query);
1961 analyze_having_clause(catalog, query);
1968 boost::replace_all(s,
"\\\\t",
"\t");
1969 boost::replace_all(s,
"\\t",
"\t");
1970 boost::replace_all(s,
"\\\\n",
"\n");
1971 boost::replace_all(s,
"\\n",
"\n");
1977 std::regex e1(
"(\\\\x[0-9A-Fa-f][0-9A-Fa-f])");
1978 while (std::regex_search(s, m, e1)) {
1979 std::string original(m[0].first, m[0].second);
1980 std::string replacement;
1981 long val = strtol(original.substr(2, 2).c_str(), NULL, 16);
1982 replacement.push_back(val);
1983 boost::replace_all(s, original, replacement);
1987 std::regex e2(
"(\\\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f])");
1988 while (std::regex_search(s, m, e2)) {
1989 std::string original(m[0].first, m[0].second);
1990 std::string replacement;
1991 long val = strtol(original.substr(2, 4).c_str(), NULL, 16);
1992 replacement.push_back(val);
1993 boost::replace_all(s, original, replacement);
2000 std::list<std::unique_ptr<NameValueAssign>>& nameValueList,
2001 bool stringToNull =
false,
2002 bool stringToInteger =
false) {
2003 if (payload.HasMember(
"options") && payload[
"options"].IsObject()) {
2004 const auto& options = payload[
"options"];
2005 for (
auto itr = options.MemberBegin(); itr != options.MemberEnd(); ++itr) {
2006 auto option_name = std::make_unique<std::string>(itr->name.GetString());
2007 std::unique_ptr<Literal> literal_value;
2008 if (itr->value.IsString()) {
2009 std::string str = itr->value.GetString();
2010 if (stringToNull && str ==
"") {
2011 literal_value = std::make_unique<NullLiteral>();
2012 }
else if (stringToInteger && std::all_of(str.begin(), str.end(), ::isdigit)) {
2013 int iVal = std::stoi(str);
2014 literal_value = std::make_unique<IntLiteral>(iVal);
2018 auto unique_literal_string = std::make_unique<std::string>(
unescape(str));
2020 std::make_unique<StringLiteral>(unique_literal_string.release());
2022 }
else if (itr->value.IsInt() || itr->value.IsInt64()) {
2023 literal_value = std::make_unique<IntLiteral>(
json_i64(itr->value));
2024 }
else if (itr->value.IsNull()) {
2025 literal_value = std::make_unique<NullLiteral>();
2027 throw std::runtime_error(
"Unable to handle literal for " + *option_name);
2029 CHECK(literal_value);
2031 nameValueList.emplace_back(std::make_unique<NameValueAssign>(
2032 option_name.release(), literal_value.release()));
2043 throw std::runtime_error(
"OFFSET cannot be negative.");
2046 query_expr_->analyze(catalog, query);
2051 const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
2053 std::list<Analyzer::OrderEntry>* order_by =
new std::list<Analyzer::OrderEntry>();
2054 if (!orderby_clause_.empty()) {
2055 for (
auto& p : orderby_clause_) {
2056 int tle_no = p->get_colno();
2060 const std::string*
name = p->get_column()->get_column();
2063 for (
auto tle : tlist) {
2064 if (tle->get_resname() == *
name) {
2071 throw std::runtime_error(
"invalid name in order by: " + *name);
2074 order_by->push_back(
2080 for (
int i = 1; i <= static_cast<int>(tlist.size()); i++) {
2081 bool in_orderby =
false;
2082 std::for_each(order_by->begin(),
2085 in_orderby = in_orderby || (i == oe.tle_no);
2096 std::string str = select_expr_->to_string();
2097 if (alias_ !=
nullptr) {
2098 str +=
" AS " + *alias_;
2104 std::string str = *table_name_;
2105 if (range_var_ !=
nullptr) {
2106 str +=
" " + *range_var_;
2113 if (table_ ==
nullptr) {
2115 }
else if (column_ ==
nullptr) {
2116 str = *table_ +
".*";
2118 str = *table_ +
"." + *column_;
2124 std::string op_str[] = {
2125 "=",
"===",
"<>",
"<",
">",
"<=",
">=",
" AND ",
" OR ",
"NOT",
"-",
"+",
"*",
"/"};
2128 str =
"-(" + left_->to_string() +
")";
2129 }
else if (optype_ ==
kNOT) {
2130 str =
"NOT (" + left_->to_string() +
")";
2132 str = left_->to_string() +
"[" + right_->to_string() +
"]";
2133 }
else if (optype_ ==
kUNNEST) {
2134 str =
"UNNEST(" + left_->to_string() +
")";
2135 }
else if (optype_ ==
kIN) {
2136 str =
"(" + left_->to_string() +
" IN " + right_->to_string() +
")";
2138 str =
"(" + left_->to_string() + op_str[optype_] + right_->to_string() +
")";
2144 std::string str = arg_->to_string();
2154 return "EXISTS (" + query_->to_string() +
")";
2160 str += query_->to_string();
2166 std::string str = arg_->to_string();
2168 str +=
" IS NOT NULL";
2177 str += subquery_->to_string();
2183 bool notfirst =
false;
2184 for (
auto& p : value_list_) {
2190 str += p->to_string();
2197 std::string str = arg_->to_string();
2199 str +=
" NOT BETWEEN ";
2203 str += lower_->to_string() +
" AND " + upper_->to_string();
2209 if (calc_encoded_length_) {
2210 str =
"CHAR_LENGTH (" + arg_->to_string() +
")";
2212 str =
"LENGTH (" + arg_->to_string() +
")";
2218 std::string str =
"CARDINALITY(" + arg_->to_string() +
")";
2223 std::string str = arg_->to_string();
2225 str +=
" NOT LIKE ";
2229 str += like_string_->to_string();
2230 if (escape_string_ !=
nullptr) {
2231 str +=
" ESCAPE " + escape_string_->to_string();
2237 std::string str = arg_->to_string();
2239 str +=
" NOT REGEXP ";
2243 str += pattern_string_->to_string();
2244 if (escape_string_ !=
nullptr) {
2245 str +=
" ESCAPE " + escape_string_->to_string();
2251 std::string str =
" WIDTH_BUCKET ";
2252 str += target_value_->to_string();
2254 str += lower_bound_->to_string();
2256 str += upper_bound_->to_string();
2258 str += partition_count_->to_string();
2264 std::string str =
" LIKELIHOOD ";
2265 str += arg_->to_string();
2267 str += boost::lexical_cast<std::string>(is_not_ ? 1.0 - likelihood_ : likelihood_);
2272 std::string str = *name_ +
"(";
2276 if (arg_ ==
nullptr) {
2279 str += arg_->to_string() +
")";
2285 std::string query_str =
"SELECT ";
2287 query_str +=
"DISTINCT ";
2289 if (select_clause_.empty()) {
2292 bool notfirst =
false;
2293 for (
auto& p : select_clause_) {
2299 query_str += p->to_string();
2302 query_str +=
" FROM ";
2303 bool notfirst =
false;
2304 for (
auto& p : from_clause_) {
2310 query_str += p->to_string();
2312 if (where_clause_) {
2313 query_str +=
" WHERE " + where_clause_->to_string();
2315 if (!groupby_clause_.empty()) {
2316 query_str +=
" GROUP BY ";
2317 bool notfirst =
false;
2318 for (
auto& p : groupby_clause_) {
2324 query_str += p->to_string();
2327 if (having_clause_) {
2328 query_str +=
" HAVING " + having_clause_->to_string();
2338 if (td ==
nullptr) {
2339 throw std::runtime_error(
"Table " + *table_ +
" does not exist.");
2342 throw std::runtime_error(
"Insert to views is not supported yet.");
2346 std::list<int> result_col_list;
2347 if (column_list_.empty()) {
2348 const std::list<const ColumnDescriptor*> all_cols =
2350 for (
auto cd : all_cols) {
2351 result_col_list.push_back(cd->columnId);
2354 for (
auto& c : column_list_) {
2356 if (cd ==
nullptr) {
2357 throw std::runtime_error(
"Column " + *c +
" does not exist.");
2359 result_col_list.push_back(cd->
columnId);
2361 if (col_ti.get_physical_cols() > 0) {
2363 for (
auto i = 1; i <= col_ti.get_physical_cols(); i++) {
2366 if (pcd ==
nullptr) {
2367 throw std::runtime_error(
"Column " + *c +
"'s metadata is incomplete.");
2369 result_col_list.push_back(pcd->
columnId);
2379 CHECK(literal.IsObject());
2380 CHECK(literal.HasMember(
"literal"));
2381 CHECK(literal.HasMember(
"type"));
2383 if (type ==
"NULL") {
2385 }
else if (type ==
"CHAR" || type ==
"BOOLEAN") {
2386 auto* val =
new std::string(
json_str(literal[
"literal"]));
2388 }
else if (type ==
"DECIMAL") {
2389 CHECK(literal.HasMember(
"scale"));
2390 CHECK(literal.HasMember(
"precision"));
2391 auto scale =
json_i64(literal[
"scale"]);
2392 auto precision =
json_i64(literal[
"precision"]);
2394 auto int_val = std::stol(
json_str(literal[
"literal"]));
2397 auto dbl_val = std::stod(
json_str(literal[
"literal"]));
2400 auto* val =
new std::string(
json_str(literal[
"literal"]));
2403 }
else if (type ==
"DOUBLE") {
2404 auto dbl_val = std::stod(
json_str(literal[
"literal"]));
2407 CHECK(
false) <<
"Unexpected calcite data type: " <<
type;
2413 CHECK(array.IsArray());
2414 auto json_elements = array.GetArray();
2415 auto* elements =
new std::list<Expr*>();
2416 for (
const auto& e : json_elements) {
2423 InsertValuesStmt::InsertValuesStmt(
const rapidjson::Value& payload)
2425 CHECK(payload.HasMember(
"name"));
2426 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
2428 if (payload.HasMember(
"columns")) {
2429 CHECK(payload[
"columns"].IsArray());
2430 for (
auto& column : payload[
"columns"].GetArray()) {
2432 column_list_.emplace_back(std::make_unique<std::string>(s));
2436 CHECK(payload.HasMember(
"values") && payload[
"values"].IsArray());
2437 auto tuples = payload[
"values"].GetArray();
2438 if (tuples.Empty()) {
2439 throw std::runtime_error(
"Values statement cannot be empty");
2442 for (
const auto& json_tuple : tuples) {
2443 auto values_list = std::make_unique<ValuesList>();
2444 CHECK(json_tuple.IsArray());
2445 auto tuple = json_tuple.GetArray();
2446 for (
const auto& value : tuple) {
2447 CHECK(value.IsObject());
2448 if (value.HasMember(
"array")) {
2461 size_t list_size =
values_lists_[0]->get_value_list().size();
2464 throw std::runtime_error(
2465 "Numbers of columns and values don't match for the "
2470 const std::list<const ColumnDescriptor*> non_phys_cols =
2472 if (non_phys_cols.size() != list_size) {
2473 throw std::runtime_error(
2474 "Number of columns in table does not match the list of values given in the "
2478 std::vector<const ColumnDescriptor*> cds;
2488 const auto& values_list =
values_lists_[i]->get_value_list();
2489 if (values_list.size() != list_size) {
2490 throw std::runtime_error(
2491 "Insert values lists should be of the same size. Expected: " +
2494 auto& query_values_list = query_values_lists[i];
2496 for (
auto& v : values_list) {
2497 auto e = v->analyze(catalog, query);
2498 const auto* cd = cds[cds_id];
2499 const auto& col_ti = cd->columnType;
2500 if (col_ti.get_notnull()) {
2502 if (c !=
nullptr && c->get_is_null()) {
2503 throw std::runtime_error(
"Cannot insert NULL into column " + cd->columnName);
2506 e = e->add_cast(col_ti);
2510 if (col_ti.get_physical_cols() > 0) {
2511 CHECK(cd->columnType.is_geometry());
2515 if (uoper && uoper->get_optype() ==
kCAST) {
2520 std::string* geo_string{
nullptr};
2522 is_null = c->get_is_null();
2524 geo_string = c->get_constval().stringval;
2527 if (!is_null && !geo_string) {
2528 throw std::runtime_error(
"Expecting a WKT or WKB hex string for column " +
2531 std::vector<double> coords;
2532 std::vector<double> bounds;
2533 std::vector<int> ring_sizes;
2534 std::vector<int> poly_rings;
2540 *geo_string, import_ti, coords, bounds, ring_sizes, poly_rings)) {
2541 throw std::runtime_error(
"Cannot read geometry to insert into column " +
2544 if (coords.empty()) {
2548 if (cd->columnType.get_type() != import_ti.get_type()) {
2552 throw std::runtime_error(
2553 "Imported geometry doesn't match the type of column " + cd->columnName);
2558 if (cd->columnType.get_type() ==
kPOINT) {
2559 if (!coords.empty()) {
2560 throw std::runtime_error(
2561 "NULL POINT with unexpected coordinates in column " + cd->columnName);
2571 const auto* cd_coords = cds[cds_id];
2574 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2575 if (!is_null || cd->columnType.get_type() ==
kPOINT) {
2577 for (
auto cc : compressed_coords) {
2580 auto e = makeExpr<Analyzer::Constant>(
kTINYINT,
false, d);
2581 value_exprs.push_back(e);
2586 makeExpr<Analyzer::Constant>(cd_coords->columnType, is_null, value_exprs),
2591 cd->columnType.get_type() ==
kPOLYGON ||
2594 const auto* cd_ring_sizes = cds[cds_id];
2595 CHECK(cd_ring_sizes);
2597 CHECK_EQ(cd_ring_sizes->columnType.get_subtype(),
kINT);
2598 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2600 for (
auto c : ring_sizes) {
2603 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
2604 value_exprs.push_back(e);
2609 makeExpr<Analyzer::Constant>(
2610 cd_ring_sizes->columnType, is_null, value_exprs),
2616 const auto* cd_poly_rings = cds[cds_id];
2617 CHECK(cd_poly_rings);
2619 CHECK_EQ(cd_poly_rings->columnType.get_subtype(),
kINT);
2620 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2622 for (
auto c : poly_rings) {
2625 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
2626 value_exprs.push_back(e);
2631 makeExpr<Analyzer::Constant>(
2632 cd_poly_rings->columnType, is_null, value_exprs),
2641 cd->columnType.get_type() ==
kPOLYGON ||
2643 const auto* cd_bounds = cds[cds_id];
2647 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2649 for (
auto b : bounds) {
2652 auto e = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
2653 value_exprs.push_back(e);
2658 makeExpr<Analyzer::Constant>(cd_bounds->columnType, is_null, value_exprs),
2663 if (cd->columnType.get_type() ==
kPOLYGON ||
2666 const auto* cd_render_group = cds[cds_id];
2667 CHECK(cd_render_group);
2668 CHECK_EQ(cd_render_group->columnType.get_type(),
kINT);
2673 makeExpr<Analyzer::Constant>(cd_render_group->columnType, is_null, d),
2683 bool read_only_mode) {
2684 if (read_only_mode) {
2685 throw std::runtime_error(
"INSERT values invalid in read only mode.");
2687 auto execute_read_lock =
2692 const auto td_with_lock =
2698 throw std::runtime_error(
"User has no insert privileges on " + *
table_ +
".");
2704 const auto insert_data_lock =
2710 auto td = td_with_lock();
2713 throw std::runtime_error(
"Singleton inserts on views is not supported.");
2721 leafs_connector_ = std::make_unique<Fragmenter_Namespace::LocalInsertConnector>();
2725 ra_executor.executeSimpleInsert(query, insert_data_loader, session);
2729 }
catch (std::exception& e) {
2730 LOG(
ERROR) <<
"An error occurred during insert rollback attempt. Table id: "
2731 << td->tableId <<
", Error: " << e.what();
2735 if (!td->isTemporaryTable()) {
2742 throw std::runtime_error(
"UPDATE statement not supported yet.");
2747 throw std::runtime_error(
"DELETE statement not supported yet.");
2754 if (!col_ti.is_integer() && !col_ti.is_time() &&
2755 !(col_ti.is_string() && col_ti.get_compression() ==
kENCODING_DICT)) {
2756 throw std::runtime_error(
"Cannot shard on type " + col_ti.get_type_name() +
2757 ", encoding " + col_ti.get_compression_name());
2762 const std::list<ColumnDescriptor>& columns) {
2764 for (
const auto& cd : columns) {
2765 if (cd.columnName == name) {
2770 if (cd.columnType.is_geometry()) {
2771 index += cd.columnType.get_physical_cols();
2779 const std::list<ColumnDescriptor>& columns) {
2781 for (
const auto& cd : columns) {
2782 if (boost::to_upper_copy<std::string>(cd.columnName) == name) {
2786 if (cd.columnType.is_geometry()) {
2787 index += cd.columnType.get_physical_cols();
2795 const std::string& field_name,
2796 const std::string& field_value,
2797 rapidjson::Document& document) {
2798 rapidjson::Value field_name_json_str;
2799 field_name_json_str.SetString(
2800 field_name.c_str(), field_name.size(), document.GetAllocator());
2801 rapidjson::Value field_value_json_str;
2802 field_value_json_str.SetString(
2803 field_value.c_str(), field_value.size(), document.GetAllocator());
2804 obj.AddMember(field_name_json_str, field_value_json_str, document.GetAllocator());
2809 const std::vector<SharedDictionaryDef>& shared_dict_defs) {
2810 rapidjson::Document document;
2811 auto& allocator = document.GetAllocator();
2812 rapidjson::Value arr(rapidjson::kArrayType);
2813 if (shard_key_def) {
2814 rapidjson::Value shard_key_obj(rapidjson::kObjectType);
2817 arr.PushBack(shard_key_obj, allocator);
2819 for (
const auto& shared_dict_def : shared_dict_defs) {
2820 rapidjson::Value shared_dict_obj(rapidjson::kObjectType);
2822 set_string_field(shared_dict_obj,
"name", shared_dict_def.get_column(), document);
2824 shared_dict_obj,
"foreign_table", shared_dict_def.get_foreign_table(), document);
2827 shared_dict_def.get_foreign_column(),
2829 arr.PushBack(shared_dict_obj, allocator);
2831 rapidjson::StringBuffer buffer;
2832 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
2834 return buffer.GetString();
2837 template <
typename LITERAL_TYPE,
2838 typename ASSIGNMENT,
2842 VALIDATE validate = VALIDATE()) {
2843 const auto val = validate(p);
2850 auto assignment = [&td](
const auto val) { td.storageType = val; };
2851 return get_property_value<StringLiteral, decltype(assignment), CaseSensitiveValidate>(
2858 return get_property_value<IntLiteral>(p,
2859 [&td](
const auto val) { td.maxFragRows = val; });
2865 return get_property_value<IntLiteral>(
2866 p, [&df_td](
const auto val) { df_td.maxFragRows = val; });
2872 return get_property_value<IntLiteral>(p,
2873 [&td](
const auto val) { td.maxChunkSize = val; });
2880 return get_property_value<IntLiteral>(
2881 p, [&df_td](
const auto val) { df_td.maxChunkSize = val; });
2887 return get_property_value<StringLiteral>(p, [&df_td](
const auto val) {
2888 if (val.size() != 1) {
2889 throw std::runtime_error(
"Length of DELIMITER must be equal to 1.");
2891 df_td.delimiter = val;
2898 return get_property_value<StringLiteral>(p, [&df_td](
const auto val) {
2899 if (val ==
"FALSE") {
2900 df_td.hasHeader =
false;
2901 }
else if (val ==
"TRUE") {
2902 df_td.hasHeader =
true;
2904 throw std::runtime_error(
"Option HEADER support only 'true' or 'false' values.");
2912 return get_property_value<IntLiteral>(p,
2913 [&td](
const auto val) { td.fragPageSize = val; });
2918 return get_property_value<IntLiteral>(p, [&td](
const auto val) { td.maxRows = val; });
2924 return get_property_value<IntLiteral>(
2925 p, [&df_td](
const auto val) { df_td.skipRows = val; });
2931 return get_property_value<StringLiteral>(p, [&td](
const auto partitions_uc) {
2932 if (partitions_uc !=
"SHARDED" && partitions_uc !=
"REPLICATED") {
2933 throw std::runtime_error(
"PARTITIONS must be SHARDED or REPLICATED");
2935 if (td.shardedColumnId != 0 && partitions_uc ==
"REPLICATED") {
2936 throw std::runtime_error(
2937 "A table cannot be sharded and replicated at the same time");
2939 td.partitions = partitions_uc;
2945 if (!td.shardedColumnId) {
2946 throw std::runtime_error(
"SHARD KEY must be defined.");
2948 return get_property_value<IntLiteral>(p, [&td](
const auto shard_count) {
2950 throw std::runtime_error(
2951 "SHARD_COUNT must be a multiple of the number of leaves in the cluster.");
2953 td.nShards = g_leaf_count ? shard_count / g_leaf_count : shard_count;
2954 if (!td.shardedColumnId && !td.nShards) {
2955 throw std::runtime_error(
2956 "Must specify the number of shards through the SHARD_COUNT option");
2964 return get_property_value<StringLiteral>(p, [&td](
const auto vacuum_uc) {
2965 if (vacuum_uc !=
"IMMEDIATE" && vacuum_uc !=
"DELAYED") {
2966 throw std::runtime_error(
"VACUUM must be IMMEDIATE or DELAYED");
2968 td.hasDeletedCol = boost::iequals(vacuum_uc,
"IMMEDIATE") ?
false :
true;
2975 return get_property_value<StringLiteral>(p, [&td, &columns](
const auto sort_upper) {
2977 if (!td.sortedColumnId) {
2978 throw std::runtime_error(
"Specified sort column " + sort_upper +
" doesn't exist");
2986 auto assignment = [&td](
const auto val) {
2987 td.maxRollbackEpochs =
2992 return get_property_value<IntLiteral, decltype(assignment), PositiveOrZeroValidate>(
3009 const std::unique_ptr<NameValueAssign>& p,
3010 const std::list<ColumnDescriptor>& columns) {
3011 const auto it = tableDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3012 if (it == tableDefFuncMap.end()) {
3013 throw std::runtime_error(
3014 "Invalid CREATE TABLE option " + *p->get_name() +
3015 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, PAGE_SIZE, MAX_ROLLBACK_EPOCHS, "
3017 "PARTITIONS, SHARD_COUNT, VACUUM, SORT_COLUMN, STORAGE_TYPE.");
3019 return it->second(td, p.get(), columns);
3023 const std::unique_ptr<NameValueAssign>& p,
3024 const std::list<ColumnDescriptor>& columns) {
3025 const auto it = tableDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3026 if (it == tableDefFuncMap.end()) {
3027 throw std::runtime_error(
3028 "Invalid CREATE TABLE AS option " + *p->get_name() +
3029 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, PAGE_SIZE, MAX_ROLLBACK_EPOCHS, "
3031 "PARTITIONS, SHARD_COUNT, VACUUM, SORT_COLUMN, STORAGE_TYPE, "
3032 "USE_SHARED_DICTIONARIES or FORCE_GEO_COMPRESSION.");
3034 return it->second(td, p.get(), columns);
3045 const std::unique_ptr<NameValueAssign>& p,
3046 const std::list<ColumnDescriptor>& columns) {
3048 dataframeDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3049 if (it == dataframeDefFuncMap.end()) {
3050 throw std::runtime_error(
3051 "Invalid CREATE DATAFRAME option " + *p->get_name() +
3052 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, SKIP_ROWS, DELIMITER or HEADER.");
3054 return it->second(df_td, p.get(), columns);
3058 CHECK(element.HasMember(
"name"));
3059 auto col_name = std::make_unique<std::string>(
json_str(element[
"name"]));
3060 CHECK(element.HasMember(
"sqltype"));
3066 if (element.HasMember(
"precision")) {
3067 precision =
json_i64(element[
"precision"]);
3069 if (element.HasMember(
"scale")) {
3070 scale =
json_i64(element[
"scale"]);
3073 std::optional<int64_t> array_size;
3074 if (element.HasMember(
"arraySize")) {
3076 array_size =
json_i64(element[
"arraySize"]);
3078 std::unique_ptr<SQLType> sql_type;
3079 if (element.HasMember(
"subtype")) {
3080 CHECK(element.HasMember(
"coordinateSystem"));
3083 std::make_unique<SQLType>(subtype_sql_types,
3084 static_cast<int>(sql_types),
3085 static_cast<int>(
json_i64(element[
"coordinateSystem"])),
3087 }
else if (precision > 0 && scale > 0) {
3088 sql_type = std::make_unique<SQLType>(sql_types,
3091 array_size.has_value(),
3092 array_size ? *array_size : -1);
3093 }
else if (precision > 0) {
3094 sql_type = std::make_unique<SQLType>(sql_types,
3097 array_size.has_value(),
3098 array_size ? *array_size : -1);
3100 sql_type = std::make_unique<SQLType>(sql_types,
3101 array_size.has_value(),
3102 array_size ? *array_size : -1);
3106 CHECK(element.HasMember(
"nullable"));
3107 const auto nullable =
json_bool(element[
"nullable"]);
3108 std::unique_ptr<ColumnConstraintDef> constraint_def;
3110 if (element.HasMember(
"default") && !element[
"default"].IsNull()) {
3111 std::string* defaultval =
new std::string(
json_str(element[
"default"]));
3112 boost::algorithm::trim_if(*defaultval, boost::is_any_of(
" \"'`"));
3116 constraint_def = std::make_unique<ColumnConstraintDef>(!nullable,
3120 std::unique_ptr<CompressDef> compress_def;
3121 if (element.HasMember(
"encodingType") && !element[
"encodingType"].IsNull()) {
3122 std::string encoding_type =
json_str(element[
"encodingType"]);
3123 CHECK(element.HasMember(
"encodingSize"));
3124 auto encoding_name = std::make_unique<std::string>(
json_str(element[
"encodingType"]));
3125 compress_def = std::make_unique<CompressDef>(encoding_name.release(),
3126 json_i64(element[
"encodingSize"]));
3128 return std::make_unique<ColumnDef>(col_name.release(),
3130 compress_def ? compress_def.release() :
nullptr,
3131 constraint_def ? constraint_def.release() :
nullptr);
3135 std::string element_name,
3136 std::string& table_name,
3137 std::list<std::unique_ptr<TableElement>>& table_element_list) {
3138 const auto elements = payload[element_name].GetArray();
3139 for (
const auto& element : elements) {
3140 CHECK(element.IsObject());
3141 CHECK(element.HasMember(
"type"));
3142 if (
json_str(element[
"type"]) ==
"SQL_COLUMN_DECLARATION") {
3144 table_element_list.emplace_back(std::move(col_def));
3145 }
else if (
json_str(element[
"type"]) ==
"SQL_COLUMN_CONSTRAINT") {
3146 CHECK(element.HasMember(
"name"));
3147 if (
json_str(element[
"name"]) ==
"SHARD_KEY") {
3148 CHECK(element.HasMember(
"columns"));
3149 CHECK(element[
"columns"].IsArray());
3150 const auto& columns = element[
"columns"].GetArray();
3151 if (columns.Size() != size_t(1)) {
3152 throw std::runtime_error(
"Only one shard column is currently supported.");
3154 auto shard_key_def = std::make_unique<ShardKeyDef>(
json_str(columns[0]));
3155 table_element_list.emplace_back(std::move(shard_key_def));
3156 }
else if (
json_str(element[
"name"]) ==
"SHARED_DICT") {
3157 CHECK(element.HasMember(
"columns"));
3158 CHECK(element[
"columns"].IsArray());
3159 const auto& columns = element[
"columns"].GetArray();
3160 if (columns.Size() != size_t(1)) {
3161 throw std::runtime_error(
3162 R
"(Only one column per shared dictionary entry is currently supported. Use multiple SHARED DICT statements to share dictionaries from multiple columns.)");
3164 CHECK(element.HasMember("references") && element[
"references"].IsObject());
3165 const auto& references = element[
"references"].GetObject();
3166 std::string references_table_name;
3167 if (references.HasMember(
"table")) {
3168 references_table_name =
json_str(references[
"table"]);
3170 references_table_name = table_name;
3172 CHECK(references.HasMember(
"column"));
3174 auto shared_dict_def = std::make_unique<SharedDictionaryDef>(
3175 json_str(columns[0]), references_table_name,
json_str(references[
"column"]));
3176 table_element_list.emplace_back(std::move(shared_dict_def));
3179 LOG(
FATAL) <<
"Unsupported type for SQL_COLUMN_CONSTRAINT: "
3183 LOG(
FATAL) <<
"Unsupported element type for CREATE TABLE: "
3184 << element[
"type"].GetString();
3191 CHECK(payload.HasMember(
"name"));
3192 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
3193 CHECK(payload.HasMember(
"elements"));
3194 CHECK(payload[
"elements"].IsArray());
3197 if (payload.HasMember(
"temporary")) {
3202 if (payload.HasMember(
"ifNotExists")) {
3213 std::list<ColumnDescriptor>& columns,
3214 std::vector<SharedDictionaryDef>& shared_dict_defs) {
3215 std::unordered_set<std::string> uc_col_names;
3219 if (dynamic_cast<SharedDictionaryDef*>(e.get())) {
3222 this, shared_dict_def, columns, shared_dict_defs, catalog);
3223 shared_dict_defs.push_back(*shared_dict_def);
3226 if (dynamic_cast<ShardKeyDef*>(e.get())) {
3227 if (shard_key_def) {
3228 throw std::runtime_error(
"Specified more than one shard key");
3230 shard_key_def =
static_cast<const ShardKeyDef*
>(e.get());
3233 if (!dynamic_cast<ColumnDef*>(e.get())) {
3234 throw std::runtime_error(
"Table constraints are not supported yet.");
3241 columns.push_back(cd);
3246 if (shard_key_def) {
3249 throw std::runtime_error(
"Specified shard column " + shard_key_def->get_column() +
3264 throw std::runtime_error(
"SHARD_COUNT needs to be specified with SHARD_KEY.");
3270 bool read_only_mode) {
3271 if (read_only_mode) {
3272 throw std::runtime_error(
"CREATE TABLE invalid in read only mode.");
3279 const auto execute_write_lock =
3287 throw std::runtime_error(
"Table " + *
table_ +
3288 " will not be created. User has no create privileges.");
3296 std::list<ColumnDescriptor> columns;
3297 std::vector<SharedDictionaryDef> shared_dict_defs;
3302 catalog.createShardedTable(td, columns, shared_dict_defs);
3305 SysCatalog::instance().createDBObject(
3310 CHECK(payload.HasMember(
"name"));
3311 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
3313 CHECK(payload.HasMember(
"elementList"));
3316 CHECK(payload.HasMember(
"filePath"));
3317 std::string fs =
json_str(payload[
"filePath"]);
3319 boost::algorithm::trim_if(fs, boost::is_any_of(
" \"'`"));
3320 filename_ = std::make_unique<std::string>(fs);
3326 bool read_only_mode) {
3327 if (read_only_mode) {
3328 throw std::runtime_error(
"CREATE DATAFRAME invalid in read only mode.");
3332 const auto execute_write_lock =
3340 throw std::runtime_error(
"Table " + *
table_ +
3341 " will not be created. User has no create privileges.");
3344 if (catalog.getMetadataForTable(*
table_) !=
nullptr) {
3345 throw std::runtime_error(
"Table " + *
table_ +
" already exists.");
3348 std::list<ColumnDescriptor> columns;
3349 std::vector<SharedDictionaryDef> shared_dict_defs;
3351 std::unordered_set<std::string> uc_col_names;
3353 if (dynamic_cast<SharedDictionaryDef*>(e.get())) {
3356 this, shared_dict_def, columns, shared_dict_defs, catalog);
3357 shared_dict_defs.push_back(*shared_dict_def);
3360 if (!dynamic_cast<ColumnDef*>(e.get())) {
3361 throw std::runtime_error(
"Table constraints are not supported yet.");
3366 const auto uc_col_name = boost::to_upper_copy<std::string>(cd.
columnName);
3367 const auto it_ok = uc_col_names.insert(uc_col_name);
3368 if (!it_ok.second) {
3369 throw std::runtime_error(
"Column '" + cd.
columnName +
"' defined more than once");
3372 columns.push_back(cd);
3394 catalog.createShardedTable(df_td, columns, shared_dict_defs);
3397 SysCatalog::instance().createDBObject(
3402 const std::string select_stmt,
3403 std::vector<TargetMetaInfo>& targets,
3404 bool validate_only =
false,
3405 std::vector<size_t> outer_fragment_indices = {},
3406 bool allow_interrupt =
false) {
3408 auto& catalog = session->getCatalog();
3412 const auto device_type = session->get_executor_device_type();
3416 auto calcite_mgr = catalog.getCalciteMgr();
3420 const auto calciteQueryParsingOption =
3421 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true);
3422 const auto calciteOptimizationOption = calcite_mgr->getCalciteOptimizationOption(
3427 const auto query_ra = calcite_mgr
3428 ->process(query_state_proxy,
3430 calciteQueryParsingOption,
3431 calciteOptimizationOption)
3434 executor.get(), query_ra, query_state_proxy->shared_from_this());
3455 std::numeric_limits<size_t>::max(),
3457 outer_fragment_indices};
3466 result = ra_executor.executeRelAlgQuery(co, eo,
false,
nullptr);
3467 targets =
result.getTargetsMeta();
3473 std::string& sql_query_string) {
3475 auto& catalog = session->getCatalog();
3479 const auto device_type = session->get_executor_device_type();
3483 auto calcite_mgr = catalog.getCalciteMgr();
3487 const auto calciteQueryParsingOption =
3488 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true);
3489 const auto calciteOptimizationOption = calcite_mgr->getCalciteOptimizationOption(
3494 const auto query_ra = calcite_mgr
3495 ->process(query_state_proxy,
3497 calciteQueryParsingOption,
3498 calciteOptimizationOption)
3519 return ra_executor.getOuterFragmentCount(co, eo);
3523 std::string& sql_query_string,
3524 std::vector<size_t> outer_frag_indices,
3526 bool allow_interrupt) {
3528 std::string pg_shimmed_select_query =
pg_shim(sql_query_string);
3530 std::vector<TargetMetaInfo> target_metainfos;
3533 auto query_session = session ? session->get_session_id() :
"";
3535 if (allow_interrupt && !validate_only && !query_session.empty()) {
3536 executor->enrollQuerySession(query_session,
3538 query_submitted_time,
3540 QuerySessionStatus::QueryStatus::PENDING_EXECUTOR);
3554 std::string& sql_query_string,
3555 std::vector<size_t> outer_frag_indices,
3556 bool allow_interrupt) {
3558 query_state_proxy, sql_query_string, outer_frag_indices,
false, allow_interrupt);
3565 std::list<ColumnDescriptor> column_descriptors;
3566 std::list<ColumnDescriptor> column_descriptors_for_create;
3568 int rowid_suffix = 0;
3569 for (
const auto& target_metainfo : result.
targets_meta) {
3571 cd.
columnName = target_metainfo.get_resname();
3575 cd.
columnType = target_metainfo.get_physical_type_info();
3595 column_descriptors_for_create.push_back(cd_for_create);
3596 column_descriptors.push_back(cd);
3600 return column_descriptors_for_create;
3603 return column_descriptors;
3607 const rapidjson::Value& payload) {
3608 CHECK(payload.HasMember(
"name"));
3611 CHECK(payload.HasMember(
"query"));
3614 boost::replace_all(select_query_,
"\n",
" ");
3615 select_query_ =
"(" + select_query_ +
")";
3617 if (payload.HasMember(
"columns")) {
3618 CHECK(payload[
"columns"].IsArray());
3619 for (
auto& column : payload[
"columns"].GetArray()) {
3621 column_list_.emplace_back(std::unique_ptr<std::string>(
new std::string(s)));
3628 bool validate_table,
3631 auto& catalog = session->getCatalog();
3633 bool populate_table =
false;
3636 populate_table =
true;
3640 populate_table =
true;
3644 auto get_target_column_descriptors = [
this, &catalog](
const TableDescriptor* td) {
3645 std::vector<const ColumnDescriptor*> target_column_descriptors;
3647 auto list = catalog.getAllColumnMetadataForTable(td->
tableId,
false,
false,
false);
3648 target_column_descriptors = {std::begin(list), std::end(list)};
3652 if (cd ==
nullptr) {
3653 throw std::runtime_error(
"Column " + *c +
" does not exist.");
3655 target_column_descriptors.push_back(cd);
3659 return target_column_descriptors;
3664 if (validate_table) {
3667 throw std::runtime_error(
"Table " +
table_name_ +
" does not exist.");
3670 throw std::runtime_error(
"Insert to views is not supported yet.");
3676 throw std::runtime_error(
"User has no insert privileges on " +
table_name_ +
".");
3685 std::vector<const ColumnDescriptor*> target_column_descriptors =
3686 get_target_column_descriptors(td);
3688 if (source_column_descriptors.size() != target_column_descriptors.size()) {
3689 throw std::runtime_error(
"The number of source and target columns does not match.");
3692 for (
int i = 0; i < source_column_descriptors.size(); i++) {
3694 &(*std::next(source_column_descriptors.begin(), i));
3698 auto type_cannot_be_cast = [](
const auto& col_type) {
3699 return (col_type.is_time() || col_type.is_geometry() || col_type.is_array() ||
3700 col_type.is_boolean());
3703 if (type_cannot_be_cast(source_cd->
columnType) ||
3704 type_cannot_be_cast(target_cd->
columnType)) {
3705 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3707 "' and target '" + target_cd->
columnName +
" " +
3709 "' column types do not match.");
3714 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3716 "' and target '" + target_cd->
columnName +
" " +
3718 "' array column element types do not match.");
3723 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3725 "' and target '" + target_cd->
columnName +
" " +
3727 "' column types do not match.");
3741 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3743 "' and target '" + target_cd->
columnName +
" " +
3745 "' decimal columns scales do not match.");
3751 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3753 "' and target '" + target_cd->
columnName +
" " +
3755 "' column types do not match.");
3759 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3761 "' and target '" + target_cd->
columnName +
" " +
3763 "' columns string encodings do not match.");
3770 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3772 "' and target '" + target_cd->
columnName +
" " +
3774 "' timestamp column precisions do not match.");
3783 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3785 "' and target '" + target_cd->
columnName +
" " +
3787 "' column encoding sizes do not match.");
3792 if (!populate_table) {
3796 int64_t total_row_count = 0;
3797 int64_t total_source_query_time_ms = 0;
3798 int64_t total_target_value_translate_time_ms = 0;
3799 int64_t total_data_load_time_ms = 0;
3802 auto target_column_descriptors = get_target_column_descriptors(td);
3803 auto outer_frag_count =
3806 size_t outer_frag_end = outer_frag_count == 0 ? 1 : outer_frag_count;
3807 auto query_session = session ? session->get_session_id() :
"";
3809 std::string work_type_str = for_CTAS ?
"CTAS" :
"ITAS";
3811 for (
size_t outer_frag_idx = 0; outer_frag_idx < outer_frag_end; outer_frag_idx++) {
3812 std::vector<size_t> allowed_outer_fragment_indices;
3814 if (outer_frag_count) {
3815 allowed_outer_fragment_indices.push_back(outer_frag_idx);
3819 std::vector<AggregatedResult> query_results =
3822 allowed_outer_fragment_indices,
3824 total_source_query_time_ms +=
timer_stop(query_clock_begin);
3827 auto query_str =
"INSERT_DATA for " + work_type_str;
3832 executor->enrollQuerySession(query_session,
3836 QuerySessionStatus::QueryStatus::RUNNING_IMPORTER);
3843 executor->clearQuerySessionStatus(query_session,
start_time);
3847 for (
auto&
res : query_results) {
3849 throw std::runtime_error(
3850 "Query execution has been interrupted while performing " + work_type_str);
3852 auto& result_rows =
res.rs;
3854 const auto num_rows = result_rows->rowCount();
3856 if (0 == num_rows) {
3860 total_row_count += num_rows;
3865 const size_t rows_per_block =
3866 std::max(std::min(num_rows / leaf_count,
size_t(64 * 1024)),
size_t(1));
3868 std::vector<std::unique_ptr<TargetValueConverter>> value_converters;
3872 const int num_worker_threads = std::thread::hardware_concurrency();
3874 std::vector<size_t> thread_start_idx(num_worker_threads),
3875 thread_end_idx(num_worker_threads);
3876 bool can_go_parallel = !result_rows->isTruncated() && rows_per_block > 20000;
3878 std::atomic<size_t> crt_row_idx{0};
3880 auto do_work = [&result_rows, &value_converters, &crt_row_idx](
3882 const size_t block_end,
3883 const size_t num_cols,
3885 bool& stop_convert) {
3886 const auto result_row = result_rows->getRowAtNoTranslations(idx);
3887 if (!result_row.empty()) {
3888 size_t target_row = crt_row_idx.fetch_add(1);
3889 if (target_row >= block_end) {
3890 stop_convert =
true;
3893 for (
unsigned int col = 0; col < num_cols; col++) {
3894 const auto& mapd_variant = result_row[col];
3895 value_converters[col]->convertToColumnarFormat(target_row, &mapd_variant);
3900 auto convert_function = [&thread_start_idx,
3906 &do_work](
const int thread_id,
const size_t block_end) {
3907 const int num_cols = value_converters.size();
3908 const size_t start = thread_start_idx[
thread_id];
3909 const size_t end = thread_end_idx[
thread_id];
3911 bool stop_convert =
false;
3913 size_t local_idx = 0;
3914 for (idx = start; idx < end; ++idx, ++local_idx) {
3915 if (
UNLIKELY((local_idx & 0xFFFF) == 0 &&
3917 throw std::runtime_error(
3918 "Query execution has been interrupted while performing " +
3921 do_work(idx, block_end, num_cols, thread_id, stop_convert);
3927 for (idx = start; idx < end; ++idx) {
3928 do_work(idx, block_end, num_cols, thread_id, stop_convert);
3937 auto single_threaded_value_converter =
3938 [&crt_row_idx, &value_converters, &result_rows](
const size_t idx,
3939 const size_t block_end,
3940 const size_t num_cols,
3941 bool& stop_convert) {
3942 size_t target_row = crt_row_idx.fetch_add(1);
3943 if (target_row >= block_end) {
3944 stop_convert =
true;
3947 const auto result_row = result_rows->getNextRow(
false,
false);
3948 CHECK(!result_row.empty());
3949 for (
unsigned int col = 0; col < num_cols; col++) {
3950 const auto& mapd_variant = result_row[col];
3951 value_converters[col]->convertToColumnarFormat(target_row, &mapd_variant);
3955 auto single_threaded_convert_function = [&value_converters,
3961 &single_threaded_value_converter](
3963 const size_t block_end) {
3964 const int num_cols = value_converters.size();
3965 const size_t start = thread_start_idx[
thread_id];
3966 const size_t end = thread_end_idx[
thread_id];
3968 bool stop_convert =
false;
3970 size_t local_idx = 0;
3971 for (idx = start; idx < end; ++idx, ++local_idx) {
3972 if (
UNLIKELY((local_idx & 0xFFFF) == 0 &&
3974 throw std::runtime_error(
3975 "Query execution has been interrupted while performing " +
3978 single_threaded_value_converter(idx, block_end, num_cols, stop_convert);
3984 for (idx = start; idx < end; ++idx) {
3985 single_threaded_value_converter(idx, end, num_cols, stop_convert);
3994 if (can_go_parallel) {
3995 const size_t entry_count = result_rows->entryCount();
3999 stride = (entry_count + num_worker_threads - 1) / num_worker_threads;
4000 i < num_worker_threads && start_entry < entry_count;
4001 ++i, start_entry += stride) {
4002 const auto end_entry = std::min(start_entry + stride, entry_count);
4003 thread_start_idx[i] = start_entry;
4004 thread_end_idx[i] = end_entry;
4007 thread_start_idx[0] = 0;
4008 thread_end_idx[0] = result_rows->entryCount();
4013 for (
size_t block_start = 0; block_start < num_rows;
4014 block_start += rows_per_block) {
4015 const auto num_rows_this_itr = block_start + rows_per_block < num_rows
4017 : num_rows - block_start;
4019 value_converters.clear();
4021 for (
const auto targetDescriptor : target_column_descriptors) {
4022 auto sourceDataMetaInfo =
res.targets_meta[colNum++];
4028 targetDescriptor->columnType,
4029 !targetDescriptor->columnType.get_notnull(),
4030 result_rows->getRowSetMemOwner()->getLiteralStringDictProxy(),
4032 sourceDataMetaInfo.get_type_info().is_dict_encoded_string()
4033 ? executor->getStringDictionaryProxy(
4034 sourceDataMetaInfo.get_type_info().getStringDictKey(),
4035 result_rows->getRowSetMemOwner(),
4038 IS_GEO_POLY(targetDescriptor->columnType.get_type()) &&
4040 ? &render_group_analyzer_map
4042 auto converter = factory.
create(param);
4043 value_converters.push_back(std::move(converter));
4047 if (can_go_parallel) {
4048 std::vector<std::future<void>> worker_threads;
4049 for (
int i = 0; i < num_worker_threads; ++i) {
4050 worker_threads.push_back(
4054 for (
auto& child : worker_threads) {
4057 for (
auto& child : worker_threads) {
4062 single_threaded_convert_function(0, num_rows_this_itr);
4066 auto finalizer_func =
4067 [](std::unique_ptr<TargetValueConverter>::pointer targetValueConverter) {
4068 targetValueConverter->finalizeDataBlocksForInsertData();
4071 std::vector<std::future<void>> worker_threads;
4072 for (
auto& converterPtr : value_converters) {
4073 worker_threads.push_back(
4077 for (
auto& child : worker_threads) {
4080 for (
auto& child : worker_threads) {
4085 insert_data.
databaseId = catalog.getCurrentDB().dbId;
4088 insert_data.
numRows = num_rows_this_itr;
4090 for (
int col_idx = 0; col_idx < target_column_descriptors.size(); col_idx++) {
4093 throw std::runtime_error(
4094 "Query execution has been interrupted while performing " +
4097 value_converters[col_idx]->addDataBlocksToInsertData(insert_data);
4099 total_target_value_translate_time_ms +=
timer_stop(translate_clock_begin);
4102 auto data_memory_holder =
4104 insertDataLoader.
insertData(*session, insert_data);
4105 total_data_load_time_ms +=
timer_stop(data_load_clock_begin);
4112 }
catch (std::exception& e) {
4113 LOG(
ERROR) <<
"An error occurred during ITAS rollback attempt. Table id: "
4114 << td->
tableId <<
", Error: " << e.what();
4119 int64_t total_time_ms = total_source_query_time_ms +
4120 total_target_value_translate_time_ms + total_data_load_time_ms;
4122 VLOG(1) <<
"CTAS/ITAS " << total_row_count <<
" rows loaded in " << total_time_ms
4123 <<
"ms (outer_frag_count=" << outer_frag_count
4124 <<
", query_time=" << total_source_query_time_ms
4125 <<
"ms, translation_time=" << total_target_value_translate_time_ms
4126 <<
"ms, data_load_time=" << total_data_load_time_ms
4129 if (!is_temporary) {
4136 const auto catalog = SysCatalog::instance().getCatalog(table[1]);
4138 const auto table_id = catalog->getTableId(table[0]);
4139 if (!table_id.has_value()) {
4140 throw std::runtime_error{
"Table \"" + table[0] +
4141 "\" does not exist in catalog: " + table[1] +
"."};
4143 return {catalog->getDatabaseId(), table_id.value()};
4147 const std::string& insert_table_db_name,
4148 const std::string& query_str,
4150 const std::optional<std::string>& insert_table_name = {}) {
4151 auto& sys_catalog = SysCatalog::instance();
4152 auto& calcite_mgr = sys_catalog.getCalciteMgr();
4153 const auto calciteQueryParsingOption =
4154 calcite_mgr.getCalciteQueryParsingOption(
true,
false,
true);
4155 const auto calciteOptimizationOption = calcite_mgr.getCalciteOptimizationOption(
4157 const auto result = calcite_mgr.process(query_state_proxy,
4159 calciteQueryParsingOption,
4160 calciteOptimizationOption);
4163 auto comparator = [](
const std::vector<std::string>& table_1,
4164 const std::vector<std::string>& table_2) {
4167 std::set<std::vector<std::string>, decltype(comparator)>
tables(comparator);
4168 for (
auto& tab :
result.resolved_accessed_objects.tables_selected_from) {
4171 if (insert_table_name.has_value()) {
4173 std::vector<std::string>{insert_table_name.value(), insert_table_db_name});
4176 for (
const auto& table :
tables) {
4177 const auto catalog = sys_catalog.getCatalog(table[1]);
4182 *catalog, table[0])));
4183 if (insert_table_name.has_value() && table[0] == insert_table_name.value() &&
4184 table[1] == insert_table_db_name) {
4188 catalog->getDatabaseId(), (*locks.back())())));
4193 catalog->getDatabaseId(), (*locks.back())())));
4201 bool read_only_mode) {
4202 if (read_only_mode) {
4203 throw std::runtime_error(
"INSERT INTO TABLE invalid in read only mode.");
4205 auto session_copy = session;
4206 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
4207 &session_copy, boost::null_deleter());
4209 auto stdlog =
STDLOG(query_state);
4210 auto& catalog = session_ptr->getCatalog();
4212 const auto execute_read_lock =
4217 if (catalog.getMetadataForTable(
table_name_) ==
nullptr) {
4218 throw std::runtime_error(
"ITAS failed: table " +
table_name_ +
" does not exist.");
4228 populateData(query_state->createQueryStateProxy(), td,
true,
false);
4236 if (payload.HasMember(
"temporary")) {
4242 if (payload.HasMember(
"ifNotExists")) {
4252 bool read_only_mode) {
4253 if (read_only_mode) {
4254 throw std::runtime_error(
"CREATE TABLE invalid in read only mode.");
4256 auto session_copy = session;
4257 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
4258 &session_copy, boost::null_deleter());
4260 auto stdlog =
STDLOG(query_state);
4265 std::set<std::string> select_tables;
4267 const auto execute_write_lock =
4275 throw std::runtime_error(
"CTAS failed. Table " +
table_name_ +
4276 " will not be created. User has no create privileges.");
4279 if (catalog.getMetadataForTable(
table_name_) !=
nullptr) {
4284 " already exists and no data was loaded.");
4290 auto validate_result = local_connector.
query(
4291 query_state->createQueryStateProxy(),
select_query_, {},
true,
false);
4293 auto column_descriptors_for_create =
4297 for (
auto& cd : column_descriptors_for_create) {
4298 if (cd.columnType.is_decimal() &&
4300 throw std::runtime_error(cd.columnName +
": Precision too high, max " +
4309 td.
nColumns = column_descriptors_for_create.size();
4324 bool use_shared_dictionaries =
true;
4325 bool force_geo_compression =
true;
4329 if (boost::to_lower_copy<std::string>(*p->get_name()) ==
4330 "use_shared_dictionaries") {
4333 if (
nullptr == literal) {
4334 throw std::runtime_error(
4335 "USE_SHARED_DICTIONARIES must be a string parameter");
4337 std::string val = boost::to_lower_copy<std::string>(*literal->
get_stringval());
4338 use_shared_dictionaries = val ==
"true" || val ==
"1" || val ==
"t";
4339 }
else if (boost::to_lower_copy<std::string>(*p->get_name()) ==
4340 "force_geo_compression") {
4343 if (
nullptr == literal) {
4344 throw std::runtime_error(
"FORCE_GEO_COMPRESSION must be a string parameter");
4346 std::string val = boost::to_lower_copy<std::string>(*literal->
get_stringval());
4347 force_geo_compression = val ==
"true" || val ==
"1" || val ==
"t";
4354 std::vector<SharedDictionaryDef> sharedDictionaryRefs;
4356 if (use_shared_dictionaries) {
4357 const auto source_column_descriptors =
4359 const auto mapping = catalog.getDictionaryToColumnMapping();
4361 for (
auto& source_cd : source_column_descriptors) {
4362 const auto& ti = source_cd.columnType;
4363 if (ti.is_string()) {
4365 int dict_id = ti.get_comp_param();
4366 auto it = mapping.find(dict_id);
4367 if (mapping.end() != it) {
4368 const auto targetColumn = it->second;
4370 catalog.getMetadataForTable(targetColumn->tableId,
false);
4372 LOG(
INFO) <<
"CTAS: sharing text dictionary on column "
4373 << source_cd.columnName <<
" with " << targetTable->tableName
4374 <<
"." << targetColumn->columnName;
4375 sharedDictionaryRefs.emplace_back(
4376 source_cd.columnName, targetTable->tableName, targetColumn->columnName);
4383 if (force_geo_compression) {
4384 for (
auto& cd_for_create : column_descriptors_for_create) {
4385 auto& ti = cd_for_create.columnType;
4386 if (ti.is_geometry() && ti.get_output_srid() == 4326) {
4389 ti.set_comp_param(32);
4397 catalog.createTable(td, column_descriptors_for_create, sharedDictionaryRefs,
true);
4400 SysCatalog::instance().createDBObject(
4406 const auto execute_read_lock =
4415 populateData(query_state->createQueryStateProxy(), td,
false,
true);
4420 catalog.dropTable(created_td);
4428 CHECK(payload.HasMember(
"tableName"));
4429 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4432 if (payload.HasMember(
"ifExists")) {
4433 if_exists_ =
json_bool(payload[
"ifExists"]);
4438 bool read_only_mode) {
4439 if (read_only_mode) {
4440 throw std::runtime_error(
"DROP TABLE invalid in read only mode.");
4445 const auto execute_read_lock =
4451 std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
4454 std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
4456 catalog, *
table_,
false));
4457 td = (*td_with_lock)();
4458 }
catch (
const std::runtime_error& e) {
4467 CHECK(td_with_lock);
4472 throw std::runtime_error(
"Table " + *
table_ +
4473 " will not be dropped. User has no proper privileges.");
4479 auto table_data_read_lock =
4484 auto table_data_write_lock =
4486 catalog.dropTable(td);
4490 bool read_only_mode) {}
4493 CHECK(payload.HasMember(
"tableName"));
4494 auto tableName =
json_str(payload[
"tableName"]);
4496 CHECK(payload.HasMember(
"alterType"));
4499 if (type ==
"RENAME_TABLE") {
4500 CHECK(payload.HasMember(
"newTableName"));
4501 auto newTableName =
json_str(payload[
"newTableName"]);
4503 new std::string(tableName),
new std::string(newTableName)));
4505 }
else if (type ==
"RENAME_COLUMN") {
4506 CHECK(payload.HasMember(
"columnName"));
4507 auto columnName =
json_str(payload[
"columnName"]);
4508 CHECK(payload.HasMember(
"newColumnName"));
4509 auto newColumnName =
json_str(payload[
"newColumnName"]);
4510 return std::unique_ptr<DDLStmt>(
4512 new std::string(columnName),
4513 new std::string(newColumnName)));
4515 }
else if (type ==
"ALTER_COLUMN") {
4516 CHECK(payload.HasMember(
"alterData"));
4517 CHECK(payload[
"alterData"].IsArray());
4518 throw std::runtime_error(
"ALTER TABLE ALTER COLUMN is not implemented.");
4519 }
else if (type ==
"ADD_COLUMN") {
4520 CHECK(payload.HasMember(
"columnData"));
4521 CHECK(payload[
"columnData"].IsArray());
4524 std::list<ColumnDef*>* table_element_list_ =
new std::list<ColumnDef*>;
4526 const auto elements = payload[
"columnData"].GetArray();
4527 for (
const auto& element : elements) {
4528 CHECK(element.IsObject());
4529 CHECK(element.HasMember(
"type"));
4530 if (
json_str(element[
"type"]) ==
"SQL_COLUMN_DECLARATION") {
4532 table_element_list_->emplace_back(col_def.release());
4534 LOG(
FATAL) <<
"Unsupported element type for ALTER TABLE: "
4535 << element[
"type"].GetString();
4539 return std::unique_ptr<DDLStmt>(
4542 }
else if (type ==
"DROP_COLUMN") {
4543 CHECK(payload.HasMember(
"columnData"));
4544 auto columnData =
json_str(payload[
"columnData"]);
4547 std::list<std::string*>* cols =
new std::list<std::string*>;
4548 std::vector<std::string> cols1;
4549 boost::split(cols1, columnData, boost::is_any_of(
","));
4550 for (
auto s : cols1) {
4552 boost::algorithm::trim_if(s, boost::is_any_of(
" \"'`"));
4553 std::string* str =
new std::string(s);
4554 cols->emplace_back(str);
4557 return std::unique_ptr<DDLStmt>(
4560 }
else if (type ==
"ALTER_OPTIONS") {
4561 CHECK(payload.HasMember(
"options"));
4562 const auto& options = payload[
"options"];
4563 if (options.IsObject()) {
4564 for (
auto itr = options.MemberBegin(); itr != options.MemberEnd(); ++itr) {
4565 std::string* option_name =
new std::string(
json_str(itr->name));
4567 if (itr->value.IsString()) {
4568 std::string literal_string =
json_str(itr->value);
4573 int iVal = std::stoi(literal_string, &sz);
4574 if (sz == literal_string.size()) {
4579 }
else if (itr->value.IsInt() || itr->value.IsInt64()) {
4581 }
else if (itr->value.IsNull()) {
4584 throw std::runtime_error(
"Unable to handle literal for " + *option_name);
4586 CHECK(literal_value);
4589 return std::unique_ptr<DDLStmt>(
4593 CHECK(options.IsNull());
4600 CHECK(payload.HasMember(
"tableName"));
4601 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4605 bool read_only_mode) {
4606 if (read_only_mode) {
4607 throw std::runtime_error(
"TRUNCATE TABLE invalid in read only mode.");
4609 const auto execute_read_lock =
4614 const auto td_with_lock =
4617 const auto td = td_with_lock();
4619 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
4623 std::vector<DBObject> privObjects;
4627 privObjects.push_back(dbObject);
4628 if (!SysCatalog::instance().checkPrivileges(session.
get_currentUser(), privObjects)) {
4629 throw std::runtime_error(
"Table " + *
table_ +
" will not be truncated. User " +
4631 " has no proper privileges.");
4635 throw std::runtime_error(*
table_ +
" is a view. Cannot Truncate.");
4641 auto table_data_read_lock =
4646 auto table_data_write_lock =
4648 catalog.truncateTable(td);
4652 CHECK(payload.HasMember(
"tableName"));
4653 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4663 std::vector<DBObject> privObjects;
4667 privObjects.push_back(dbObject);
4668 return SysCatalog::instance().checkPrivileges(session_info.
get_currentUser(),
4674 bool read_only_mode) {
4675 if (read_only_mode) {
4676 throw std::runtime_error(
"OPTIMIZE TABLE invalid in read only mode.");
4680 const auto execute_read_lock =
4685 const auto td_with_lock =
4688 const auto td = td_with_lock();
4691 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
4695 throw std::runtime_error(
"OPTIMIZE TABLE command is not supported on views.");
4699 std::vector<int> table_key{catalog.getCurrentDB().dbId, td->
tableId};
4710 bool repair_type(std::list<std::unique_ptr<NameValueAssign>>& options) {
4711 for (
const auto& opt : options) {
4712 if (boost::iequals(*opt->get_name(),
"REPAIR_TYPE")) {
4714 static_cast<const StringLiteral*
>(opt->get_value())->get_stringval();
4719 throw std::runtime_error(
"REPAIR_TYPE must be REMOVE.");
4722 throw std::runtime_error(
"The only VALIDATE WITH options is REPAIR_TYPE.");
4731 throw std::runtime_error(
"Validation Type is required for VALIDATE command.");
4733 std::list<std::unique_ptr<NameValueAssign>> options;
4735 for (
const auto e : *with_opts) {
4736 options.emplace_back(e);
4745 CHECK(payload.HasMember(
"type"));
4746 type_ = std::make_unique<std::string>(
json_str(payload[
"type"]));
4748 std::list<std::unique_ptr<NameValueAssign>> options;
4760 std::vector<DBObject> privObjects;
4764 privObjects.push_back(dbObject);
4765 if (!SysCatalog::instance().checkPrivileges(session.
get_currentUser(), privObjects)) {
4766 throw std::runtime_error(
"Current user does not have the privilege to alter table: " +
4772 CHECK(payload.HasMember(
"name"));
4774 CHECK(payload.HasMember(
"newName"));
4779 bool read_only_mode) {
4780 if (read_only_mode) {
4781 throw std::runtime_error(
"RENAME TABLE invalid in read only mode.");
4784 throw std::runtime_error(
"Only a super user can rename users.");
4788 if (!SysCatalog::instance().getMetadataForUser(*
username_, user)) {
4789 throw std::runtime_error(
"User " + *
username_ +
" does not exist.");
4796 CHECK(payload.HasMember(
"name"));
4798 CHECK(payload.HasMember(
"newName"));
4803 bool read_only_mode) {
4804 if (read_only_mode) {
4805 throw std::runtime_error(
"RENAME DATABASE invalid in read only mode.");
4810 const auto execute_write_lock =
4815 if (!SysCatalog::instance().getMetadataForDB(*
database_name_, db)) {
4816 throw std::runtime_error(
"Database " + *
database_name_ +
" does not exist.");
4821 throw std::runtime_error(
"Only a super user or the owner can rename the database.");
4828 CHECK(payload.HasMember(
"tableNames"));
4829 CHECK(payload[
"tableNames"].IsArray());
4830 const auto elements = payload[
"tableNames"].GetArray();
4831 for (
const auto& element : elements) {
4832 CHECK(element.HasMember(
"name"));
4833 CHECK(element.HasMember(
"newName"));
4835 new std::string(
json_str(element[
"newName"])));
4844 std::list<std::pair<std::string, std::string>> tableNames) {
4845 for (
auto item : tableNames) {
4847 new std::string(item.second));
4862 std::time_t
result = std::time(
nullptr);
4867 sMap[oldName] = newName;
4872 std::string tableName) {
4873 if (sMap.find(tableName) != sMap.end()) {
4877 return sMap[tableName];
4882 sMap[tableName] = tableName;
4899 for (
auto it : sMap) {
4900 if ((it.second) !=
EMPTY_NAME && (it.first) != (it.second)) {
4901 throw std::runtime_error(
4902 "Error: Attempted to overwrite and lose data in table: \'" + (it.first) +
"\'");
4911 throw std::runtime_error(td->
tableName +
" is a foreign table. " +
4912 "Use ALTER FOREIGN TABLE.");
4918 bool read_only_mode) {
4919 if (read_only_mode) {
4920 throw std::runtime_error(
"RENAME TABLE invalid in read only mode.");
4925 const auto execute_write_lock =
4931 std::vector<std::pair<std::string, std::string>> names;
4936 std::string curTableName = *(item.first);
4937 std::string newTableName = *(item.second);
4944 std::string altCurTableName =
loadTable(catalog, tableSubtituteMap, curTableName);
4945 std::string altNewTableName =
loadTable(catalog, tableSubtituteMap, newTableName);
4947 if (altCurTableName != curTableName && altCurTableName !=
EMPTY_NAME) {
4949 recordRename(tableSubtituteMap, curTableName, curTableName);
4960 if (
hasData(tableSubtituteMap, altCurTableName)) {
4961 const TableDescriptor* td = catalog.getMetadataForTable(altCurTableName);
4969 if (
hasData(tableSubtituteMap, altNewTableName)) {
4974 recordRename(tableSubtituteMap, altNewTableName, tmpNewTableName);
4975 recordRename(tableSubtituteMap, tmpNewTableName, tmpNewTableName);
4976 names.emplace_back(altNewTableName, tmpNewTableName);
4977 names.emplace_back(altCurTableName, altNewTableName);
4981 recordRename(tableSubtituteMap, altNewTableName, altNewTableName);
4982 names.emplace_back(altCurTableName, altNewTableName);
4985 throw std::runtime_error(
"Source table \'" + curTableName +
"\' does not exist.");
4990 catalog.renameTable(names);
4993 while (!tablesToRename_.empty()) {
4994 tablesToRename_.pop_front();
5001 if (cc ==
nullptr) {
5006 std::string default_value;
5007 const std::string* default_value_ptr =
nullptr;
5010 auto defaultsp =
dynamic_cast<const StringLiteral*
>(def_val_literal);
5012 defaultsp ? *defaultsp->
get_stringval() : def_val_literal->to_string();
5017 std::regex array_re(R
"(^ARRAY\s*\[(.*)\]$)", std::regex_constants::icase);
5018 default_value = std::regex_replace(default_value, array_re, "{$1}");
5019 boost::erase_all(default_value,
"\'");
5021 default_value_ptr = &default_value;
5036 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5039 throw std::runtime_error(
"Adding columns to a view is not supported.");
5043 throw std::runtime_error(
5044 "Adding columns to temporary tables is not yet supported.");
5054 for (
const auto& coldef :
coldefs_) {
5055 auto& new_column_name = *coldef->get_column_name();
5056 if (catalog.getMetadataForColumn(td->
tableId, new_column_name) !=
nullptr) {
5057 throw std::runtime_error(
"Column " + new_column_name +
" already exists.");
5063 bool read_only_mode) {
5064 if (read_only_mode) {
5065 throw std::runtime_error(
"ADD COLUMN invalid in read only mode.");
5068 const auto execute_write_lock =
5073 const auto td_with_lock =
5076 const auto td = td_with_lock();
5081 if (std::dynamic_pointer_cast<Fragmenter_Namespace::SortedOrderFragmenter>(
5083 throw std::runtime_error(
5084 "Adding columns to a table is not supported when using the \"sort_column\" "
5089 std::vector<int> table_key{catalog.getCurrentDB().dbId, td->
tableId};
5096 catalog.getSqliteConnector().query(
"BEGIN TRANSACTION");
5098 std::map<const std::string, const ColumnDescriptor> cds;
5099 std::map<const int, const ColumnDef*> cid_coldefs;
5100 for (
const auto& coldef :
coldefs_) {
5103 catalog.addColumn(*td, cd);
5104 cds.emplace(*coldef->get_column_name(), cd);
5105 cid_coldefs.emplace(cd.
columnId, coldef.get());
5109 std::list<ColumnDescriptor> phy_geo_columns;
5110 catalog.expandGeoColumn(cd, phy_geo_columns);
5111 for (
auto& cd : phy_geo_columns) {
5112 catalog.addColumn(*td, cd);
5114 cid_coldefs.emplace(cd.
columnId,
nullptr);
5120 std::vector<std::unique_ptr<import_export::TypedImportBuffer>> import_buffers;
5121 for (
const auto& cd : cds) {
5122 import_buffers.emplace_back(std::make_unique<import_export::TypedImportBuffer>(
5123 &cd.second, loader->getStringDict(&cd.second)));
5125 loader->setAddingColumns(
true);
5129 import_buffers.end(),
5130 [](decltype(import_buffers[0])&
a, decltype(import_buffers[0])& b) {
5131 return a->getColumnDesc()->columnId < b->getColumnDesc()->columnId;
5137 const auto physical_tds = catalog.getPhysicalTablesDescriptors(td);
5139 std::for_each(physical_tds.begin(), physical_tds.end(), [&nrows](
const auto& td) {
5144 int skip_physical_cols = 0;
5145 for (
const auto cit : cid_coldefs) {
5146 const auto cd = catalog.getMetadataForColumn(td->
tableId, cit.first);
5147 const auto coldef = cit.second;
5148 const bool is_null = !cd->default_value.has_value();
5150 if (cd->columnType.get_notnull() &&
is_null) {
5151 throw std::runtime_error(
"Default value required for column " + cd->columnName +
5152 " because of NOT NULL constraint");
5155 for (
auto it = import_buffers.begin(); it < import_buffers.end(); ++it) {
5156 auto& import_buffer = *it;
5157 if (cd->columnId == import_buffer->getColumnDesc()->columnId) {
5158 if (coldef !=
nullptr ||
5159 skip_physical_cols-- <= 0) {
5160 import_buffer->add_value(cd,
5161 cd->default_value.value_or(
"NULL"),
5164 if (cd->columnType.is_geometry()) {
5165 std::vector<double> coords, bounds;
5166 std::vector<int> ring_sizes, poly_rings;
5167 int render_group = 0;
5170 cd->default_value.value_or(
"NULL"),
5177 throw std::runtime_error(
"Bad geometry data: '" +
5178 cd->default_value.value_or(
"NULL") +
"'");
5180 size_t col_idx = 1 + std::distance(import_buffers.begin(), it);
5191 skip_physical_cols = cd->columnType.get_physical_cols();
5200 if (!loader->loadNoCheckpoint(import_buffers, nrows, &session)) {
5201 throw std::runtime_error(
"loadNoCheckpoint failed!");
5204 catalog.resetTableEpochFloor(td->
tableId);
5205 loader->checkpoint();
5206 catalog.getSqliteConnector().query(
"END TRANSACTION");
5208 catalog.roll(
false);
5209 catalog.getSqliteConnector().query(
"ROLLBACK TRANSACTION");
5215 bool read_only_mode) {
5216 if (read_only_mode) {
5217 throw std::runtime_error(
"DROP COLUMN invalid in read only mode.");
5220 const auto execute_write_lock =
5225 const auto td_with_lock =
5228 const auto td = td_with_lock();
5230 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5234 throw std::runtime_error(
"Dropping a column from a view is not supported.");
5237 throw std::runtime_error(
5238 "Dropping a column from a temporary table is not yet supported.");
5243 for (
const auto& column :
columns_) {
5244 if (
nullptr == catalog.getMetadataForColumn(td->
tableId, *column)) {
5245 throw std::runtime_error(
"Column " + *column +
" does not exist.");
5250 throw std::runtime_error(
"Table " + *
table_ +
" has only one column.");
5256 catalog.getSqliteConnector().query(
"BEGIN TRANSACTION");
5258 std::vector<int> columnIds;
5259 for (
const auto& column : columns_) {
5262 throw std::runtime_error(
"Dropping sharding column " + cd.
columnName +
5263 " is not supported.");
5265 catalog.dropColumn(*td, cd);
5268 const auto pcd = catalog.getMetadataForColumn(td->
tableId, cd.
columnId + i + 1);
5270 catalog.dropColumn(*td, *pcd);
5271 columnIds.push_back(cd.
columnId + i + 1);
5275 for (
auto shard : catalog.getPhysicalTablesDescriptors(td)) {
5276 shard->fragmenter->dropColumns(columnIds);
5280 throw std::runtime_error(
"lol!");
5284 catalog.resetTableEpochFloor(td->
tableId);
5285 catalog.checkpoint(td->
tableId);
5287 catalog.getSqliteConnector().query(
"END TRANSACTION");
5289 catalog.setForReload(td->
tableId);
5290 catalog.roll(
false);
5291 catalog.getSqliteConnector().query(
"ROLLBACK TRANSACTION");
5297 bool read_only_mode) {
5298 if (read_only_mode) {
5299 throw std::runtime_error(
"RENAME COLUMN invalid in read only mode.");
5303 const auto execute_read_lock =
5308 const auto td_with_lock =
5310 catalog, *
table_,
false);
5311 const auto td = td_with_lock();
5317 if (cd ==
nullptr) {
5318 throw std::runtime_error(
"Column " + *
column_ +
" does not exist.");
5321 throw std::runtime_error(
"Column " + *
new_column_name_ +
" already exists.");
5327 bool read_only_mode) {
5328 if (read_only_mode) {
5329 throw std::runtime_error(
"ALTER TABLE invalid in read only mode.");
5331 enum TableParamType { MaxRollbackEpochs,
Epoch, MaxRows };
5332 static const std::unordered_map<std::string, TableParamType> param_map = {
5333 {
"max_rollback_epochs", TableParamType::MaxRollbackEpochs},
5334 {
"epoch", TableParamType::Epoch},
5335 {
"max_rows", TableParamType::MaxRows}};
5336 const auto execute_read_lock =
5341 const auto td_with_lock =
5343 catalog, *
table_,
false);
5344 const auto td = td_with_lock();
5346 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5349 throw std::runtime_error(
"Setting parameters for a view is not supported.");
5352 throw std::runtime_error(
5353 "Setting parameters for a temporary table is not yet supported.");
5358 std::vector<int> table_key{catalog.getCurrentDB().dbId, td->
tableId};
5361 std::string param_name(*
param_->get_name());
5365 if (val_int_literal ==
nullptr) {
5366 throw std::runtime_error(
"Table parameters should be integers.");
5368 const int64_t param_val = val_int_literal->
get_intval();
5370 const auto param_it = param_map.find(param_name);
5371 if (param_it == param_map.end()) {
5372 throw std::runtime_error(param_name +
" is not a settable table parameter.");
5374 switch (param_it->second) {
5375 case MaxRollbackEpochs: {
5376 catalog.setMaxRollbackEpochs(td->
tableId, param_val);
5380 catalog.setTableEpoch(catalog.getDatabaseId(), td->
tableId, param_val);
5384 catalog.setMaxRows(td->
tableId, param_val);
5388 UNREACHABLE() <<
"Unexpected TableParamType value: " << param_it->second
5389 <<
", key: " << param_it->first;
5396 std::list<NameValueAssign*>* o)
5397 : table_(t), copy_from_source_pattern_(f), success_(
true) {
5399 for (
const auto e : *o) {