[FEAT MERGE]4_1_sql_feature
Co-authored-by: leslieyuchen <leslieyuchen@gmail.com> Co-authored-by: Charles0429 <xiezhenjiang@gmail.com> Co-authored-by: raywill <hustos@gmail.com>
This commit is contained in:
		@ -24,22 +24,17 @@ namespace sql
 | 
			
		||||
 | 
			
		||||
void ObSelectStmtPrinter::init(char *buf, int64_t buf_len, int64_t *pos,
 | 
			
		||||
                               ObSelectStmt *stmt,
 | 
			
		||||
                               ObIArray<ObString> *column_list,
 | 
			
		||||
                               bool is_set_subquery)
 | 
			
		||||
                               ObIArray<ObString> *column_list)
 | 
			
		||||
{
 | 
			
		||||
  ObDMLStmtPrinter::init(buf, buf_len, pos, stmt);
 | 
			
		||||
  column_list_ = column_list;
 | 
			
		||||
  is_set_subquery_ = is_set_subquery;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSelectStmtPrinter::do_print()
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
 | 
			
		||||
  if (OB_UNLIKELY(!is_inited_)) {
 | 
			
		||||
    ret = OB_NOT_INIT;
 | 
			
		||||
    LOG_WARN("not inited!", K(ret));
 | 
			
		||||
  } else if (OB_ISNULL(stmt_)) {
 | 
			
		||||
  if (OB_ISNULL(stmt_)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("stmt should not be NULL", K(ret));
 | 
			
		||||
  } else if (!stmt_->is_select_stmt()) {
 | 
			
		||||
@ -54,7 +49,10 @@ int ObSelectStmtPrinter::do_print()
 | 
			
		||||
          K(column_list_->count()), K(select_stmt->get_select_item_size()));
 | 
			
		||||
    } else {
 | 
			
		||||
      expr_printer_.init(buf_, buf_len_, pos_, schema_guard_, print_params_, param_store_);
 | 
			
		||||
      if (stmt_->is_unpivot_select()) {
 | 
			
		||||
      if ((print_params_.force_print_cte_ || print_params_.print_with_cte_) &&
 | 
			
		||||
           OB_FAIL(print_cte_define())) {
 | 
			
		||||
        LOG_WARN("failed to print cte", K(ret));
 | 
			
		||||
      } else if (stmt_->is_unpivot_select()) {
 | 
			
		||||
        if (OB_FAIL(print_unpivot())) {
 | 
			
		||||
          LOG_WARN("fail to print_unpivot",
 | 
			
		||||
                   KPC(stmt_->get_transpose_item()), K(ret));
 | 
			
		||||
@ -80,29 +78,20 @@ int ObSelectStmtPrinter::print()
 | 
			
		||||
    LOG_WARN("Not a valid select stmt", K(stmt_->get_stmt_type()), K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(stmt_);
 | 
			
		||||
    if (!select_stmt->is_root_stmt() || is_set_subquery_) {
 | 
			
		||||
      DATA_PRINTF("(");
 | 
			
		||||
    }
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      if (OB_FAIL(print_with())) {
 | 
			
		||||
        LOG_WARN("print with failed");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      if (select_stmt->is_set_stmt()) {
 | 
			
		||||
        // union, intersect, except
 | 
			
		||||
        if (OB_FAIL(print_set_op_stmt())) {
 | 
			
		||||
          LOG_WARN("fail to print set_op stmt", K(ret), K(*stmt_));
 | 
			
		||||
    if (OB_FAIL(print_with())) {
 | 
			
		||||
      LOG_WARN("print with failed");
 | 
			
		||||
    } else if (select_stmt->is_set_stmt()) {
 | 
			
		||||
      if (select_stmt->is_recursive_union() &&
 | 
			
		||||
          !print_params_.print_origin_stmt_) {
 | 
			
		||||
        // for dblink, print a embeded recursive union query block
 | 
			
		||||
        if (OB_FAIL(print_recursive_union_stmt())) {
 | 
			
		||||
          LOG_WARN("failed to print recursive union stmt", K(ret));
 | 
			
		||||
        }
 | 
			
		||||
      } else if (OB_FAIL(print_basic_stmt())) {
 | 
			
		||||
        LOG_WARN("fail to print basic stmt", K(ret), K(*stmt_));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      if (!select_stmt->is_root_stmt() || is_set_subquery_) {
 | 
			
		||||
        DATA_PRINTF(")");
 | 
			
		||||
      } else if (OB_FAIL(print_set_op_stmt())) {
 | 
			
		||||
        LOG_WARN("fail to print set_op stmt", K(ret), K(*stmt_));
 | 
			
		||||
      }
 | 
			
		||||
    } else if (OB_FAIL(print_basic_stmt())) {
 | 
			
		||||
      LOG_WARN("fail to print basic stmt", K(ret), K(*stmt_));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -126,9 +115,6 @@ int ObSelectStmtPrinter::print_unpivot()
 | 
			
		||||
             K(stmt_->get_table_items().count()), K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(stmt_);
 | 
			
		||||
    if (!select_stmt->is_root_stmt()) {
 | 
			
		||||
      DATA_PRINTF("(");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      if (OB_FAIL(print_select())) {
 | 
			
		||||
@ -251,12 +237,6 @@ int ObSelectStmtPrinter::print_unpivot()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    DATA_PRINTF(" )");
 | 
			
		||||
 | 
			
		||||
    if (OB_SUCC(ret)) {
 | 
			
		||||
      if (!select_stmt->is_root_stmt()) {
 | 
			
		||||
        DATA_PRINTF(")");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
@ -271,8 +251,8 @@ int ObSelectStmtPrinter::print_set_op_stmt()
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("Not a valid select stmt", K(stmt_->get_stmt_type()), K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    // todo: 目前 union 展平后无法保证与原始 sql 相同
 | 
			
		||||
    const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(stmt_);
 | 
			
		||||
    // todo: 目前 union 展平后无法保证与原始 sql 相同
 | 
			
		||||
    ObSEArray<ObSelectStmt*, 2> child_stmts;
 | 
			
		||||
    if (!select_stmt->is_set_stmt() || 2 > select_stmt->get_set_query().count()) {
 | 
			
		||||
      ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
@ -287,14 +267,16 @@ int ObSelectStmtPrinter::print_set_op_stmt()
 | 
			
		||||
      if (select_stmt->get_children_swapped()) {
 | 
			
		||||
        std::swap(child_stmts.at(0), child_stmts.at(1));
 | 
			
		||||
      }
 | 
			
		||||
      bool is_set_subquery = true;
 | 
			
		||||
      ObSelectStmtPrinter stmt_printer(buf_, buf_len_, pos_, child_stmts.at(0),
 | 
			
		||||
                                       schema_guard_, print_params_,
 | 
			
		||||
                                       column_list_, is_set_subquery);
 | 
			
		||||
      DATA_PRINTF("(");
 | 
			
		||||
      ObSelectStmtPrinter stmt_printer(buf_, buf_len_, pos_, child_stmts.at(0), schema_guard_, print_params_, need_print_alias());
 | 
			
		||||
      stmt_printer.set_column_list(column_list_);
 | 
			
		||||
      stmt_printer.disable_print_cte();
 | 
			
		||||
      ObString set_op_str = ObString::make_string(
 | 
			
		||||
                                ObSelectStmt::set_operator_str(select_stmt->get_set_op()));
 | 
			
		||||
      if (OB_FAIL(stmt_printer.do_print())) {
 | 
			
		||||
        LOG_WARN("fail to print left stmt", K(ret), K(*child_stmts.at(0)));
 | 
			
		||||
      } else {
 | 
			
		||||
        DATA_PRINTF(")");
 | 
			
		||||
      }
 | 
			
		||||
      for (int64_t i = 1; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
 | 
			
		||||
        DATA_PRINTF(" %.*s ", LEN_AND_PTR(set_op_str)); // print set_op
 | 
			
		||||
@ -306,9 +288,12 @@ int ObSelectStmtPrinter::print_set_op_stmt()
 | 
			
		||||
          ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
          LOG_WARN("child_stmt should not be NULL", K(ret));
 | 
			
		||||
        } else {
 | 
			
		||||
          stmt_printer.init(buf_, buf_len_, pos_, child_stmts.at(i), column_list_, is_set_subquery);
 | 
			
		||||
          DATA_PRINTF("(");
 | 
			
		||||
          stmt_printer.init(buf_, buf_len_, pos_, child_stmts.at(i), column_list_);
 | 
			
		||||
          if (OB_FAIL(stmt_printer.do_print())) {
 | 
			
		||||
            LOG_WARN("fail to print child stmt", K(ret));
 | 
			
		||||
          } else {
 | 
			
		||||
            DATA_PRINTF(")");
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
@ -324,7 +309,45 @@ int ObSelectStmtPrinter::print_set_op_stmt()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSelectStmtPrinter::print_recursive_union_stmt()
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_ISNULL(stmt_)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("stmt_ should not be NULL", K(ret));
 | 
			
		||||
  } else if (!stmt_->is_select_stmt()) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("Not a valid select stmt", K(stmt_->get_stmt_type()), K(ret));
 | 
			
		||||
  } else {
 | 
			
		||||
    const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(stmt_);
 | 
			
		||||
    TableItem *table = NULL;
 | 
			
		||||
    if (OB_FAIL(find_recursive_cte_table(select_stmt, table))) {
 | 
			
		||||
      LOG_WARN("failed to find recursive cte table", K(ret));
 | 
			
		||||
    } else if (OB_ISNULL(table)) {
 | 
			
		||||
      ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
      LOG_WARN("unexpect null table item", K(ret));
 | 
			
		||||
    } else  {
 | 
			
		||||
      DATA_PRINTF("WITH RECURSIVE ");
 | 
			
		||||
      DATA_PRINTF("%.*s", LEN_AND_PTR(table->table_name_));
 | 
			
		||||
      if (OB_FAIL(print_cte_define_title(select_stmt))) {
 | 
			
		||||
        LOG_WARN("failed to printf cte title", K(ret));
 | 
			
		||||
      } else {
 | 
			
		||||
        DATA_PRINTF("(");
 | 
			
		||||
        if (OB_FAIL(print_set_op_stmt())) {
 | 
			
		||||
          LOG_WARN("failed to print", K(ret));
 | 
			
		||||
        } else if (OB_FAIL(print_search_and_cycle(select_stmt))) {
 | 
			
		||||
          LOG_WARN("print search and cycle failed", K(ret));
 | 
			
		||||
        } else {
 | 
			
		||||
          DATA_PRINTF(")");
 | 
			
		||||
          DATA_PRINTF(" select * from ");
 | 
			
		||||
          DATA_PRINTF("%.*s", LEN_AND_PTR(table->table_name_));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -408,28 +431,13 @@ int ObSelectStmtPrinter::print_select()
 | 
			
		||||
          // create view(a,b) v as select c1,c2 as alias from t1;
 | 
			
		||||
          // 替换后:              select c1 as a, c2 as b from t1
 | 
			
		||||
          // 因此需要将最顶层stmt中相应别名表达式的func_name替换成column_name
 | 
			
		||||
          bool need_add_alias = force_col_alias_;
 | 
			
		||||
          if (OB_ISNULL(expr)) {
 | 
			
		||||
            ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
            LOG_WARN("select item expr is null");
 | 
			
		||||
          } else if (select_item.is_real_alias_) {
 | 
			
		||||
            need_add_alias = true;
 | 
			
		||||
          } else if (select_stmt->is_root_stmt()) {
 | 
			
		||||
            if (print_params_.is_show_create_view_) {
 | 
			
		||||
              need_add_alias = true;
 | 
			
		||||
            }
 | 
			
		||||
          } else if (OB_ISNULL(select_stmt->get_parent_namespace_stmt())) {
 | 
			
		||||
            ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
            LOG_WARN("upper_scope_stmt is NULL", K(ret));
 | 
			
		||||
          } else if (select_stmt->get_parent_namespace_stmt()->is_delete_stmt() ||
 | 
			
		||||
                     select_stmt->get_parent_namespace_stmt()->is_update_stmt() ||
 | 
			
		||||
                     (select_stmt->get_parent_namespace_stmt()->is_root_stmt() &&
 | 
			
		||||
                      is_set_subquery_)) {
 | 
			
		||||
            need_add_alias = true;
 | 
			
		||||
          }
 | 
			
		||||
          bool need_add_alias = need_print_alias() || select_item.is_real_alias_;
 | 
			
		||||
          if (OB_SUCC(ret)) {
 | 
			
		||||
            ObRawExpr *tmp_expr = expr;
 | 
			
		||||
            if (OB_FAIL(ObRawExprUtils::erase_inner_added_exprs(tmp_expr, expr))) {
 | 
			
		||||
            if (OB_ISNULL(expr)) {
 | 
			
		||||
              ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
              LOG_WARN("expr is null", K(ret), K(expr));
 | 
			
		||||
            } else if (OB_FAIL(ObRawExprUtils::erase_inner_added_exprs(tmp_expr, expr))) {
 | 
			
		||||
              LOG_WARN("erase inner cast expr failed", K(ret));
 | 
			
		||||
            } else if (OB_ISNULL(expr)) {
 | 
			
		||||
              ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
@ -461,11 +469,10 @@ int ObSelectStmtPrinter::print_select()
 | 
			
		||||
                                                                             arena_alloc))) {
 | 
			
		||||
              LOG_WARN("failed to remove double quotation for string", K(ret));
 | 
			
		||||
            } else {
 | 
			
		||||
              if (is_oracle_mode) {
 | 
			
		||||
                DATA_PRINTF(" AS \"%.*s\"", LEN_AND_PTR(alias_string));
 | 
			
		||||
              } else {
 | 
			
		||||
                DATA_PRINTF(" AS `%.*s`", LEN_AND_PTR(alias_string));
 | 
			
		||||
              }
 | 
			
		||||
              DATA_PRINTF(" AS ");
 | 
			
		||||
              PRINT_QUOT;
 | 
			
		||||
              DATA_PRINTF("%.*s", LEN_AND_PTR(alias_string));
 | 
			
		||||
              PRINT_QUOT;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          DATA_PRINTF(",");
 | 
			
		||||
@ -802,9 +809,7 @@ int ObSelectStmtPrinter::print_for_update()
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("Not a valid select stmt", K(stmt_->get_stmt_type()), K(ret));
 | 
			
		||||
  } else if (is_oracle_mode()) {
 | 
			
		||||
    if (is_generated_table_ || stmt_->get_parent_namespace_stmt() != NULL) {
 | 
			
		||||
      // do nothing
 | 
			
		||||
    } else {
 | 
			
		||||
    if (is_root_stmt()) {
 | 
			
		||||
      const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(stmt_);
 | 
			
		||||
      bool has_for_update_ = false;
 | 
			
		||||
      int64_t wait_time = -1;
 | 
			
		||||
@ -864,193 +869,6 @@ int ObSelectStmtPrinter::print_for_update()
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//把cte的定义完整的恢复出来
 | 
			
		||||
int ObSelectStmtPrinter::print_with()
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  if (OB_SUCC(ret)) {
 | 
			
		||||
    const ObSelectStmt *select_stmt = static_cast<const ObSelectStmt*>(stmt_);
 | 
			
		||||
    const ObIArray<TableItem *> &cte_tables = select_stmt->get_cte_definitions();
 | 
			
		||||
    if (select_stmt->get_cte_definition_size() == 0) {
 | 
			
		||||
      // don't print
 | 
			
		||||
    } else {
 | 
			
		||||
      DATA_PRINTF(is_oracle_mode() ? "WITH " : "WITH RECURSIVE");
 | 
			
		||||
      //恢复定义,cte先放本stmt中T_WITH_CLAUSE产生的的cte,再放parent放过来的
 | 
			
		||||
      for (int64_t i = 0; 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_ISNULL(cte_table->node_)) {
 | 
			
		||||
            ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
            LOG_WARN("the parser node of a cte table can not be null", 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_table(cte_table, true))) {
 | 
			
		||||
            LOG_WARN("print table failed", K(ret));
 | 
			
		||||
          } else if ((TableItem::RECURSIVE_CTE == cte_table->cte_type_)
 | 
			
		||||
                      && OB_FAIL(print_search_and_cycle(cte_table))) {
 | 
			
		||||
            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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSelectStmtPrinter::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;
 | 
			
		||||
  PRINT_TABLE_NAME(cte_table);
 | 
			
		||||
  if (OB_ISNULL(cte_table->node_->children_[1]) && (TableItem::RECURSIVE_CTE == cte_table->cte_type_)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("the recursive cte must have the column definition", K(ret));
 | 
			
		||||
  } else if (OB_NOT_NULL(cte_table->node_->children_[1])) {
 | 
			
		||||
    DATA_PRINTF("(");
 | 
			
		||||
    sub_select_stmt = cte_table->ref_query_;
 | 
			
		||||
    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 {
 | 
			
		||||
        DATA_PRINTF("%.*s", LEN_AND_PTR(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(")");
 | 
			
		||||
  } else {
 | 
			
		||||
    //do nothing, the normal cte without column alias is OK
 | 
			
		||||
  }
 | 
			
		||||
  DATA_PRINTF(" as ");
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSelectStmtPrinter::print_search_and_cycle(TableItem* cte_table)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  ObArenaAllocator allocator("PrintSelectStmt");
 | 
			
		||||
  ObSelectStmt *sub_select_stmt = NULL;
 | 
			
		||||
  if (OB_ISNULL(sub_select_stmt = cte_table->ref_query_)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("the cte table must have ref sub query", K(ret));
 | 
			
		||||
  } else if (OB_ISNULL(cte_table->node_->children_[1])) {
 | 
			
		||||
    //优化路径,没有列定义的肯定不是递归cte
 | 
			
		||||
    //do nothing
 | 
			
		||||
  } 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();
 | 
			
		||||
      CONVERT_CHARSET_FOR_RPINT(allocator, column_name);
 | 
			
		||||
      DATA_PRINTF(" %.*s ", LEN_AND_PTR(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 ");
 | 
			
		||||
        DATA_PRINTF(" %.*s ", LEN_AND_PTR(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();
 | 
			
		||||
      CONVERT_CHARSET_FOR_RPINT(allocator, column_name);
 | 
			
		||||
      DATA_PRINTF("%.*s ", LEN_AND_PTR(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 ");
 | 
			
		||||
        DATA_PRINTF("%.*s ", LEN_AND_PTR(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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSelectStmtPrinter::print_with_check_option()
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
@ -1082,5 +900,32 @@ int ObSelectStmtPrinter::print_with_check_option()
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObSelectStmtPrinter::find_recursive_cte_table(const ObSelectStmt* stmt, TableItem* &table)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  table = NULL;
 | 
			
		||||
  ObSelectStmt* set_query = NULL;
 | 
			
		||||
  if (OB_ISNULL(stmt)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("unexpect null stmt", K(ret));
 | 
			
		||||
  } else if (!stmt->is_recursive_union() ||
 | 
			
		||||
             OB_ISNULL(set_query=stmt->get_set_query(1))) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("expect recurisve cte stmt", K(ret));
 | 
			
		||||
  }
 | 
			
		||||
  for (int i = 0; OB_SUCC(ret) && !table && i < set_query->get_table_items().count(); ++i) {
 | 
			
		||||
    TableItem *table_item = set_query->get_table_item(i);
 | 
			
		||||
    if (OB_ISNULL(table_item)) {
 | 
			
		||||
      ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
      LOG_WARN("unexpect null table item", K(ret));
 | 
			
		||||
    } else if (!table_item->is_fake_cte_table()) {
 | 
			
		||||
      //do nothing
 | 
			
		||||
    } else {
 | 
			
		||||
      table = table_item;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} //end of namespace sql
 | 
			
		||||
} //end of namespace oceanbase
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user