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>
74 #include "gen-cpp/CalciteServer.h"
82 #ifdef ENABLE_IMPORT_PARQUET
83 bool g_enable_legacy_parquet_import{
false};
90 using namespace std::string_literals;
94 const std::list<ColumnDescriptor>& columns)>;
99 const std::list<ColumnDescriptor>& columns)>;
108 executor->getSessionLock());
109 return executor->checkIsQuerySessionInterrupted(query_session, session_read_lock);
116 std::vector<int> table_chunk_key_prefix;
119 table_chunk_key_prefix = td->
fragmenter->getFragmentsForQuery().chunkKeyPrefix;
122 table_chunk_key_prefix.push_back(td->
tableId);
125 return table_chunk_key_prefix;
128 std::shared_ptr<Analyzer::Expr> NullLiteral::analyze(
132 return makeExpr<Analyzer::Constant>(
kNULLT,
true);
135 std::shared_ptr<Analyzer::Expr> StringLiteral::analyze(
139 return analyzeValue(*stringval_,
false);
142 std::shared_ptr<Analyzer::Expr> StringLiteral::analyzeValue(
const std::string& stringval,
147 d.
stringval =
new std::string(stringval);
148 return makeExpr<Analyzer::Constant>(ti,
false, d);
151 return makeExpr<Analyzer::Constant>(
kVARCHAR,
true);
154 std::shared_ptr<Analyzer::Expr> IntLiteral::analyze(
158 return analyzeValue(intval_);
161 std::shared_ptr<Analyzer::Expr> IntLiteral::analyzeValue(
const int64_t intval) {
164 if (intval >= INT16_MIN && intval <= INT16_MAX) {
167 }
else if (intval >= INT32_MIN && intval <= INT32_MAX) {
169 d.
intval = (int32_t)intval;
174 return makeExpr<Analyzer::Constant>(t,
false, d);
177 std::shared_ptr<Analyzer::Expr> FixedPtLiteral::analyze(
183 return makeExpr<Analyzer::Constant>(ti,
false, d);
186 std::shared_ptr<Analyzer::Expr> FixedPtLiteral::analyzeValue(
const int64_t numericval,
188 const int precision) {
194 return makeExpr<Analyzer::Constant>(ti,
false, d);
197 std::shared_ptr<Analyzer::Expr> FloatLiteral::analyze(
203 return makeExpr<Analyzer::Constant>(
kFLOAT,
false, d);
206 std::shared_ptr<Analyzer::Expr> DoubleLiteral::analyze(
212 return makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
215 std::shared_ptr<Analyzer::Expr> TimestampLiteral::analyze(
219 return get(timestampval_);
222 std::shared_ptr<Analyzer::Expr> TimestampLiteral::get(
const int64_t timestampval) {
225 return makeExpr<Analyzer::Constant>(
kTIMESTAMP,
false, d);
228 std::shared_ptr<Analyzer::Expr> UserLiteral::analyze(
233 return makeExpr<Analyzer::Constant>(
kTEXT,
false, d);
236 std::shared_ptr<Analyzer::Expr> UserLiteral::get(
const std::string& user) {
239 return makeExpr<Analyzer::Constant>(
kTEXT,
false, d);
242 std::shared_ptr<Analyzer::Expr> ArrayLiteral::analyze(
247 bool set_subtype =
true;
248 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
249 for (
auto& p : value_list_) {
250 auto e = p->analyze(catalog, query, allow_tlist_ref);
253 if (c !=
nullptr && c->get_is_null()) {
254 value_exprs.push_back(c);
260 }
else if (set_subtype) {
264 value_exprs.push_back(e);
266 std::shared_ptr<Analyzer::Expr>
result =
267 makeExpr<Analyzer::Constant>(ti,
false, value_exprs);
272 std::string str =
"{";
273 bool notfirst =
false;
274 for (
auto& p : value_list_) {
280 str += p->to_string();
286 std::shared_ptr<Analyzer::Expr> OperExpr::analyze(
290 auto left_expr = left_->analyze(catalog, query, allow_tlist_ref);
291 const auto& left_type = left_expr->get_type_info();
292 if (right_ ==
nullptr) {
293 return makeExpr<Analyzer::UOper>(
294 left_type, left_expr->get_contains_agg(), optype_, left_expr->decompress());
297 if (left_type.get_type() !=
kARRAY) {
298 throw std::runtime_error(left_->to_string() +
" is not of array type.");
300 auto right_expr = right_->analyze(catalog, query, allow_tlist_ref);
301 const auto& right_type = right_expr->get_type_info();
302 if (!right_type.is_integer()) {
303 throw std::runtime_error(right_->to_string() +
" is not of integer type.");
305 return makeExpr<Analyzer::BinOper>(
306 left_type.get_elem_type(),
false,
kARRAY_AT,
kONE, left_expr, right_expr);
308 auto right_expr = right_->analyze(catalog, query, allow_tlist_ref);
309 return normalize(optype_, opqualifier_, left_expr, right_expr);
313 const std::shared_ptr<Analyzer::Expr>& rhs_expr) {
314 std::set<int> lhs_rte_idx;
315 lhs_expr->collect_rte_idx(lhs_rte_idx);
316 CHECK(!lhs_rte_idx.empty());
317 std::set<int> rhs_rte_idx;
318 rhs_expr->collect_rte_idx(rhs_rte_idx);
319 CHECK(!rhs_rte_idx.empty());
320 return lhs_rte_idx.size() == 1UL && lhs_rte_idx == rhs_rte_idx;
325 const Executor* executor) {
332 CHECK_NE(lhs_comp_param, rhs_comp_param);
334 return rhs_type_info;
337 return lhs_type_info;
341 const auto lhs_sdp = executor->getStringDictionaryProxy(lhs_comp_param,
true);
342 const auto rhs_sdp = executor->getStringDictionaryProxy(rhs_comp_param,
true);
343 return lhs_sdp->entryCount() >= rhs_sdp->entryCount() ? lhs_type_info : rhs_type_info;
348 const Executor* executor) {
354 if (lhs_comp_param == rhs_comp_param ||
356 return lhs_comp_param <= rhs_comp_param ? lhs_type_info : rhs_type_info;
363 if (ret_ti.is_none_encoded_string()) {
370 std::shared_ptr<Analyzer::Expr> OperExpr::normalize(
373 std::shared_ptr<Analyzer::Expr> left_expr,
374 std::shared_ptr<Analyzer::Expr> right_expr,
375 const Executor* executor) {
376 if (left_expr->get_type_info().is_date_in_days() ||
377 right_expr->get_type_info().is_date_in_days()) {
379 left_expr = left_expr->decompress();
380 right_expr = right_expr->decompress();
382 const auto& left_type = left_expr->get_type_info();
383 auto right_type = right_expr->get_type_info();
386 CHECK(!std::dynamic_pointer_cast<Analyzer::Subquery>(right_expr));
387 if (right_type.get_type() !=
kARRAY) {
388 throw std::runtime_error(
389 "Existential or universal qualifiers can only be used in front of a subquery "
391 "expression of array type.");
393 right_type = right_type.get_elem_type();
398 optype, left_type, right_type, &new_left_type, &new_right_type);
399 if (result_type.is_timeinterval()) {
400 return makeExpr<Analyzer::BinOper>(
401 result_type,
false, optype, qual, left_expr, right_expr);
403 if (left_type != new_left_type) {
404 left_expr = left_expr->add_cast(new_left_type);
406 if (right_type != new_right_type) {
408 right_expr = right_expr->add_cast(new_right_type);
410 right_expr = right_expr->add_cast(new_right_type.
get_array_type());
417 throw std::runtime_error(
418 "Comparison operators are not yet supported for geospatial types.");
424 if (optype ==
kEQ || optype ==
kNE) {
430 const bool should_translate_strings =
432 if (should_translate_strings && (optype ==
kEQ || optype ==
kNE)) {
438 auto& expr_to_cast = ti == new_left_type ? right_expr : left_expr;
441 expr_to_cast = expr_to_cast->add_cast(ti);
446 left_expr = left_expr->decompress();
447 right_expr = right_expr->decompress();
453 left_expr = left_expr->decompress();
454 right_expr = right_expr->decompress();
457 if (!(optype ==
kEQ || optype ==
kNE)) {
460 left_expr = left_expr->decompress();
461 right_expr = right_expr->decompress();
474 right_expr = right_expr->add_cast(ti);
481 left_expr = left_expr->add_cast(ti);
483 left_expr = left_expr->decompress();
484 right_expr = right_expr->decompress();
488 left_expr = left_expr->decompress();
489 right_expr = right_expr->decompress();
491 bool has_agg = (left_expr->get_contains_agg() || right_expr->get_contains_agg());
492 return makeExpr<Analyzer::BinOper>(
493 result_type, has_agg, optype, qual, left_expr, right_expr);
496 std::shared_ptr<Analyzer::Expr> SubqueryExpr::analyze(
500 throw std::runtime_error(
"Subqueries are not supported yet.");
504 std::shared_ptr<Analyzer::Expr> IsNullExpr::analyze(
508 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
516 std::shared_ptr<Analyzer::Expr> InSubquery::analyze(
520 throw std::runtime_error(
"Subqueries are not supported yet.");
524 std::shared_ptr<Analyzer::Expr> InValues::analyze(
528 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
531 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
532 for (
auto& p : value_list_) {
533 auto e = p->analyze(catalog, query, allow_tlist_ref);
534 if (ti != e->get_type_info()) {
535 if (ti.
is_string() && e->get_type_info().is_string()) {
538 }
else if (ti.
is_number() && e->get_type_info().is_number()) {
541 throw std::runtime_error(
"IN expressions must contain compatible types.");
545 value_exprs.push_back(e->add_cast(arg_expr->get_type_info()));
547 value_exprs.push_back(e);
551 arg_expr = arg_expr->decompress();
552 arg_expr = arg_expr->add_cast(ti);
553 std::list<std::shared_ptr<Analyzer::Expr>> cast_vals;
554 for (
auto p : value_exprs) {
555 cast_vals.push_back(p->add_cast(ti));
557 value_exprs.swap(cast_vals);
559 std::shared_ptr<Analyzer::Expr>
result =
560 makeExpr<Analyzer::InValues>(arg_expr, value_exprs);
567 std::shared_ptr<Analyzer::Expr> BetweenExpr::analyze(
571 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
572 auto lower_expr = lower_->analyze(catalog, query, allow_tlist_ref);
573 auto upper_expr = upper_->analyze(catalog, query, allow_tlist_ref);
576 arg_expr->get_type_info(),
577 lower_expr->get_type_info(),
581 makeExpr<Analyzer::BinOper>(
kBOOLEAN,
584 arg_expr->add_cast(new_left_type)->decompress(),
585 lower_expr->add_cast(new_right_type)->decompress());
587 arg_expr->get_type_info(),
588 lower_expr->get_type_info(),
591 auto upper_pred = makeExpr<Analyzer::BinOper>(
595 arg_expr->deep_copy()->add_cast(new_left_type)->decompress(),
596 upper_expr->add_cast(new_right_type)->decompress());
597 std::shared_ptr<Analyzer::Expr>
result =
605 std::shared_ptr<Analyzer::Expr> CharLengthExpr::analyze(
609 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
610 if (!arg_expr->get_type_info().is_string()) {
611 throw std::runtime_error(
612 "expression in char_length clause must be of a string type.");
614 std::shared_ptr<Analyzer::Expr>
result =
615 makeExpr<Analyzer::CharLengthExpr>(arg_expr->decompress(), calc_encoded_length_);
619 std::shared_ptr<Analyzer::Expr> CardinalityExpr::analyze(
623 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
624 if (!arg_expr->get_type_info().is_array()) {
625 throw std::runtime_error(
626 "expression in cardinality clause must be of an array type.");
628 std::shared_ptr<Analyzer::Expr>
result =
629 makeExpr<Analyzer::CardinalityExpr>(arg_expr->decompress());
633 void LikeExpr::check_like_expr(
const std::string& like_str,
char escape_char) {
634 if (like_str.back() == escape_char) {
635 throw std::runtime_error(
"LIKE pattern must not end with escape character.");
639 bool LikeExpr::test_is_simple_expr(
const std::string& like_str,
char escape_char) {
641 if (like_str.size() < 2 || like_str[0] !=
'%' || like_str[like_str.size() - 1] !=
'%') {
645 if (like_str[like_str.size() - 2] == escape_char &&
646 like_str[like_str.size() - 3] != escape_char) {
649 for (
size_t i = 1; i < like_str.size() - 1; i++) {
650 if (like_str[i] ==
'%' || like_str[i] ==
'_' || like_str[i] ==
'[' ||
651 like_str[i] ==
']') {
652 if (like_str[i - 1] != escape_char) {
660 void LikeExpr::erase_cntl_chars(std::string& like_str,
char escape_char) {
661 char prev_char =
'\0';
666 for (
char& cur_char : like_str) {
667 if (cur_char ==
'%' || cur_char == escape_char) {
668 if (prev_char != escape_char) {
669 prev_char = cur_char;
673 new_str.push_back(cur_char);
674 prev_char = cur_char;
679 std::shared_ptr<Analyzer::Expr> LikeExpr::analyze(
683 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
684 auto like_expr = like_string_->analyze(catalog, query, allow_tlist_ref);
685 auto escape_expr = escape_string_ ==
nullptr
687 : escape_string_->analyze(catalog, query, allow_tlist_ref);
688 return LikeExpr::get(arg_expr, like_expr, escape_expr, is_ilike_, is_not_);
691 std::shared_ptr<Analyzer::Expr> LikeExpr::get(std::shared_ptr<Analyzer::Expr> arg_expr,
692 std::shared_ptr<Analyzer::Expr> like_expr,
693 std::shared_ptr<Analyzer::Expr> escape_expr,
696 if (!arg_expr->get_type_info().is_string()) {
697 throw std::runtime_error(
"expression before LIKE must be of a string type.");
699 if (!like_expr->get_type_info().is_string()) {
700 throw std::runtime_error(
"expression after LIKE must be of a string type.");
702 char escape_char =
'\\';
703 if (escape_expr !=
nullptr) {
704 if (!escape_expr->get_type_info().is_string()) {
705 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
707 if (!escape_expr->get_type_info().is_string()) {
708 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
711 if (c !=
nullptr && c->get_constval().stringval->length() > 1) {
712 throw std::runtime_error(
"String after ESCAPE must have a single character.");
714 escape_char = (*c->get_constval().stringval)[0];
717 bool is_simple =
false;
721 std::transform(pattern.begin(), pattern.end(), pattern.begin(), ::tolower);
723 check_like_expr(pattern, escape_char);
724 is_simple = test_is_simple_expr(pattern, escape_char);
726 erase_cntl_chars(pattern, escape_char);
729 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::LikeExpr>(
730 arg_expr->decompress(), like_expr, escape_expr, is_ilike, is_simple);
737 void RegexpExpr::check_pattern_expr(
const std::string& pattern_str,
char escape_char) {
738 if (pattern_str.back() == escape_char) {
739 throw std::runtime_error(
"REGEXP pattern must not end with escape character.");
743 bool RegexpExpr::translate_to_like_pattern(std::string& pattern_str,
char escape_char) {
744 char prev_char =
'\0';
745 char prev_prev_char =
'\0';
746 std::string like_str;
747 for (
char& cur_char : pattern_str) {
748 if (prev_char == escape_char || isalnum(cur_char) || cur_char ==
' ' ||
750 like_str.push_back((cur_char ==
'.') ?
'_' : cur_char);
751 prev_prev_char = prev_char;
752 prev_char = cur_char;
755 if (prev_char ==
'.' && prev_prev_char != escape_char) {
756 if (cur_char ==
'*' || cur_char ==
'+') {
757 if (cur_char ==
'*') {
762 like_str.push_back(
'%');
763 prev_prev_char = prev_char;
764 prev_char = cur_char;
770 pattern_str = like_str;
774 std::shared_ptr<Analyzer::Expr> RegexpExpr::analyze(
778 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
779 auto pattern_expr = pattern_string_->analyze(catalog, query, allow_tlist_ref);
780 auto escape_expr = escape_string_ ==
nullptr
782 : escape_string_->analyze(catalog, query, allow_tlist_ref);
783 return RegexpExpr::get(arg_expr, pattern_expr, escape_expr, is_not_);
786 std::shared_ptr<Analyzer::Expr> RegexpExpr::get(
787 std::shared_ptr<Analyzer::Expr> arg_expr,
788 std::shared_ptr<Analyzer::Expr> pattern_expr,
789 std::shared_ptr<Analyzer::Expr> escape_expr,
791 if (!arg_expr->get_type_info().is_string()) {
792 throw std::runtime_error(
"expression before REGEXP must be of a string type.");
794 if (!pattern_expr->get_type_info().is_string()) {
795 throw std::runtime_error(
"expression after REGEXP must be of a string type.");
797 char escape_char =
'\\';
798 if (escape_expr !=
nullptr) {
799 if (!escape_expr->get_type_info().is_string()) {
800 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
802 if (!escape_expr->get_type_info().is_string()) {
803 throw std::runtime_error(
"expression after ESCAPE must be of a string type.");
806 if (c !=
nullptr && c->get_constval().stringval->length() > 1) {
807 throw std::runtime_error(
"String after ESCAPE must have a single character.");
809 escape_char = (*c->get_constval().stringval)[0];
810 if (escape_char !=
'\\') {
811 throw std::runtime_error(
"Only supporting '\\' escape character.");
817 if (translate_to_like_pattern(pattern, escape_char)) {
818 return LikeExpr::get(arg_expr, pattern_expr, escape_expr,
false, is_not);
821 std::shared_ptr<Analyzer::Expr>
result =
822 makeExpr<Analyzer::RegexpExpr>(arg_expr->decompress(), pattern_expr, escape_expr);
829 std::shared_ptr<Analyzer::Expr> LikelihoodExpr::analyze(
833 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
834 return LikelihoodExpr::get(arg_expr, likelihood_, is_not_);
837 std::shared_ptr<Analyzer::Expr> LikelihoodExpr::get(
838 std::shared_ptr<Analyzer::Expr> arg_expr,
841 if (!arg_expr->get_type_info().is_boolean()) {
842 throw std::runtime_error(
"likelihood expression expects boolean type.");
844 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::LikelihoodExpr>(
845 arg_expr->decompress(), is_not ? 1 - likelihood : likelihood);
849 std::shared_ptr<Analyzer::Expr> WidthBucketExpr::analyze(
853 auto target_value = target_value_->analyze(catalog, query, allow_tlist_ref);
854 auto lower_bound = lower_bound_->analyze(catalog, query, allow_tlist_ref);
855 auto upper_bound = upper_bound_->analyze(catalog, query, allow_tlist_ref);
856 auto partition_count = partition_count_->analyze(catalog, query, allow_tlist_ref);
860 std::shared_ptr<Analyzer::Expr> WidthBucketExpr::get(
861 std::shared_ptr<Analyzer::Expr> target_value,
864 std::shared_ptr<Analyzer::Expr> partition_count) {
865 std::shared_ptr<Analyzer::Expr>
result = makeExpr<Analyzer::WidthBucketExpr>(
870 std::shared_ptr<Analyzer::Expr> ExistsExpr::analyze(
874 throw std::runtime_error(
"Subqueries are not supported yet.");
878 std::shared_ptr<Analyzer::Expr> ColumnRef::analyze(
885 if (column_ ==
nullptr) {
886 throw std::runtime_error(
"invalid column name *.");
888 if (table_ !=
nullptr) {
891 throw std::runtime_error(
"range variable or table name " + *table_ +
897 throw std::runtime_error(
"Column name " + *column_ +
" does not exist.");
904 cd = rte->get_column_desc(catalog, *column_);
905 if (cd !=
nullptr && !found) {
908 table_id = rte->get_table_id();
909 }
else if (cd !=
nullptr && found) {
910 throw std::runtime_error(
"Column name " + *column_ +
" is ambiguous.");
914 if (cd ==
nullptr && allow_tlist_ref != TlistRefType::TLIST_NONE) {
919 std::shared_ptr<Analyzer::TargetEntry> tle;
921 if (*column_ == p->get_resname() && !found) {
925 }
else if (*column_ == p->get_resname() && found) {
926 throw std::runtime_error(
"Output alias " + *column_ +
" is ambiguous.");
931 if (dynamic_cast<Analyzer::Var*>(tle->get_expr())) {
937 if (allow_tlist_ref == TlistRefType::TLIST_COPY) {
938 return tle->get_expr()->deep_copy();
940 return makeExpr<Analyzer::Var>(
946 throw std::runtime_error(
"Column name " + *column_ +
" does not exist.");
949 return makeExpr<Analyzer::ColumnVar>(cd->columnType, table_id, cd->columnId, rte_idx);
952 std::shared_ptr<Analyzer::Expr> FunctionRef::analyze(
958 std::shared_ptr<Analyzer::Expr> arg_expr;
960 if (boost::iequals(*name_,
"count")) {
964 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
967 throw std::runtime_error(
968 "Strings must be dictionary-encoded in COUNT(DISTINCT).");
971 throw std::runtime_error(
"Only COUNT(DISTINCT) is supported on arrays.");
974 is_distinct = distinct_;
977 throw std::runtime_error(
"Cannot compute " + *name_ +
" with argument '*'.");
979 if (boost::iequals(*name_,
"min")) {
981 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
982 arg_expr = arg_expr->decompress();
983 result_type = arg_expr->get_type_info();
984 }
else if (boost::iequals(*name_,
"max")) {
986 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
987 arg_expr = arg_expr->decompress();
988 result_type = arg_expr->get_type_info();
989 }
else if (boost::iequals(*name_,
"avg")) {
991 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
992 if (!arg_expr->get_type_info().is_number()) {
993 throw std::runtime_error(
"Cannot compute AVG on non-number-type arguments.");
995 arg_expr = arg_expr->decompress();
997 }
else if (boost::iequals(*name_,
"sum")) {
999 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1000 if (!arg_expr->get_type_info().is_number()) {
1001 throw std::runtime_error(
"Cannot compute SUM on non-number-type arguments.");
1003 arg_expr = arg_expr->decompress();
1005 : arg_expr->get_type_info();
1006 }
else if (boost::iequals(*name_,
"unnest")) {
1007 arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1008 const SQLTypeInfo& arg_ti = arg_expr->get_type_info();
1010 throw std::runtime_error(arg_->to_string() +
" is not of array type.");
1014 throw std::runtime_error(
"invalid function name: " + *name_);
1016 if (arg_expr->get_type_info().is_string() ||
1017 arg_expr->get_type_info().get_type() ==
kARRAY) {
1018 throw std::runtime_error(
1019 "Only COUNT(DISTINCT ) aggregate is supported on strings and arrays.");
1024 return makeExpr<Analyzer::AggExpr>(
1025 result_type, agg_type, arg_expr,
is_distinct,
nullptr);
1028 std::shared_ptr<Analyzer::Expr> CastExpr::analyze(
1032 target_type_->check_type();
1033 auto arg_expr = arg_->analyze(catalog, query, allow_tlist_ref);
1035 target_type_->get_param1(),
1036 target_type_->get_param2(),
1037 arg_expr->get_type_info().get_notnull());
1038 if (arg_expr->get_type_info().get_type() != target_type_->get_type() &&
1040 arg_expr->decompress();
1042 return arg_expr->add_cast(ti);
1045 std::shared_ptr<Analyzer::Expr> CaseExpr::analyze(
1050 std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1052 for (
auto& p : when_then_list_) {
1053 auto e1 = p->get_expr1()->analyze(catalog, query, allow_tlist_ref);
1054 if (e1->get_type_info().get_type() !=
kBOOLEAN) {
1055 throw std::runtime_error(
"Only boolean expressions can be used after WHEN.");
1057 auto e2 = p->get_expr2()->analyze(catalog, query, allow_tlist_ref);
1058 expr_pair_list.emplace_back(e1, e2);
1061 else_expr_ ? else_expr_->analyze(catalog, query, allow_tlist_ref) :
nullptr;
1062 return normalize(expr_pair_list, else_e);
1069 if (*s ==
"t" || *s ==
"true" || *s ==
"T" || *s ==
"True") {
1071 }
else if (*s ==
"f" || *s ==
"false" || *s ==
"F" || *s ==
"False") {
1074 throw std::runtime_error(
"Invalid string for boolean " + *s);
1080 std::vector<std::string>& warnings,
1081 std::string& deferred_copy_from_partitions_) {
1082 if (!options_.empty()) {
1083 for (
auto& p : options_) {
1084 if (boost::iequals(*p->get_name(),
"max_reject")) {
1086 if (int_literal ==
nullptr) {
1087 throw std::runtime_error(
"max_reject option must be an integer.");
1090 }
else if (boost::iequals(*p->get_name(),
"buffer_size")) {
1092 if (int_literal ==
nullptr) {
1093 throw std::runtime_error(
"buffer_size option must be an integer.");
1096 }
else if (boost::iequals(*p->get_name(),
"threads")) {
1098 if (int_literal ==
nullptr) {
1099 throw std::runtime_error(
"Threads option must be an integer.");
1102 }
else if (boost::iequals(*p->get_name(),
"delimiter")) {
1105 if (str_literal ==
nullptr) {
1106 throw std::runtime_error(
"Delimiter option must be a string.");
1108 throw std::runtime_error(
"Delimiter must be a single character string.");
1111 }
else if (boost::iequals(*p->get_name(),
"nulls")) {
1114 if (str_literal ==
nullptr) {
1115 throw std::runtime_error(
"Nulls option must be a string.");
1118 }
else if (boost::iequals(*p->get_name(),
"header")) {
1121 if (str_literal ==
nullptr) {
1122 throw std::runtime_error(
"Header option must be a boolean.");
1127 #ifdef ENABLE_IMPORT_PARQUET
1128 }
else if (boost::iequals(*p->get_name(),
"parquet")) {
1130 "Deprecation Warning: COPY FROM WITH (parquet='true') is deprecated. Use "
1131 "WITH (source_type='parquet_file') instead.");
1134 if (str_literal ==
nullptr) {
1135 throw std::runtime_error(
"'parquet' option must be a boolean.");
1142 #endif // ENABLE_IMPORT_PARQUET
1143 }
else if (boost::iequals(*p->get_name(),
"s3_access_key")) {
1146 if (str_literal ==
nullptr) {
1147 throw std::runtime_error(
"Option s3_access_key must be a string.");
1150 }
else if (boost::iequals(*p->get_name(),
"s3_secret_key")) {
1153 if (str_literal ==
nullptr) {
1154 throw std::runtime_error(
"Option s3_secret_key must be a string.");
1157 }
else if (boost::iequals(*p->get_name(),
"s3_session_token")) {
1160 if (str_literal ==
nullptr) {
1161 throw std::runtime_error(
"Option s3_session_token must be a string.");
1164 }
else if (boost::iequals(*p->get_name(),
"s3_region")) {
1167 if (str_literal ==
nullptr) {
1168 throw std::runtime_error(
"Option s3_region must be a string.");
1171 }
else if (boost::iequals(*p->get_name(),
"s3_endpoint")) {
1174 if (str_literal ==
nullptr) {
1175 throw std::runtime_error(
"Option s3_endpoint must be a string.");
1178 }
else if (boost::iequals(*p->get_name(),
"s3_max_concurrent_downloads")) {
1180 if (int_literal ==
nullptr) {
1181 throw std::runtime_error(
1182 "'s3_max_concurrent_downloads' option must be an integer");
1184 const int s3_max_concurrent_downloads = int_literal->
get_intval();
1185 if (s3_max_concurrent_downloads > 0) {
1188 throw std::runtime_error(
1189 "Invalid value for 's3_max_concurrent_downloads' option (must be > 0): " +
1192 }
else if (boost::iequals(*p->get_name(),
"quote")) {
1195 if (str_literal ==
nullptr) {
1196 throw std::runtime_error(
"Quote option must be a string.");
1198 throw std::runtime_error(
"Quote must be a single character string.");
1201 }
else if (boost::iequals(*p->get_name(),
"escape")) {
1204 if (str_literal ==
nullptr) {
1205 throw std::runtime_error(
"Escape option must be a string.");
1207 throw std::runtime_error(
"Escape must be a single character string.");
1210 }
else if (boost::iequals(*p->get_name(),
"line_delimiter")) {
1213 if (str_literal ==
nullptr) {
1214 throw std::runtime_error(
"Line_delimiter option must be a string.");
1216 throw std::runtime_error(
"Line_delimiter must be a single character string.");
1219 }
else if (boost::iequals(*p->get_name(),
"quoted")) {
1222 if (str_literal ==
nullptr) {
1223 throw std::runtime_error(
"Quoted option must be a boolean.");
1226 }
else if (boost::iequals(*p->get_name(),
"plain_text")) {
1229 if (str_literal ==
nullptr) {
1230 throw std::runtime_error(
"plain_text option must be a boolean.");
1233 }
else if (boost::iequals(*p->get_name(),
"trim_spaces")) {
1236 if (str_literal ==
nullptr) {
1237 throw std::runtime_error(
"trim_spaces option must be a boolean.");
1240 }
else if (boost::iequals(*p->get_name(),
"array_marker")) {
1243 if (str_literal ==
nullptr) {
1244 throw std::runtime_error(
"Array Marker option must be a string.");
1246 throw std::runtime_error(
1247 "Array Marker option must be exactly two characters. Default is {}.");
1251 }
else if (boost::iequals(*p->get_name(),
"array_delimiter")) {
1254 if (str_literal ==
nullptr) {
1255 throw std::runtime_error(
"Array Delimiter option must be a string.");
1257 throw std::runtime_error(
"Array Delimiter must be a single character string.");
1260 }
else if (boost::iequals(*p->get_name(),
"lonlat")) {
1263 if (str_literal ==
nullptr) {
1264 throw std::runtime_error(
"Lonlat option must be a boolean.");
1267 }
else if (boost::iequals(*p->get_name(),
"geo")) {
1269 "Deprecation Warning: COPY FROM WITH (geo='true') is deprecated. Use WITH "
1270 "(source_type='geo_file') instead.");
1273 if (str_literal ==
nullptr) {
1274 throw std::runtime_error(
"'geo' option must be a boolean.");
1279 }
else if (boost::iequals(*p->get_name(),
"source_type")) {
1282 if (str_literal ==
nullptr) {
1283 throw std::runtime_error(
"'source_type' option must be a string.");
1286 if (boost::iequals(*s,
"delimited_file")) {
1288 }
else if (boost::iequals(*s,
"geo_file")) {
1290 #if ENABLE_IMPORT_PARQUET
1291 }
else if (boost::iequals(*s,
"parquet_file")) {
1294 }
else if (boost::iequals(*s,
"raster_file")) {
1296 }
else if (boost::iequals(*s,
"regex_parsed_file")) {
1299 throw std::runtime_error(
1300 "Invalid string for 'source_type' option (must be 'GEO_FILE', 'RASTER_FILE'"
1301 #
if ENABLE_IMPORT_PARQUET
1304 ", 'REGEX_PARSED_FILE'"
1305 " or 'DELIMITED_FILE'): " +
1308 }
else if (boost::iequals(*p->get_name(),
"geo_coords_type")) {
1311 if (str_literal ==
nullptr) {
1312 throw std::runtime_error(
"'geo_coords_type' option must be a string");
1315 if (boost::iequals(*s,
"geography")) {
1316 throw std::runtime_error(
1317 "GEOGRAPHY coords type not yet supported. Please use GEOMETRY.");
1319 }
else if (boost::iequals(*s,
"geometry")) {
1322 throw std::runtime_error(
1323 "Invalid string for 'geo_coords_type' option (must be 'GEOGRAPHY' or "
1327 }
else if (boost::iequals(*p->get_name(),
"raster_point_type")) {
1330 if (str_literal ==
nullptr) {
1331 throw std::runtime_error(
"'raster_point_type' option must be a string");
1334 if (boost::iequals(*s,
"none")) {
1336 }
else if (boost::iequals(*s,
"auto")) {
1338 }
else if (boost::iequals(*s,
"smallint")) {
1340 }
else if (boost::iequals(*s,
"int")) {
1342 }
else if (boost::iequals(*s,
"float")) {
1344 }
else if (boost::iequals(*s,
"double")) {
1346 }
else if (boost::iequals(*s,
"point")) {
1349 throw std::runtime_error(
1350 "Invalid string for 'raster_point_type' option (must be 'NONE', 'AUTO', "
1351 "'SMALLINT', 'INT', 'FLOAT', 'DOUBLE' or 'POINT'): " +
1354 }
else if (boost::iequals(*p->get_name(),
"raster_point_transform")) {
1357 if (str_literal ==
nullptr) {
1358 throw std::runtime_error(
"'raster_point_transform' option must be a string");
1361 if (boost::iequals(*s,
"none")) {
1363 }
else if (boost::iequals(*s,
"auto")) {
1365 }
else if (boost::iequals(*s,
"file")) {
1367 }
else if (boost::iequals(*s,
"world")) {
1371 throw std::runtime_error(
1372 "Invalid string for 'raster_point_transform' option (must be 'NONE', "
1373 "'AUTO', 'FILE' or 'WORLD'): " +
1376 }
else if (boost::iequals(*p->get_name(),
"raster_import_bands")) {
1379 if (str_literal ==
nullptr) {
1380 throw std::runtime_error(
"'raster_import_bands' option must be a string");
1382 const std::string* raster_import_bands = str_literal->
get_stringval();
1383 if (raster_import_bands) {
1386 throw std::runtime_error(
"Invalid value for 'raster_import_bands' option");
1388 }
else if (boost::iequals(*p->get_name(),
"raster_import_dimensions")) {
1391 if (str_literal ==
nullptr) {
1392 throw std::runtime_error(
"'raster_import_dimensions' option must be a string");
1394 const std::string* raster_import_dimensions = str_literal->
get_stringval();
1395 if (raster_import_dimensions) {
1398 throw std::runtime_error(
"Invalid value for 'raster_import_dimensions' option");
1400 }
else if (boost::iequals(*p->get_name(),
"geo_coords_encoding")) {
1403 if (str_literal ==
nullptr) {
1404 throw std::runtime_error(
"'geo_coords_encoding' option must be a string");
1407 if (boost::iequals(*s,
"none")) {
1410 }
else if (boost::iequals(*s,
"compressed(32)")) {
1414 throw std::runtime_error(
1415 "Invalid string for 'geo_coords_encoding' option (must be 'NONE' or "
1416 "'COMPRESSED(32)'): " +
1419 }
else if (boost::iequals(*p->get_name(),
"raster_scanlines_per_thread")) {
1421 if (int_literal ==
nullptr) {
1422 throw std::runtime_error(
1423 "'raster_scanlines_per_thread' option must be an integer");
1425 const int raster_scanlines_per_thread = int_literal->
get_intval();
1426 if (raster_scanlines_per_thread < 0) {
1427 throw std::runtime_error(
1428 "'raster_scanlines_per_thread' option must be >= 0, with 0 denoting auto "
1432 }
else if (boost::iequals(*p->get_name(),
"geo_coords_srid")) {
1434 if (int_literal ==
nullptr) {
1435 throw std::runtime_error(
"'geo_coords_srid' option must be an integer");
1438 if (srid == 4326 || srid == 3857 || srid == 900913) {
1441 throw std::runtime_error(
1442 "Invalid value for 'geo_coords_srid' option (must be 4326, 3857, or "
1446 }
else if (boost::iequals(*p->get_name(),
"geo_layer_name")) {
1449 if (str_literal ==
nullptr) {
1450 throw std::runtime_error(
"'geo_layer_name' option must be a string");
1452 const std::string* layer_name = str_literal->
get_stringval();
1456 throw std::runtime_error(
"Invalid value for 'geo_layer_name' option");
1458 }
else if (boost::iequals(*p->get_name(),
"partitions")) {
1459 const auto partitions =
1460 static_cast<const StringLiteral*
>(p->get_value())->get_stringval();
1462 const auto partitions_uc = boost::to_upper_copy<std::string>(*partitions);
1463 if (partitions_uc !=
"REPLICATED") {
1464 throw std::runtime_error(
1465 "Invalid value for 'partitions' option. Must be 'REPLICATED'.");
1467 deferred_copy_from_partitions_ = partitions_uc;
1468 }
else if (boost::iequals(*p->get_name(),
"geo_assign_render_groups")) {
1471 if (str_literal ==
nullptr) {
1472 throw std::runtime_error(
"geo_assign_render_groups option must be a boolean.");
1475 }
else if (boost::iequals(*p->get_name(),
"geo_explode_collections")) {
1478 if (str_literal ==
nullptr) {
1479 throw std::runtime_error(
"geo_explode_collections option must be a boolean.");
1482 }
else if (boost::iequals(*p->get_name(),
"source_srid")) {
1484 if (int_literal ==
nullptr) {
1485 throw std::runtime_error(
"'source_srid' option must be an integer");
1491 throw std::runtime_error(
1492 "'source_srid' option can only be used on csv/tsv files");
1494 }
else if (boost::iequals(*p->get_name(),
"regex_path_filter")) {
1497 if (str_literal ==
nullptr) {
1498 throw std::runtime_error(
"Option regex_path_filter must be a string.");
1502 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1503 }
else if (boost::iequals(*p->get_name(),
"file_sort_order_by")) {
1506 if (str_literal ==
nullptr) {
1507 throw std::runtime_error(
"Option file_sort_order_by must be a string.");
1511 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1512 }
else if (boost::iequals(*p->get_name(),
"file_sort_regex")) {
1515 if (str_literal ==
nullptr) {
1516 throw std::runtime_error(
"Option file_sort_regex must be a string.");
1520 string_val.empty() ? std::nullopt : std::optional<std::string>{string_val};
1521 }
else if (boost::iequals(*p->get_name(),
"raster_point_compute_angle")) {
1524 if (str_literal ==
nullptr) {
1525 throw std::runtime_error(
1526 "'raster_point_compute_angle' option must be a boolean.");
1531 }
else if (boost::iequals(*p->get_name(),
"sql_order_by")) {
1532 if (
auto str_literal = dynamic_cast<const StringLiteral*>(p->get_value())) {
1533 copy_params.
sql_order_by = *str_literal->get_stringval();
1535 throw std::runtime_error(
"Option sql_order_by must be a string.");
1537 }
else if (boost::iequals(*p->get_name(),
"username")) {
1540 if (str_literal ==
nullptr) {
1541 throw std::runtime_error(
"Option username must be a string.");
1545 }
else if (boost::iequals(*p->get_name(),
"password")) {
1548 if (str_literal ==
nullptr) {
1549 throw std::runtime_error(
"Option password must be a string.");
1553 }
else if (boost::iequals(*p->get_name(),
"credential_string")) {
1556 if (str_literal ==
nullptr) {
1557 throw std::runtime_error(
"Option credential_string must be a string.");
1561 }
else if (boost::iequals(*p->get_name(),
"dsn")) {
1564 if (str_literal ==
nullptr) {
1565 throw std::runtime_error(
"Option dsn must be a string.");
1568 copy_params.
dsn = string_val;
1569 }
else if (boost::iequals(*p->get_name(),
"connection_string")) {
1572 if (str_literal ==
nullptr) {
1573 throw std::runtime_error(
"Option connection_string must be a string.");
1577 }
else if (boost::iequals(*p->get_name(),
"line_start_regex")) {
1580 if (str_literal ==
nullptr) {
1581 throw std::runtime_error(
"Option line_start_regex must be a string.");
1585 }
else if (boost::iequals(*p->get_name(),
"line_regex")) {
1588 if (str_literal ==
nullptr) {
1589 throw std::runtime_error(
"Option line_regex must be a string.");
1593 }
else if (boost::iequals(*p->get_name(),
"add_metadata_columns") &&
1597 if (str_literal ==
nullptr) {
1598 throw std::runtime_error(
"'add_metadata_columns' option must be a string.");
1602 throw std::runtime_error(
"Invalid option for COPY: " + *p->get_name());
1618 std::shared_ptr<Analyzer::Expr> CaseExpr::normalize(
1619 const std::list<std::pair<std::shared_ptr<Analyzer::Expr>,
1620 std::shared_ptr<Analyzer::Expr>>>& expr_pair_list,
1621 const std::shared_ptr<Analyzer::Expr> else_e_in,
1622 const Executor* executor) {
1624 bool has_agg =
false;
1635 for (
auto& p : expr_pair_list) {
1637 CHECK(e1->get_type_info().is_boolean());
1639 if (e2->get_contains_agg()) {
1642 const auto& e2_ti = e2->get_type_info();
1643 if (e2_ti.is_string() && !e2_ti.is_dict_encoded_string() &&
1645 CHECK(e2_ti.is_none_encoded_string());
1646 none_encoded_literal_ti =
1654 }
else if (e2_ti.get_type() ==
kNULLT) {
1656 e2->set_type_info(ti);
1657 }
else if (ti != e2_ti) {
1658 if (ti.
is_string() && e2_ti.is_string()) {
1662 }
else if (ti.
is_number() && e2_ti.is_number()) {
1664 }
else if (ti.
is_boolean() && e2_ti.is_boolean()) {
1667 throw std::runtime_error(
1668 "Expressions in THEN clause must be of the same or compatible types.");
1672 auto else_e = else_e_in;
1673 const auto& else_ti = else_e->get_type_info();
1675 if (else_e->get_contains_agg()) {
1678 if (else_ti.is_string() && !else_ti.is_dict_encoded_string() &&
1680 CHECK(else_ti.is_none_encoded_string());
1681 none_encoded_literal_ti =
1690 else_e->set_type_info(ti);
1691 }
else if (ti != else_ti) {
1693 if (ti.
is_string() && else_ti.is_string()) {
1697 }
else if (ti.
is_number() && else_ti.is_number()) {
1699 }
else if (ti.
is_boolean() && else_ti.is_boolean()) {
1702 throw std::runtime_error(
1704 "Expressions in ELSE clause must be of the same or compatible types as "
1705 "those in the THEN clauses.");
1715 ti = none_encoded_literal_ti;
1718 std::list<std::pair<std::shared_ptr<Analyzer::Expr>, std::shared_ptr<Analyzer::Expr>>>
1719 cast_expr_pair_list;
1720 for (
auto p : expr_pair_list) {
1722 cast_expr_pair_list.emplace_back(p.first, p.second->add_cast(ti));
1724 if (else_e !=
nullptr) {
1725 else_e = else_e->add_cast(ti);
1730 else_e = makeExpr<Analyzer::Constant>(ti,
true, d);
1733 throw std::runtime_error(
1734 "Cannot deduce the type for case expressions, all branches null");
1737 auto case_expr = makeExpr<Analyzer::CaseExpr>(ti, has_agg, cast_expr_pair_list, else_e);
1742 std::string str(
"CASE ");
1743 for (
auto& p : when_then_list_) {
1744 str +=
"WHEN " + p->get_expr1()->to_string() +
" THEN " +
1745 p->get_expr2()->to_string() +
" ";
1747 if (else_expr_ !=
nullptr) {
1748 str +=
"ELSE " + else_expr_->to_string();
1756 left_->analyze(catalog, query);
1758 right_->analyze(catalog, *right_query);
1765 std::shared_ptr<Analyzer::Expr> p;
1766 if (having_clause_ !=
nullptr) {
1767 p = having_clause_->analyze(catalog, query, Expr::TlistRefType::TLIST_COPY);
1768 if (p->get_type_info().get_type() !=
kBOOLEAN) {
1769 throw std::runtime_error(
"Only boolean expressions can be in HAVING clause.");
1778 std::list<std::shared_ptr<Analyzer::Expr>> groupby;
1779 if (!groupby_clause_.empty()) {
1781 std::shared_ptr<Analyzer::Expr> gexpr;
1782 const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
1784 for (
auto& c : groupby_clause_) {
1786 if (dynamic_cast<Literal*>(c.get())) {
1789 throw std::runtime_error(
"Invalid literal in GROUP BY clause.");
1792 if (varno <= 0 || varno > static_cast<int>(tlist.size())) {
1793 throw std::runtime_error(
"Invalid ordinal number in GROUP BY clause.");
1795 if (tlist[varno - 1]->get_expr()->get_contains_agg()) {
1796 throw std::runtime_error(
1797 "Ordinal number in GROUP BY cannot reference an expression containing "
1801 gexpr = makeExpr<Analyzer::Var>(
1804 gexpr = c->analyze(catalog, query, Expr::TlistRefType::TLIST_REF);
1807 bool set_new_type =
false;
1810 set_new_type =
true;
1815 std::shared_ptr<Analyzer::Var> v;
1816 if (std::dynamic_pointer_cast<Analyzer::Var>(gexpr)) {
1818 int n = v->get_varno();
1819 gexpr = tlist[n - 1]->get_own_expr();
1821 if (cv !=
nullptr) {
1826 v->set_varno(gexpr_no);
1827 tlist[n - 1]->set_expr(v);
1831 groupby.push_back(new_e);
1833 v->set_type_info(new_e->get_type_info());
1836 groupby.push_back(gexpr);
1843 auto e = t->get_expr();
1844 e->check_group_by(groupby);
1852 if (where_clause_ ==
nullptr) {
1856 auto p = where_clause_->analyze(catalog, query, Expr::TlistRefType::TLIST_COPY);
1857 if (p->get_type_info().get_type() !=
kBOOLEAN) {
1858 throw std::runtime_error(
"Only boolean expressions can be in WHERE clause.");
1865 std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
1867 if (select_clause_.empty()) {
1871 rte->expand_star_in_targetlist(catalog, tlist, rte_idx++);
1874 for (
auto& p : select_clause_) {
1875 const Parser::Expr* select_expr = p->get_select_expr();
1877 if (
typeid(*select_expr) ==
typeid(
ColumnRef) &&
1878 dynamic_cast<const ColumnRef*>(select_expr)->get_column() ==
nullptr) {
1879 const std::string* range_var_name =
1880 dynamic_cast<const ColumnRef*
>(select_expr)->get_table();
1883 throw std::runtime_error(
"invalid range variable name: " + *range_var_name);
1888 auto e = select_expr->
analyze(catalog, query);
1889 std::string resname;
1891 if (p->get_alias() !=
nullptr) {
1892 resname = *p->get_alias();
1893 }
else if (std::dynamic_pointer_cast<Analyzer::ColumnVar>(e) &&
1894 !std::dynamic_pointer_cast<Analyzer::Var>(e)) {
1897 colvar->get_table_id(), colvar->get_column_id());
1900 if (e->get_type_info().get_type() ==
kNULLT) {
1901 throw std::runtime_error(
1902 "Untyped NULL in SELECT clause. Use CAST to specify a type.");
1905 bool unnest = (o !=
nullptr && o->get_optype() ==
kUNNEST);
1906 auto tle = std::make_shared<Analyzer::TargetEntry>(resname, e, unnest);
1907 tlist.push_back(tle);
1916 for (
auto& p : from_clause_) {
1919 if (table_desc ==
nullptr) {
1920 throw std::runtime_error(
"Table " + *p->get_table_name() +
" does not exist.");
1922 std::string range_var;
1923 if (p->get_range_var() ==
nullptr) {
1924 range_var = *p->get_table_name();
1926 range_var = *p->get_range_var();
1936 analyze_from_clause(catalog, query);
1937 analyze_select_clause(catalog, query);
1938 analyze_where_clause(catalog, query);
1939 analyze_group_by(catalog, query);
1940 analyze_having_clause(catalog, query);
1947 boost::replace_all(s,
"\\\\t",
"\t");
1948 boost::replace_all(s,
"\\t",
"\t");
1949 boost::replace_all(s,
"\\\\n",
"\n");
1950 boost::replace_all(s,
"\\n",
"\n");
1956 std::regex e1(
"(\\\\x[0-9A-Fa-f][0-9A-Fa-f])");
1957 while (std::regex_search(s, m, e1)) {
1958 std::string original(m[0].first, m[0].second);
1959 std::string replacement;
1960 long val = strtol(original.substr(2, 2).c_str(), NULL, 16);
1961 replacement.push_back(val);
1962 boost::replace_all(s, original, replacement);
1966 std::regex e2(
"(\\\\u[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f])");
1967 while (std::regex_search(s, m, e2)) {
1968 std::string original(m[0].first, m[0].second);
1969 std::string replacement;
1970 long val = strtol(original.substr(2, 4).c_str(), NULL, 16);
1971 replacement.push_back(val);
1972 boost::replace_all(s, original, replacement);
1979 std::list<std::unique_ptr<NameValueAssign>>& nameValueList,
1980 bool stringToNull =
false,
1981 bool stringToInteger =
false) {
1982 if (payload.HasMember(
"options") && payload[
"options"].IsObject()) {
1983 for (
const auto& option : payload[
"options"].GetObject()) {
1984 auto option_name = std::make_unique<std::string>(option.name.GetString());
1985 std::unique_ptr<Literal> literal_value;
1986 if (option.value.IsString()) {
1987 std::string str = option.value.GetString();
1988 if (stringToNull && str ==
"") {
1989 literal_value = std::make_unique<NullLiteral>();
1990 }
else if (stringToInteger && std::all_of(str.begin(), str.end(), ::isdigit)) {
1991 int iVal = std::stoi(str);
1992 literal_value = std::make_unique<IntLiteral>(iVal);
1996 auto unique_literal_string = std::make_unique<std::string>(
unescape(str));
1998 std::make_unique<StringLiteral>(unique_literal_string.release());
2000 }
else if (option.value.IsInt() || option.value.IsInt64()) {
2001 literal_value = std::make_unique<IntLiteral>(
json_i64(option.value));
2002 }
else if (option.value.IsNull()) {
2003 literal_value = std::make_unique<NullLiteral>();
2005 throw std::runtime_error(
"Unable to handle literal for " + *option_name);
2007 CHECK(literal_value);
2009 nameValueList.emplace_back(std::make_unique<NameValueAssign>(
2010 option_name.release(), literal_value.release()));
2021 throw std::runtime_error(
"OFFSET cannot be negative.");
2024 query_expr_->analyze(catalog, query);
2029 const std::vector<std::shared_ptr<Analyzer::TargetEntry>>& tlist =
2031 std::list<Analyzer::OrderEntry>* order_by =
new std::list<Analyzer::OrderEntry>();
2032 if (!orderby_clause_.empty()) {
2033 for (
auto& p : orderby_clause_) {
2034 int tle_no = p->get_colno();
2038 const std::string*
name = p->get_column()->get_column();
2041 for (
auto tle : tlist) {
2042 if (tle->get_resname() == *
name) {
2049 throw std::runtime_error(
"invalid name in order by: " + *name);
2052 order_by->push_back(
2058 for (
int i = 1; i <= static_cast<int>(tlist.size()); i++) {
2059 bool in_orderby =
false;
2060 std::for_each(order_by->begin(),
2063 in_orderby = in_orderby || (i == oe.tle_no);
2074 std::string str = select_expr_->to_string();
2075 if (alias_ !=
nullptr) {
2076 str +=
" AS " + *alias_;
2082 std::string str = *table_name_;
2083 if (range_var_ !=
nullptr) {
2084 str +=
" " + *range_var_;
2091 if (table_ ==
nullptr) {
2093 }
else if (column_ ==
nullptr) {
2094 str = *table_ +
".*";
2096 str = *table_ +
"." + *column_;
2102 std::string op_str[] = {
2103 "=",
"===",
"<>",
"<",
">",
"<=",
">=",
" AND ",
" OR ",
"NOT",
"-",
"+",
"*",
"/"};
2106 str =
"-(" + left_->to_string() +
")";
2107 }
else if (optype_ ==
kNOT) {
2108 str =
"NOT (" + left_->to_string() +
")";
2110 str = left_->to_string() +
"[" + right_->to_string() +
"]";
2111 }
else if (optype_ ==
kUNNEST) {
2112 str =
"UNNEST(" + left_->to_string() +
")";
2113 }
else if (optype_ ==
kIN) {
2114 str =
"(" + left_->to_string() +
" IN " + right_->to_string() +
")";
2116 str =
"(" + left_->to_string() + op_str[optype_] + right_->to_string() +
")";
2122 std::string str = arg_->to_string();
2132 return "EXISTS (" + query_->to_string() +
")";
2138 str += query_->to_string();
2144 std::string str = arg_->to_string();
2146 str +=
" IS NOT NULL";
2155 str += subquery_->to_string();
2161 bool notfirst =
false;
2162 for (
auto& p : value_list_) {
2168 str += p->to_string();
2175 std::string str = arg_->to_string();
2177 str +=
" NOT BETWEEN ";
2181 str += lower_->to_string() +
" AND " + upper_->to_string();
2187 if (calc_encoded_length_) {
2188 str =
"CHAR_LENGTH (" + arg_->to_string() +
")";
2190 str =
"LENGTH (" + arg_->to_string() +
")";
2196 std::string str =
"CARDINALITY(" + arg_->to_string() +
")";
2201 std::string str = arg_->to_string();
2203 str +=
" NOT LIKE ";
2207 str += like_string_->to_string();
2208 if (escape_string_ !=
nullptr) {
2209 str +=
" ESCAPE " + escape_string_->to_string();
2215 std::string str = arg_->to_string();
2217 str +=
" NOT REGEXP ";
2221 str += pattern_string_->to_string();
2222 if (escape_string_ !=
nullptr) {
2223 str +=
" ESCAPE " + escape_string_->to_string();
2229 std::string str =
" WIDTH_BUCKET ";
2230 str += target_value_->to_string();
2232 str += lower_bound_->to_string();
2234 str += upper_bound_->to_string();
2236 str += partition_count_->to_string();
2242 std::string str =
" LIKELIHOOD ";
2243 str += arg_->to_string();
2245 str += boost::lexical_cast<std::string>(is_not_ ? 1.0 - likelihood_ : likelihood_);
2250 std::string str = *name_ +
"(";
2254 if (arg_ ==
nullptr) {
2257 str += arg_->to_string() +
")";
2263 std::string query_str =
"SELECT ";
2265 query_str +=
"DISTINCT ";
2267 if (select_clause_.empty()) {
2270 bool notfirst =
false;
2271 for (
auto& p : select_clause_) {
2277 query_str += p->to_string();
2280 query_str +=
" FROM ";
2281 bool notfirst =
false;
2282 for (
auto& p : from_clause_) {
2288 query_str += p->to_string();
2290 if (where_clause_) {
2291 query_str +=
" WHERE " + where_clause_->to_string();
2293 if (!groupby_clause_.empty()) {
2294 query_str +=
" GROUP BY ";
2295 bool notfirst =
false;
2296 for (
auto& p : groupby_clause_) {
2302 query_str += p->to_string();
2305 if (having_clause_) {
2306 query_str +=
" HAVING " + having_clause_->to_string();
2316 if (td ==
nullptr) {
2317 throw std::runtime_error(
"Table " + *table_ +
" does not exist.");
2320 throw std::runtime_error(
"Insert to views is not supported yet.");
2324 std::list<int> result_col_list;
2325 if (column_list_.empty()) {
2326 const std::list<const ColumnDescriptor*> all_cols =
2328 for (
auto cd : all_cols) {
2329 result_col_list.push_back(cd->columnId);
2332 for (
auto& c : column_list_) {
2334 if (cd ==
nullptr) {
2335 throw std::runtime_error(
"Column " + *c +
" does not exist.");
2337 result_col_list.push_back(cd->
columnId);
2339 if (col_ti.get_physical_cols() > 0) {
2341 for (
auto i = 1; i <= col_ti.get_physical_cols(); i++) {
2344 if (pcd ==
nullptr) {
2345 throw std::runtime_error(
"Column " + *c +
"'s metadata is incomplete.");
2347 result_col_list.push_back(pcd->
columnId);
2357 CHECK(literal.IsObject());
2358 CHECK(literal.HasMember(
"literal"));
2359 CHECK(literal.HasMember(
"type"));
2361 if (type ==
"NULL") {
2363 }
else if (type ==
"CHAR" || type ==
"BOOLEAN") {
2364 auto* val =
new std::string(
json_str(literal[
"literal"]));
2366 }
else if (type ==
"DECIMAL") {
2367 CHECK(literal.HasMember(
"scale"));
2368 CHECK(literal.HasMember(
"precision"));
2369 auto scale =
json_i64(literal[
"scale"]);
2370 auto precision =
json_i64(literal[
"precision"]);
2372 auto int_val = std::stol(
json_str(literal[
"literal"]));
2374 }
else if (precision > 18) {
2375 auto dbl_val = std::stod(
json_str(literal[
"literal"]));
2378 auto* val =
new std::string(
json_str(literal[
"literal"]));
2381 }
else if (type ==
"DOUBLE") {
2382 auto dbl_val = std::stod(
json_str(literal[
"literal"]));
2385 CHECK(
false) <<
"Unexpected calcite data type: " <<
type;
2391 CHECK(array.IsArray());
2392 auto json_elements = array.GetArray();
2393 auto* elements =
new std::list<Expr*>();
2394 for (
const auto& e : json_elements) {
2401 InsertValuesStmt::InsertValuesStmt(
const rapidjson::Value& payload)
2403 CHECK(payload.HasMember(
"name"));
2404 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
2406 if (payload.HasMember(
"columns")) {
2407 CHECK(payload[
"columns"].IsArray());
2408 for (
auto& column : payload[
"columns"].GetArray()) {
2410 column_list_.emplace_back(std::make_unique<std::string>(s));
2414 CHECK(payload.HasMember(
"values") && payload[
"values"].IsArray());
2415 auto tuples = payload[
"values"].GetArray();
2416 if (tuples.Empty()) {
2417 throw std::runtime_error(
"Values statement cannot be empty");
2420 for (
const auto& json_tuple : tuples) {
2421 auto values_list = std::make_unique<ValuesList>();
2422 CHECK(json_tuple.IsArray());
2423 auto tuple = json_tuple.GetArray();
2424 for (
const auto& value : tuple) {
2425 CHECK(value.IsObject());
2426 if (value.HasMember(
"array")) {
2439 size_t list_size =
values_lists_[0]->get_value_list().size();
2442 throw std::runtime_error(
2443 "Numbers of columns and values don't match for the "
2448 const std::list<const ColumnDescriptor*> non_phys_cols =
2450 if (non_phys_cols.size() != list_size) {
2451 throw std::runtime_error(
2452 "Number of columns in table does not match the list of values given in the "
2456 std::vector<const ColumnDescriptor*> cds;
2466 const auto& values_list =
values_lists_[i]->get_value_list();
2467 if (values_list.size() != list_size) {
2468 throw std::runtime_error(
2469 "Insert values lists should be of the same size. Expected: " +
2472 auto& query_values_list = query_values_lists[i];
2474 for (
auto& v : values_list) {
2475 auto e = v->analyze(catalog, query);
2476 const auto* cd = cds[cds_id];
2477 const auto& col_ti = cd->columnType;
2478 if (col_ti.get_notnull()) {
2480 if (c !=
nullptr && c->get_is_null()) {
2481 throw std::runtime_error(
"Cannot insert NULL into column " + cd->columnName);
2484 e = e->add_cast(col_ti);
2488 if (col_ti.get_physical_cols() > 0) {
2489 CHECK(cd->columnType.is_geometry());
2493 if (uoper && uoper->get_optype() ==
kCAST) {
2498 std::string* geo_string{
nullptr};
2500 is_null = c->get_is_null();
2502 geo_string = c->get_constval().stringval;
2505 if (!is_null && !geo_string) {
2506 throw std::runtime_error(
"Expecting a WKT or WKB hex string for column " +
2509 std::vector<double> coords;
2510 std::vector<double> bounds;
2511 std::vector<int> ring_sizes;
2512 std::vector<int> poly_rings;
2518 *geo_string, import_ti, coords, bounds, ring_sizes, poly_rings)) {
2519 throw std::runtime_error(
"Cannot read geometry to insert into column " +
2522 if (coords.empty()) {
2526 if (cd->columnType.get_type() != import_ti.get_type()) {
2530 throw std::runtime_error(
2531 "Imported geometry doesn't match the type of column " + cd->columnName);
2536 if (cd->columnType.get_type() ==
kPOINT) {
2537 if (!coords.empty()) {
2538 throw std::runtime_error(
2539 "NULL POINT with unexpected coordinates in column " + cd->columnName);
2549 const auto* cd_coords = cds[cds_id];
2552 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2553 if (!is_null || cd->columnType.get_type() ==
kPOINT) {
2555 for (
auto cc : compressed_coords) {
2558 auto e = makeExpr<Analyzer::Constant>(
kTINYINT,
false, d);
2559 value_exprs.push_back(e);
2564 makeExpr<Analyzer::Constant>(cd_coords->columnType, is_null, value_exprs),
2568 if (cd->columnType.get_type() ==
kPOLYGON ||
2571 const auto* cd_ring_sizes = cds[cds_id];
2572 CHECK(cd_ring_sizes);
2574 CHECK_EQ(cd_ring_sizes->columnType.get_subtype(),
kINT);
2575 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2577 for (
auto c : ring_sizes) {
2580 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
2581 value_exprs.push_back(e);
2586 makeExpr<Analyzer::Constant>(
2587 cd_ring_sizes->columnType, is_null, value_exprs),
2593 const auto* cd_poly_rings = cds[cds_id];
2594 CHECK(cd_poly_rings);
2596 CHECK_EQ(cd_poly_rings->columnType.get_subtype(),
kINT);
2597 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2599 for (
auto c : poly_rings) {
2602 auto e = makeExpr<Analyzer::Constant>(
kINT,
false, d);
2603 value_exprs.push_back(e);
2608 makeExpr<Analyzer::Constant>(
2609 cd_poly_rings->columnType, is_null, value_exprs),
2616 cd->columnType.get_type() ==
kPOLYGON ||
2618 const auto* cd_bounds = cds[cds_id];
2622 std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2624 for (
auto b : bounds) {
2627 auto e = makeExpr<Analyzer::Constant>(
kDOUBLE,
false, d);
2628 value_exprs.push_back(e);
2633 makeExpr<Analyzer::Constant>(cd_bounds->columnType, is_null, value_exprs),
2638 if (cd->columnType.get_type() ==
kPOLYGON ||
2641 const auto* cd_render_group = cds[cds_id];
2642 CHECK(cd_render_group);
2643 CHECK_EQ(cd_render_group->columnType.get_type(),
kINT);
2648 makeExpr<Analyzer::Constant>(cd_render_group->columnType, is_null, d),
2658 bool read_only_mode) {
2659 if (read_only_mode) {
2660 throw std::runtime_error(
"INSERT values invalid in read only mode.");
2662 auto execute_read_lock =
2667 const auto td_with_lock =
2673 throw std::runtime_error(
"User has no insert privileges on " + *
table_ +
".");
2679 const auto insert_data_lock =
2685 auto td = td_with_lock();
2688 throw std::runtime_error(
"Singleton inserts on views is not supported.");
2701 ra_executor.executeSimpleInsert(query, insert_data_loader, session);
2705 }
catch (std::exception& e) {
2706 LOG(
ERROR) <<
"An error occurred during insert rollback attempt. Table id: "
2707 << td->tableId <<
", Error: " << e.what();
2711 if (!td->isTemporaryTable()) {
2718 throw std::runtime_error(
"UPDATE statement not supported yet.");
2723 throw std::runtime_error(
"DELETE statement not supported yet.");
2730 if (!col_ti.is_integer() && !col_ti.is_time() &&
2731 !(col_ti.is_string() && col_ti.get_compression() ==
kENCODING_DICT)) {
2732 throw std::runtime_error(
"Cannot shard on type " + col_ti.get_type_name() +
2733 ", encoding " + col_ti.get_compression_name());
2738 const std::list<ColumnDescriptor>& columns) {
2740 for (
const auto& cd : columns) {
2741 if (cd.columnName == name) {
2746 if (cd.columnType.is_geometry()) {
2747 index += cd.columnType.get_physical_cols();
2755 const std::list<ColumnDescriptor>& columns) {
2757 for (
const auto& cd : columns) {
2758 if (boost::to_upper_copy<std::string>(cd.columnName) == name) {
2762 if (cd.columnType.is_geometry()) {
2763 index += cd.columnType.get_physical_cols();
2771 const std::string& field_name,
2772 const std::string& field_value,
2773 rapidjson::Document& document) {
2774 rapidjson::Value field_name_json_str;
2775 field_name_json_str.SetString(
2776 field_name.c_str(), field_name.size(), document.GetAllocator());
2777 rapidjson::Value field_value_json_str;
2778 field_value_json_str.SetString(
2779 field_value.c_str(), field_value.size(), document.GetAllocator());
2780 obj.AddMember(field_name_json_str, field_value_json_str, document.GetAllocator());
2785 const std::vector<SharedDictionaryDef>& shared_dict_defs) {
2786 rapidjson::Document document;
2787 auto& allocator = document.GetAllocator();
2788 rapidjson::Value arr(rapidjson::kArrayType);
2789 if (shard_key_def) {
2790 rapidjson::Value shard_key_obj(rapidjson::kObjectType);
2793 arr.PushBack(shard_key_obj, allocator);
2795 for (
const auto& shared_dict_def : shared_dict_defs) {
2796 rapidjson::Value shared_dict_obj(rapidjson::kObjectType);
2798 set_string_field(shared_dict_obj,
"name", shared_dict_def.get_column(), document);
2800 shared_dict_obj,
"foreign_table", shared_dict_def.get_foreign_table(), document);
2803 shared_dict_def.get_foreign_column(),
2805 arr.PushBack(shared_dict_obj, allocator);
2807 rapidjson::StringBuffer buffer;
2808 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
2810 return buffer.GetString();
2813 template <
typename LITERAL_TYPE,
2814 typename ASSIGNMENT,
2818 VALIDATE validate = VALIDATE()) {
2819 const auto val = validate(p);
2826 auto assignment = [&td](
const auto val) { td.storageType = val; };
2827 return get_property_value<StringLiteral, decltype(assignment), CaseSensitiveValidate>(
2834 return get_property_value<IntLiteral>(p,
2835 [&td](
const auto val) { td.maxFragRows = val; });
2841 return get_property_value<IntLiteral>(
2842 p, [&df_td](
const auto val) { df_td.maxFragRows = val; });
2848 return get_property_value<IntLiteral>(p,
2849 [&td](
const auto val) { td.maxChunkSize = val; });
2856 return get_property_value<IntLiteral>(
2857 p, [&df_td](
const auto val) { df_td.maxChunkSize = val; });
2863 return get_property_value<StringLiteral>(p, [&df_td](
const auto val) {
2864 if (val.size() != 1) {
2865 throw std::runtime_error(
"Length of DELIMITER must be equal to 1.");
2867 df_td.delimiter = val;
2874 return get_property_value<StringLiteral>(p, [&df_td](
const auto val) {
2875 if (val ==
"FALSE") {
2876 df_td.hasHeader =
false;
2877 }
else if (val ==
"TRUE") {
2878 df_td.hasHeader =
true;
2880 throw std::runtime_error(
"Option HEADER support only 'true' or 'false' values.");
2888 return get_property_value<IntLiteral>(p,
2889 [&td](
const auto val) { td.fragPageSize = val; });
2894 return get_property_value<IntLiteral>(p, [&td](
const auto val) { td.maxRows = val; });
2900 return get_property_value<IntLiteral>(
2901 p, [&df_td](
const auto val) { df_td.skipRows = val; });
2907 return get_property_value<StringLiteral>(p, [&td](
const auto partitions_uc) {
2908 if (partitions_uc !=
"SHARDED" && partitions_uc !=
"REPLICATED") {
2909 throw std::runtime_error(
"PARTITIONS must be SHARDED or REPLICATED");
2911 if (td.shardedColumnId != 0 && partitions_uc ==
"REPLICATED") {
2912 throw std::runtime_error(
2913 "A table cannot be sharded and replicated at the same time");
2915 td.partitions = partitions_uc;
2921 if (!td.shardedColumnId) {
2922 throw std::runtime_error(
"SHARD KEY must be defined.");
2924 return get_property_value<IntLiteral>(p, [&td](
const auto shard_count) {
2926 throw std::runtime_error(
2927 "SHARD_COUNT must be a multiple of the number of leaves in the cluster.");
2929 td.nShards = g_leaf_count ? shard_count / g_leaf_count : shard_count;
2930 if (!td.shardedColumnId && !td.nShards) {
2931 throw std::runtime_error(
2932 "Must specify the number of shards through the SHARD_COUNT option");
2940 return get_property_value<StringLiteral>(p, [&td](
const auto vacuum_uc) {
2941 if (vacuum_uc !=
"IMMEDIATE" && vacuum_uc !=
"DELAYED") {
2942 throw std::runtime_error(
"VACUUM must be IMMEDIATE or DELAYED");
2944 td.hasDeletedCol = boost::iequals(vacuum_uc,
"IMMEDIATE") ?
false :
true;
2951 return get_property_value<StringLiteral>(p, [&td, &columns](
const auto sort_upper) {
2953 if (!td.sortedColumnId) {
2954 throw std::runtime_error(
"Specified sort column " + sort_upper +
" doesn't exist");
2962 auto assignment = [&td](
const auto val) {
2963 td.maxRollbackEpochs =
2968 return get_property_value<IntLiteral, decltype(assignment), PositiveOrZeroValidate>(
2985 const std::unique_ptr<NameValueAssign>& p,
2986 const std::list<ColumnDescriptor>& columns) {
2987 const auto it = tableDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
2988 if (it == tableDefFuncMap.end()) {
2989 throw std::runtime_error(
2990 "Invalid CREATE TABLE option " + *p->get_name() +
2991 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, PAGE_SIZE, MAX_ROLLBACK_EPOCHS, "
2993 "PARTITIONS, SHARD_COUNT, VACUUM, SORT_COLUMN, STORAGE_TYPE.");
2995 return it->second(td, p.get(), columns);
2999 const std::unique_ptr<NameValueAssign>& p,
3000 const std::list<ColumnDescriptor>& columns) {
3001 const auto it = tableDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3002 if (it == tableDefFuncMap.end()) {
3003 throw std::runtime_error(
3004 "Invalid CREATE TABLE AS option " + *p->get_name() +
3005 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, PAGE_SIZE, MAX_ROLLBACK_EPOCHS, "
3007 "PARTITIONS, SHARD_COUNT, VACUUM, SORT_COLUMN, STORAGE_TYPE or "
3008 "USE_SHARED_DICTIONARIES.");
3010 return it->second(td, p.get(), columns);
3021 const std::unique_ptr<NameValueAssign>& p,
3022 const std::list<ColumnDescriptor>& columns) {
3024 dataframeDefFuncMap.find(boost::to_lower_copy<std::string>(*p->get_name()));
3025 if (it == dataframeDefFuncMap.end()) {
3026 throw std::runtime_error(
3027 "Invalid CREATE DATAFRAME option " + *p->get_name() +
3028 ". Should be FRAGMENT_SIZE, MAX_CHUNK_SIZE, SKIP_ROWS, DELIMITER or HEADER.");
3030 return it->second(df_td, p.get(), columns);
3034 CHECK(element.HasMember(
"name"));
3035 auto col_name = std::make_unique<std::string>(
json_str(element[
"name"]));
3036 CHECK(element.HasMember(
"sqltype"));
3042 if (element.HasMember(
"precision")) {
3043 precision =
json_i64(element[
"precision"]);
3045 if (element.HasMember(
"scale")) {
3046 scale =
json_i64(element[
"scale"]);
3049 std::optional<int64_t> array_size;
3050 if (element.HasMember(
"arraySize")) {
3052 array_size =
json_i64(element[
"arraySize"]);
3054 std::unique_ptr<SQLType> sql_type;
3055 if (element.HasMember(
"subtype")) {
3056 CHECK(element.HasMember(
"coordinateSystem"));
3059 std::make_unique<SQLType>(subtype_sql_types,
3060 static_cast<int>(sql_types),
3061 static_cast<int>(
json_i64(element[
"coordinateSystem"])),
3063 }
else if (precision > 0 && scale > 0) {
3064 sql_type = std::make_unique<SQLType>(sql_types,
3067 array_size.has_value(),
3068 array_size ? *array_size : -1);
3069 }
else if (precision > 0) {
3070 sql_type = std::make_unique<SQLType>(sql_types,
3073 array_size.has_value(),
3074 array_size ? *array_size : -1);
3076 sql_type = std::make_unique<SQLType>(sql_types,
3077 array_size.has_value(),
3078 array_size ? *array_size : -1);
3082 CHECK(element.HasMember(
"nullable"));
3083 const auto nullable =
json_bool(element[
"nullable"]);
3084 std::unique_ptr<ColumnConstraintDef> constraint_def;
3086 if (element.HasMember(
"default") && !element[
"default"].IsNull()) {
3087 std::string* defaultval =
new std::string(
json_str(element[
"default"]));
3088 boost::algorithm::trim_if(*defaultval, boost::is_any_of(
" \"'`"));
3092 constraint_def = std::make_unique<ColumnConstraintDef>(!nullable,
3096 std::unique_ptr<CompressDef> compress_def;
3097 if (element.HasMember(
"encodingType") && !element[
"encodingType"].IsNull()) {
3098 std::string encoding_type =
json_str(element[
"encodingType"]);
3099 CHECK(element.HasMember(
"encodingSize"));
3100 auto encoding_name = std::make_unique<std::string>(
json_str(element[
"encodingType"]));
3101 compress_def = std::make_unique<CompressDef>(encoding_name.release(),
3102 json_i64(element[
"encodingSize"]));
3104 return std::make_unique<ColumnDef>(col_name.release(),
3106 compress_def ? compress_def.release() :
nullptr,
3107 constraint_def ? constraint_def.release() :
nullptr);
3111 std::string element_name,
3112 std::string& table_name,
3113 std::list<std::unique_ptr<TableElement>>& table_element_list) {
3114 const auto elements = payload[element_name].GetArray();
3115 for (
const auto& element : elements) {
3116 CHECK(element.IsObject());
3117 CHECK(element.HasMember(
"type"));
3118 if (
json_str(element[
"type"]) ==
"SQL_COLUMN_DECLARATION") {
3120 table_element_list.emplace_back(std::move(col_def));
3121 }
else if (
json_str(element[
"type"]) ==
"SQL_COLUMN_CONSTRAINT") {
3122 CHECK(element.HasMember(
"name"));
3123 if (
json_str(element[
"name"]) ==
"SHARD_KEY") {
3124 CHECK(element.HasMember(
"columns"));
3125 CHECK(element[
"columns"].IsArray());
3126 const auto& columns = element[
"columns"].GetArray();
3127 if (columns.Size() != size_t(1)) {
3128 throw std::runtime_error(
"Only one shard column is currently supported.");
3130 auto shard_key_def = std::make_unique<ShardKeyDef>(
json_str(columns[0]));
3131 table_element_list.emplace_back(std::move(shard_key_def));
3132 }
else if (
json_str(element[
"name"]) ==
"SHARED_DICT") {
3133 CHECK(element.HasMember(
"columns"));
3134 CHECK(element[
"columns"].IsArray());
3135 const auto& columns = element[
"columns"].GetArray();
3136 if (columns.Size() != size_t(1)) {
3137 throw std::runtime_error(
3138 R
"(Only one column per shared dictionary entry is currently supported. Use multiple SHARED DICT statements to share dictionaries from multiple columns.)");
3140 CHECK(element.HasMember("references") && element[
"references"].IsObject());
3141 const auto& references = element[
"references"].GetObject();
3142 std::string references_table_name;
3143 if (references.HasMember(
"table")) {
3144 references_table_name =
json_str(references[
"table"]);
3146 references_table_name = table_name;
3148 CHECK(references.HasMember(
"column"));
3150 auto shared_dict_def = std::make_unique<SharedDictionaryDef>(
3151 json_str(columns[0]), references_table_name,
json_str(references[
"column"]));
3152 table_element_list.emplace_back(std::move(shared_dict_def));
3155 LOG(
FATAL) <<
"Unsupported type for SQL_COLUMN_CONSTRAINT: "
3159 LOG(
FATAL) <<
"Unsupported element type for CREATE TABLE: "
3160 << element[
"type"].GetString();
3167 CHECK(payload.HasMember(
"name"));
3168 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
3169 CHECK(payload.HasMember(
"elements"));
3170 CHECK(payload[
"elements"].IsArray());
3173 if (payload.HasMember(
"temporary")) {
3178 if (payload.HasMember(
"ifNotExists")) {
3189 std::list<ColumnDescriptor>& columns,
3190 std::vector<SharedDictionaryDef>& shared_dict_defs) {
3191 std::unordered_set<std::string> uc_col_names;
3195 if (dynamic_cast<SharedDictionaryDef*>(e.get())) {
3198 this, shared_dict_def, columns, shared_dict_defs, catalog);
3199 shared_dict_defs.push_back(*shared_dict_def);
3202 if (dynamic_cast<ShardKeyDef*>(e.get())) {
3203 if (shard_key_def) {
3204 throw std::runtime_error(
"Specified more than one shard key");
3206 shard_key_def =
static_cast<const ShardKeyDef*
>(e.get());
3209 if (!dynamic_cast<ColumnDef*>(e.get())) {
3210 throw std::runtime_error(
"Table constraints are not supported yet.");
3217 columns.push_back(cd);
3222 if (shard_key_def) {
3225 throw std::runtime_error(
"Specified shard column " + shard_key_def->get_column() +
3240 throw std::runtime_error(
"SHARD_COUNT needs to be specified with SHARD_KEY.");
3246 bool read_only_mode) {
3247 if (read_only_mode) {
3248 throw std::runtime_error(
"CREATE TABLE invalid in read only mode.");
3252 const auto execute_write_lock =
3260 throw std::runtime_error(
"Table " + *
table_ +
3261 " will not be created. User has no create privileges.");
3269 std::list<ColumnDescriptor> columns;
3270 std::vector<SharedDictionaryDef> shared_dict_defs;
3275 catalog.createShardedTable(td, columns, shared_dict_defs);
3278 SysCatalog::instance().createDBObject(
3283 CHECK(payload.HasMember(
"name"));
3284 table_ = std::make_unique<std::string>(
json_str(payload[
"name"]));
3286 CHECK(payload.HasMember(
"elementList"));
3289 CHECK(payload.HasMember(
"filePath"));
3290 std::string fs =
json_str(payload[
"filePath"]);
3292 boost::algorithm::trim_if(fs, boost::is_any_of(
" \"'`"));
3293 filename_ = std::make_unique<std::string>(fs);
3299 bool read_only_mode) {
3300 if (read_only_mode) {
3301 throw std::runtime_error(
"CREATE DATAFRAME invalid in read only mode.");
3305 const auto execute_write_lock =
3313 throw std::runtime_error(
"Table " + *
table_ +
3314 " will not be created. User has no create privileges.");
3317 if (catalog.getMetadataForTable(*
table_) !=
nullptr) {
3318 throw std::runtime_error(
"Table " + *
table_ +
" already exists.");
3321 std::list<ColumnDescriptor> columns;
3322 std::vector<SharedDictionaryDef> shared_dict_defs;
3324 std::unordered_set<std::string> uc_col_names;
3326 if (dynamic_cast<SharedDictionaryDef*>(e.get())) {
3329 this, shared_dict_def, columns, shared_dict_defs, catalog);
3330 shared_dict_defs.push_back(*shared_dict_def);
3333 if (!dynamic_cast<ColumnDef*>(e.get())) {
3334 throw std::runtime_error(
"Table constraints are not supported yet.");
3339 const auto uc_col_name = boost::to_upper_copy<std::string>(cd.
columnName);
3340 const auto it_ok = uc_col_names.insert(uc_col_name);
3341 if (!it_ok.second) {
3342 throw std::runtime_error(
"Column '" + cd.
columnName +
"' defined more than once");
3345 columns.push_back(cd);
3367 catalog.createShardedTable(df_td, columns, shared_dict_defs);
3370 SysCatalog::instance().createDBObject(
3375 const std::string select_stmt,
3376 std::vector<TargetMetaInfo>& targets,
3377 bool validate_only =
false,
3378 std::vector<size_t> outer_fragment_indices = {},
3379 bool allow_interrupt =
false) {
3381 auto& catalog = session->getCatalog();
3385 const auto device_type = session->get_executor_device_type();
3389 auto calcite_mgr = catalog.getCalciteMgr();
3393 const auto calciteQueryParsingOption =
3394 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true);
3395 const auto calciteOptimizationOption =
3397 const auto query_ra = calcite_mgr
3398 ->process(query_state_proxy,
3400 calciteQueryParsingOption,
3401 calciteOptimizationOption)
3427 outer_fragment_indices};
3437 result = ra_executor.executeRelAlgQuery(co, eo,
false,
nullptr);
3438 targets =
result.getTargetsMeta();
3444 std::string& sql_query_string) {
3446 auto& catalog = session->getCatalog();
3450 const auto device_type = session->get_executor_device_type();
3454 auto calcite_mgr = catalog.getCalciteMgr();
3458 const auto calciteQueryParsingOption =
3459 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true);
3460 const auto calciteOptimizationOption =
3462 const auto query_ra = calcite_mgr
3463 ->process(query_state_proxy,
3465 calciteQueryParsingOption,
3466 calciteOptimizationOption)
3486 return ra_executor.getOuterFragmentCount(co, eo);
3490 std::string& sql_query_string,
3491 std::vector<size_t> outer_frag_indices,
3493 bool allow_interrupt) {
3495 std::string pg_shimmed_select_query =
pg_shim(sql_query_string);
3497 std::vector<TargetMetaInfo> target_metainfos;
3500 auto query_session = session ? session->get_session_id() :
"";
3502 if (allow_interrupt && !validate_only && !query_session.empty()) {
3503 executor->enrollQuerySession(query_session,
3505 query_submitted_time,
3507 QuerySessionStatus::QueryStatus::PENDING_EXECUTOR);
3521 std::string& sql_query_string,
3522 std::vector<size_t> outer_frag_indices,
3523 bool allow_interrupt) {
3525 query_state_proxy, sql_query_string, outer_frag_indices,
false, allow_interrupt);
3532 std::list<ColumnDescriptor> column_descriptors;
3533 std::list<ColumnDescriptor> column_descriptors_for_create;
3535 int rowid_suffix = 0;
3536 for (
const auto& target_metainfo : result.
targets_meta) {
3538 cd.
columnName = target_metainfo.get_resname();
3542 cd.
columnType = target_metainfo.get_physical_type_info();
3562 column_descriptors_for_create.push_back(cd_for_create);
3563 column_descriptors.push_back(cd);
3567 return column_descriptors_for_create;
3570 return column_descriptors;
3574 const rapidjson::Value& payload) {
3575 CHECK(payload.HasMember(
"name"));
3578 CHECK(payload.HasMember(
"query"));
3581 boost::replace_all(select_query_,
"\n",
" ");
3582 select_query_ =
"(" + select_query_ +
")";
3584 if (payload.HasMember(
"columns")) {
3585 CHECK(payload[
"columns"].IsArray());
3586 for (
auto& column : payload[
"columns"].GetArray()) {
3588 column_list_.emplace_back(std::unique_ptr<std::string>(
new std::string(s)));
3595 bool validate_table,
3598 auto& catalog = session->getCatalog();
3602 bool populate_table =
false;
3605 populate_table =
true;
3609 populate_table =
true;
3613 auto get_target_column_descriptors = [
this, &catalog](
const TableDescriptor* td) {
3614 std::vector<const ColumnDescriptor*> target_column_descriptors;
3616 auto list = catalog.getAllColumnMetadataForTable(td->
tableId,
false,
false,
false);
3617 target_column_descriptors = {std::begin(list), std::end(list)};
3621 if (cd ==
nullptr) {
3622 throw std::runtime_error(
"Column " + *c +
" does not exist.");
3624 target_column_descriptors.push_back(cd);
3628 return target_column_descriptors;
3633 if (validate_table) {
3636 throw std::runtime_error(
"Table " +
table_name_ +
" does not exist.");
3639 throw std::runtime_error(
"Insert to views is not supported yet.");
3645 throw std::runtime_error(
"User has no insert privileges on " +
table_name_ +
".");
3653 std::vector<const ColumnDescriptor*> target_column_descriptors =
3654 get_target_column_descriptors(td);
3656 if (source_column_descriptors.size() != target_column_descriptors.size()) {
3657 throw std::runtime_error(
"The number of source and target columns does not match.");
3660 for (
int i = 0; i < source_column_descriptors.size(); i++) {
3662 &(*std::next(source_column_descriptors.begin(), i));
3666 auto type_cannot_be_cast = [](
const auto& col_type) {
3667 return (col_type.is_time() || col_type.is_geometry() || col_type.is_array() ||
3668 col_type.is_boolean());
3671 if (type_cannot_be_cast(source_cd->
columnType) ||
3672 type_cannot_be_cast(target_cd->
columnType)) {
3673 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3675 "' and target '" + target_cd->
columnName +
" " +
3677 "' column types do not match.");
3682 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3684 "' and target '" + target_cd->
columnName +
" " +
3686 "' array column element types do not match.");
3701 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3703 "' and target '" + target_cd->
columnName +
" " +
3705 "' decimal columns scales do not match.");
3711 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3713 "' and target '" + target_cd->
columnName +
" " +
3715 "' column types do not match.");
3719 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3721 "' and target '" + target_cd->
columnName +
" " +
3723 "' columns string encodings do not match.");
3730 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3732 "' and target '" + target_cd->
columnName +
" " +
3734 "' timestamp column precisions do not match.");
3743 throw std::runtime_error(
"Source '" + source_cd->
columnName +
" " +
3745 "' and target '" + target_cd->
columnName +
" " +
3747 "' column encoding sizes do not match.");
3752 if (!populate_table) {
3756 int64_t total_row_count = 0;
3757 int64_t total_source_query_time_ms = 0;
3758 int64_t total_target_value_translate_time_ms = 0;
3759 int64_t total_data_load_time_ms = 0;
3762 auto target_column_descriptors = get_target_column_descriptors(td);
3763 auto outer_frag_count =
3766 size_t outer_frag_end = outer_frag_count == 0 ? 1 : outer_frag_count;
3767 auto query_session = session ? session->get_session_id() :
"";
3769 std::string work_type_str = for_CTAS ?
"CTAS" :
"ITAS";
3771 for (
size_t outer_frag_idx = 0; outer_frag_idx < outer_frag_end; outer_frag_idx++) {
3772 std::vector<size_t> allowed_outer_fragment_indices;
3774 if (outer_frag_count) {
3775 allowed_outer_fragment_indices.push_back(outer_frag_idx);
3779 std::vector<AggregatedResult> query_results =
3782 allowed_outer_fragment_indices,
3784 total_source_query_time_ms +=
timer_stop(query_clock_begin);
3787 auto query_str =
"INSERT_DATA for " + work_type_str;
3792 executor->enrollQuerySession(query_session,
3796 QuerySessionStatus::QueryStatus::RUNNING_IMPORTER);
3803 executor->clearQuerySessionStatus(query_session,
start_time);
3807 for (
auto&
res : query_results) {
3809 throw std::runtime_error(
3810 "Query execution has been interrupted while performing " + work_type_str);
3812 auto& result_rows =
res.rs;
3814 const auto num_rows = result_rows->rowCount();
3816 if (0 == num_rows) {
3820 total_row_count += num_rows;
3825 const size_t rows_per_block =
3826 std::max(std::min(num_rows / leaf_count,
size_t(64 * 1024)),
size_t(1));
3828 std::vector<std::unique_ptr<TargetValueConverter>> value_converters;
3832 const int num_worker_threads = std::thread::hardware_concurrency();
3834 std::vector<size_t> thread_start_idx(num_worker_threads),
3835 thread_end_idx(num_worker_threads);
3836 bool can_go_parallel = !result_rows->isTruncated() && rows_per_block > 20000;
3838 std::atomic<size_t> crt_row_idx{0};
3840 auto do_work = [&result_rows, &value_converters, &crt_row_idx](
3842 const size_t block_end,
3843 const size_t num_cols,
3845 bool& stop_convert) {
3846 const auto result_row = result_rows->getRowAtNoTranslations(idx);
3847 if (!result_row.empty()) {
3848 size_t target_row = crt_row_idx.fetch_add(1);
3849 if (target_row >= block_end) {
3850 stop_convert =
true;
3853 for (
unsigned int col = 0; col < num_cols; col++) {
3854 const auto& mapd_variant = result_row[col];
3855 value_converters[col]->convertToColumnarFormat(target_row, &mapd_variant);
3860 auto convert_function = [&thread_start_idx,
3866 &do_work](
const int thread_id,
const size_t block_end) {
3867 const int num_cols = value_converters.size();
3868 const size_t start = thread_start_idx[
thread_id];
3869 const size_t end = thread_end_idx[
thread_id];
3871 bool stop_convert =
false;
3873 size_t local_idx = 0;
3874 for (idx = start; idx < end; ++idx, ++local_idx) {
3875 if (
UNLIKELY((local_idx & 0xFFFF) == 0 &&
3877 throw std::runtime_error(
3878 "Query execution has been interrupted while performing " +
3881 do_work(idx, block_end, num_cols, thread_id, stop_convert);
3887 for (idx = start; idx < end; ++idx) {
3888 do_work(idx, block_end, num_cols, thread_id, stop_convert);
3897 auto single_threaded_value_converter =
3898 [&crt_row_idx, &value_converters, &result_rows](
const size_t idx,
3899 const size_t block_end,
3900 const size_t num_cols,
3901 bool& stop_convert) {
3902 size_t target_row = crt_row_idx.fetch_add(1);
3903 if (target_row >= block_end) {
3904 stop_convert =
true;
3907 const auto result_row = result_rows->getNextRow(
false,
false);
3908 CHECK(!result_row.empty());
3909 for (
unsigned int col = 0; col < num_cols; col++) {
3910 const auto& mapd_variant = result_row[col];
3911 value_converters[col]->convertToColumnarFormat(target_row, &mapd_variant);
3915 auto single_threaded_convert_function = [&value_converters,
3921 &single_threaded_value_converter](
3923 const size_t block_end) {
3924 const int num_cols = value_converters.size();
3925 const size_t start = thread_start_idx[
thread_id];
3926 const size_t end = thread_end_idx[
thread_id];
3928 bool stop_convert =
false;
3930 size_t local_idx = 0;
3931 for (idx = start; idx < end; ++idx, ++local_idx) {
3932 if (
UNLIKELY((local_idx & 0xFFFF) == 0 &&
3934 throw std::runtime_error(
3935 "Query execution has been interrupted while performing " +
3938 single_threaded_value_converter(idx, block_end, num_cols, stop_convert);
3944 for (idx = start; idx < end; ++idx) {
3945 single_threaded_value_converter(idx, end, num_cols, stop_convert);
3954 if (can_go_parallel) {
3955 const size_t entry_count = result_rows->entryCount();
3959 stride = (entry_count + num_worker_threads - 1) / num_worker_threads;
3960 i < num_worker_threads && start_entry < entry_count;
3961 ++i, start_entry += stride) {
3962 const auto end_entry = std::min(start_entry + stride, entry_count);
3963 thread_start_idx[i] = start_entry;
3964 thread_end_idx[i] = end_entry;
3967 thread_start_idx[0] = 0;
3968 thread_end_idx[0] = result_rows->entryCount();
3973 for (
size_t block_start = 0; block_start < num_rows;
3974 block_start += rows_per_block) {
3975 const auto num_rows_this_itr = block_start + rows_per_block < num_rows
3977 : num_rows - block_start;
3979 value_converters.clear();
3981 for (
const auto targetDescriptor : target_column_descriptors) {
3982 auto sourceDataMetaInfo =
res.targets_meta[colNum++];
3988 targetDescriptor->columnType,
3989 !targetDescriptor->columnType.get_notnull(),
3990 result_rows->getRowSetMemOwner()->getLiteralStringDictProxy(),
3992 sourceDataMetaInfo.get_type_info().is_dict_encoded_string()
3993 ? executor->getStringDictionaryProxy(
3994 sourceDataMetaInfo.get_type_info().get_comp_param(),
3995 result_rows->getRowSetMemOwner(),
3998 IS_GEO_POLY(targetDescriptor->columnType.get_type()) &&
4000 ? &render_group_analyzer_map
4002 auto converter = factory.
create(param);
4003 value_converters.push_back(std::move(converter));
4007 if (can_go_parallel) {
4008 std::vector<std::future<void>> worker_threads;
4009 for (
int i = 0; i < num_worker_threads; ++i) {
4010 worker_threads.push_back(
4014 for (
auto& child : worker_threads) {
4017 for (
auto& child : worker_threads) {
4022 single_threaded_convert_function(0, num_rows_this_itr);
4026 auto finalizer_func =
4027 [](std::unique_ptr<TargetValueConverter>::pointer targetValueConverter) {
4028 targetValueConverter->finalizeDataBlocksForInsertData();
4031 std::vector<std::future<void>> worker_threads;
4032 for (
auto& converterPtr : value_converters) {
4033 worker_threads.push_back(
4037 for (
auto& child : worker_threads) {
4040 for (
auto& child : worker_threads) {
4045 insert_data.
databaseId = catalog.getCurrentDB().dbId;
4048 insert_data.
numRows = num_rows_this_itr;
4050 for (
int col_idx = 0; col_idx < target_column_descriptors.size(); col_idx++) {
4053 throw std::runtime_error(
4054 "Query execution has been interrupted while performing " +
4057 value_converters[col_idx]->addDataBlocksToInsertData(insert_data);
4059 total_target_value_translate_time_ms +=
timer_stop(translate_clock_begin);
4062 auto data_memory_holder =
4064 insertDataLoader.
insertData(*session, insert_data);
4065 total_data_load_time_ms +=
timer_stop(data_load_clock_begin);
4072 }
catch (std::exception& e) {
4073 LOG(
ERROR) <<
"An error occurred during ITAS rollback attempt. Table id: "
4074 << td->
tableId <<
", Error: " << e.what();
4079 int64_t total_time_ms = total_source_query_time_ms +
4080 total_target_value_translate_time_ms + total_data_load_time_ms;
4082 VLOG(1) <<
"CTAS/ITAS " << total_row_count <<
" rows loaded in " << total_time_ms
4083 <<
"ms (outer_frag_count=" << outer_frag_count
4084 <<
", query_time=" << total_source_query_time_ms
4085 <<
"ms, translation_time=" << total_target_value_translate_time_ms
4086 <<
"ms, data_load_time=" << total_data_load_time_ms
4089 if (!is_temporary) {
4096 const std::string& table_name) {
4097 auto table_id = catalog.
getTableId(table_name);
4098 if (!table_id.has_value()) {
4099 throw std::runtime_error{
"Table \"" + table_name +
"\" does not exist."};
4101 return table_id.value();
4106 const std::string& query_str,
4108 const std::optional<std::string>& insert_table_name = {}) {
4110 const auto calciteQueryParsingOption =
4111 calcite_mgr->getCalciteQueryParsingOption(
true,
false,
true);
4112 const auto calciteOptimizationOption =
4114 const auto result = calcite_mgr->process(query_state_proxy,
4116 calciteQueryParsingOption,
4117 calciteOptimizationOption);
4120 auto comparator = [&catalog](
const std::string& table_1,
const std::string& table_2) {
4123 std::set<std::string, decltype(comparator)>
tables(comparator);
4124 for (
auto& tab :
result.resolved_accessed_objects.tables_selected_from) {
4127 if (insert_table_name.has_value()) {
4128 tables.emplace(insert_table_name.value());
4131 for (
const auto& table :
tables) {
4136 if (insert_table_name.has_value() && table == insert_table_name.value()) {
4153 bool read_only_mode) {
4154 if (read_only_mode) {
4155 throw std::runtime_error(
"INSERT INTO TABLE invalid in read only mode.");
4157 auto session_copy = session;
4158 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
4159 &session_copy, boost::null_deleter());
4161 auto stdlog =
STDLOG(query_state);
4162 auto& catalog = session_ptr->getCatalog();
4164 const auto execute_read_lock =
4170 throw std::runtime_error(
"ITAS failed: table " +
table_name_ +
" does not exist.");
4180 populateData(query_state->createQueryStateProxy(), td,
true,
false);
4188 if (payload.HasMember(
"temporary")) {
4194 if (payload.HasMember(
"ifNotExists")) {
4204 bool read_only_mode) {
4205 if (read_only_mode) {
4206 throw std::runtime_error(
"CREATE TABLE invalid in read only mode.");
4208 auto session_copy = session;
4209 auto session_ptr = std::shared_ptr<Catalog_Namespace::SessionInfo>(
4210 &session_copy, boost::null_deleter());
4212 auto stdlog =
STDLOG(query_state);
4217 std::set<std::string> select_tables;
4219 const auto execute_write_lock =
4227 throw std::runtime_error(
"CTAS failed. Table " +
table_name_ +
4228 " will not be created. User has no create privileges.");
4236 " already exists and no data was loaded.");
4242 auto validate_result = local_connector.
query(
4243 query_state->createQueryStateProxy(),
select_query_, {},
true,
false);
4245 const auto column_descriptors_for_create =
4249 for (
auto& cd : column_descriptors_for_create) {
4250 if (cd.columnType.is_decimal() && cd.columnType.get_precision() > 18) {
4251 throw std::runtime_error(cd.columnName +
": Precision too high, max 18.");
4258 td.
nColumns = column_descriptors_for_create.size();
4273 bool use_shared_dictionaries =
true;
4277 if (boost::to_lower_copy<std::string>(*p->get_name()) ==
4278 "use_shared_dictionaries") {
4281 if (
nullptr == literal) {
4282 throw std::runtime_error(
4283 "USE_SHARED_DICTIONARIES must be a string parameter");
4285 std::string val = boost::to_lower_copy<std::string>(*literal->
get_stringval());
4286 use_shared_dictionaries = val ==
"true" || val ==
"1" || val ==
"t";
4293 std::vector<SharedDictionaryDef> sharedDictionaryRefs;
4295 if (use_shared_dictionaries) {
4296 const auto source_column_descriptors =
4300 for (
auto& source_cd : source_column_descriptors) {
4301 const auto& ti = source_cd.columnType;
4302 if (ti.is_string()) {
4304 int dict_id = ti.get_comp_param();
4305 auto it = mapping.find(dict_id);
4306 if (mapping.end() != it) {
4307 const auto targetColumn = it->second;
4311 LOG(
INFO) <<
"CTAS: sharing text dictionary on column "
4312 << source_cd.columnName <<
" with " << targetTable->tableName
4313 <<
"." << targetColumn->columnName;
4314 sharedDictionaryRefs.emplace_back(
4315 source_cd.columnName, targetTable->tableName, targetColumn->columnName);
4325 catalog.
createTable(td, column_descriptors_for_create, sharedDictionaryRefs,
true);
4328 SysCatalog::instance().createDBObject(
4334 const auto execute_read_lock =
4343 populateData(query_state->createQueryStateProxy(), td,
false,
true);
4356 CHECK(payload.HasMember(
"tableName"));
4357 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4360 if (payload.HasMember(
"ifExists")) {
4361 if_exists_ =
json_bool(payload[
"ifExists"]);
4366 bool read_only_mode) {
4367 if (read_only_mode) {
4368 throw std::runtime_error(
"DROP TABLE invalid in read only mode.");
4370 const auto execute_read_lock =
4376 std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>> td_with_lock;
4379 std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::WriteLock>>(
4381 catalog, *
table_,
false));
4382 td = (*td_with_lock)();
4383 }
catch (
const std::runtime_error& e) {
4392 CHECK(td_with_lock);
4397 throw std::runtime_error(
"Table " + *
table_ +
4398 " will not be dropped. User has no proper privileges.");
4404 auto table_data_read_lock =
4409 auto table_data_write_lock =
4411 catalog.dropTable(td);
4415 bool read_only_mode) {}
4418 CHECK(payload.HasMember(
"tableName"));
4419 auto tableName =
json_str(payload[
"tableName"]);
4421 CHECK(payload.HasMember(
"alterType"));
4424 if (type ==
"RENAME_TABLE") {
4425 CHECK(payload.HasMember(
"newTableName"));
4426 auto newTableName =
json_str(payload[
"newTableName"]);
4428 new std::string(tableName),
new std::string(newTableName)));
4430 }
else if (type ==
"RENAME_COLUMN") {
4431 CHECK(payload.HasMember(
"columnName"));
4432 auto columnName =
json_str(payload[
"columnName"]);
4433 CHECK(payload.HasMember(
"newColumnName"));
4434 auto newColumnName =
json_str(payload[
"newColumnName"]);
4435 return std::unique_ptr<DDLStmt>(
4437 new std::string(columnName),
4438 new std::string(newColumnName)));
4440 }
else if (type ==
"ADD_COLUMN") {
4441 CHECK(payload.HasMember(
"columnData"));
4442 CHECK(payload[
"columnData"].IsArray());
4445 std::list<ColumnDef*>* table_element_list_ =
new std::list<ColumnDef*>;
4447 const auto elements = payload[
"columnData"].GetArray();
4448 for (
const auto& element : elements) {
4449 CHECK(element.IsObject());
4450 CHECK(element.HasMember(
"type"));
4451 if (
json_str(element[
"type"]) ==
"SQL_COLUMN_DECLARATION") {
4453 table_element_list_->emplace_back(col_def.release());
4455 LOG(
FATAL) <<
"Unsupported element type for ALTER TABLE: "
4456 << element[
"type"].GetString();
4460 return std::unique_ptr<DDLStmt>(
4463 }
else if (type ==
"DROP_COLUMN") {
4464 CHECK(payload.HasMember(
"columnData"));
4465 auto columnData =
json_str(payload[
"columnData"]);
4468 std::list<std::string*>* cols =
new std::list<std::string*>;
4469 std::vector<std::string> cols1;
4470 boost::split(cols1, columnData, boost::is_any_of(
","));
4471 for (
auto s : cols1) {
4473 boost::algorithm::trim_if(s, boost::is_any_of(
" \"'`"));
4474 std::string* str =
new std::string(s);
4475 cols->emplace_back(str);
4478 return std::unique_ptr<DDLStmt>(
4481 }
else if (type ==
"ALTER_OPTIONS") {
4482 CHECK(payload.HasMember(
"options"));
4484 if (payload[
"options"].IsObject()) {
4485 for (
const auto& option : payload[
"options"].GetObject()) {
4486 std::string* option_name =
new std::string(
json_str(option.name));
4488 if (option.value.IsString()) {
4489 std::string literal_string =
json_str(option.value);
4494 int iVal = std::stoi(literal_string, &sz);
4495 if (sz == literal_string.size()) {
4500 }
else if (option.value.IsInt() || option.value.IsInt64()) {
4502 }
else if (option.value.IsNull()) {
4505 throw std::runtime_error(
"Unable to handle literal for " + *option_name);
4507 CHECK(literal_value);
4510 return std::unique_ptr<DDLStmt>(
4515 CHECK(payload[
"options"].IsNull());
4522 CHECK(payload.HasMember(
"tableName"));
4523 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4527 bool read_only_mode) {
4528 if (read_only_mode) {
4529 throw std::runtime_error(
"TRUNCATE TABLE invalid in read only mode.");
4531 const auto execute_read_lock =
4536 const auto td_with_lock =
4539 const auto td = td_with_lock();
4541 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
4545 std::vector<DBObject> privObjects;
4549 privObjects.push_back(dbObject);
4550 if (!SysCatalog::instance().checkPrivileges(session.
get_currentUser(), privObjects)) {
4551 throw std::runtime_error(
"Table " + *
table_ +
" will not be truncated. User " +
4553 " has no proper privileges.");
4557 throw std::runtime_error(*
table_ +
" is a view. Cannot Truncate.");
4563 auto table_data_read_lock =
4568 auto table_data_write_lock =
4570 catalog.truncateTable(td);
4574 CHECK(payload.HasMember(
"tableName"));
4575 table_ = std::make_unique<std::string>(
json_str(payload[
"tableName"]));
4585 std::vector<DBObject> privObjects;
4589 privObjects.push_back(dbObject);
4590 return SysCatalog::instance().checkPrivileges(session_info.
get_currentUser(),
4596 bool read_only_mode) {
4597 if (read_only_mode) {
4598 throw std::runtime_error(
"OPTIMIZE TABLE invalid in read only mode.");
4602 const auto execute_read_lock =
4607 const auto td_with_lock =
4610 const auto td = td_with_lock();
4613 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
4617 throw std::runtime_error(
"OPTIMIZE TABLE command is not supported on views.");
4632 bool repair_type(std::list<std::unique_ptr<NameValueAssign>>& options) {
4633 for (
const auto& opt : options) {
4634 if (boost::iequals(*opt->get_name(),
"REPAIR_TYPE")) {
4636 static_cast<const StringLiteral*
>(opt->get_value())->get_stringval();
4641 throw std::runtime_error(
"REPAIR_TYPE must be REMOVE.");
4644 throw std::runtime_error(
"The only VALIDATE WITH options is REPAIR_TYPE.");
4653 throw std::runtime_error(
"Validation Type is required for VALIDATE command.");
4655 std::list<std::unique_ptr<NameValueAssign>> options;
4657 for (
const auto e : *with_opts) {
4658 options.emplace_back(e);
4667 CHECK(payload.HasMember(
"type"));
4668 type_ = std::make_unique<std::string>(
json_str(payload[
"type"]));
4670 std::list<std::unique_ptr<NameValueAssign>> options;
4682 std::vector<DBObject> privObjects;
4686 privObjects.push_back(dbObject);
4687 if (!SysCatalog::instance().checkPrivileges(session.
get_currentUser(), privObjects)) {
4688 throw std::runtime_error(
"Current user does not have the privilege to alter table: " +
4694 CHECK(payload.HasMember(
"name"));
4696 CHECK(payload.HasMember(
"newName"));
4701 bool read_only_mode) {
4702 if (read_only_mode) {
4703 throw std::runtime_error(
"RENAME TABLE invalid in read only mode.");
4706 throw std::runtime_error(
"Only a super user can rename users.");
4710 if (!SysCatalog::instance().getMetadataForUser(*
username_, user)) {
4711 throw std::runtime_error(
"User " + *
username_ +
" does not exist.");
4718 CHECK(payload.HasMember(
"name"));
4720 CHECK(payload.HasMember(
"newName"));
4725 bool read_only_mode) {
4726 if (read_only_mode) {
4727 throw std::runtime_error(
"RENAME DATABASE invalid in read only mode.");
4732 const auto execute_write_lock =
4737 if (!SysCatalog::instance().getMetadataForDB(*
database_name_, db)) {
4738 throw std::runtime_error(
"Database " + *
database_name_ +
" does not exist.");
4743 throw std::runtime_error(
"Only a super user or the owner can rename the database.");
4750 CHECK(payload.HasMember(
"tableNames"));
4751 CHECK(payload[
"tableNames"].IsArray());
4752 const auto elements = payload[
"tableNames"].GetArray();
4753 for (
const auto& element : elements) {
4754 CHECK(element.HasMember(
"name"));
4755 CHECK(element.HasMember(
"newName"));
4757 new std::string(
json_str(element[
"newName"])));
4766 std::list<std::pair<std::string, std::string>> tableNames) {
4767 for (
auto item : tableNames) {
4769 new std::string(item.second));
4784 std::time_t
result = std::time(
nullptr);
4789 sMap[oldName] = newName;
4794 std::string tableName) {
4795 if (sMap.find(tableName) != sMap.end()) {
4799 return sMap[tableName];
4804 sMap[tableName] = tableName;
4821 for (
auto it : sMap) {
4822 if ((it.second) !=
EMPTY_NAME && (it.first) != (it.second)) {
4823 throw std::runtime_error(
4824 "Error: Attempted to overwrite and lose data in table: \'" + (it.first) +
"\'");
4833 throw std::runtime_error(td->
tableName +
" is a foreign table. " +
4834 "Use ALTER FOREIGN TABLE.");
4840 bool read_only_mode) {
4841 if (read_only_mode) {
4842 throw std::runtime_error(
"RENAME TABLE invalid in read only mode.");
4847 const auto execute_write_lock =
4853 std::vector<std::pair<std::string, std::string>> names;
4858 std::string curTableName = *(item.first);
4859 std::string newTableName = *(item.second);
4866 std::string altCurTableName =
loadTable(catalog, tableSubtituteMap, curTableName);
4867 std::string altNewTableName =
loadTable(catalog, tableSubtituteMap, newTableName);
4869 if (altCurTableName != curTableName && altCurTableName !=
EMPTY_NAME) {
4871 recordRename(tableSubtituteMap, curTableName, curTableName);
4882 if (
hasData(tableSubtituteMap, altCurTableName)) {
4891 if (
hasData(tableSubtituteMap, altNewTableName)) {
4896 recordRename(tableSubtituteMap, altNewTableName, tmpNewTableName);
4897 recordRename(tableSubtituteMap, tmpNewTableName, tmpNewTableName);
4898 names.emplace_back(altNewTableName, tmpNewTableName);
4899 names.emplace_back(altCurTableName, altNewTableName);
4903 recordRename(tableSubtituteMap, altNewTableName, altNewTableName);
4904 names.emplace_back(altCurTableName, altNewTableName);
4907 throw std::runtime_error(
"Source table \'" + curTableName +
"\' does not exist.");
4915 while (!tablesToRename_.empty()) {
4916 tablesToRename_.pop_front();
4923 if (cc ==
nullptr) {
4928 std::string default_value;
4929 const std::string* default_value_ptr =
nullptr;
4932 auto defaultsp =
dynamic_cast<const StringLiteral*
>(def_val_literal);
4934 defaultsp ? *defaultsp->
get_stringval() : def_val_literal->to_string();
4939 std::regex array_re(R
"(^ARRAY\s*\[(.*)\]$)", std::regex_constants::icase);
4940 default_value = std::regex_replace(default_value, array_re, "{$1}");
4941 boost::erase_all(default_value,
"\'");
4943 default_value_ptr = &default_value;
4958 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
4961 throw std::runtime_error(
"Adding columns to a view is not supported.");
4965 throw std::runtime_error(
4966 "Adding columns to temporary tables is not yet supported.");
4976 for (
const auto& coldef :
coldefs_) {
4977 auto& new_column_name = *coldef->get_column_name();
4979 throw std::runtime_error(
"Column " + new_column_name +
" already exists.");
4985 bool read_only_mode) {
4986 if (read_only_mode) {
4987 throw std::runtime_error(
"ADD COLUMN invalid in read only mode.");
4990 const auto execute_write_lock =
4995 const auto td_with_lock =
4998 const auto td = td_with_lock();
5003 if (std::dynamic_pointer_cast<Fragmenter_Namespace::SortedOrderFragmenter>(
5005 throw std::runtime_error(
5006 "Adding columns to a table is not supported when using the \"sort_column\" "
5011 std::vector<int> table_key{catalog.getCurrentDB().dbId, td->
tableId};
5018 catalog.getSqliteConnector().query(
"BEGIN TRANSACTION");
5020 std::map<const std::string, const ColumnDescriptor> cds;
5021 std::map<const int, const ColumnDef*> cid_coldefs;
5022 for (
const auto& coldef :
coldefs_) {
5025 catalog.addColumn(*td, cd);
5026 cds.emplace(*coldef->get_column_name(), cd);
5027 cid_coldefs.emplace(cd.
columnId, coldef.get());
5031 std::list<ColumnDescriptor> phy_geo_columns;
5032 catalog.expandGeoColumn(cd, phy_geo_columns);
5033 for (
auto& cd : phy_geo_columns) {
5034 catalog.addColumn(*td, cd);
5036 cid_coldefs.emplace(cd.
columnId,
nullptr);
5042 std::vector<std::unique_ptr<import_export::TypedImportBuffer>> import_buffers;
5043 for (
const auto& cd : cds) {
5044 import_buffers.emplace_back(std::make_unique<import_export::TypedImportBuffer>(
5045 &cd.second, loader->getStringDict(&cd.second)));
5047 loader->setAddingColumns(
true);
5051 import_buffers.end(),
5052 [](decltype(import_buffers[0])&
a, decltype(import_buffers[0])& b) {
5053 return a->getColumnDesc()->columnId < b->getColumnDesc()->columnId;
5059 const auto physical_tds = catalog.getPhysicalTablesDescriptors(td);
5061 std::for_each(physical_tds.begin(), physical_tds.end(), [&nrows](
const auto& td) {
5066 int skip_physical_cols = 0;
5067 for (
const auto cit : cid_coldefs) {
5068 const auto cd = catalog.getMetadataForColumn(td->
tableId, cit.first);
5069 const auto coldef = cit.second;
5070 const bool is_null = !cd->default_value.has_value();
5072 if (cd->columnType.get_notnull() &&
is_null) {
5073 throw std::runtime_error(
"Default value required for column " + cd->columnName +
5074 " because of NOT NULL constraint");
5077 for (
auto it = import_buffers.begin(); it < import_buffers.end(); ++it) {
5078 auto& import_buffer = *it;
5079 if (cd->columnId == import_buffer->getColumnDesc()->columnId) {
5080 if (coldef !=
nullptr ||
5081 skip_physical_cols-- <= 0) {
5082 import_buffer->add_value(cd,
5083 cd->default_value.value_or(
"NULL"),
5086 if (cd->columnType.is_geometry()) {
5087 std::vector<double> coords, bounds;
5088 std::vector<int> ring_sizes, poly_rings;
5089 int render_group = 0;
5092 cd->default_value.value_or(
"NULL"),
5099 throw std::runtime_error(
"Bad geometry data: '" +
5100 cd->default_value.value_or(
"NULL") +
"'");
5102 size_t col_idx = 1 + std::distance(import_buffers.begin(), it);
5113 skip_physical_cols = cd->columnType.get_physical_cols();
5122 if (!loader->loadNoCheckpoint(import_buffers, nrows, &session)) {
5123 throw std::runtime_error(
"loadNoCheckpoint failed!");
5126 catalog.resetTableEpochFloor(td->
tableId);
5127 loader->checkpoint();
5128 catalog.getSqliteConnector().query(
"END TRANSACTION");
5130 catalog.roll(
false);
5131 catalog.getSqliteConnector().query(
"ROLLBACK TRANSACTION");
5137 bool read_only_mode) {
5138 if (read_only_mode) {
5139 throw std::runtime_error(
"DROP COLUMN invalid in read only mode.");
5142 const auto execute_write_lock =
5147 const auto td_with_lock =
5150 const auto td = td_with_lock();
5152 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5156 throw std::runtime_error(
"Dropping a column from a view is not supported.");
5159 throw std::runtime_error(
5160 "Dropping a column from a temporary table is not yet supported.");
5165 for (
const auto& column :
columns_) {
5166 if (
nullptr == catalog.getMetadataForColumn(td->
tableId, *column)) {
5167 throw std::runtime_error(
"Column " + *column +
" does not exist.");
5172 throw std::runtime_error(
"Table " + *
table_ +
" has only one column.");
5178 catalog.getSqliteConnector().query(
"BEGIN TRANSACTION");
5180 std::vector<int> columnIds;
5181 for (
const auto& column : columns_) {
5184 throw std::runtime_error(
"Dropping sharding column " + cd.
columnName +
5185 " is not supported.");
5187 catalog.dropColumn(*td, cd);
5190 const auto pcd = catalog.getMetadataForColumn(td->
tableId, cd.
columnId + i + 1);
5192 catalog.dropColumn(*td, *pcd);
5193 columnIds.push_back(cd.
columnId + i + 1);
5197 for (
auto shard : catalog.getPhysicalTablesDescriptors(td)) {
5198 shard->fragmenter->dropColumns(columnIds);
5202 throw std::runtime_error(
"lol!");
5206 catalog.resetTableEpochFloor(td->
tableId);
5207 catalog.checkpoint(td->
tableId);
5209 catalog.getSqliteConnector().query(
"END TRANSACTION");
5211 catalog.setForReload(td->
tableId);
5212 catalog.roll(
false);
5213 catalog.getSqliteConnector().query(
"ROLLBACK TRANSACTION");
5219 bool read_only_mode) {
5220 if (read_only_mode) {
5221 throw std::runtime_error(
"RENAME COLUMN invalid in read only mode.");
5225 const auto execute_read_lock =
5230 const auto td_with_lock =
5232 catalog, *
table_,
false);
5233 const auto td = td_with_lock();
5239 if (cd ==
nullptr) {
5240 throw std::runtime_error(
"Column " + *
column_ +
" does not exist.");
5243 throw std::runtime_error(
"Column " + *
new_column_name_ +
" already exists.");
5249 bool read_only_mode) {
5250 if (read_only_mode) {
5251 throw std::runtime_error(
"ALTER TABLE invalid in read only mode.");
5253 enum TableParamType { MaxRollbackEpochs,
Epoch, MaxRows };
5254 static const std::unordered_map<std::string, TableParamType> param_map = {
5255 {
"max_rollback_epochs", TableParamType::MaxRollbackEpochs},
5256 {
"epoch", TableParamType::Epoch},
5257 {
"max_rows", TableParamType::MaxRows}};
5258 const auto execute_read_lock =
5263 const auto td_with_lock =
5265 catalog, *
table_,
false);
5266 const auto td = td_with_lock();
5268 throw std::runtime_error(
"Table " + *
table_ +
" does not exist.");
5271 throw std::runtime_error(
"Setting parameters for a view is not supported.");
5274 throw std::runtime_error(
5275 "Setting parameters for a temporary table is not yet supported.");
5280 std::vector<int> table_key{catalog.getCurrentDB().dbId, td->
tableId};
5283 std::string param_name(*
param_->get_name());
5287 if (val_int_literal ==
nullptr) {
5288 throw std::runtime_error(
"Table parameters should be integers.");
5290 const int64_t param_val = val_int_literal->
get_intval();
5292 const auto param_it = param_map.find(param_name);
5293 if (param_it == param_map.end()) {
5294 throw std::runtime_error(param_name +
" is not a settable table parameter.");
5296 switch (param_it->second) {
5297 case MaxRollbackEpochs: {
5298 catalog.setMaxRollbackEpochs(td->
tableId, param_val);
5302 catalog.setTableEpoch(catalog.getDatabaseId(), td->
tableId, param_val);
5306 catalog.setMaxRows(td->
tableId, param_val);
5310 UNREACHABLE() <<
"Unexpected TableParamType value: " << param_it->second
5311 <<
", key: " << param_it->first;
5318 std::list<NameValueAssign*>* o)
5319 : table_(t), copy_from_source_pattern_(f), success_(
true) {
5321 for (
const auto e : *o) {
5329 CHECK(payload.HasMember(
"table"));
5330 table_ = std::make_unique<std::string>(
json_str(payload[
"table"]));
5332 CHECK(payload.HasMember(
"filePath"));
5333 std::string fs =
json_str(payload[
"filePath"]);
5335 boost::algorithm::trim_if(fs, boost::is_any_of(
" \"'`"));
5342 bool read_only_mode) {
5343 if (read_only_mode) {
5344 throw std::runtime_error(
"IMPORT invalid in read only mode.");
5348 const std::string& copy_from_source,
5350 -> std::unique_ptr<import_export::AbstractImporter> {
5353 return execute(session, read_only_mode, importer_factory);
5358 bool read_only_mode,
5359 const std::function<std::unique_ptr<import_export::AbstractImporter>(
5364 if (read_only_mode) {
5365 throw std::runtime_error(
"COPY FROM invalid in read only mode.");
5368 size_t total_time = 0;
5371 const auto execute_read_lock =
5377 std::unique_ptr<lockmgr::TableSchemaLockContainer<lockmgr::ReadLock>> td_with_lock;
5378 std::unique_ptr<lockmgr::WriteLock> insert_data_lock;
5383 td_with_lock = std::make_unique<lockmgr::TableSchemaLockContainer<lockmgr::ReadLock>>(
5386 td = (*td_with_lock)();
5387 insert_data_lock = std::make_unique<lockmgr::WriteLock>(
5389 }
catch (
const std::runtime_error& e) {