diff --git a/src/sql/engine/dml/ob_dml_service.cpp b/src/sql/engine/dml/ob_dml_service.cpp index 51b5725d7d..9e27471b71 100644 --- a/src/sql/engine/dml/ob_dml_service.cpp +++ b/src/sql/engine/dml/ob_dml_service.cpp @@ -38,6 +38,28 @@ using namespace share; using namespace transaction; namespace sql { + +bool ObDMLService::check_cascaded_reference(const ObExpr *expr, const ObExprPtrIArray &row) +{ + bool bret = false; + if (OB_ISNULL(expr) || expr->parent_cnt_ <= 0) { + bret = false; + } else { + for (int i = 0; !bret && i < expr->parent_cnt_; ++i) { + ObExpr *parent_expr = expr->parents_[i]; + if (parent_expr != nullptr) { + if (parent_expr->type_ == T_FUN_COLUMN_CONV) { + bret = has_exist_in_array(row, parent_expr); + } + } + if (!bret) { + bret = check_cascaded_reference(parent_expr, row); + } + } + } + return bret; +} + int ObDMLService::check_row_null(const ObExprPtrIArray &row, ObEvalCtx &eval_ctx, int64_t row_num, @@ -74,6 +96,12 @@ int ObDMLService::check_row_null(const ObExprPtrIArray &row, ret = OB_BAD_NULL_ERROR; LOG_WARN("dml with ignore not supported in geometry type"); LOG_USER_ERROR(OB_BAD_NULL_ERROR, column_infos.at(i).column_name_.length(), column_infos.at(i).column_name_.ptr()); + } else if (check_cascaded_reference(row.at(col_idx), row)) { + //This column is dependent on other columns and cannot be modified again; + //otherwise, it will necessitate a cascading recalculation of the dependent expression results. + ret = OB_BAD_NULL_ERROR; + LOG_WARN("dml with ignore not supported with cascaded column", KPC(row.at(col_idx))); + LOG_USER_ERROR(OB_BAD_NULL_ERROR, column_infos.at(i).column_name_.length(), column_infos.at(i).column_name_.ptr()); } else if (OB_FAIL(ObObjCaster::get_zero_value( row.at(col_idx)->obj_meta_.get_type(), row.at(col_idx)->obj_meta_.get_collation_type(), diff --git a/src/sql/engine/dml/ob_dml_service.h b/src/sql/engine/dml/ob_dml_service.h index 6349057d81..5ac304f4fe 100644 --- a/src/sql/engine/dml/ob_dml_service.h +++ b/src/sql/engine/dml/ob_dml_service.h @@ -24,6 +24,8 @@ class ObErrLogService; class ObDMLService { public: + static bool check_cascaded_reference(const ObExpr *expr, const ObExprPtrIArray &row); + static int check_row_null(const ObExprPtrIArray &row, ObEvalCtx &eval_ctx, int64_t row_num, diff --git a/tools/deploy/mysql_test/test_suite/insert/r/mysql/insert_ignore.result b/tools/deploy/mysql_test/test_suite/insert/r/mysql/insert_ignore.result index fc5d60a932..22b382ff89 100644 --- a/tools/deploy/mysql_test/test_suite/insert/r/mysql/insert_ignore.result +++ b/tools/deploy/mysql_test/test_suite/insert/r/mysql/insert_ignore.result @@ -1,4 +1,4 @@ -drop table if exists t1,t2, test, t_ignore; +drop table if exists t1,t2, test, t_ignore, t3; CREATE TABLE t1(a BIGINT primary key); insert into t1 values(100); insert into t1 values(100); @@ -324,3 +324,9 @@ SELECT * FROM t_ignore; c1 c2 1 DROP TABLE t_ignore; +create TABLE t3 ( str varchar(255) character set utf8mb4 not null, key str (str(2)) ); +INSERT ignore INTO t3 VALUES (NULL); +ERROR 23000: Column 'str' cannot be null +select /*+ opt_param('hidden_column_visible', 'true') index('str')*/__pk_increment, __substr2_16 from t3; +__pk_increment __substr2_16 +drop table t3; diff --git a/tools/deploy/mysql_test/test_suite/insert/t/insert_ignore.test b/tools/deploy/mysql_test/test_suite/insert/t/insert_ignore.test index 5bed92f756..9df9579212 100644 --- a/tools/deploy/mysql_test/test_suite/insert/t/insert_ignore.test +++ b/tools/deploy/mysql_test/test_suite/insert/t/insert_ignore.test @@ -8,7 +8,7 @@ set @@session.explicit_defaults_for_timestamp=off; ##增加新的语法,支持ignore --disable_warnings -drop table if exists t1,t2, test, t_ignore; +drop table if exists t1,t2, test, t_ignore, t3; --enable_warnings CREATE TABLE t1(a BIGINT primary key); @@ -185,3 +185,9 @@ CREATE TABLE t_ignore (`c1` bigint(20) NOT NULL AUTO_INCREMENT, `c2` varchar(50) INSERT IGNORE INTO t_ignore (c1) value (1); SELECT * FROM t_ignore; DROP TABLE t_ignore; + +create TABLE t3 ( str varchar(255) character set utf8mb4 not null, key str (str(2)) ); +--error 1048 +INSERT ignore INTO t3 VALUES (NULL); +select /*+ opt_param('hidden_column_visible', 'true') index('str')*/__pk_increment, __substr2_16 from t3; +drop table t3; diff --git a/tools/deploy/mysql_test/test_suite/update/r/mysql/update_ignore.result b/tools/deploy/mysql_test/test_suite/update/r/mysql/update_ignore.result index b58b3b1224..e9939ea253 100644 Binary files a/tools/deploy/mysql_test/test_suite/update/r/mysql/update_ignore.result and b/tools/deploy/mysql_test/test_suite/update/r/mysql/update_ignore.result differ diff --git a/tools/deploy/mysql_test/test_suite/update/t/update_ignore.test b/tools/deploy/mysql_test/test_suite/update/t/update_ignore.test index 167b786d20..e168079550 100644 --- a/tools/deploy/mysql_test/test_suite/update/t/update_ignore.test +++ b/tools/deploy/mysql_test/test_suite/update/t/update_ignore.test @@ -244,6 +244,7 @@ INSERT /*+ ENABLE_PARALLEL_DML PARALLEL(3) */ INTO table0_innodb_key_pk_parts_2 INSERT /*+ ENABLE_PARALLEL_DML PARALLEL(3) */ INTO table0_innodb_key_pk_parts_2 ( col_enum , col_enum_not_null , col_decimal ) VALUES ( '2006-04-09 05:33:14.045216' , '2008' , '2004-09-17 09:11:54.004359' ); INSERT /*+ ENABLE_PARALLEL_DML PARALLEL(3) */ INTO table0_innodb_key_pk_parts_2 ( col_blob_key , col_int_unsigned_not_null , col_int_not_null_key ) VALUES ( '20:35:45' , 47682 , 1319 ); +--error 1048 UPDATE /*+ ENABLE_PARALLEL_DML PARALLEL(3) */ table0_innodb_key_pk_parts_2 SET col_blob_not_null_key = NULL WHERE col_bit_not_null <> '08:59:21'; select * from table0_innodb_key_pk_parts_2; drop table table0_innodb_key_pk_parts_2;