Files
oceanbase/src/sql/printer/ob_dml_stmt_printer.cpp
helloamateur ce458e96f8 [FEAT MERGE] ARRAY EXPRS IMPLEMENTS
Co-authored-by: qijiax <qijia_xu@163.com>
2024-11-21 13:44:48 +00:00

2516 lines
89 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX SQL
#include "sql/printer/ob_dml_stmt_printer.h"
#include "sql/printer/ob_select_stmt_printer.h"
#include "sql/ob_sql_context.h"
#include "sql/resolver/dml/ob_del_upd_stmt.h"
#include "common/ob_smart_call.h"
#include "lib/charset/ob_charset.h"
#include "sql/optimizer/ob_log_plan.h"
#include "sql/monitor/ob_sql_plan.h"
namespace oceanbase
{
using namespace common;
namespace sql
{
ObDMLStmtPrinter::ObDMLStmtPrinter(char *buf, int64_t buf_len, int64_t *pos, const ObDMLStmt *stmt,
ObSchemaGetterGuard *schema_guard,
ObObjPrintParams print_params,
const ParamStore *param_store,
const ObSQLSessionInfo *session)
: buf_(buf),
buf_len_(buf_len),
pos_(pos),
stmt_(stmt),
is_root_(false),
is_first_stmt_for_hint_(false),
print_cte_(false),
schema_guard_(schema_guard),
print_params_(print_params),
expr_printer_(buf, buf_len, pos, schema_guard_, print_params_, param_store),
param_store_(param_store),
session_(session)
{
}
ObDMLStmtPrinter::~ObDMLStmtPrinter()
{
}
void ObDMLStmtPrinter::init(char *buf, int64_t buf_len, int64_t *pos, ObDMLStmt *stmt)
{
buf_ = buf;
buf_len_ = buf_len;
pos_ = pos;
stmt_ = stmt;
print_cte_ = false;
}
int ObDMLStmtPrinter::prepare_dblink_hint(ObQueryHint &query_hint_dblink)
{
int ret = OB_SUCCESS;
if (!print_params_.for_dblink_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected to print dblink hint", K(ret), K(print_params_.for_dblink_));
} else if (is_first_stmt_for_hint_) {
const ObQueryHint &query_hint = stmt_->get_query_ctx()->get_query_hint();
const ObGlobalHint &global_hint = query_hint.get_global_hint();
ObGlobalHint &global_hint_dblink = query_hint_dblink.get_global_hint();
global_hint_dblink.reset();
global_hint_dblink.merge_query_timeout_hint(global_hint.query_timeout_);
global_hint_dblink.merge_read_consistency_hint(global_hint.read_consistency_, global_hint.frozen_version_);
global_hint_dblink.merge_log_level_hint(global_hint.log_level_);
global_hint_dblink.force_trace_log_ = global_hint.force_trace_log_;
global_hint_dblink.monitor_ = global_hint.monitor_;
int64_t session_query_timeout_us = 0;
if (OB_ISNULL(session_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null ptr", K(ret), K(lbt()));
} else if (stmt_->is_select_stmt()) {
uint64_t dblink_id = OB_INVALID_ID;
dblink_id = stmt_->get_dblink_id();
if (0 == dblink_id) {
// set dblink_info, to unparse a link sql with dblink_info hint
oceanbase::sql::ObReverseLink *reverse_dblink_info = NULL;
if (OB_FAIL(const_cast<oceanbase::sql::ObSQLSessionInfo *>(session_)->get_dblink_context().get_reverse_link(reverse_dblink_info))) {
LOG_WARN("failed to get reverse link info from session", K(ret), K(session_->get_sessid()));
} else if (NULL == reverse_dblink_info) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else {
query_hint_dblink.get_global_hint().merge_tm_sessid_tx_id(reverse_dblink_info->get_tx_id(),
reverse_dblink_info->get_tm_sessid());
LOG_TRACE("set tx_id_ and tm_sessid to stmt", K(reverse_dblink_info->get_tx_id()),
K(reverse_dblink_info->get_tm_sessid()));
}
} else {
// reset dblink hint, to unparse a link sql without dblink_info hint
query_hint_dblink.get_global_hint().reset_tm_sessid_tx_id_hint();
}
if ((session_->is_in_transaction() &&
transaction::ObTxIsolationLevel::RC == session_->get_tx_desc()->get_isolation_level()) ||
!session_->is_in_transaction()) {
query_hint_dblink.get_global_hint().set_flashback_read_tx_uncommitted(true);
}
// link scan have not xa_trans_stop_check_lock hint
query_hint_dblink.get_global_hint().set_xa_trans_stop_check_lock(false);
} else { // T_INSERT T_DELETE T_UPDATE T_MERGE
bool has_reverse_link = false;
// link dml have not tm_sessid and tx_id hint
query_hint_dblink.get_global_hint().reset_tm_sessid_tx_id_hint();
if (OB_FAIL(ObDblinkUtils::has_reverse_link_or_any_dblink(stmt_, has_reverse_link))) {
LOG_WARN("failed to exec has_reverse_link", K(ret));
} else {
/**
restore xa_trans_stop_check_lock info, to avoid affecting the next execution flow.
if xa_trans_stop_check_lock == true and this is RM(0==dblink_id), RM will stop check xa lock.
eg:
step 1.
TM get sql1 like "insert into t2@my_link1 select a.c1, b.c2 from t1 a, t2@my_link1 b where a.c1=b.c1;",
and my_link1 and my_link2 have the same conneciton info.
step 2.
TM will send sql2 to RM like below
insert into "LCQ1"."T2"("C1","C2") select "A"."C1" AS "C1","LCQ1"."B"."C2" AS "C2" from "LCQ1"."T1"@! "A","LCQ1"."T2" "B" where ("A"."C1" = "LCQ1"."B"."C1")
TM will attach DBLINK_XA_TRANS_STOP_CHECK_LOCK hint to sql2, telling RM to stop check xa lock.
step 3.
RM get sql2, stop checking xa lock, then send sql3 like below to TM
"select * from T2@my_link2"
step 4.
TM get sql3, and send sql4 like below to RM
"select * from T2"
RM received sql4 and the meantime of excuting of sql2 is still runing.
sql4 can excuted directory without wait ending of sql2, cause sql2 has stoped check xa lock.
*/
// When TM detects a reverse link in the SQL sent to RM, add a xa_trans_stop_check_lock hint tag to the SQL.
query_hint_dblink.get_global_hint().set_xa_trans_stop_check_lock(has_reverse_link);
}
}
if (OB_SUCC(ret) && -1 == query_hint_dblink.get_global_hint().query_timeout_) {
if (OB_FAIL(session_->get_query_timeout(session_query_timeout_us))) {
LOG_WARN("failed to get session query timeout", K(ret));
} else {
query_hint_dblink.get_global_hint().merge_query_timeout_hint(session_query_timeout_us);
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_hint()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(stmt_->get_query_ctx()) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else {
const char *hint_begin = "/*+";
const char *hint_end = " */";
DATA_PRINTF("%s", hint_begin);
if (OB_SUCC(ret)) {
const ObQueryHint &query_hint = stmt_->get_query_ctx()->get_query_hint();
ObQueryHint query_hint_dblink;
if (print_params_.for_dblink_ &&
is_first_stmt_for_hint_ &&
OB_FAIL(prepare_dblink_hint(query_hint_dblink))) {
LOG_WARN("failed to print dblink hint", K(ret));
}
PlanText plan_text;
plan_text.buf_ = buf_;
plan_text.buf_len_ = buf_len_;
plan_text.pos_ = *pos_;
plan_text.is_oneline_ = true;
plan_text.type_ = print_params_.for_dblink_
? EXPLAIN_DBLINK_STMT
: EXPLAIN_UNINITIALIZED; // just for print hint, ExplainType set as invalid type
if (OB_FAIL(ret)) {
// do nothing
} else if (print_params_.for_dblink_ && is_first_stmt_for_hint_ && OB_FAIL(query_hint_dblink.get_global_hint().print_global_hint(plan_text))) {
LOG_WARN("failed to print stmt hint", K(ret));
} else if (!print_params_.for_dblink_ && OB_FAIL(query_hint.print_stmt_hint(plan_text, *stmt_, is_first_stmt_for_hint_))) {
LOG_WARN("failed to print stmt hint", K(ret));
} else if (plan_text.pos_ == *pos_) {
// no hint, roolback buffer!
*pos_ -= strlen(hint_begin);
} else {
*pos_ = plan_text.pos_;
DATA_PRINTF("%s", hint_end);
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_from(bool need_from)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else {
int64_t from_item_size = stmt_->get_from_item_size();
if (from_item_size > 0) {
if (need_from) {
DATA_PRINTF(" from ");
}
for (int64_t i = 0; OB_SUCC(ret) && i < from_item_size; ++i) {
const FromItem &from_item = stmt_->get_from_item(i);
const TableItem *table_item = NULL;
if (from_item.is_joined_) {
table_item = stmt_->get_joined_table(from_item.table_id_);
} else {
table_item = stmt_->get_table_item_by_id(from_item.table_id_);
}
if (OB_ISNULL(table_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table_item should not be NULL", K(ret));
} else if (OB_FAIL(print_table(table_item))) {
LOG_WARN("fail to print table", K(ret), K(*table_item));
} else {
DATA_PRINTF(",");
}
}
if (OB_SUCC(ret)) {
--*pos_;
}
} else if (0 != stmt_->get_condition_exprs().count()) {
// create view v as select 1 from dual where 1;
DATA_PRINTF(" from DUAL");
} else if (lib::is_oracle_mode() && 0 == from_item_size) {
// select 1 from dual
// in oracle mode
DATA_PRINTF(" from DUAL");
}
if (OB_SUCC(ret) && !print_params_.for_dblink_) {
if (OB_FAIL(print_semi_join())) {
LOG_WARN("failed to print semi info", K(ret));
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_table_with_subquery(const TableItem *table_item)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(table_item) ||
OB_ISNULL(table_item->ref_query_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret));
} else {
// force print alias name for select item in generated table. Otherwise,
// create view v as select 1 from dual where 1 > (select `abs(c1)` from (select abs(c1) from t));
// Definition of v would be:
// CREATE VIEW `v` AS select 1 AS `1` from DUAL where (1 > (select `abs(c1)` from ((select abs(`test`.`t`.`c1`) from `test`.`t`)) ))
// `abs(c1)` would be an unknown column.
const uint64_t subquery_print_params =
PRINT_BRACKET |
(stmt_->is_select_stmt() ? FORCE_COL_ALIAS : 0);
if (table_item->is_lateral_table()) {
DATA_PRINTF("lateral ");
}
if (OB_SUCC(ret) && OB_FAIL(print_subquery(table_item->ref_query_,
subquery_print_params))) {
LOG_WARN("failed to print subquery", K(ret));
} else if (!table_item->alias_name_.empty()) {
DATA_PRINTF(" ");
PRINT_IDENT_WITH_QUOT(table_item->alias_name_);
} else {
DATA_PRINTF(" ");
PRINT_TABLE_NAME(print_params_, table_item);
}
}
return ret;
}
int ObDMLStmtPrinter::print_table(const TableItem *table_item,
bool no_print_alias/*default false*/)
{
int ret = OB_SUCCESS;
bool is_stack_overflow = false;
if (OB_FAIL(check_stack_overflow(is_stack_overflow))) {
LOG_WARN("failed to check stack overflow", K(ret), K(is_stack_overflow));
} else if (is_stack_overflow) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow));
} else if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_) || OB_ISNULL(table_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else {
switch (table_item->type_) {
case TableItem::LINK_TABLE: {
if (OB_FAIL(print_base_table(table_item))) {
LOG_WARN("failed to print base table", K(ret), K(*table_item));
} else if (!no_print_alias && !table_item->alias_name_.empty()) {
DATA_PRINTF(lib::is_oracle_mode() ? " \"%.*s\"" : " `%.*s`",
LEN_AND_PTR(table_item->alias_name_));
}
break;
}
case TableItem::BASE_TABLE: {
if (OB_FAIL(print_base_table(table_item))) {
LOG_WARN("failed to print base table", K(ret), K(*table_item));
} else if (!no_print_alias && !table_item->alias_name_.empty()) {
DATA_PRINTF(lib::is_oracle_mode() ? " \"%.*s\"" : " `%.*s`",
LEN_AND_PTR(table_item->alias_name_));
}
break;
}
case TableItem::ALIAS_TABLE: {
if (OB_FAIL(print_base_table(table_item))) {
LOG_WARN("failed to print base table", K(ret), K(*table_item));
//table in insert all can't print alias(bug:
} else if (!no_print_alias) {
DATA_PRINTF(" ");
PRINT_IDENT_WITH_QUOT(table_item->alias_name_);
}
break;
}
case TableItem::JOINED_TABLE: {
const JoinedTable *join_table = static_cast<const JoinedTable*>(table_item);
if (OB_ISNULL(join_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("join_table should not be NULL", K(ret));
} else {
// left table
const TableItem *left_table = join_table->left_table_;
if (OB_ISNULL(left_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("left_table should not be NULL", K(ret));
} else {
DATA_PRINTF("(");
if (OB_SUCC(ret)) {
if (OB_FAIL(SMART_CALL(print_table(left_table)))) {
LOG_WARN("fail to print left table", K(ret), K(*left_table));
}
}
// join type
if (OB_SUCC(ret)) {
// not support cross join and natural join
ObString type_str("");
switch (join_table->joined_type_) {
case FULL_OUTER_JOIN: {
type_str = "full join";
break;
}
case LEFT_OUTER_JOIN: {
type_str = "left join";
break;
}
case RIGHT_OUTER_JOIN: {
type_str = "right join";
break;
}
case INNER_JOIN: {
type_str = join_table->is_straight_join_ ? "straight_join" : "join";
break;
}
case CONNECT_BY_JOIN: {
type_str = "connect by join";
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown join type", K(ret), K(join_table->joined_type_));
break;
}
}
DATA_PRINTF(" %.*s ", LEN_AND_PTR(type_str));
}
// right table
if (OB_SUCC(ret)) {
const TableItem *right_table = join_table->right_table_;
if (OB_ISNULL(right_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("right_table should not be NULL", K(ret));
} else if (OB_FAIL(SMART_CALL(print_table(right_table)))) {
LOG_WARN("fail to print right table", K(ret), K(*right_table));
} else {
// join conditions
const ObIArray<ObRawExpr*> &join_conditions =
join_table->join_conditions_;
int64_t join_conditions_size = join_conditions.count();
if (join_conditions_size > 0) {
DATA_PRINTF(" on ");
for (int64_t i = 0; OB_SUCC(ret) && i < join_conditions_size;
++i) {
if (OB_FAIL(expr_printer_.do_print(join_conditions.at(i), T_NONE_SCOPE))) {
LOG_WARN("fail to print join condition", K(ret));
}
DATA_PRINTF(" and ");
}
if (OB_SUCC(ret)) {
*pos_ -= 5; // strlen(" and ")
}
} else {
DATA_PRINTF(" on 1=1 ");
}
DATA_PRINTF(")");
}
}
}
}
break;
}
case TableItem::LATERAL_TABLE:
case TableItem::GENERATED_TABLE: {
if (OB_ISNULL(table_item->ref_query_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table item ref query is null", K(ret));
// generated_table cannot appear in view_definition
// view在resolver阶段被转换为生成表, 需要当做基表处理
} else if (table_item->is_view_table_ && !print_params_.for_dblink_) {
PRINT_TABLE_NAME(print_params_, table_item);
if (OB_SUCC(ret)) {
if (table_item->alias_name_.length() > 0) {
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item->alias_name_));
}
}
} else if (table_item->cte_type_ != TableItem::NOT_CTE && !print_params_.for_dblink_) {
PRINT_TABLE_NAME(print_params_, table_item);
if (table_item->alias_name_.length() > 0) {
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item->alias_name_));
}
} else if (OB_FAIL(print_table_with_subquery(table_item))) {
LOG_WARN("failed to print table with subquery", K(ret));
}
break;
}
case TableItem::CTE_TABLE: {
PRINT_TABLE_NAME(print_params_, table_item);
if (! table_item->alias_name_.empty()) {
DATA_PRINTF(" ");
PRINT_IDENT_WITH_QUOT(table_item->alias_name_);
}
break;
}
case TableItem::FUNCTION_TABLE: {
DATA_PRINTF("TABLE(");
OZ (expr_printer_.do_print(table_item->function_table_expr_, T_FROM_SCOPE));
DATA_PRINTF(") ");
PRINT_IDENT_WITH_QUOT(table_item->alias_name_);
break;
}
case TableItem::JSON_TABLE: {
switch (table_item->json_table_def_->table_type_) {
case MulModeTableType::OB_ORA_JSON_TABLE_TYPE : {
DATA_PRINTF("JSON_TABLE(");
OZ (expr_printer_.do_print(table_item->json_table_def_->doc_exprs_.at(0), T_FROM_SCOPE));
OZ (print_json_table(table_item));
DATA_PRINTF(")");
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item->alias_name_));
break;
}
case MulModeTableType::OB_ORA_XML_TABLE_TYPE : {
DATA_PRINTF("XMLTABLE(");
OZ (print_xml_table(table_item));
DATA_PRINTF(")");
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item->alias_name_));
break;
}
case MulModeTableType::OB_RB_ITERATE_TABLE_TYPE : {
if (table_item->json_table_def_->doc_exprs_.count() > 1 ) {
ret = OB_NOT_SUPPORTED;
LOG_USER_ERROR(OB_NOT_SUPPORTED, "print rb_iterate table with more than 1 params");
} else {
DATA_PRINTF("RB_ITERATE(");
if (OB_FAIL(expr_printer_.do_print(table_item->json_table_def_->doc_exprs_.at(0), T_FROM_SCOPE))) {
LOG_WARN("failed to print expr", K(ret));
}
DATA_PRINTF(")");
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item->alias_name_));
DATA_PRINTF("(");
DATA_PRINTF("%.*s", LEN_AND_PTR(table_item->json_table_def_->all_cols_.at(1)->col_name_));
DATA_PRINTF(")");
}
break;
}
case MulModeTableType::OB_UNNEST_TABLE_TYPE : {
DATA_PRINTF("UNNEST(");
for (int64_t i = 0; OB_SUCC(ret) && i < table_item->json_table_def_->doc_exprs_.count(); ++i) {
if (OB_FAIL(expr_printer_.do_print(table_item->json_table_def_->doc_exprs_.at(i), T_FROM_SCOPE))) {
LOG_WARN("failed to print expr", K(ret));
} else if (i != table_item->json_table_def_->doc_exprs_.count() - 1) {
DATA_PRINTF(",");
} else {
DATA_PRINTF(")");
}
}
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item->alias_name_));
DATA_PRINTF("(");
for (int64_t i = 1; OB_SUCC(ret) && i < table_item->json_table_def_->all_cols_.count(); ++i) {
DATA_PRINTF("%.*s", LEN_AND_PTR(table_item->json_table_def_->all_cols_.at(i)->col_name_));
if (i != table_item->json_table_def_->all_cols_.count() - 1) {
DATA_PRINTF(",");
} else {
DATA_PRINTF(")");
}
}
break;
}
default : {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected table function type");
}
}
break;
}
case TableItem::TEMP_TABLE: {
if (!print_params_.for_dblink_) {
PRINT_TABLE_NAME(print_params_, table_item);
if (!table_item->alias_name_.empty()) {
DATA_PRINTF(" ");
PRINT_IDENT_WITH_QUOT(table_item->alias_name_);
}
} else if (OB_FAIL(print_table_with_subquery(table_item))) {
LOG_WARN("failed to print table with subquery", K(ret));
}
break;
}
case TableItem::VALUES_TABLE: {
if (OB_FAIL(print_values_table(*table_item, no_print_alias))) {
LOG_WARN("failed to print values table", K(ret));
}
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown table type", K(ret), K(table_item->type_));
break;
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_values_table(const TableItem &table_item, bool no_print_alias)
{
int ret = OB_SUCCESS;
ObValuesTableDef *table_def = table_item.values_table_def_;
if (print_params_.for_dblink_ || lib::is_oracle_mode()) {
if (OB_FAIL(print_values_table_to_union_all(table_item, no_print_alias))) {
LOG_WARN("failed to print values table for dblink", K(ret));
}
} else if (OB_UNLIKELY(!table_item.is_values_table()) || OB_ISNULL(table_def)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("values table def should not be NULL", K(ret), KP(table_def));
} else {
const int64_t column_cnt = table_def->column_cnt_;
if (ObValuesTableDef::ACCESS_EXPR == table_def->access_type_ ||
ObValuesTableDef::FOLD_ACCESS_EXPR == table_def->access_type_) {
const ObIArray<ObRawExpr *> &values = table_def->access_exprs_;
if (OB_UNLIKELY(column_cnt <= 0 || values.empty() || values.count() % column_cnt != 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(column_cnt), K(values));
} else {
DATA_PRINTF("(VALUES ");
for (int64_t i = 0; OB_SUCC(ret) && i < values.count(); ++i) {
if (i % column_cnt == 0) {
if (i == 0) {
DATA_PRINTF("ROW("); // first row
} else {
DATA_PRINTF("), ROW("); // next row
}
}
if (OB_SUCC(ret)) {
OZ (expr_printer_.do_print(values.at(i), T_FROM_SCOPE));
if (OB_SUCC(ret) && (i + 1) % column_cnt != 0) {
DATA_PRINTF(", ");
}
}
}
DATA_PRINTF("))");
DATA_PRINTF(" %.*s", LEN_AND_PTR(table_item.alias_name_));
}
} else {
DATA_PRINTF("%.*s", LEN_AND_PTR(table_item.get_table_name()));
}
}
return ret;
}
int ObDMLStmtPrinter::print_values_table_to_union_all(const TableItem &table_item, bool no_print_alias)
{
int ret = OB_SUCCESS;
ObValuesTableDef *table_def = table_item.values_table_def_;
if (OB_UNLIKELY(!table_item.is_values_table()) || OB_ISNULL(table_def)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("values table def should not be NULL", K(ret), KP(table_def));
} else {
int64_t column_cnt = table_def->column_cnt_;
int64_t row_cnt = table_def->row_cnt_;
if (OB_UNLIKELY(column_cnt <= 0) || OB_UNLIKELY(row_cnt <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(column_cnt), K(row_cnt));
} else if (ObValuesTableDef::ACCESS_EXPR == table_def->access_type_ ||
ObValuesTableDef::FOLD_ACCESS_EXPR == table_def->access_type_) {
const ObIArray<ObRawExpr *> &values = table_def->access_exprs_;
if (OB_UNLIKELY(values.count() % column_cnt != 0 || values.empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got unexpected param", K(ret));
}
DATA_PRINTF("(");
for (int64_t i = 0; OB_SUCC(ret) && i < values.count(); ++i) {
if (i % column_cnt == 0) {
if (i == 0) {
DATA_PRINTF("SELECT ");
} else {
DATA_PRINTF(" FROM DUAL UNION ALL SELECT ");
}
}
if (OB_SUCC(ret)) {
OZ (expr_printer_.do_print(values.at(i), T_FROM_SCOPE));
if (i < column_cnt) {
DATA_PRINTF(" AS \"column_%ld\"", i);
}
if ((i + 1) % column_cnt != 0) {
DATA_PRINTF(", ");
}
}
}
DATA_PRINTF(" FROM DUAL) \"%.*s\"", LEN_AND_PTR(table_item.alias_name_));
} else if (ObValuesTableDef::ACCESS_PARAM == table_def->access_type_) {
const int64_t start_idx = table_def->start_param_idx_;
const int64_t end_idx = table_def->end_param_idx_;
DATA_PRINTF("(");
if (param_store_ == NULL) {
for (int64_t i = 0; OB_SUCC(ret) && i < row_cnt; i++) {
if (i == 0) {
DATA_PRINTF("SELECT ");
} else {
DATA_PRINTF(" FROM DUAL UNION ALL SELECT ");
}
for (int64_t j = 0; OB_SUCC(ret) && j < column_cnt; j++) {
OZ (ObLinkStmtParam::write(buf_, buf_len_, *pos_, start_idx + i * column_cnt + j,
table_def->column_types_.at(j).get_calc_type()));
if (i == 0) {
DATA_PRINTF(" AS \"column_%ld\"", j);
}
if (j + 1 != column_cnt) {
DATA_PRINTF(", ");
}
}
}
} else if (OB_ISNULL(param_store_) ||
OB_UNLIKELY(start_idx < 0 || end_idx < start_idx) ||
OB_UNLIKELY(start_idx >= param_store_->count() || end_idx >= param_store_->count())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(start_idx), K(end_idx));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < row_cnt; i++) {
if (i == 0) {
DATA_PRINTF("SELECT ");
} else {
DATA_PRINTF(" FROM DUAL UNION ALL SELECT ");
}
for (int64_t j = 0; OB_SUCC(ret) && j < column_cnt; j++) {
OZ (param_store_->at(start_idx + i * column_cnt + j).print_sql_literal(buf_, buf_len_, *pos_, print_params_));
if (i == 0) {
DATA_PRINTF(" AS \"column_%ld\"", j);
}
if (j + 1 != column_cnt) {
DATA_PRINTF(", ");
}
}
}
}
DATA_PRINTF(" FROM DUAL) \"%.*s\"", LEN_AND_PTR(table_item.alias_name_));
} else if (ObValuesTableDef::ACCESS_OBJ == table_def->access_type_) {
if (OB_UNLIKELY(table_def->access_objs_.count() != column_cnt * row_cnt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("got unexpected param", K(ret));
}
DATA_PRINTF("(");
for (int64_t i = 0; OB_SUCC(ret) && i < row_cnt; i++) {
if (i == 0) {
DATA_PRINTF("SELECT ");
} else {
DATA_PRINTF(" FROM DUAL UNION ALL SELECT ");
}
for (int64_t j = 0; OB_SUCC(ret) && j < column_cnt; j++) {
OZ (table_def->access_objs_.at(j + i * column_cnt).print_sql_literal(buf_, buf_len_, *pos_, print_params_));
if (i == 0) {
DATA_PRINTF(" AS \"column_%ld\"", j);
}
if (j + 1 != column_cnt) {
DATA_PRINTF(", ");
}
}
}
DATA_PRINTF(" FROM DUAL) \"%.*s\"", LEN_AND_PTR(table_item.alias_name_));
}
}
return ret;
}
int ObDMLStmtPrinter::print_json_return_type(int64_t value, ObDataType data_type)
{
int ret = OB_SUCCESS;
if (lib::is_mysql_mode()) {
if (OB_FAIL(print_mysql_json_return_type(value, data_type))) {
LOG_WARN("fail to print json table column in mysql mode", K(ret));
}
} else {
ParseNode parse_node;
parse_node.value_ = value;
int16_t cast_type = parse_node.int16_values_[OB_NODE_CAST_TYPE_IDX];
const ObLengthSemantics length_semantics = data_type.get_length_semantics();
const ObScale scale = data_type.get_scale();
switch (cast_type) {
case T_CHAR: {
int16_t collation = parse_node.int16_values_[OB_NODE_CAST_COLL_IDX];
int32_t len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
DATA_PRINTF("char(%d %s)", len, get_length_semantics_str(length_semantics));
break;
}
case T_VARCHAR: {
int16_t collation = parse_node.int16_values_[OB_NODE_CAST_COLL_IDX];
int32_t len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
const int32_t DEFAULT_VARCHAR_LEN = 4000;
if (BINARY_COLLATION == collation) {
DATA_PRINTF("varbinary(%d)", len);
} else {
// CHARACTER
if (len == DEFAULT_VARCHAR_LEN) {
break;
} else if (length_semantics == LS_BYTE && len == -1) {
DATA_PRINTF(" VARCHAR2");
break;
} else {
DATA_PRINTF("varchar2(%d %s)", len, get_length_semantics_str(length_semantics));
}
}
break;
}
case T_NVARCHAR2: {
DATA_PRINTF("nvarchar2(%d)", parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX]);
break;
}
case T_NCHAR: {
DATA_PRINTF("nchar(%d)", parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX]);
break;
}
case T_DATETIME: {
//oracle mode treats date as datetime
DATA_PRINTF("date");
break;
}
case T_DATE: {
DATA_PRINTF("date");
break;
}
case T_TIME: {
int16_t scale = parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX];
if (scale >= 0) {
DATA_PRINTF("time(%d)", scale);
} else {
DATA_PRINTF("time");
}
break;
}
case T_NUMBER: {
int16_t precision = parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX];
int16_t scale = parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX];
DATA_PRINTF("number(%d,%d)", precision, scale);
break;
}
case T_NUMBER_FLOAT: {
int16_t precision = parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX];
DATA_PRINTF("float(%d)", precision);
break;
}
case T_TINYINT:
case T_SMALLINT:
case T_MEDIUMINT:
case T_INT32:
case T_INT: {
DATA_PRINTF("signed");
break;
}
case T_UTINYINT:
case T_USMALLINT:
case T_UMEDIUMINT:
case T_UINT32:
case T_UINT64: {
DATA_PRINTF("unsigned");
break;
}
case T_INTERVAL_YM: {
int year_scale = ObIntervalScaleUtil::ob_scale_to_interval_ym_year_scale(static_cast<int8_t>(scale));
DATA_PRINTF("interval year(%d) to month", year_scale);
break;
}
case T_INTERVAL_DS: {
int day_scale = ObIntervalScaleUtil::ob_scale_to_interval_ds_day_scale(static_cast<int8_t>(scale));
int fs_scale = ObIntervalScaleUtil::ob_scale_to_interval_ds_second_scale(static_cast<int8_t>(scale));
DATA_PRINTF("interval day(%d) to second(%d)", day_scale, fs_scale);
break;
}
case T_TIMESTAMP_TZ: {
int16_t scale = parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX];
if (scale >= 0) {
DATA_PRINTF("timestamp(%d) with time zone", scale);
} else {
DATA_PRINTF("timestamp with time zone");
}
break;
}
case T_TIMESTAMP_LTZ: {
int16_t scale = parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX];
if (scale >= 0) {
DATA_PRINTF("timestamp(%d) with local time zone", scale);
} else {
DATA_PRINTF("timestamp with local time zone");
}
break;
}
case T_TIMESTAMP_NANO: {
int16_t scale = parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX];
if (scale >= 0) {
DATA_PRINTF("timestamp(%d)", scale);
} else {
DATA_PRINTF("timestamp");
}
break;
}
case T_RAW: {
int32_t len = parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX];
DATA_PRINTF("raw(%d)", len);
break;
}
case T_FLOAT: {
const char *type_str = lib::is_oracle_mode() ? "binary_float" : "float";
DATA_PRINTF("%s", type_str);
break;
}
case T_DOUBLE: {
const char *type_str = lib::is_oracle_mode() ? "binary_double" : "double";
DATA_PRINTF("%s", type_str);
break;
}
case T_UROWID: {
DATA_PRINTF("urowid(%d)", parse_node.int32_values_[OB_NODE_CAST_C_LEN_IDX]);
break;
}
case T_LOB: {
int16_t collation = parse_node.int16_values_[OB_NODE_CAST_COLL_IDX];
if (BINARY_COLLATION == collation) {
DATA_PRINTF("blob");
} else {
DATA_PRINTF("clob");
}
break;
}
case T_JSON: {
DATA_PRINTF("json");
break;
}
case T_LONGTEXT: {
int16_t collation = parse_node.int16_values_[OB_NODE_CAST_COLL_IDX];
if (BINARY_COLLATION == collation) {
DATA_PRINTF("blob");
} else {
DATA_PRINTF("clob");
}
break;
}
case T_EXTEND: {
ret = OB_ERR_INVALID_CAST_UDT;
LOG_WARN("invalid CAST to a type that is not a nested table or VARRAY", K(ret));
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown cast type", K(ret), K(cast_type));
break;
}
} // end switch
} // oracle mode
return ret;
}
int ObDMLStmtPrinter::print_binary_charset_collation(int64_t value, ObDataType data_type)
{
INIT_SUCC(ret);
if (data_type.is_binary_collation()) {
DATA_PRINTF("binary ");
}
if (CHARSET_INVALID != data_type.get_charset_type()) {
DATA_PRINTF("CHARACTER SET %s ", ObCharset::charset_name(data_type.get_charset_type()));
}
if (CS_TYPE_INVALID != data_type.get_collation_type()) {
DATA_PRINTF("COLLATE %s ", ObCharset::collation_name(data_type.get_collation_type()));
}
return ret;
}
int ObDMLStmtPrinter::print_mysql_json_return_type(int64_t value, ObDataType data_type)
{
int ret = OB_SUCCESS;
ParseNode parse_node;
parse_node.value_ = value;
int16_t cast_type = data_type.get_obj_type();
const ObLengthSemantics length_semantics = data_type.get_length_semantics();
const ObScale scale = data_type.get_scale();
switch (cast_type) {
case T_CHAR: {
int32_t len = parse_node.int32_values_[0];
int32_t collation = parse_node.int32_values_[1];
if (1 == collation) {
DATA_PRINTF("binary(%d)", len);
} else {
DATA_PRINTF("char(%d) ", len);
if (OB_FAIL(ret)) {
} else if (OB_FAIL(print_binary_charset_collation(value, data_type))) {
LOG_WARN("fail to print binary,charset,collection clause", K(ret));
}
}
break;
}
case T_VARCHAR: {
int32_t collation = parse_node.int32_values_[1];
int32_t len = parse_node.int32_values_[0];
const int32_t DEFAULT_VARCHAR_LEN = 4000;
if (1 == collation) {
DATA_PRINTF("varbinary(%d) ", len);
} else {
DATA_PRINTF("varchar(%d) ", len);
if (OB_SUCC(ret) && OB_FAIL(print_binary_charset_collation(value, data_type))) {
LOG_WARN("fail to print binary,charset,collection clause", K(ret));
}
}
break;
}
case T_BIT: {
int32_t len = parse_node.int16_values_[0];
DATA_PRINTF("bit(%d) ", len);
break;
}
case T_TINYTEXT: {
int16_t collation = parse_node.int32_values_[1];
if (1 == collation) {
DATA_PRINTF("TINYBLOB ");
} else {
DATA_PRINTF("TINYTEXT ");
}
if (OB_SUCC(ret) && !collation && OB_FAIL(print_binary_charset_collation(value, data_type))) {
LOG_WARN("fail to print binary,charset,collection clause", K(ret));
}
break;
}
case T_TEXT: {
int16_t collation = parse_node.int32_values_[1];
if (1 == collation) {
DATA_PRINTF("BLOB ");
} else {
DATA_PRINTF("TEXT ");
}
if (OB_SUCC(ret) && !collation && OB_FAIL(print_binary_charset_collation(value, data_type))) {
LOG_WARN("fail to print binary,charset,collection clause", K(ret));
}
break;
}
case T_MEDIUMTEXT: {
int16_t collation = parse_node.int32_values_[1];
if (1 == collation) {
DATA_PRINTF("MEDIUMBLOB ");
} else {
DATA_PRINTF("MEDIUMTEXT ");
}
if (OB_SUCC(ret) && !collation && OB_FAIL(print_binary_charset_collation(value, data_type))) {
LOG_WARN("fail to print binary,charset,collection clause", K(ret));
}
break;
}
case T_LONGTEXT: {
int16_t collation = parse_node.int32_values_[1];
if (1 == collation) {
DATA_PRINTF("LONGBLOB ");
} else {
DATA_PRINTF("LONGTEXT ");
}
if (OB_SUCC(ret) && !collation && OB_FAIL(print_binary_charset_collation(value, data_type))) {
LOG_WARN("fail to print binary,charset,collection clause", K(ret));
}
break;
}
case T_DATETIME: {
int16_t scale = parse_node.int16_values_[1];
if (scale >= 0) {
DATA_PRINTF("datetime(%d) ", scale);
} else {
DATA_PRINTF("datetime ");
}
break;
}
case T_DATE: {
DATA_PRINTF("date ");
break;
}
case T_YEAR: {
DATA_PRINTF("year ");
break;
}
case T_TIMESTAMP: {
int16_t scale = parse_node.int16_values_[1];
if (scale >= 0) {
DATA_PRINTF("timestamp(%d) ", scale);
} else {
DATA_PRINTF("timestamp ");
}
break;
}
case T_TIME: {
int16_t scale = parse_node.int16_values_[1];
if (scale >= 0) {
DATA_PRINTF("time(%d) ", scale);
} else {
DATA_PRINTF("time ");
}
break;
}
case T_NUMBER: { // number, decimal, fixed, numeric
int16_t precision = parse_node.int16_values_[OB_NODE_CAST_N_PREC_IDX];
int16_t scale = parse_node.int16_values_[OB_NODE_CAST_N_SCALE_IDX];
DATA_PRINTF("DECIMAL(%d,%d) ", precision, scale);
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_TINYINT: {
if (parse_node.int16_values_[OB_NODE_CAST_COLL_IDX] == 1) {
DATA_PRINTF("BOOL ");
} else if (parse_node.int16_values_[OB_NODE_CAST_COLL_IDX] == 2) {
DATA_PRINTF("BOOLEAN ");
} else {
DATA_PRINTF("TINYINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_SMALLINT: {
DATA_PRINTF("SMALLINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_MEDIUMINT: {
DATA_PRINTF("MEDIUMINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_INT32: {
DATA_PRINTF("INTEGER ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_INT: {
DATA_PRINTF("BIGINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_UTINYINT: {
DATA_PRINTF("TINYINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_USMALLINT:{
DATA_PRINTF("SMALLINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_UMEDIUMINT:{
DATA_PRINTF("MEDIUMINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_UINT32: {
DATA_PRINTF("INTEGER ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_UINT64: {
DATA_PRINTF("BIGINT ");
if (OB_SUCC(ret) && parse_node.int16_values_[0] != -1){
DATA_PRINTF("(%d)", parse_node.int16_values_[0]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_INTERVAL_YM: {
int year_scale = ObIntervalScaleUtil::ob_scale_to_interval_ym_year_scale(static_cast<int8_t>(scale));
DATA_PRINTF("interval year(%d) to month", year_scale);
break;
}
case T_INTERVAL_DS: {
int day_scale = ObIntervalScaleUtil::ob_scale_to_interval_ds_day_scale(static_cast<int8_t>(scale));
int fs_scale = ObIntervalScaleUtil::ob_scale_to_interval_ds_second_scale(static_cast<int8_t>(scale));
DATA_PRINTF("interval day(%d) to second(%d)", day_scale, fs_scale);
break;
}
case T_FLOAT: {
DATA_PRINTF("FLOAT ");
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[0] <= 0) {
} else {
DATA_PRINTF("(%d,%d) ", parse_node.int16_values_[0], parse_node.int16_values_[1]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_DOUBLE: {
DATA_PRINTF("DOUBLE ");
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[0] <= 0) {
} else {
DATA_PRINTF("(%d,%d) ", parse_node.int16_values_[0], parse_node.int16_values_[1]);
}
if (OB_FAIL(ret)) {
} else if (parse_node.int16_values_[3]) {
DATA_PRINTF("UNSIGNED ");
} else {
DATA_PRINTF("SIGNED ");
}
if (OB_SUCC(ret) && parse_node.int16_values_[2]) {
DATA_PRINTF("ZEROFILL ");
}
break;
}
case T_JSON: {
DATA_PRINTF("json ");
break;
}
case T_GEOMETRY: {
ObGeoType geo_type = static_cast<ObGeoType>(parse_node.int32_values_[1]);
switch (geo_type) {
case ObGeoType::GEOMETRY: {
DATA_PRINTF("geometry");
break;
}
case ObGeoType::POINT: {
DATA_PRINTF("point");
break;
}
case ObGeoType::LINESTRING: {
DATA_PRINTF("linestring");
break;
}
case ObGeoType::POLYGON: {
DATA_PRINTF("polygon");
break;
}
case ObGeoType::MULTIPOINT: {
DATA_PRINTF("multipoint");
break;
}
case ObGeoType::MULTILINESTRING: {
DATA_PRINTF("multilinestring");
break;
}
case ObGeoType::MULTIPOLYGON: {
DATA_PRINTF("multipolygon");
break;
}
case ObGeoType::GEOMETRYCOLLECTION: {
DATA_PRINTF("geometrycollection");
break;
}
case ObGeoType::GEOTYPEMAX: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid cast geo sub type", K(ret), K(cast_type), K(geo_type));
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown cast geo sub type", K(ret), K(cast_type), K(geo_type));
break;
}
}
break;
}
case T_ROARINGBITMAP: {
DATA_PRINTF("roaringbitmap ");
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown cast type", K(ret), K(cast_type));
break;
}
} // end switch
return ret;
}
int ObDMLStmtPrinter::get_json_table_column_if_exists(int32_t id, ObDmlJtColDef* root, ObDmlJtColDef*& col)
{
INIT_SUCC(ret);
common::ObArray<ObDmlJtColDef*> col_stack;
if (OB_FAIL(col_stack.push_back(root))) {
LOG_WARN("fail to store col node tmp", K(ret));
}
bool exists = false;
while (OB_SUCC(ret) && !exists && col_stack.count() > 0) {
ObDmlJtColDef* cur_col = col_stack.at(col_stack.count() - 1);
if (OB_ISNULL(cur_col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("current column info is null", K(ret));
} else if (cur_col->col_base_info_.id_ == id) {
exists = true;
col = cur_col;
} else if (cur_col->col_base_info_.parent_id_ < 0
|| cur_col->col_base_info_.col_type_ == static_cast<int32_t>(NESTED_COL_TYPE)) {
col_stack.remove(col_stack.count() - 1);
for (size_t i = 0; !exists && i < cur_col->nested_cols_.count(); ++i) {
ObDmlJtColDef* nest_col = cur_col->nested_cols_.at(i);
if (OB_ISNULL(nest_col)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("current column info is null", K(ret));
} else if (nest_col->col_base_info_.id_ == id) {
exists = true;
col = nest_col;
} else if (nest_col->col_base_info_.col_type_ == static_cast<int32_t>(NESTED_COL_TYPE)
&& OB_FAIL(col_stack.push_back(nest_col))) {
LOG_WARN("fail to store col node tmp", K(ret));
}
}
}
}
if (OB_SUCC(ret) && !exists) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to find col node", K(ret));
}
return ret;
}
int ObDMLStmtPrinter::build_json_table_nested_tree(const TableItem* table_item, ObIAllocator* allocator, ObDmlJtColDef*& root)
{
int ret = OB_SUCCESS;
const ObIArray<ObJtColBaseInfo*>& plain_def = table_item->json_table_def_->all_cols_;
for (size_t i = 0; OB_SUCC(ret) && i < plain_def.count(); ++i) {
const ObJtColBaseInfo& info = *plain_def.at(i);
ObDmlJtColDef* col_def = static_cast<ObDmlJtColDef*>(allocator->alloc(sizeof(ObDmlJtColDef)));
if (OB_ISNULL(col_def)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate col node", K(ret));
} else {
col_def = new (col_def) ObDmlJtColDef();
col_def->col_base_info_.assign(info);
if (info.col_type_ != NESTED_COL_TYPE) {
ColumnItem* col_item = stmt_->get_column_item_by_id(table_item->table_id_, info.output_column_idx_);
if (OB_ISNULL(col_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get column item", K(ret), K(info.output_column_idx_));
} else {
col_def->error_expr_ = col_item->default_value_expr_;
col_def->empty_expr_ = col_item->default_empty_expr_;
}
}
}
if (OB_SUCC(ret)) {
ObDmlJtColDef* parent = nullptr;
if (info.parent_id_ < 0) {
root = col_def;
} else if (OB_FAIL(get_json_table_column_if_exists(info.parent_id_, root, parent))) {
LOG_WARN("fail to find col node parent", K(ret), K(info.parent_id_));
} else if (info.col_type_ == static_cast<int32_t>(NESTED_COL_TYPE)) {
if (OB_FAIL(parent->nested_cols_.push_back(col_def))) {
LOG_WARN("fail to store col node", K(ret), K(parent->nested_cols_.count()));
}
} else if (OB_FAIL(parent->regular_cols_.push_back(col_def))) {
LOG_WARN("fail to store col node", K(ret), K(parent->nested_cols_.count()));
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_json_table_nested_column(const TableItem *table_item, const ObDmlJtColDef& col_def)
{
int ret = OB_SUCCESS;
ObJsonTableDef* tbl_def = table_item->json_table_def_;
bool has_reg_column = false;
for (size_t i = 0; OB_SUCC(ret) && i < col_def.regular_cols_.count(); ++i) {
has_reg_column = true;
ObDmlJtColDef* cur_def = col_def.regular_cols_.at(i);
if (OB_ISNULL(cur_def)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("current column info is null", K(ret));
} else {
const ObJtColBaseInfo& col_info = col_def.regular_cols_.at(i)->col_base_info_;
if (i > 0) {
DATA_PRINTF(", ");
}
if (col_info.is_name_quoted_) {
PRINT_QUOT;
DATA_PRINTF("%.*s", LEN_AND_PTR(col_info.col_name_));
PRINT_QUOT;
DATA_PRINTF(" ");
} else {
DATA_PRINTF("%.*s ", LEN_AND_PTR(col_info.col_name_));
}
if (OB_FAIL(ret)) {
} else if (col_info.col_type_ == static_cast<int32_t>(COL_TYPE_ORDINALITY)
|| col_info.col_type_ == static_cast<int32_t>(COL_TYPE_ORDINALITY_XML)) {
DATA_PRINTF(" for ordinality");
} else if (col_info.col_type_ == static_cast<int32_t>(COL_TYPE_EXISTS)) {
// to print returning type
OZ (print_json_return_type(col_info.res_type_, col_info.data_type_));
if (OB_SUCC(ret) && col_info.truncate_) {
DATA_PRINTF(" truncate");
}
DATA_PRINTF(" exists");
if (OB_SUCC(ret) && col_info.path_.length() > 0) {
DATA_PRINTF(" path \'%.*s\'", LEN_AND_PTR(col_info.path_));
}
if (OB_FAIL(ret)) {
} else if (col_info.on_empty_ == 0) {
DATA_PRINTF(" false on empty");
} else if (col_info.on_empty_ == 1) {
DATA_PRINTF(" true on empty");
} else if (col_info.on_empty_ == 2) {
DATA_PRINTF(" error on empty");
}
if (OB_FAIL(ret)) {
} else if (col_info.on_error_ == 0) {
DATA_PRINTF(" false on error");
} else if (col_info.on_error_ == 1) {
DATA_PRINTF(" true on error");
} else if (col_info.on_error_ == 2) {
DATA_PRINTF(" error on error");
}
} else if (col_info.col_type_ == static_cast<int32_t>(COL_TYPE_QUERY)) {
// to print returning type
OZ (print_json_return_type(col_info.res_type_, col_info.data_type_));
ObObjType cast_type = col_info.data_type_.get_obj_type();
if (cast_type != ObJsonType){
DATA_PRINTF(" format json");
}
if (OB_SUCC(ret) && col_info.truncate_) {
DATA_PRINTF(" truncate");
}
if (OB_FAIL(ret)) {
} else if (col_info.allow_scalar_ == 0) {
DATA_PRINTF(" allow scalars");
} else if (col_info.allow_scalar_ == 1) {
DATA_PRINTF(" disallow scalars");
}
if (OB_FAIL(ret)) {
} else if (col_info.wrapper_ == 0) {
DATA_PRINTF(" without wrapper");
} else if (col_info.wrapper_ == 1) {
DATA_PRINTF(" without array wrapper");
} else if (col_info.wrapper_ == 2) {
DATA_PRINTF(" with wrapper");
} else if (col_info.wrapper_ == 3) {
DATA_PRINTF(" with array wrapper");
} else if (col_info.wrapper_ == 4) {
DATA_PRINTF(" with unconditional wrapper");
} else if (col_info.wrapper_ == 5) {
DATA_PRINTF(" with conditional wrapper");
} else if (col_info.wrapper_ == 6) {
DATA_PRINTF(" with unconditional array wrapper");
} else if (col_info.wrapper_ == 7) {
DATA_PRINTF(" with conditional array wrapper");
}
if (OB_SUCC(ret) && col_info.path_.length() > 0) {
DATA_PRINTF(" path \'%.*s\'", LEN_AND_PTR(col_info.path_));
}
if (OB_FAIL(ret)) {
} else if (col_info.on_empty_ == 0) {
DATA_PRINTF(" error on empty" );
} else if (col_info.on_empty_ == 1) {
DATA_PRINTF(" null on empty" );
} else if (col_info.on_empty_ == 2) {
DATA_PRINTF(" empty on empty" );
} else if (col_info.on_empty_ == 3) {
DATA_PRINTF(" empty array on empty" );
} else if (col_info.on_empty_ == 4) {
DATA_PRINTF(" empty object on empty" );
}
if (OB_FAIL(ret)) {
} else if (col_info.on_error_ == 0) {
DATA_PRINTF(" error on error" );
} else if (col_info.on_error_ == 1) {
DATA_PRINTF(" null on error" );
} else if (col_info.on_error_ == 2) {
DATA_PRINTF(" empty on error" );
} else if (col_info.on_error_ == 3) {
DATA_PRINTF(" empty array on error" );
} else if (col_info.on_error_ == 4) {
DATA_PRINTF(" empty object on error" );
}
if (OB_FAIL(ret)) {
} else if (col_info.on_mismatch_ == 0) {
DATA_PRINTF(" error on mismatch" );
} else if (col_info.on_mismatch_ == 1) {
DATA_PRINTF(" null on mismatch" );
}
} else if (col_info.col_type_ == static_cast<int32_t>(COL_TYPE_VALUE)) {
OZ (print_json_return_type(col_info.res_type_, col_info.data_type_));
if (col_info.truncate_) {
DATA_PRINTF(" truncate" );
}
if (OB_SUCC(ret) && col_info.path_.length() > 0) {
DATA_PRINTF(" path \'%.*s\'", LEN_AND_PTR(col_info.path_));
}
if (OB_FAIL(ret)) {
} else if (col_info.on_empty_ == 0) {
DATA_PRINTF(" error on empty");
} else if (col_info.on_empty_ == 1) {
DATA_PRINTF(" null on empty");
} else if (col_info.on_empty_ == 2) {
DATA_PRINTF(" default ");
if (OB_FAIL(ret)) {
} else if (T_BOOL == cur_def->empty_expr_->get_expr_type()) { // bool need print 'true' or 'false' int json_table, not 1=1'
ObConstRawExpr *con_expr = static_cast<ObConstRawExpr*>(cur_def->empty_expr_);
if (OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, con_expr->get_value().get_bool() ? "true" : "false"))) {
LOG_WARN("fail to print startup filter", K(ret));
}
} else if (OB_FAIL(expr_printer_.do_print(cur_def->empty_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print default value col", K(ret));
}
DATA_PRINTF(" on empty");
}
if (OB_FAIL(ret)) {
} else if (col_info.on_error_ == 0) {
DATA_PRINTF(" error on error");
} else if (col_info.on_error_ == 1) {
DATA_PRINTF(" null on error");
} else if (col_info.on_error_ == 2) {
DATA_PRINTF(" default ");
if (OB_FAIL(ret)) {
} else if (T_BOOL == cur_def->error_expr_->get_expr_type()) { // bool need print 'true' or 'false' int json_table, not 1=1'
ObConstRawExpr *con_expr = static_cast<ObConstRawExpr*>(cur_def->error_expr_);
if (OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, con_expr->get_value().get_bool() ? "true" : "false"))) {
LOG_WARN("fail to print startup filter", K(ret));
}
} else if (OB_FAIL(expr_printer_.do_print(cur_def->error_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print default value col", K(ret));
}
DATA_PRINTF(" on error");
}
if (OB_FAIL(ret)) {
} else if (col_info.on_mismatch_ == 0) {
DATA_PRINTF(" error on mismatch");
} else if (col_info.on_mismatch_ == 1) {
DATA_PRINTF(" null on mismatch");
} else if (col_info.on_mismatch_ == 2) {
DATA_PRINTF(" ignore on mismatch");
}
if (OB_FAIL(ret)) {
} else if (col_info.on_mismatch_type_ == 0) {
DATA_PRINTF(" (missing data)");
} else if (col_info.on_mismatch_type_ == 1) {
DATA_PRINTF(" (extra data)");
} else if (col_info.on_mismatch_type_ == 2) {
DATA_PRINTF(" (type error)");
}
} else if (col_info.col_type_ == static_cast<int32_t>(COL_TYPE_VAL_EXTRACT_XML)) {
OZ (print_json_return_type(col_info.res_type_, col_info.data_type_));
if (OB_SUCC(ret) && col_info.path_.length() > 0) {
DATA_PRINTF(" path \'%.*s\'", LEN_AND_PTR(col_info.path_));
}
if (OB_SUCC(ret) && col_info.on_empty_ == 2) {
DATA_PRINTF(" default ");
if (OB_SUCC(ret)
&& OB_FAIL(expr_printer_.do_print(cur_def->empty_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print default value col", K(ret));
}
}
} else if (col_info.col_type_ == static_cast<int32_t>(COL_TYPE_XMLTYPE_XML)) {
DATA_PRINTF(" XMLTYPE");
if (OB_SUCC(ret) && col_info.truncate_) {
DATA_PRINTF(" ( SEQUENCE ) BY REF");
}
if (OB_SUCC(ret) && col_info.path_.length() > 0) {
DATA_PRINTF(" path \'%.*s\'", LEN_AND_PTR(col_info.path_));
}
if (OB_SUCC(ret) && col_info.on_empty_ == 2) {
DATA_PRINTF(" default ");
if (OB_SUCC(ret)
&& OB_FAIL(expr_printer_.do_print(cur_def->empty_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print default value col", K(ret));
}
}
}
}
}
for (size_t i = 0; OB_SUCC(ret) && i < col_def.nested_cols_.count(); ++i) {
const ObJtColBaseInfo& col_info = col_def.nested_cols_.at(i)->col_base_info_;
if (i > 0 || has_reg_column) {
DATA_PRINTF(",");
}
DATA_PRINTF(" nested path \'%.*s\' columns(", LEN_AND_PTR(col_info.path_));
OZ (print_json_table_nested_column(table_item, *col_def.nested_cols_.at(i)));
DATA_PRINTF(")");
}
return ret;
}
int ObDMLStmtPrinter::print_xml_namespace(const TableItem *table_item)
{
INIT_SUCC(ret);
DATA_PRINTF("XMLNAMESPACES( ");
bool is_default = false;
for (int64_t i = 0; OB_SUCC(ret) && i < table_item->json_table_def_->namespace_arr_.count(); i ++) {
if (i % 2 == 0) { // first value is uri
if (i > 0) {
DATA_PRINTF(", ");
}
if (table_item->json_table_def_->namespace_arr_.at(i + 1).empty()) {
DATA_PRINTF("DEFAULT \'%.*s\' ", LEN_AND_PTR(table_item->json_table_def_->namespace_arr_.at(i)));
} else {
DATA_PRINTF("\'%.*s\' AS ", LEN_AND_PTR(table_item->json_table_def_->namespace_arr_.at(i)));
}
} else if (!table_item->json_table_def_->namespace_arr_.at(i).empty()) {
DATA_PRINTF("%.*s ", LEN_AND_PTR(table_item->json_table_def_->namespace_arr_.at(i)));
}
}
DATA_PRINTF("),");
return ret;
}
int ObDMLStmtPrinter::print_xml_table(const TableItem *table_item)
{
int ret = OB_SUCCESS;
ObJsonTableDef* tbl_def = table_item->json_table_def_;
ObArenaAllocator alloc;
ObDmlJtColDef* root_def = nullptr;
if (OB_FAIL(build_json_table_nested_tree(table_item, &alloc, root_def))) {
LOG_WARN("fail to build column tree.", K(ret));
} else if (table_item->json_table_def_->namespace_arr_.count() > 0 && OB_FAIL(print_xml_namespace(table_item))) {
LOG_WARN("fail to print xml ns", K(ret));
} else if (root_def->col_base_info_.path_.length() > 0) {
DATA_PRINTF(" \'%.*s\'", LEN_AND_PTR(root_def->col_base_info_.path_));
}
DATA_PRINTF(" PASSING ");
if (OB_FAIL(ret)) {
} else if (OB_FAIL(expr_printer_.do_print(table_item->json_table_def_->doc_exprs_.at(0), T_FROM_SCOPE))) {
LOG_WARN("fail to print xml doc", K(ret));
} else if (root_def->col_base_info_.allow_scalar_) {
DATA_PRINTF(" RETURNING SEQUENCE BY REF");
}
DATA_PRINTF(" COLUMNS ");
OZ (print_json_table_nested_column(table_item, *root_def));
return ret;
}
int ObDMLStmtPrinter::print_json_table(const TableItem *table_item)
{
int ret = OB_SUCCESS;
ObJsonTableDef* tbl_def = table_item->json_table_def_;
ObArenaAllocator alloc;
ObDmlJtColDef* root_def = nullptr;
if (OB_SUCC(ret) && OB_FAIL(build_json_table_nested_tree(table_item, &alloc, root_def))) {
LOG_WARN("fail to build column tree.", K(ret));
} else if (root_def->col_base_info_.path_.length() > 0) {
DATA_PRINTF(" , \'%.*s\'", LEN_AND_PTR(root_def->col_base_info_.path_));
}
if (OB_SUCC(ret)) {
if (root_def->col_base_info_.on_empty_ == 0) {
DATA_PRINTF(" error on empty");
} else if (root_def->col_base_info_.on_empty_ == 1) {
DATA_PRINTF(" null on empty");
} else if (root_def->col_base_info_.on_empty_ == 2) {
DATA_PRINTF(" default ");
if (OB_FAIL(expr_printer_.do_print(root_def->empty_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print where expr", K(ret));
}
DATA_PRINTF(" on empty");
}
if (OB_FAIL(ret)) {
} else if (root_def->col_base_info_.on_error_ == 0) {
DATA_PRINTF(" error on error");
} else if (root_def->col_base_info_.on_error_ == 1) {
DATA_PRINTF(" null on error");
} else if (root_def->col_base_info_.on_error_ == 2) {
DATA_PRINTF(" default ");
if (OB_SUCC(ret) && OB_FAIL(expr_printer_.do_print(root_def->error_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print default expr", K(ret));
}
DATA_PRINTF(" on error");
}
}
DATA_PRINTF(" columns (");
OZ (print_json_table_nested_column(table_item, *root_def));
DATA_PRINTF(" )");
return ret;
}
int ObDMLStmtPrinter::print_base_table(const TableItem *table_item)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else if (OB_ISNULL(table_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table_item should not be NULL", K(ret));
} else if (TableItem::BASE_TABLE != table_item->type_
&& TableItem::ALIAS_TABLE != table_item->type_
&& TableItem::LINK_TABLE != table_item->type_) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table_type should be BASE_TABLE or ALIAS_TABLE or LINK_TABLE", K(ret),
K(table_item->type_));
} else {
PRINT_TABLE_NAME(print_params_, table_item);
if (OB_SUCC(ret)) {
// partition
if (!table_item->access_all_part()) {
const ObIArray<ObString> &part_names = table_item->part_names_;
DATA_PRINTF(" partition(");
for (int64_t i = 0; OB_SUCC(ret) && i < part_names.count(); ++i) {
PRINT_IDENT_WITH_QUOT(part_names.at(i));
DATA_PRINTF(",");
}
if (OB_SUCC(ret)) {
--*pos_;
DATA_PRINTF(")");
}
}
if (OB_SUCC(ret) && OB_NOT_NULL(table_item->sample_info_)) {
if (SampleInfo::SampleMethod::BLOCK_SAMPLE == table_item->sample_info_->method_) {
DATA_PRINTF(" sample block(");
DATA_PRINTF("%lf", table_item->sample_info_->percent_);
DATA_PRINTF(")");
} else if (SampleInfo::SampleMethod::ROW_SAMPLE == table_item->sample_info_->method_) {
DATA_PRINTF(" sample(");
DATA_PRINTF("%lf", table_item->sample_info_->percent_);
DATA_PRINTF(")");
}
if (table_item->sample_info_->seed_ != -1) {
DATA_PRINTF(" seed(");
DATA_PRINTF(" %ld ", table_item->sample_info_->seed_);
DATA_PRINTF(")");
}
}
// flashback query
if (OB_SUCC(ret)) {
bool explain_non_extend = false;
if (OB_NOT_NULL(stmt_->get_query_ctx()) &&
OB_NOT_NULL(stmt_->get_query_ctx()->root_stmt_) &&
stmt_->get_query_ctx()->root_stmt_->is_explain_stmt()) {
explain_non_extend = !static_cast<const ObExplainStmt *>
(stmt_->get_query_ctx()->root_stmt_)->is_explain_extended();
}
if (OB_NOT_NULL(table_item->flashback_query_expr_) &&
// do not print flashback of link table when explain [basic]
!(table_item->is_link_table() && explain_non_extend)) {
if (table_item->flashback_query_type_ == TableItem::USING_TIMESTAMP) {
DATA_PRINTF(" as of timestamp ");
if (OB_FAIL(expr_printer_.do_print(table_item->flashback_query_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print where expr", K(ret));
}
} else if (table_item->flashback_query_type_ == TableItem::USING_SCN) {
if (lib::is_oracle_mode()) {
DATA_PRINTF(" as of scn ");
} else {
DATA_PRINTF(" as of snapshot ");
}
if (OB_FAIL(expr_printer_.do_print(table_item->flashback_query_expr_, T_NONE_SCOPE))) {
LOG_WARN("fail to print where expr", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected type", K(ret), K(table_item->flashback_query_type_));
}
}
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_semi_join()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null stmt", K(ret));
}
for (int i = 0; OB_SUCC(ret) && i < stmt_->get_semi_info_size(); ++i) {
SemiInfo *semi_info = stmt_->get_semi_infos().at(i);
const TableItem *right_table = NULL;
if (OB_ISNULL(semi_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null semi info", K(ret));
} else if (OB_ISNULL(right_table = stmt_->get_table_item_by_id(semi_info->right_table_id_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null table item", K(ret));
} else {
DATA_PRINTF(", ");
// join type
ObString type_str("");
switch (semi_info->join_type_) {
case LEFT_SEMI_JOIN: {
type_str = "left semi join";
break;
}
case RIGHT_SEMI_JOIN: {
type_str = "right semi join";
break;
}
case LEFT_ANTI_JOIN: {
type_str = "left anti join";
break;
}
case RIGHT_ANTI_JOIN: {
type_str = "right anti join";
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown join type", K(ret));
break;
}
}
DATA_PRINTF(" %.*s ", LEN_AND_PTR(type_str));
// right table
if (OB_SUCC(ret)) {
if (OB_FAIL(print_table(right_table))) {
LOG_WARN("fail to print right table", K(ret), K(*right_table));
} else {
// join conditions
const ObIArray<ObRawExpr*> &join_conditions = semi_info->semi_conditions_;
int64_t join_conditions_size = join_conditions.count();
if (join_conditions_size > 0) {
DATA_PRINTF(" on ");
for (int64_t i = 0; OB_SUCC(ret) && i < join_conditions_size; ++i) {
if (OB_FAIL(expr_printer_.do_print(join_conditions.at(i), T_NONE_SCOPE))) {
LOG_WARN("fail to print join condition", K(ret));
}
DATA_PRINTF(" and ");
}
if (OB_SUCC(ret)) {
*pos_ -= 5; // strlen(" and ")
}
} else {
DATA_PRINTF(" on 1=1 ");
}
}
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_semi_info_to_subquery()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null stmt", K(ret));
}
for (int i = 0; OB_SUCC(ret) && i < stmt_->get_semi_info_size(); ++i) {
SemiInfo *semi_info = stmt_->get_semi_infos().at(i);
const TableItem *right_table = NULL;
if (OB_ISNULL(semi_info)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null semi info", K(ret));
} else if (OB_ISNULL(right_table = stmt_->get_table_item_by_id(semi_info->right_table_id_))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null table item", K(ret));
} else {
DATA_PRINTF(" ");
// join type
ObString type_str("");
switch (semi_info->join_type_) {
case LEFT_SEMI_JOIN: {
type_str = "exists";
break;
}
case LEFT_ANTI_JOIN: {
type_str = "not exists";
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unknown join type", K(ret));
break;
}
}
DATA_PRINTF("%.*s(select 1 from ", LEN_AND_PTR(type_str));
// right table
if (OB_SUCC(ret)) {
if (OB_FAIL(print_table(right_table))) {
LOG_WARN("fail to print right table", K(ret), K(*right_table));
} else {
// join conditions
const ObIArray<ObRawExpr*> &join_conditions = semi_info->semi_conditions_;
int64_t join_conditions_size = join_conditions.count();
if (join_conditions_size > 0) {
DATA_PRINTF(" where ");
for (int64_t i = 0; OB_SUCC(ret) && i < join_conditions_size; ++i) {
if (OB_FAIL(expr_printer_.do_print(join_conditions.at(i), T_NONE_SCOPE))) {
LOG_WARN("fail to print join condition", K(ret));
}
DATA_PRINTF(" and ");
}
if (OB_SUCC(ret)) {
*pos_ -= 5; // strlen(" and ")
}
}
}
}
DATA_PRINTF(") and ");
}
}
if (OB_SUCC(ret) && stmt_->get_semi_info_size() > 0) {
*pos_ -= 5; // strlen(" and ")
}
return ret;
}
int ObDMLStmtPrinter::print_where()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else {
const ObIArray<ObRawExpr*> &condition_exprs = stmt_->get_condition_exprs();
int64_t condition_exprs_size = condition_exprs.count();
if (condition_exprs_size > 0) {
DATA_PRINTF(" where ");
for (int64_t i = 0; OB_SUCC(ret) && i < condition_exprs_size; ++i) {
if (OB_FAIL(expr_printer_.do_print(condition_exprs.at(i), T_WHERE_SCOPE))) {
LOG_WARN("fail to print where expr", K(ret));
}
DATA_PRINTF(" and ");
}
if (OB_SUCC(ret)) {
*pos_ -= 5; // strlen(" and ")
}
}
if (print_params_.for_dblink_) {
if (condition_exprs_size == 0 && stmt_->get_semi_info_size() > 0) {
DATA_PRINTF(" where ");
} else if (condition_exprs_size > 0 && stmt_->get_semi_info_size() > 0) {
DATA_PRINTF(" and ");
}
if (OB_SUCC(ret) && OB_FAIL(print_semi_info_to_subquery())) {
LOG_WARN("failed to print semi info to subquery", K(ret));
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_quote_for_const(ObRawExpr* expr, bool &print_quote)
{
int ret = OB_SUCCESS;
print_quote = false;
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret));
} else if (expr->is_const_or_param_expr()) {
print_quote = expr->get_result_type().is_numeric_type();
}
return ret;
}
int ObDMLStmtPrinter::print_expr_except_const_number(ObRawExpr* expr, ObStmtScope scope)
{
int ret = OB_SUCCESS;
bool print_quote = false;
if (OB_FAIL(print_quote_for_const(expr, print_quote))) {
LOG_WARN("failed to check is const number", K(ret));
} else if (print_quote) {
DATA_PRINTF("'");
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(expr_printer_.do_print(expr, scope))) {
LOG_WARN("fail to print order by expr", K(ret));
} else if (print_quote) {
DATA_PRINTF("'");
}
return ret;
}
int ObDMLStmtPrinter::print_order_by()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else {
ObArenaAllocator alloc;
ObConstRawExpr expr(alloc);
int64_t order_item_size = stmt_->get_order_item_size();
if (order_item_size > 0) {
DATA_PRINTF(" order by ");
for (int64_t i = 0; OB_SUCC(ret) && i < order_item_size; ++i) {
const OrderItem &order_item = stmt_->get_order_item(i);
if (OB_FAIL(print_expr_except_const_number(order_item.expr_, T_ORDER_SCOPE))) {
LOG_WARN("fail to print order by expr", K(ret));
} else if (lib::is_mysql_mode()) {
if (is_descending_direction(order_item.order_type_)) {
DATA_PRINTF("desc");
}
} else if (order_item.order_type_ == NULLS_FIRST_ASC) {
DATA_PRINTF("asc nulls first");
} else if (order_item.order_type_ == NULLS_LAST_ASC) {//use default value
/*do nothing*/
} else if (order_item.order_type_ == NULLS_FIRST_DESC) {//use default value
DATA_PRINTF("desc");
} else if (order_item.order_type_ == NULLS_LAST_DESC) {
DATA_PRINTF("desc nulls last");
} else {/*do nothing*/}
DATA_PRINTF(",");
}
if (OB_SUCC(ret)) {
--*pos_;
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_approx()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else if (stmt_->has_vec_approx()) {
DATA_PRINTF(" approx ");
}
return ret;
}
int ObDMLStmtPrinter::print_limit()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else if (stmt_->has_fetch() || is_oracle_mode()) {
/*有fetch,说明是oracle mode下的fetch填充的limit,这里不应该打印 */
} else {
ObRawExpr *offset_expr = stmt_->get_offset_expr();
ObRawExpr *limit_expr = stmt_->get_limit_expr();
if (NULL != offset_expr || NULL != limit_expr) {
DATA_PRINTF(" limit ");
}
// offset
if (OB_SUCC(ret)) {
if (NULL != offset_expr) {
if (NULL != print_params_.exec_ctx_) {
ObArenaAllocator allocator("PrintDMLStmt");
ObObj result;
bool got_result = false;
if (!offset_expr->is_static_const_expr()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("offset expr should be a const int", K(ret), KPC(offset_expr));
} else if (OB_FAIL(ObSQLUtils::calc_const_or_calculable_expr(print_params_.exec_ctx_,
offset_expr,
result,
got_result,
allocator))) {
LOG_WARN("failed to calc offset expr", K(ret));
} else if (!got_result || !result.is_int()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get the result of offset expr", K(ret), KPC(offset_expr));
} else {
DATA_PRINTF("%ld", result.get_int());
}
} else {
if (OB_FAIL(expr_printer_.do_print(offset_expr, T_NONE_SCOPE))) {
LOG_WARN("fail to print offset expr", K(ret));
}
}
DATA_PRINTF(",");
}
}
// limit
if (OB_SUCC(ret)) {
if (NULL != limit_expr) {
if (NULL != print_params_.exec_ctx_) {
ObArenaAllocator allocator("PrintDMLStmt");
ObObj result;
bool got_result = false;
if (!limit_expr->is_static_const_expr()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("limit expr should be a const int", K(ret), KPC(limit_expr));
} else if (OB_FAIL(ObSQLUtils::calc_const_or_calculable_expr(print_params_.exec_ctx_,
limit_expr,
result,
got_result,
allocator))) {
LOG_WARN("failed to calc limit expr", K(ret));
} else if (!got_result || !result.is_int()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("failed to get the result of limit expr", K(ret), KPC(limit_expr));
} else {
DATA_PRINTF("%ld", result.get_int());
}
} else {
if (OB_FAIL(expr_printer_.do_print(limit_expr, T_NONE_SCOPE))) {
LOG_WARN("fail to print limit expr", K(ret));
}
}
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_fetch()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret));
} else if (stmt_->has_fetch() || (stmt_->has_limit() && is_oracle_mode())) {
// offset
if (OB_SUCC(ret)) {
if (NULL != stmt_->get_offset_expr()) {
DATA_PRINTF(" offset ");
if (OB_FAIL(expr_printer_.do_print(stmt_->get_offset_expr(), T_NONE_SCOPE))) {
LOG_WARN("fail to print order offset expr", K(ret));
}
DATA_PRINTF(" rows");
}
}
// fetch
if (OB_SUCC(ret)) {
if (NULL != stmt_->get_limit_expr()) {
DATA_PRINTF(" fetch next ");
if (OB_FAIL(expr_printer_.do_print(stmt_->get_limit_expr(), T_NONE_SCOPE))) {
LOG_WARN("fail to print order limit expr", K(ret));
}
DATA_PRINTF(" rows");
}
}
//fetch percent
if (OB_SUCC(ret)) {
if (NULL != stmt_->get_limit_percent_expr()) {
DATA_PRINTF(" fetch next ");
if (OB_FAIL(expr_printer_.do_print(stmt_->get_limit_percent_expr(), T_NONE_SCOPE))) {
LOG_WARN("fail to print order limit expr", K(ret));
}
DATA_PRINTF(" percent rows");
}
}
//fetch only/with ties
if (OB_SUCC(ret) &&
(NULL != stmt_->get_limit_expr() || NULL != stmt_->get_limit_percent_expr()) ) {
if (stmt_->is_fetch_with_ties()) {
DATA_PRINTF(" with ties");
} else {
DATA_PRINTF(" only");
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_returning()
{
int ret = OB_SUCCESS;
CK (OB_NOT_NULL(stmt_),
OB_NOT_NULL(buf_),
OB_NOT_NULL(pos_));
CK (stmt_->is_insert_stmt() || stmt_->is_update_stmt() || stmt_->is_delete_stmt());
if (OB_SUCC(ret)) {
const ObDelUpdStmt &dml_stmt = static_cast<const ObDelUpdStmt&>(*stmt_);
const ObIArray<ObRawExpr*> &returning_exprs = dml_stmt.get_returning_exprs();
if (returning_exprs.count() > 0) {
DATA_PRINTF(" returning ");
OZ (expr_printer_.do_print(returning_exprs.at(0), T_NONE_SCOPE));
for (uint64_t i = 1; OB_SUCC(ret) && i < returning_exprs.count(); ++i) {
DATA_PRINTF(",");
OZ (expr_printer_.do_print(returning_exprs.at(i), T_NONE_SCOPE));
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_subquery(const ObSelectStmt *subselect_stmt,
uint64_t subquery_print_params)
{
int ret = OB_SUCCESS;
ObSelectStmtPrinter printer(buf_, buf_len_, pos_,
subselect_stmt,
schema_guard_,
print_params_,
param_store_,
subquery_print_params & FORCE_COL_ALIAS,
session_);
if (subquery_print_params & PRINT_CTE) {
printer.enable_print_temp_table_as_cte();
}
if (subquery_print_params & PRINT_BRACKET) {
DATA_PRINTF("(");
}
if (OB_FAIL(printer.do_print())) {
LOG_WARN("failed to print sub select printer", K(ret));
}
if (subquery_print_params & PRINT_BRACKET) {
DATA_PRINTF(")");
}
return ret;
}
int ObDMLStmtPrinter::print_temp_table_as_cte()
{
int ret = OB_SUCCESS;
ObSEArray<ObDMLStmt::TempTableInfo, 8> temp_table_infos;
if (print_params_.print_origin_stmt_) {
//do nothing
} else if (!print_cte_) {
//do nothing
} else if (print_params_.for_dblink_) {
// always print temp table as generated table
// do nothing
} else if (OB_ISNULL(stmt_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null stmt", K(ret));
} else if (OB_FAIL(const_cast<ObDMLStmt*>(stmt_)->collect_temp_table_infos(temp_table_infos))) {
LOG_WARN("failed to collect temp table infos", K(ret));
} else if (temp_table_infos.empty()) {
//do nothing
} else {
DATA_PRINTF(is_oracle_mode() ? "WITH " : "WITH RECURSIVE ");
for(int64_t i = 0; OB_SUCC(ret) && i < temp_table_infos.count(); ++i) {
if (temp_table_infos.at(i).table_items_.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the cte tableitem can not be empty", K(ret));
} else {
TableItem *cte_table = temp_table_infos.at(i).table_items_.at(0);
if (OB_ISNULL(cte_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null table item", K(ret));
} else if (OB_FAIL(print_cte_define_title(cte_table))) {
LOG_WARN("print column name failed", K(ret));
} else if (OB_FAIL(print_subquery(cte_table->ref_query_, PRINT_BRACKET))) {
LOG_WARN("print table failed", K(ret));
} else if (OB_FAIL(print_search_and_cycle(cte_table->ref_query_))) {
LOG_WARN("print search and cycle failed", K(ret));
}
}
//打印尾巴
if (OB_FAIL(ret)) {
//do nothing
} else if (i == temp_table_infos.count() - 1) {
DATA_PRINTF(" ");
} else {
DATA_PRINTF(", ");
}
}
}
return ret;
}
int ObDMLStmtPrinter::print_cte_define_title(TableItem* cte_table)
{
int ret = OB_SUCCESS;
//递归cte一定是定义了别名列表的
//打印cte的表一定不要打印库名?
//DATA_PRINTF(" %.*s)", LEN_AND_PTR(cte_table->table_name_));
//cte在mysql中定义和使用是,不允许类似 db.cte_name这种使用方法,打印的时候我们
//不能打印database name
ObSelectStmt *sub_select_stmt = NULL;
if (OB_ISNULL(cte_table) || OB_ISNULL(sub_select_stmt = cte_table->ref_query_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null params", K(ret));
} else {
PRINT_TABLE_NAME(print_params_, cte_table);
}
if (OB_SUCC(ret) && OB_NOT_NULL(cte_table->node_) && OB_NOT_NULL(cte_table->node_->children_[1])) {
DATA_PRINTF("(");
const ObIArray<SelectItem> &sub_select_items = sub_select_stmt->get_select_items();
//打印列
for (int64_t i = 0; i < sub_select_items.count() && OB_SUCC(ret); ++i) {
if (T_CTE_SEARCH_COLUMN == sub_select_items.at(i).expr_->get_expr_type()
|| T_CTE_CYCLE_COLUMN == sub_select_items.at(i).expr_->get_expr_type()) {
//伪列不需要打印出来
} else {
PRINT_IDENT_WITH_QUOT(sub_select_items.at(i).alias_name_);
if (i != sub_select_items.count() - 1
&& T_CTE_SEARCH_COLUMN != sub_select_items.at(i+1).expr_->get_expr_type()
&& T_CTE_CYCLE_COLUMN != sub_select_items.at(i+1).expr_->get_expr_type()) {
DATA_PRINTF(", ");
}
}
}
DATA_PRINTF(")");
}
if (OB_SUCC(ret)) {
DATA_PRINTF(" as ");
}
return ret;
}
int ObDMLStmtPrinter::print_cte_define_title(const ObSelectStmt *sub_select_stmt)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(sub_select_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null params", K(ret));
} else {
DATA_PRINTF("(");
const ObIArray<SelectItem> &sub_select_items = sub_select_stmt->get_select_items();
//打印列
for (int64_t i = 0; i < sub_select_items.count() && OB_SUCC(ret); ++i) {
if (T_CTE_SEARCH_COLUMN == sub_select_items.at(i).expr_->get_expr_type()
|| T_CTE_CYCLE_COLUMN == sub_select_items.at(i).expr_->get_expr_type()) {
//伪列不需要打印出来
} else {
PRINT_COLUMN_NAME(sub_select_items.at(i).alias_name_);
if (i != sub_select_items.count() - 1
&& T_CTE_SEARCH_COLUMN != sub_select_items.at(i+1).expr_->get_expr_type()
&& T_CTE_CYCLE_COLUMN != sub_select_items.at(i+1).expr_->get_expr_type()) {
DATA_PRINTF(", ");
}
}
}
DATA_PRINTF(") as ");
}
return ret;
}
int ObDMLStmtPrinter::print_search_and_cycle(const ObSelectStmt *sub_select_stmt)
{
int ret = OB_SUCCESS;
ObArenaAllocator allocator("PrintSelectStmt");
if (OB_ISNULL(sub_select_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the cte table must have ref sub query", K(ret));
} else {
const ObIArray<SelectItem> &sub_select_items = sub_select_stmt->get_select_items();
const ObIArray<OrderItem> &search_items = sub_select_stmt->get_search_by_items();
if (!search_items.empty()) {
DATA_PRINTF(" search ");
if (sub_select_stmt->is_breadth_search()) {
DATA_PRINTF("breadth first by ");
} else {
DATA_PRINTF("depth first by ");
}
}
for (int64_t i = 0; i < search_items.count() && OB_SUCC(ret); ++i) {
allocator.reuse();
ObString column_name = ((ObColumnRefRawExpr*)(search_items.at(i).expr_))->get_column_name();
PRINT_COLUMN_NAME(column_name);
if (lib::is_mysql_mode()) {
if (is_descending_direction(search_items.at(i).order_type_)) {
DATA_PRINTF("DESC ");
}
} else if (search_items.at(i).order_type_ == NULLS_FIRST_ASC) {
DATA_PRINTF("ASC NULLS FIRST ");
} else if (search_items.at(i).order_type_ == NULLS_LAST_ASC) {//use default value
/*do nothing*/
} else if (search_items.at(i).order_type_ == NULLS_FIRST_DESC) {//use default value
DATA_PRINTF("DESC ");
} else if (search_items.at(i).order_type_== NULLS_LAST_DESC) {
DATA_PRINTF("DESC NULLS LAST ");
}
if (i != search_items.count() - 1) {
DATA_PRINTF(", ");
} else {
DATA_PRINTF(" ");
}
}
for (int64_t i = 0; i < sub_select_items.count() && OB_SUCC(ret); ++i) {
if (T_CTE_SEARCH_COLUMN == sub_select_items.at(i).expr_->get_expr_type()) {
DATA_PRINTF("set ");
PRINT_COLUMN_NAME(sub_select_items.at(i).alias_name_);
}
}
const ObIArray<ColumnItem> &cycle_items = sub_select_stmt->get_cycle_items();
if (!cycle_items.empty()) {
DATA_PRINTF("cycle ");
}
for (int64_t i = 0; i < cycle_items.count() && OB_SUCC(ret); ++i) {
allocator.reuse();
ObString column_name = ((ObColumnRefRawExpr*)(cycle_items.at(i).expr_))->get_column_name();
PRINT_COLUMN_NAME(column_name);
if (i != cycle_items.count() - 1) {
DATA_PRINTF(", ");
} else {
DATA_PRINTF(" ");
}
}
for (int64_t i = 0; i < sub_select_items.count() && OB_SUCC(ret); ++i) {
if (T_CTE_CYCLE_COLUMN == sub_select_items.at(i).expr_->get_expr_type()) {
ObRawExpr *v;
ObRawExpr *d_v;
DATA_PRINTF("set ");
PRINT_COLUMN_NAME(sub_select_items.at(i).alias_name_);
DATA_PRINTF("to ");
((ObPseudoColumnRawExpr*)(sub_select_items.at(i).expr_))->get_cte_cycle_value(v, d_v);
if (OB_ISNULL(v)
|| OB_ISNULL(d_v)
|| !v->is_const_raw_expr()
|| !d_v->is_const_raw_expr()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected const expr", K(ret), KPC(v), KPC(d_v));
} else {
ObObj non_cycle_vale = ((ObConstRawExpr*)v)->get_value();
ObObj cycle_vale = ((ObConstRawExpr*)d_v)->get_value();
DATA_PRINTF("'%.*s' ", LEN_AND_PTR(non_cycle_vale.get_string()));
DATA_PRINTF("default ");
DATA_PRINTF("'%.*s' ", LEN_AND_PTR(cycle_vale.get_string()));
}
}
}
}
return ret;
}
//把cte的定义完整的恢复出来
int ObDMLStmtPrinter::print_with()
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null stmt", K(ret));
} else if (!print_params_.print_origin_stmt_) {
//do nothing
} else if (stmt_->get_cte_definition_size() == 0) {
// don't print
} else {
const ObIArray<TableItem *> &cte_tables = stmt_->get_cte_definitions();
DATA_PRINTF(is_oracle_mode() ? "WITH " : "WITH RECURSIVE ");
//恢复定义,cte先放本stmt中T_WITH_CLAUSE产生的的cte,再放parent放过来的
for (int64_t i = 0; OB_SUCC(ret) && i < cte_tables.count() && OB_SUCC(ret); i++) {
TableItem* cte_table = cte_tables.at(i);
//打印定义
if (OB_ISNULL(cte_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the cte tableitem can not be null", K(ret));
} else if (TableItem::NORMAL_CTE == cte_table->cte_type_
|| TableItem::RECURSIVE_CTE == cte_table->cte_type_) {
if (OB_FAIL(print_cte_define_title(cte_table))) {
LOG_WARN("print column name failed", K(ret));
} else if (OB_FAIL(print_subquery(cte_table->ref_query_, PRINT_BRACKET | FORCE_COL_ALIAS))) {
LOG_WARN("print table failed", K(ret));
} else if (OB_FAIL(print_search_and_cycle(cte_table->ref_query_))) {
LOG_WARN("print search and cycle failed", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected cte type", K(ret), K(cte_table->cte_type_));
}
//打印尾巴
if (OB_FAIL(ret)) {
//do nothing
} else if (i == cte_tables.count() - 1) {
DATA_PRINTF(" ");
} else {
DATA_PRINTF(", ");
}
}
}
return ret;
}
} //end of namespace sql
} //end of namespace oceanbase