提交 1777c976 编写于 作者: O obdev 提交者: wangzelin.wzl

cherry-pick from 3_1_x_release to 3.1_opensource_release

上级 850ef4e4
......@@ -183,12 +183,13 @@ int ObServerConnectionPool::init_dblink(uint64_t dblink_id, const ObAddr& server
LOG_WARN("db param buffer is not enough", K(ret), K(dblink_id), K(db_tenant), K(db_user), K(db_pass), K(db_name));
} else {
dblink_id_ = dblink_id;
(void)snprintf(db_user_, sizeof(db_user_), "%s@%s", db_user.ptr(), db_tenant.ptr());
(void)snprintf(db_pass_, sizeof(db_pass_), "%s", db_pass.ptr());
(void)snprintf(
db_user_, sizeof(db_user_), "%.*s@%.*s", db_user.length(), db_user.ptr(), db_tenant.length(), db_tenant.ptr());
(void)snprintf(db_pass_, sizeof(db_pass_), "%.*s", db_pass.length(), db_pass.ptr());
// https://baike.baidu.com/item/mysql_real_connect/4007597
// if db is NULL, the default database is used.
if (!db_name.empty()) {
(void)snprintf(db_name_, sizeof(db_name_), "%s", db_name.ptr());
(void)snprintf(db_name_, sizeof(db_name_), "%.*s", db_name.length(), db_name.ptr());
}
}
return ret;
......
......@@ -11214,9 +11214,9 @@ static struct ObStrErrorInit {
MYSQL_ERRNO[-OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION] = -1;
SQLSTATE[-OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION] = "HY000";
STR_ERROR[-OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION] =
"only pure functions can be specified in a virtual column expression";
"Expression of generated column contains a disallowed function";
STR_USER_ERROR[-OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION] =
"only pure functions can be specified in a virtual column expression";
"Expression of generated column contains a disallowed function";
ORACLE_ERRNO[-OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION] = 54002;
ORACLE_STR_ERROR[-OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION] =
"ORA-54002: only pure functions can be specified in a virtual column expression";
......
......@@ -1284,7 +1284,7 @@ DEFINE_ORACLE_ERROR(OB_ROWID_VIEW_NO_KEY_PRESERVED, -5902, -1, "HY000", "cannot
DEFINE_ORACLE_ERROR(OB_ROWID_VIEW_HAS_DISTINCT_ETC, -5903, -1, "HY000", "cannot select ROWID from, or sample, a view with DISTINCT, GROUP BY, etc", 1446, "cannot select ROWID from, or sample, a view with DISTINCT, GROUP BY, etc");
DEFINE_ORACLE_ERROR(OB_ERR_AT_LEAST_ONE_COLUMN_NOT_VIRTUAL, -5904, -1, "HY000", "table must have at least 1 column that is not virtual", 54037, "table must have at least 1 column that is not virtual");
DEFINE_ORACLE_ERROR(OB_ERR_ONLY_PURE_FUNC_CANBE_INDEXED, -5905, -1, "HY000", "only pure functions can be indexed", 1743, "only pure functions can be indexed");
DEFINE_ORACLE_ERROR(OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION, -5906, -1, "HY000", "only pure functions can be specified in a virtual column expression", 54002, "only pure functions can be specified in a virtual column expression");
DEFINE_ORACLE_ERROR(OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION, -5906, -1, "HY000", "Expression of generated column contains a disallowed function", 54002, "only pure functions can be specified in a virtual column expression");
DEFINE_ORACLE_ERROR(OB_ERR_UPDATE_OPERATION_ON_VIRTUAL_COLUMNS, -5907, -1, "HY000", "UPDATE operation disallowed on virtual columns", 54017, "UPDATE operation disallowed on virtual columns");
DEFINE_ORACLE_ERROR(OB_ERR_INVALID_COLUMN_EXPRESSION, -5908, -1, "HY000", "Invalid column expression was specified", 54016, "Invalid column expression was specified");
DEFINE_ORACLE_ERROR(OB_ERR_IDENTITY_COLUMN_COUNT_EXCE_LIMIT, -5909, -1, "HY000", "table can have only one identity column", 30669, "table can have only one identity column");
......
......@@ -2549,7 +2549,7 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219;
#define OB_ERR_AT_LEAST_ONE_COLUMN_NOT_VIRTUAL__USER_ERROR_MSG "table must have at least 1 column that is not virtual"
#define OB_ERR_ONLY_PURE_FUNC_CANBE_INDEXED__USER_ERROR_MSG "only pure functions can be indexed"
#define OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION__USER_ERROR_MSG \
"only pure functions can be specified in a virtual column expression"
"Expression of generated column contains a disallowed function"
#define OB_ERR_UPDATE_OPERATION_ON_VIRTUAL_COLUMNS__USER_ERROR_MSG "UPDATE operation disallowed on virtual columns"
#define OB_ERR_INVALID_COLUMN_EXPRESSION__USER_ERROR_MSG "Invalid column expression was specified"
#define OB_ERR_IDENTITY_COLUMN_COUNT_EXCE_LIMIT__USER_ERROR_MSG "table can have only one identity column"
......
......@@ -552,8 +552,13 @@ int ObIndexBuilderUtil::adjust_ordinary_index_column_args(
LOG_WARN("init session failed", K(ret));
} else if (OB_FAIL(session.load_default_sys_variable(false, false))) {
LOG_WARN("session load default system variable failed", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(
index_expr_def, expr_factory, session, data_schema, expr))) {
} else if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(index_expr_def,
expr_factory,
session,
data_schema,
expr,
NULL,
ObResolverUtils::CHECK_FOR_FUNCTION_INDEX))) {
LOG_WARN("build generated column expr failed", K(ret));
} else if (!expr->is_deterministic()) {
ret = OB_ERR_ONLY_PURE_FUNC_CANBE_INDEXED;
......
......@@ -22,7 +22,7 @@
#include "share/schema/ob_server_schema_service.h"
#include "share/ob_cluster_type.h"
#include "share/ob_get_compat_mode.h"
#include "sql/resolver/expr/ob_raw_expr_util.h"
#include "sql/resolver/ob_resolver_utils.h"
#include "sql/session/ob_sql_session_info.h"
#include "observer/ob_server_struct.h"
namespace oceanbase {
......@@ -145,51 +145,40 @@ int ObSchemaUtils::cascaded_generated_column(ObTableSchema& table_schema, ObColu
int ret = OB_SUCCESS;
ObString col_def;
ObArenaAllocator allocator(ObModIds::OB_SCHEMA);
ObRawExprFactory expr_factory(allocator);
ObRawExpr* expr = NULL;
ObArray<ObQualifiedName> columns;
ObItemType root_expr_type = T_INVALID;
ObArray<ObString> column_names;
ObColumnSchemaV2* col_schema = NULL;
bool is_oracle_mode = false;
if (column.is_generated_column()) {
// This is the mock session, so test_init should be used, otherwise it cannot be initialized for tz_mgr
ObSQLSessionInfo default_session;
if (OB_FAIL(default_session.test_init(0, 0, 0, &allocator))) {
LOG_WARN("init empty session failed", K(ret));
} else if (OB_FAIL(default_session.load_default_sys_variable(false, false))) {
LOG_WARN("session load default system variable failed", K(ret));
if (ObSchemaService::g_liboblog_mode_ && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_1471) {
// when 2.0liboblog fetch <1471 cluster, Parsing the column schema only needs to read orig_default_value
// Can not judge cur_default_value.is_null(), because the dependent column may have a default value
// cur_default_value is is_not_null, misjudgment
if (OB_FAIL(column.get_orig_default_value().get_string(col_def))) {
LOG_WARN("get orig default value failed", K(ret));
}
} else {
if (ObSchemaService::g_liboblog_mode_ && GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_1471) {
// when 2.0liboblog fetch <1471 cluster, Parsing the column schema only needs to read orig_default_value
// Can not judge cur_default_value.is_null(), because the dependent column may have a default value
// cur_default_value is is_not_null, misjudgment
// If the dependent column of the generated column has a change column, the current default value
// should be used instead of orig vaule
if (column.get_cur_default_value().is_null()) {
if (OB_FAIL(column.get_orig_default_value().get_string(col_def))) {
LOG_WARN("get orig default value failed", K(ret));
}
} else {
// If the dependent column of the generated column has a change column, the current default value
// should be used instead of orig vaule
if (column.get_cur_default_value().is_null()) {
if (OB_FAIL(column.get_orig_default_value().get_string(col_def))) {
LOG_WARN("get orig default value failed", K(ret));
}
} else {
if (OB_FAIL(column.get_cur_default_value().get_string(col_def))) {
LOG_WARN("get cur default value failed", K(ret));
}
if (OB_FAIL(column.get_cur_default_value().get_string(col_def))) {
LOG_WARN("get cur default value failed", K(ret));
}
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(col_def, expr_factory, default_session, expr, columns))) {
if (OB_FAIL(ObResolverUtils::resolve_generated_column_info(col_def, allocator, root_expr_type, column_names))) {
LOG_WARN("get generated column expr failed", K(ret));
} else if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("expr is null");
} else if (T_FUN_SYS_WORD_SEGMENT == expr->get_expr_type()) {
} else if (T_FUN_SYS_WORD_SEGMENT == root_expr_type) {
column.add_column_flag(GENERATED_CTXCAT_CASCADE_FLAG);
} else {
LOG_DEBUG("succ to build_generated_column_expr", K(col_def), KPC(expr), K(columns), K(table_schema));
LOG_DEBUG(
"succ to resolve_generated_column_info", K(col_def), K(root_expr_type), K(column_names), K(table_schema));
}
}
......@@ -202,18 +191,10 @@ int ObSchemaUtils::cascaded_generated_column(ObTableSchema& table_schema, ObColu
// TODO: materialized view
if (table_schema.is_table() || table_schema.is_tmp_table()) {
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); ++i) {
// alter table t add b char(10) as(concat(a, '1')); oracle mode
// The pl implementation causes concat to be parsed into T_OBJ_ACCESS_REF, so column_name may be empty
if (is_oracle_mode && columns.at(i).access_idents_.count() > 0 &&
columns.at(i).access_idents_[0].type_ != UNKNOWN) {
continue;
} else if (!columns.at(i).database_name_.empty() || !columns.at(i).tbl_name_.empty()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column is invalid", K(columns.at(i)));
} else if (OB_ISNULL(col_schema = table_schema.get_column_schema(columns.at(i).col_name_))) {
for (int64_t i = 0; OB_SUCC(ret) && i < column_names.count(); ++i) {
if (OB_ISNULL(col_schema = table_schema.get_column_schema(column_names.at(i)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get column schema failed", K(columns.at(i)));
LOG_WARN("get column schema failed", K(column_names.at(i)));
} else if (OB_FAIL(column.add_cascaded_column_id(col_schema->get_column_id()))) {
LOG_WARN("add cascaded column id failed", K(ret));
} else {
......
......@@ -28,18 +28,27 @@ int ObExprSysConnectByPath::calc_result_type2(
ObExprResType& type, ObExprResType& type1, ObExprResType& type2, common::ObExprTypeCtx& type_ctx) const
{
int ret = OB_SUCCESS;
type.set_varchar();
// The length value result is related to the row count and cannot be determined in the analysis stage
type.set_length(OB_MAX_VARCHAR_LENGTH);
ObExprResType types[2];
type1.set_calc_type(ObVarcharType);
type2.set_calc_type(ObVarcharType);
types[0] = type1;
types[1] = type2;
if (OB_FAIL(aggregate_charsets_for_string_result(type, types, 2, type_ctx.get_coll_type()))) {
LOG_WARN("fail to aggregate charset", K(type1), K(type2), K(ret));
} else if (OB_FAIL(aggregate_charsets_for_comparison(type, types, 2, type_ctx.get_coll_type()))) {
LOG_WARN("fail to aggregate charset", K(type1), K(type2), K(ret));
if (is_oracle_mode()) {
ObSEArray<ObExprResType*, 2, ObNullAllocator> params;
OZ(params.push_back(&type1));
OZ(params.push_back(&type2));
OZ(aggregate_string_type_and_charset_oracle(*type_ctx.get_session(), params, type, true));
OZ(deduce_string_param_calc_type_and_charset(*type_ctx.get_session(), type, params));
type.set_calc_meta(type); // old engine need to set the calc_meta of type
} else {
type.set_varchar();
// The length value result is related to the row count and cannot be determined in the analysis stage
type.set_length(OB_MAX_VARCHAR_LENGTH);
ObExprResType types[2];
type1.set_calc_type(ObVarcharType);
type2.set_calc_type(ObVarcharType);
types[0] = type1;
types[1] = type2;
if (OB_FAIL(aggregate_charsets_for_string_result(type, types, 2, type_ctx.get_coll_type()))) {
LOG_WARN("fail to aggregate charset", K(type1), K(type2), K(ret));
} else if (OB_FAIL(aggregate_charsets_for_comparison(type, types, 2, type_ctx.get_coll_type()))) {
LOG_WARN("fail to aggregate charset", K(type1), K(type2), K(ret));
}
}
return ret;
}
......@@ -52,7 +61,7 @@ int ObExprSysConnectByPath::calc_result2(
if (OB_ISNULL(expr_ctx.exec_ctx_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("exec ctx is null", K(ret));
} else if ((left.get_type() != ObVarcharType && left.get_type() != ObNullType) || right.get_type() != ObVarcharType) {
} else if ((!left.is_string_type() && left.get_type() != ObNullType) || !right.is_string_type()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid input type", K(left), K(right), K(ret));
} else {
......
......@@ -513,13 +513,13 @@ int ObDDLResolver::set_database_name(const ObString& database_name)
return ret;
}
int ObDDLResolver::resolve_table_id_pre(ParseNode *node)
int ObDDLResolver::resolve_table_id_pre(ParseNode* node)
{
int ret = OB_SUCCESS;
if (NULL != node) {
ParseNode *option_node = NULL;
ParseNode* option_node = NULL;
int32_t num = 0;
if(T_TABLE_OPTION_LIST != node->type_ || node->num_child_ < 1) {
if (T_TABLE_OPTION_LIST != node->type_ || node->num_child_ < 1) {
ret = OB_ERR_UNEXPECTED;
SQL_RESV_LOG(WARN, "invalid parse node", K(ret));
} else if (OB_ISNULL(node->children_) || OB_ISNULL(session_info_)) {
......@@ -2945,12 +2945,8 @@ int ObDDLResolver::check_urowid_column_length(const share::schema::ObColumnSchem
return ret;
}
int ObDDLResolver::check_text_length(ObCharsetType cs_type,
ObCollationType co_type,
const char* name,
ObObjType& type,
int32_t& length,
bool need_rewrite_length)
int ObDDLResolver::check_text_length(ObCharsetType cs_type, ObCollationType co_type, const char* name, ObObjType& type,
int32_t& length, bool need_rewrite_length)
{
int ret = OB_SUCCESS;
int64_t mbmaxlen = 0;
......@@ -3009,14 +3005,13 @@ int ObDDLResolver::check_text_length(ObCharsetType cs_type,
// old version ObTinyTextType, ObTextType, ObMediumTextType, ObLongTextType max_length is incorrect
// correct max_legth is ObTinyTextType:255 etc.
// so when create new user table, must rewrite max column length
int ObDDLResolver::rewrite_text_length_mysql(ObObjType &type, int32_t &length)
int ObDDLResolver::rewrite_text_length_mysql(ObObjType& type, int32_t& length)
{
int ret = OB_SUCCESS;
int32_t max_length = ObAccuracy::MAX_ACCURACY[type].get_length();
if (length < 0 || length > max_length) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("length can not be less than 0 or larger than max_length",
K(ret), K(type), K(length), K(max_length));
LOG_WARN("length can not be less than 0 or larger than max_length", K(ret), K(type), K(length), K(max_length));
} else if (ob_is_text_tc(type) && max_length == length) {
length = length - 1;
}
......@@ -3036,11 +3031,11 @@ int ObDDLResolver::check_text_column_length_and_promote(ObColumnSchemaV2& column
need_check_length = false;
}
if (OB_FAIL(check_text_length(column.get_charset_type(),
column.get_collation_type(),
column.get_column_name(),
type,
length,
need_check_length))) {
column.get_collation_type(),
column.get_column_name(),
type,
length,
need_check_length))) {
LOG_WARN("failed to check text length", K(ret), K(column));
} else {
column.set_data_type(type);
......@@ -3772,7 +3767,8 @@ int ObDDLResolver::check_default_value(ObObj& default_value, const common::ObTim
LOG_WARN("session load default system variable failed", K(ret));
} else if (OB_FAIL(input_default_value.get_string(expr_str))) {
LOG_WARN("get expr string from default value failed", K(ret), K(input_default_value));
} else if (OB_FAIL(ObResolverUtils::resolve_generated_column_expr(params, expr_str, table_schema, column, expr))) {
} else if (OB_FAIL(ObResolverUtils::resolve_generated_column_expr(
params, expr_str, table_schema, column, expr, ObResolverUtils::CHECK_FOR_GENERATED_COLUMN))) {
LOG_WARN("resolve generated column expr failed", K(ret));
} else if (column.get_meta_type().is_null()) {
column.set_data_type(expr->get_data_type());
......
......@@ -472,6 +472,37 @@ int ObRawExpr::set_enum_set_values(const common::ObIArray<common::ObString>& val
return ret;
}
bool ObRawExpr::is_non_pure_sys_func_expr() const
{
if (lib::is_oracle_mode()) {
if (T_FUN_SYS_LOCALTIMESTAMP == type_ || T_FUN_SYS_SESSIONTIMEZONE == type_ || T_FUN_SYS_DBTIMEZONE == type_ ||
T_FUN_SYS_SYSDATE == type_ || T_FUN_SYS_SYSTIMESTAMP == type_ || T_FUN_SYS_UID == type_ ||
T_FUN_SYS_USER == type_ || T_FUN_SYS_CUR_TIMESTAMP == type_ || T_FUN_SYS_GUID == type_ ||
T_FUN_SYS_CUR_DATE == type_ || T_FUN_SYS_USERENV == type_ || T_FUN_SYS_REGEXP_REPLACE == type_) {
return true;
}
} else {
if (T_FUN_SYS_CONNECTION_ID == type_ || T_FUN_SYS_VERSION == type_ || T_FUN_SYS_CURRENT_USER == type_ ||
T_FUN_SYS_USER == type_ || T_FUN_SYS_DATABASE == type_ || T_FUN_SYS_SYSDATE == type_ ||
T_FUN_SYS_CUR_DATE == type_ || T_FUN_SYS_CUR_TIME == type_ || T_FUN_SYS_CUR_TIMESTAMP == type_ ||
T_FUN_SYS_UNIX_TIMESTAMP == type_ || T_FUN_SYS_UTC_TIMESTAMP == type_ || T_FUN_SYS_RAND == type_ ||
T_FUN_SYS_UUID == type_ || T_FUN_SYS_SLEEP == type_ || T_FUN_SYS_LAST_INSERT_ID == type_ ||
T_FUN_SYS_ROW_COUNT == type_ || T_FUN_SYS_FOUND_ROWS == type_ || T_FUN_SYS_REGEXP_INSTR == type_ ||
T_FUN_SYS_REGEXP_LIKE == type_ || T_FUN_SYS_REGEXP_REPLACE == type_ || T_FUN_SYS_REGEXP_SUBSTR == type_) {
return true;
}
}
return false;
}
bool ObRawExpr::is_specified_pseudocolumn_expr() const
{
if (T_FUN_SYS_ROWNUM == type_ || T_LEVEL == type_ || T_CONNECT_BY_ISCYCLE == type_ || T_CONNECT_BY_ISLEAF == type_) {
return true;
}
return false;
}
////////////////////////////////////////////////////////////////
int ObConstRawExpr::assign(const ObConstRawExpr& other)
{
......
......@@ -1351,6 +1351,8 @@ public:
{
return T_FUN_PL_ASSOCIATIVE_INDEX == get_expr_type();
}
bool is_non_pure_sys_func_expr() const;
bool is_specified_pseudocolumn_expr() const;
void set_alias_column_name(const common::ObString& alias_name)
{
alias_column_name_ = alias_name;
......
......@@ -1014,7 +1014,7 @@ int ObRawExprUtils::parse_bool_expr_node_from_str(
int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns,
const ObSchemaChecker* schema_checker)
const ObSchemaChecker* schema_checker, const ObResolverUtils::PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
const ParseNode* node = NULL;
......@@ -1023,15 +1023,73 @@ int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawE
} else if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is null");
} else if (OB_FAIL(build_generated_column_expr(expr_factory, session_info, *node, expr, columns, schema_checker))) {
} else if (OB_FAIL(build_generated_column_expr(
expr_factory, session_info, *node, expr, columns, schema_checker, check_status))) {
LOG_WARN("build generated column expr failed", K(ret));
}
return ret;
}
int ObRawExprUtils::check_deterministic(
const ObRawExpr* expr, ObIAllocator& allocator, const ObResolverUtils::PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
CK(OB_NOT_NULL(expr));
CK(expr->get_children_count() >= 0);
ObList<const ObRawExpr*, ObIAllocator> expr_queue(allocator);
OZ(expr_queue.push_back(expr));
const ObRawExpr* cur_expr = NULL;
while (OB_SUCC(ret) && expr_queue.size() > 0) {
OZ(expr_queue.pop_front(cur_expr));
CK(OB_NOT_NULL(cur_expr));
OZ(check_deterministic_single(cur_expr, check_status));
for (int i = 0; OB_SUCC(ret) && i < cur_expr->get_param_count(); ++i) {
OZ(expr_queue.push_back(cur_expr->get_param_expr(i)));
}
}
return ret;
}
int ObRawExprUtils::check_deterministic_single(
const ObRawExpr* expr, const ObResolverUtils::PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
CK(OB_NOT_NULL(expr));
if (OB_SUCC(ret) && ObResolverUtils::DISABLE_CHECK != check_status) {
if (expr->is_sys_func_expr()) {
if (expr->is_non_pure_sys_func_expr()) {
if (ObResolverUtils::CHECK_FOR_GENERATED_COLUMN == check_status) {
ret = OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION;
} else if (ObResolverUtils::CHECK_FOR_FUNCTION_INDEX == check_status) {
ret = OB_ERR_ONLY_PURE_FUNC_CANBE_INDEXED;
}
LOG_WARN("only pure sys function can be indexed", K(ret), K(check_status), K(*expr));
} else if (T_FUN_SYS_ROWNUM == expr->get_expr_type()) {
ret = OB_ERR_CBY_PSEUDO_COLUMN_NOT_ALLOWED;
LOG_WARN("ROWNUM is not allowed", K(ret), K(*expr));
}
} else if (expr->is_pseudo_column_expr()) {
if (expr->is_specified_pseudocolumn_expr()) {
ret = OB_ERR_CBY_PSEUDO_COLUMN_NOT_ALLOWED;
LOG_WARN("not allowed pesudo column", K(ret), K(*expr));
}
} else if (expr->is_udf_expr()) {
if (lib::is_mysql_mode()) {
ret = OB_ERR_ONLY_PURE_FUNC_CANBE_VIRTUAL_COLUMN_EXPRESSION;
LOG_WARN("user-defined functions are not allowd in generated column", K(ret), K(*expr));
} else {
ret = OB_NOT_SUPPORTED;
LOG_WARN("user-defined function is not supported", K(ret), K(*expr));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "The user-defined function");
}
}
}
return ret;
}
int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, const ObTableSchema& table_schema, ObRawExpr*& expr,
const ObSchemaChecker* schema_checker)
const ObSchemaChecker* schema_checker, const ObResolverUtils::PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
const ParseNode* node = NULL;
......@@ -1042,9 +1100,11 @@ int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawE
} else if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is null");
} else if (OB_FAIL(build_generated_column_expr(expr_factory, session_info, *node, expr, columns, schema_checker))) {
} else if (OB_FAIL(build_generated_column_expr(
expr_factory, session_info, *node, expr, columns, schema_checker, check_status))) {
LOG_WARN("build generated column expr failed", K(ret), K(expr_str));
}
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); i++) {
const ObQualifiedName& q_name = columns.at(i);
if (OB_UNLIKELY(!q_name.database_name_.empty())) {
......@@ -1121,7 +1181,8 @@ int ObRawExprUtils::build_check_constraint_expr(ObRawExprFactory& expr_factory,
}
int ObRawExprUtils::build_generated_column_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
const ParseNode& node, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns, const ObSchemaChecker* schema_checker)
const ParseNode& node, ObRawExpr*& expr, ObIArray<ObQualifiedName>& columns, const ObSchemaChecker* schema_checker,
const ObResolverUtils::PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
ObArray<ObVarInfo> sys_vars;
......@@ -1188,6 +1249,10 @@ int ObRawExprUtils::build_generated_column_expr(ObRawExprFactory& expr_factory,
OZ(columns.assign(real_columns), real_columns);
}
}
// check whether the expression is deterministic recursively
if (OB_SUCC(ret) && ObResolverUtils::DISABLE_CHECK != check_status) {
OZ(check_deterministic(expr, expr_factory.get_allocator(), check_status));
}
return ret;
}
......@@ -1259,12 +1324,14 @@ int ObRawExprUtils::build_raw_expr(ObRawExprFactory& expr_factory, const ObSQLSe
int ObRawExprUtils::build_generated_column_expr(const ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, uint64_t table_id, const ObTableSchema& table_schema,
const ObColumnSchemaV2& gen_col_schema, ObRawExpr*& expr, const ObSchemaChecker* schema_checker)
const ObColumnSchemaV2& gen_col_schema, ObRawExpr*& expr, const ObSchemaChecker* schema_checker,
const ObResolverUtils::PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
ObArray<ObQualifiedName> columns;
const ObColumnSchemaV2* col_schema = NULL;
if (OB_FAIL(build_generated_column_expr(expr_str, expr_factory, session_info, expr, columns, schema_checker))) {
if (OB_FAIL(build_generated_column_expr(
expr_str, expr_factory, session_info, expr, columns, schema_checker, check_status))) {
LOG_WARN("build generated column expr failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); ++i) {
......
......@@ -174,19 +174,27 @@ public:
const common::ObString& expr_str, common::ObIAllocator& allocator, const ParseNode*& node);
static int build_check_constraint_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
const ParseNode& node, ObRawExpr*& expr, common::ObIArray<ObQualifiedName>& columns);
static int check_deterministic(const ObRawExpr* expr, common::ObIAllocator& allocator,
const ObResolverUtils::PureFunctionCheckStatus check_status = ObResolverUtils::DISABLE_CHECK);
static int check_deterministic_single(const ObRawExpr* expr,
const ObResolverUtils::PureFunctionCheckStatus check_status = ObResolverUtils::DISABLE_CHECK);
static int build_generated_column_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info,
const ParseNode& node, ObRawExpr*& expr, common::ObIArray<ObQualifiedName>& columns,
const ObSchemaChecker* schema_checker = NULL);
const ObSchemaChecker* schema_checker = NULL,
const ObResolverUtils::PureFunctionCheckStatus check_status = ObResolverUtils::DISABLE_CHECK);
static int build_generated_column_expr(const common::ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, ObRawExpr*& expr, common::ObIArray<ObQualifiedName>& columns,
const ObSchemaChecker* schema_checker = NULL);
const ObSchemaChecker* schema_checker = NULL,
const ObResolverUtils::PureFunctionCheckStatus check_status = ObResolverUtils::DISABLE_CHECK);
static int build_generated_column_expr(const common::ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, const share::schema::ObTableSchema& table_schema, ObRawExpr*& expr,
const ObSchemaChecker* schema_checker = NULL);
const ObSchemaChecker* schema_checker = NULL,
const ObResolverUtils::PureFunctionCheckStatus check_status = ObResolverUtils::DISABLE_CHECK);
static int build_generated_column_expr(const common::ObString& expr_str, ObRawExprFactory& expr_factory,
const ObSQLSessionInfo& session_info, uint64_t table_id, const share::schema::ObTableSchema& table_schema,
const share::schema::ObColumnSchemaV2& gen_col_schema, ObRawExpr*& expr,
const ObSchemaChecker* schema_checker = NULL);
const ObSchemaChecker* schema_checker = NULL,
const ObResolverUtils::PureFunctionCheckStatus check_status = ObResolverUtils::DISABLE_CHECK);
static int build_raw_expr(ObRawExprFactory& expr_factory, const ObSQLSessionInfo& session_info, const ParseNode& node,
ObRawExpr*& expr, common::ObIArray<ObQualifiedName>& columns, common::ObIArray<ObVarInfo>& sys_vars,
common::ObIArray<ObAggFunRawExpr*>& aggr_exprs, common::ObIArray<ObWinFunRawExpr*>& win_exprs,
......
......@@ -3078,7 +3078,8 @@ int ObResolverUtils::resolve_partition_expr(ObResolverParams& params, const Pars
}
int ObResolverUtils::resolve_generated_column_expr(ObResolverParams& params, const ObString& expr_str,
ObTableSchema& tbl_schema, ObColumnSchemaV2& generated_column, ObRawExpr*& expr)
ObTableSchema& tbl_schema, ObColumnSchemaV2& generated_column, ObRawExpr*& expr,
const PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
const ParseNode* expr_node = NULL;
......@@ -3087,14 +3088,16 @@ int ObResolverUtils::resolve_generated_column_expr(ObResolverParams& params, con
LOG_WARN("allocator is null");
} else if (OB_FAIL(ObRawExprUtils::parse_expr_node_from_str(expr_str, *params.allocator_, expr_node))) {
LOG_WARN("parse expr node from str failed", K(ret), K(expr_str));
} else if (OB_FAIL(resolve_generated_column_expr(params, expr_node, tbl_schema, generated_column, expr))) {
} else if (OB_FAIL(
resolve_generated_column_expr(params, expr_node, tbl_schema, generated_column, expr, check_status))) {
LOG_WARN("resolve generated column expr failed", K(ret), K(expr_str));
}
return ret;
}
int ObResolverUtils::resolve_generated_column_expr(ObResolverParams& params, const ParseNode* node,
ObTableSchema& tbl_schema, ObColumnSchemaV2& generated_column, ObRawExpr*& expr)
ObTableSchema& tbl_schema, ObColumnSchemaV2& generated_column, ObRawExpr*& expr,
const PureFunctionCheckStatus check_status)
{
int ret = OB_SUCCESS;
ObColumnSchemaV2* col_schema = NULL;
......@@ -3105,7 +3108,8 @@ int ObResolverUtils::resolve_generated_column_expr(ObResolverParams& params, con
if (OB_ISNULL(expr_factory) || OB_ISNULL(session_info) || OB_ISNULL(node)) {
ret = OB_NOT_INIT;
LOG_WARN("resolve status is invalid", K_(params.expr_factory), K(session_info), K(node));
} else if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(*expr_factory, *session_info, *node, expr, columns))) {
} else if (OB_FAIL(ObRawExprUtils::build_generated_column_expr(
*expr_factory, *session_info, *node, expr, columns, params.schema_checker_, check_status))) {
LOG_WARN("build generated column expr failed", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < columns.count(); ++i) {
......@@ -3134,6 +3138,10 @@ int ObResolverUtils::resolve_generated_column_expr(ObResolverParams& params, con
ret = OB_NOT_SUPPORTED;
LOG_WARN("Define a blob column in generated column def is not supported", K(ret));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "blob column in generated column definition");
} else if (share::is_mysql_mode() && col_schema->is_autoincrement()) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("generated column cannot refer to auto-increment column", K(ret), K(*expr));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "generated column refer to auto-increment column");
} else if (OB_FAIL(ObRawExprUtils::init_column_expr(*col_schema, *q_name.ref_expr_))) {
LOG_WARN("init column expr failed", K(ret));
} else if (OB_FAIL(generated_column.add_cascaded_column_id(col_schema->get_column_id()))) {
......@@ -3203,6 +3211,104 @@ int ObResolverUtils::resolve_generated_column_expr(ObResolverParams& params, con
return ret;
}
// This function is used to resolve the dependent columns of generated column when retrieve schema.
// We use this function instead of build_generated_column_expr because there is not a thread-safe
// mem_context and the expr is not necessary.
int ObResolverUtils::resolve_generated_column_info(
const ObString& expr_str, ObIAllocator& allocator, ObItemType& root_expr_type, ObIArray<ObString>& column_names)
{
int ret = OB_SUCCESS;
const ParseNode* node = NULL;
if (OB_FAIL(ObRawExprUtils::parse_expr_node_from_str(expr_str, allocator, node))) {
LOG_WARN("parse expr node from string failed", K(ret), K(expr_str));
} else if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is null", K(ret));
} else if (OB_FAIL(SMART_CALL(resolve_column_info_recursively(node, column_names)))) {
LOG_WARN("failed to resolve column into");
} else {
ObItemType type = node->type_;
if (T_FUN_SYS == type) {
if (OB_UNLIKELY(1 > node->num_child_) || OB_ISNULL(node->children_) || OB_ISNULL(node->children_[0])) {
ret = OB_ERR_PARSER_SYNTAX;
LOG_WARN("invalid node children for fun_sys node", K(ret));
} else {
ObString func_name(node->children_[0]->str_len_, node->children_[0]->str_value_);
if (0 == func_name.case_compare("bin")) {
type = ObExprOperatorFactory::get_type_by_name("conv");
} else if (0 == func_name.case_compare("oct")) {
type = ObExprOperatorFactory::get_type_by_name("conv");
} else if (0 == func_name.case_compare("lcase")) {
type = ObExprOperatorFactory::get_type_by_name("lower");
} else if (0 == func_name.case_compare("ucase")) {
type = ObExprOperatorFactory::get_type_by_name("upper");
// don't alias "power" to "pow" in oracle mode
} else if (!lib::is_oracle_mode() && 0 == func_name.case_compare("power")) {
type = ObExprOperatorFactory::get_type_by_name("pow");
} else if (0 == func_name.case_compare("ws")) {
type = ObExprOperatorFactory::get_type_by_name("word_segment");
} else {
type = ObExprOperatorFactory::get_type_by_name(func_name);
}
if (OB_UNLIKELY(T_INVALID == (type))) {
ret = OB_ERR_FUNCTION_UNKNOWN;
LOG_WARN("function not exist", K(func_name), K(ret));
}
}
}
OX(root_expr_type = type);
}
return ret;
}
int ObResolverUtils::resolve_column_info_recursively(const ParseNode* node, ObIArray<ObString>& column_names)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is null");
} else if (T_COLUMN_REF == node->type_) {
if (OB_UNLIKELY(node->num_child_ != 3)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid node type", K_(node->type), K(node->num_child_), K(ret));
} else if (OB_UNLIKELY(node->children_[0] != NULL || node->children_[1] != NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("database node or table node is not null", K_(node->type), K(ret));
} else if (OB_ISNULL(node->children_[2])) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("column node is null", K_(node->type), K(ret));
} else if (OB_UNLIKELY(T_STAR == node->children_[2]->type_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("column node can't be T_STAR", K_(node->type), K(ret));
} else {
ObString column_name(static_cast<int32_t>(node->children_[2]->str_len_), node->children_[2]->str_value_);
if (OB_FAIL(column_names.push_back(column_name))) {
LOG_WARN("Add column failed", K(ret));
}
}
} else if (T_OBJ_ACCESS_REF == node->type_) {
if (OB_UNLIKELY(node->num_child_ != 2)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid node type", K_(node->type), K(node->num_child_), K(ret));
} else if (OB_ISNULL(node->children_[0])) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("node is NULL", K(node->num_child_));
} else if (T_IDENT == node->children_[0]->type_) {
ObString column_name(static_cast<int32_t>(node->children_[0]->str_len_), node->children_[0]->str_value_);
OZ(column_names.push_back(column_name));
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; ++i) {
const ParseNode* child_node = node->children_[i];
if (NULL == child_node) {
// do nothing
} else if (OB_FAIL(SMART_CALL(resolve_column_info_recursively(child_node, column_names)))) {
LOG_WARN("recursive resolve column node failed", K(ret));
}
}
return ret;
}
int ObResolverUtils::resolve_default_expr_v2_column_expr(
ObResolverParams& params, const ObString& expr_str, ObColumnSchemaV2& default_expr_v2_column, ObRawExpr*& expr)
{
......
......@@ -32,6 +32,7 @@
namespace oceanbase {
namespace sql {
class ObRawExprUtils;
class ObRoutineMatchInfo {
public:
struct MatchInfo {
......@@ -87,6 +88,11 @@ public:
};
struct ObResolverUtils {
enum RangeElementsNode { PARTITION_NAME_NODE = 0, PARTITION_ELEMENT_NODE = 1 };
enum PureFunctionCheckStatus {
DISABLE_CHECK = 0,
CHECK_FOR_GENERATED_COLUMN,
CHECK_FOR_FUNCTION_INDEX,
};
static const int NAMENODE = 1;
static ObItemType item_type_;
......@@ -184,9 +190,14 @@ public:
const share::schema::ObTableSchema& tbl_schema, share::schema::ObPartitionFuncType part_func_type,
ObRawExpr*& part_expr, common::ObIArray<common::ObString>* part_keys);
static int resolve_generated_column_expr(ObResolverParams& params, const common::ObString& expr_str,
share::schema::ObTableSchema& tbl_schema, share::schema::ObColumnSchemaV2& generated_column, ObRawExpr*& expr);
share::schema::ObTableSchema& tbl_schema, share::schema::ObColumnSchemaV2& generated_column, ObRawExpr*& expr,
const PureFunctionCheckStatus check_status = DISABLE_CHECK);
static int resolve_generated_column_expr(ObResolverParams& params, const ParseNode* node,
share::schema::ObTableSchema& tbl_schema, share::schema::ObColumnSchemaV2& generated_column, ObRawExpr*& expr);
share::schema::ObTableSchema& tbl_schema, share::schema::ObColumnSchemaV2& generated_column, ObRawExpr*& expr,
const PureFunctionCheckStatus check_status = DISABLE_CHECK);
static int resolve_generated_column_info(const common::ObString& expr_str, ObIAllocator& allocator,
ObItemType& root_expr_type, common::ObIArray<common::ObString>& column_names);
static int resolve_column_info_recursively(const ParseNode* node, common::ObIArray<common::ObString>& column_names);
static int resolve_default_expr_v2_column_expr(ObResolverParams& params, const common::ObString& expr_str,
share::schema::ObColumnSchemaV2& default_expr_v2_column, ObRawExpr*& expr);
static int resolve_default_expr_v2_column_expr(ObResolverParams& params, const ParseNode* node,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册