diff --git a/dbcon/mysql/ha_mcs_execplan.cpp b/dbcon/mysql/ha_mcs_execplan.cpp index e4746ebf8..142bcd786 100755 --- a/dbcon/mysql/ha_mcs_execplan.cpp +++ b/dbcon/mysql/ha_mcs_execplan.cpp @@ -6326,6 +6326,48 @@ bool isMCSTable(TABLE* table_ptr) return false; } +bool isForeignTableUpdate(THD* thd) +{ + LEX* lex = thd->lex; + + if (lex->sql_command != SQLCOM_UPDATE_MULTI) + return false; + + Item_field* item; + List_iterator_fast field_it(lex->first_select_lex()->item_list); + + while ((item = (Item_field*) field_it++)) + { + if (item->field && item->field->table && !isMCSTable(item->field->table)) + return true; + } + + return false; +} + +// This function is different from isForeignTableUpdate() +// above as it only checks if any of the tables involved +// in the multi-table update statement is a foreign table, +// irrespective of whether the update is performed on the +// foreign table or not, as in isForeignTableUpdate(). +bool isUpdateHasForeignTable(THD* thd) +{ + LEX* lex = thd->lex; + + if (lex->sql_command != SQLCOM_UPDATE_MULTI) + return false; + + TABLE_LIST* table_ptr = lex->first_select_lex()->get_table_list(); + + for (; table_ptr; table_ptr = table_ptr->next_local) + { + if (table_ptr->table && !isMCSTable(table_ptr->table)) + return true; + } + + return false; +} + /*@brief set some runtime params to run the query */ /*********************************************************** * DESCRIPTION: @@ -6577,10 +6619,7 @@ int processWhere(SELECT_LEX &select_lex, else if (select_lex.where) icp = select_lex.where; } - else if (!join && ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || - ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || - ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || - ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI ))) + else if (!join && isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { isUpdateDelete = true; } @@ -7393,7 +7432,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, } //@Bug 3030 Add error check for dml statement - if ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI ) ) + if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { if ( after_size - before_size != 0 ) { @@ -7427,7 +7466,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, case REAL_RESULT: case TIME_RESULT: { - if ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI )) + if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { } else { @@ -7459,7 +7498,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, case Item::NULL_ITEM: { - if ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI ) ) + if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { } else { @@ -9259,7 +9298,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro } //@Bug 3030 Add error check for dml statement - if ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI ) ) + if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { if ( after_size - before_size != 0 ) { @@ -9290,7 +9329,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro case REAL_RESULT: case TIME_RESULT: { - if ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI )) + if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { } else { @@ -9322,7 +9361,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro case Item::NULL_ITEM: { - if ( ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE ) || ((gwi.thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) || ((gwi.thd->lex)->sql_command == SQLCOM_DELETE_MULTI ) ) + if (isUpdateOrDeleteStatement(gwi.thd->lex->sql_command)) { } else { diff --git a/dbcon/mysql/ha_mcs_impl.cpp b/dbcon/mysql/ha_mcs_impl.cpp index f69982955..482f95140 100644 --- a/dbcon/mysql/ha_mcs_impl.cpp +++ b/dbcon/mysql/ha_mcs_impl.cpp @@ -854,7 +854,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c { Message::Args args; - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + if (isUpdateStatement(thd->lex->sql_command)) args.add("Update"); #if 0 else if (thd->rgi_slave && thd->rgi_slave->m_table_map.count() != 0) @@ -909,7 +909,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c updateCP->isDML(true); //@Bug 2753. the memory already freed by destructor of UpdateSqlStatement - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + if (isUpdateStatement(thd->lex->sql_command)) { ColumnAssignment* columnAssignmentPtr; Item_field* item; @@ -1202,8 +1202,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c // Exit early if there is nothing to update if (colAssignmentListPtr->empty() && - (((thd->lex)->sql_command == SQLCOM_UPDATE) || - ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI))) + isUpdateStatement(thd->lex->sql_command)) { ci->affectedRows = 0; return 0; @@ -1216,7 +1215,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c CalpontSystemCatalog::TableName aTableName; TABLE_LIST* first_table = 0; - if (( (thd->lex)->sql_command == SQLCOM_UPDATE ) || ( (thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) ) + if (isUpdateStatement(thd->lex->sql_command)) { aTableName.schema = schemaName; aTableName.table = tableName; @@ -1238,10 +1237,10 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c IDEBUG( cout << "STMT: " << dmlStmt << " and sessionID " << thd->thread_id << endl ); VendorDMLStatement dmlStatement(dmlStmt, sessionID); - if (( (thd->lex)->sql_command == SQLCOM_UPDATE ) || ( (thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) ) - dmlStatement.set_DMLStatementType( DML_UPDATE ); + if (isUpdateStatement(thd->lex->sql_command)) + dmlStatement.set_DMLStatementType(DML_UPDATE); else - dmlStatement.set_DMLStatementType( DML_DELETE ); + dmlStatement.set_DMLStatementType(DML_DELETE); TableName* qualifiedTablName = new TableName(); @@ -1249,7 +1248,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c //@Bug 2753. To make sure the momory is freed. updateStmt.fColAssignmentListPtr = colAssignmentListPtr; - if (( (thd->lex)->sql_command == SQLCOM_UPDATE ) || ( (thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) ) + if (isUpdateStatement(thd->lex->sql_command)) { qualifiedTablName->fName = tableName; qualifiedTablName->fSchema = schemaName; @@ -1343,7 +1342,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c List items; SELECT_LEX select_lex; - if (( (thd->lex)->sql_command == SQLCOM_UPDATE ) || ( (thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) ) + if (isUpdateStatement(thd->lex->sql_command)) { items = (thd->lex->first_select_lex()->item_list); thd->lex->first_select_lex()->item_list = thd->lex->value_list; @@ -1492,7 +1491,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c returnedCols.push_back((updateCP->columnMap()).begin()->second); //@Bug 6123. get the correct returned columnlist - if (( (thd->lex)->sql_command == SQLCOM_DELETE ) || ( (thd->lex)->sql_command == SQLCOM_DELETE_MULTI ) ) + if (isDeleteStatement(thd->lex->sql_command)) { returnedCols.clear(); //choose the smallest column to project @@ -1543,7 +1542,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c updateCP->returnedCols( returnedCols ); - if (( (thd->lex)->sql_command == SQLCOM_UPDATE ) || ( (thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) ) + if (isUpdateStatement(thd->lex->sql_command)) { const ParseTree* ptsub = updateCP->filters(); @@ -1561,8 +1560,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector& c ptsub->walk(makeUpdateSemiJoin, &tbList[0] ); } - if (( (thd->lex)->sql_command == SQLCOM_UPDATE ) || ( (thd->lex)->sql_command == SQLCOM_UPDATE_MULTI ) ) - thd->lex->first_select_lex()->item_list = items; + thd->lex->first_select_lex()->item_list = items; } } @@ -2039,10 +2037,7 @@ int ha_mcs::impl_rnd_init(TABLE* table, const std::vector& condStack) UPDATE innotab1 SET a=100 WHERE a NOT IN (SELECT a FROM cstab1 WHERE a=1); */ if (!isReadOnly() && // make sure the current table is being modified - (thd->lex->sql_command == SQLCOM_UPDATE || - thd->lex->sql_command == SQLCOM_DELETE || - thd->lex->sql_command == SQLCOM_DELETE_MULTI || - thd->lex->sql_command == SQLCOM_UPDATE_MULTI)) + isUpdateOrDeleteStatement(thd->lex->sql_command)) return doUpdateDelete(thd, gwi, condStack); uint32_t sessionID = tid2sid(thd->thread_id); @@ -2372,8 +2367,10 @@ int ha_mcs_impl_rnd_next(uchar* buf, TABLE* table) thd->lex->sql_command == SQLCOM_LOAD)) return HA_ERR_END_OF_FILE; - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || ((thd->lex)->sql_command == SQLCOM_DELETE) || - ((thd->lex)->sql_command == SQLCOM_DELETE_MULTI) || ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + if ((thd->lex->sql_command == SQLCOM_UPDATE) || + (thd->lex->sql_command == SQLCOM_DELETE) || + (thd->lex->sql_command == SQLCOM_DELETE_MULTI) || + ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI) && !isForeignTableUpdate(thd))) return HA_ERR_END_OF_FILE; // @bug 2547 @@ -2461,22 +2458,15 @@ int ha_mcs_impl_rnd_end(TABLE* table, bool is_pushdown_hand) thd->lex->sql_command == SQLCOM_LOAD)) return 0; - - // MCOL-2178 isUnion member only assigned, never used - // if (is_pushdown_hand) - // { - // MIGR::infinidb_vtable.isUnion = false; - // } - if (get_fe_conn_info_ptr() != NULL) ci = reinterpret_cast(get_fe_conn_info_ptr()); if ( (thd->lex)->sql_command == SQLCOM_ALTER_TABLE ) return rc; - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || - ((thd->lex)->sql_command == SQLCOM_DELETE) || - ((thd->lex)->sql_command == SQLCOM_DELETE_MULTI) || - ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + if ((thd->lex->sql_command == SQLCOM_UPDATE) || + (thd->lex->sql_command == SQLCOM_DELETE) || + (thd->lex->sql_command == SQLCOM_DELETE_MULTI) || + ((thd->lex->sql_command == SQLCOM_UPDATE_MULTI) && !isForeignTableUpdate(thd))) return rc; if (!ci) @@ -3668,10 +3658,7 @@ COND* ha_mcs_impl_cond_push(COND* cond, TABLE* table, std::vector& condSt { THD* thd = current_thd; - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || - ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI) || - ((thd->lex)->sql_command == SQLCOM_DELETE) || - ((thd->lex)->sql_command == SQLCOM_DELETE_MULTI)) + if (isUpdateOrDeleteStatement(thd->lex->sql_command)) { condStack.push_back(cond); return nullptr; @@ -3921,7 +3908,6 @@ int ha_mcs_impl_group_by_init(mcs_handler_info *handler_info, TABLE* table) idbassert(ci != 0); - if (thd->killed == KILL_QUERY || thd->killed == KILL_QUERY_HARD) { force_close_fep_conn(thd, ci); @@ -4326,15 +4312,12 @@ int ha_mcs_impl_group_by_next(TABLE* table) { THD* thd = current_thd; - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || ((thd->lex)->sql_command == SQLCOM_DELETE) || - ((thd->lex)->sql_command == SQLCOM_DELETE_MULTI) || ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + if ((thd->lex->sql_command == SQLCOM_UPDATE) || + (thd->lex->sql_command == SQLCOM_DELETE) || + (thd->lex->sql_command == SQLCOM_DELETE_MULTI) || + (thd->lex->sql_command == SQLCOM_UPDATE_MULTI && !isForeignTableUpdate(thd))) return HA_ERR_END_OF_FILE; - // @bug 2547 - // MCOL-2178 - // if (MIGR::infinidb_vtable.impossibleWhereOnUnion) - // return HA_ERR_END_OF_FILE; - if (get_fe_conn_info_ptr() == nullptr) set_fe_conn_info_ptr((void*)new cal_connection_info()); @@ -4426,9 +4409,6 @@ int ha_mcs_impl_group_by_end(TABLE* table) thd->lex->sql_command == SQLCOM_LOAD)) return 0; - // MCOL-2178 isUnion member only assigned, never used - // MIGR::infinidb_vtable.isUnion = false; - if (get_fe_conn_info_ptr() != NULL) ci = reinterpret_cast(get_fe_conn_info_ptr()); @@ -4638,8 +4618,8 @@ int ha_mcs_impl_pushdown_init(mcs_handler_info* handler_info, TABLE* table) return 0; // MCOL-4023 We need to test this code path. - //Update and delete code - if ( ((thd->lex)->sql_command == SQLCOM_UPDATE) || ((thd->lex)->sql_command == SQLCOM_DELETE) || ((thd->lex)->sql_command == SQLCOM_DELETE_MULTI) || ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + // Update and delete code + if (isUpdateOrDeleteStatement(thd->lex->sql_command)) return doUpdateDelete(thd, gwi, std::vector()); uint32_t sessionID = tid2sid(thd->thread_id); @@ -5059,8 +5039,7 @@ int ha_mcs_impl_select_next(uchar* buf, TABLE* table) thd->lex->sql_command == SQLCOM_LOAD)) return HA_ERR_END_OF_FILE; - if (((thd->lex)->sql_command == SQLCOM_UPDATE) || ((thd->lex)->sql_command == SQLCOM_DELETE) || - ((thd->lex)->sql_command == SQLCOM_DELETE_MULTI) || ((thd->lex)->sql_command == SQLCOM_UPDATE_MULTI)) + if (isUpdateOrDeleteStatement(thd->lex->sql_command)) return rc; // @bug 2547 diff --git a/dbcon/mysql/ha_mcs_impl_if.h b/dbcon/mysql/ha_mcs_impl_if.h index a82324208..b0f3106f7 100644 --- a/dbcon/mysql/ha_mcs_impl_if.h +++ b/dbcon/mysql/ha_mcs_impl_if.h @@ -366,6 +366,8 @@ void gp_walk(const Item* item, void* arg); void parse_item (Item* item, std::vector& field_vec, bool& hasNonSupportItem, uint16& parseInfo, gp_walk_info* gwip = NULL); const std::string bestTableName(const Item_field* ifp); bool isMCSTable(TABLE* table_ptr); +bool isForeignTableUpdate(THD* thd); +bool isUpdateHasForeignTable(THD* thd); // execution plan util functions prototypes execplan::ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, bool isRefItem = false); @@ -409,6 +411,24 @@ bool buildEqualityPredicate(execplan::ReturnedColumn* lhs, const std::vector& itemList, bool isInSubs = false); +inline bool isUpdateStatement(const enum_sql_command& command) +{ + return (command == SQLCOM_UPDATE) || + (command == SQLCOM_UPDATE_MULTI); +} + +inline bool isDeleteStatement(const enum_sql_command& command) +{ + return (command == SQLCOM_DELETE) || + (command == SQLCOM_DELETE_MULTI); +} + +inline bool isUpdateOrDeleteStatement(const enum_sql_command& command) +{ + return isUpdateStatement(command) || + isDeleteStatement(command); +} + #ifdef DEBUG_WALK_COND void debug_walk(const Item* item, void* arg); #endif diff --git a/dbcon/mysql/ha_mcs_pushdown.cpp b/dbcon/mysql/ha_mcs_pushdown.cpp index e18d44d2d..67a0cde13 100644 --- a/dbcon/mysql/ha_mcs_pushdown.cpp +++ b/dbcon/mysql/ha_mcs_pushdown.cpp @@ -498,6 +498,13 @@ create_columnstore_derived_handler(THD* thd, TABLE_LIST *table_ptr) if (thd->stmt_arena && thd->stmt_arena->is_stmt_execute()) return handler; + // MCOL-1482 Disable derived_handler if the multi-table update + // statement contains a non-columnstore table. + if (cal_impl_if::isUpdateHasForeignTable(thd)) + { + return handler; + } + SELECT_LEX_UNIT *unit = table_ptr->derived; SELECT_LEX *sl = unit->first_select(); @@ -754,6 +761,14 @@ create_columnstore_select_handler(THD* thd, SELECT_LEX* select_lex) return nullptr; } + // MCOL-1482 Disable select_handler for a multi-table update + // with a non-columnstore table as the target table of the update + // operation. + if (cal_impl_if::isForeignTableUpdate(thd)) + { + return nullptr; + } + // Flag to indicate if this is a prepared statement bool isPS = thd->stmt_arena && thd->stmt_arena->is_stmt_execute(); diff --git a/mysql-test/columnstore/basic/r/mcs45_write_crossengine_join.result b/mysql-test/columnstore/basic/r/mcs45_write_crossengine_join.result index 712a21d8e..9be241ecc 100644 --- a/mysql-test/columnstore/basic/r/mcs45_write_crossengine_join.result +++ b/mysql-test/columnstore/basic/r/mcs45_write_crossengine_join.result @@ -6,6 +6,7 @@ GRANT ALL PRIVILEGES ON *.* TO 'cejuser'@'localhost'; FLUSH PRIVILEGES; CREATE TABLE t1 (t1_int INT, t1_char CHAR(5))ENGINE=Innodb; CREATE TABLE t2 (t2_int INT, t2_char CHAR(5))ENGINE=Columnstore; +CREATE VIEW v1 AS SELECT * FROM t1; INSERT INTO t1 VALUES (NULL,''),(1,'aaa'),(2,'bbb'),(3,'ccc'),(4,'ddd'),(5,'eee'),(6,'ffff'),(7,'ggggg'); INSERT INTO t2 VALUES (NULL,''),(1,'hhhh'),(3,'iii'),(5,'jjj'),(7,'kkkk'),(9,'lll'),(11,'m'),(13,'nnn'); SELECT * FROM t1, t2 WHERE t1.t1_int = t2.t2_int AND t1.t1_int = 3; @@ -23,17 +24,38 @@ t1_int t1_char t2_int t2_char 5 eee 5 sssss 7 ggggg 7 sssss UPDATE t1 JOIN t2 on t1.t1_int=t2.t2_int SET t1.t1_char='s'; -ERROR HY000: Internal error: IDB-2006: 'mcs45_db.t1' does not exist in Columnstore. SELECT * FROM t1; t1_int t1_char NULL -1 aaa +1 s 2 bbb -3 ccc +3 s 4 ddd -5 eee +5 s 6 ffff -7 ggggg +7 s +UPDATE v1 JOIN t2 on v1.t1_int=t2.t2_int SET v1.t1_char='t'; +SELECT * FROM t1; +t1_int t1_char +NULL +1 t +2 bbb +3 t +4 ddd +5 t +6 ffff +7 t +UPDATE t1 JOIN (SELECT * FROM t2 WHERE t2_int < 5) d_t2 on t1.t1_int=d_t2.t2_int SET t1.t1_char='u'; +SELECT * FROM t1; +t1_int t1_char +NULL +1 u +2 bbb +3 u +4 ddd +5 t +6 ffff +7 t SELECT * FROM t2; t2_int t2_char NULL NULL @@ -48,13 +70,13 @@ DELETE t2 FROM t2 JOIN t1 ON t1.t1_int = t2.t2_int AND t1.t1_int = 7; SELECT * FROM t1; t1_int t1_char NULL -1 aaa +1 u 2 bbb -3 ccc +3 u 4 ddd -5 eee +5 t 6 ffff -7 ggggg +7 t SELECT * FROM t2; t2_int t2_char NULL NULL @@ -66,5 +88,21 @@ NULL NULL 13 nnn DELETE t1 FROM t1 JOIN t2 ON t1.t1_int = t2.t2_int AND t1.t1_int = 5; ERROR HY000: Internal error: IDB-2006: 'mcs45_db.t1' does not exist in Columnstore. +CREATE TABLE mcs(a INT, b INT)ENGINE=Columnstore; +CREATE TABLE idb(a INT, b INT)ENGINE=Innodb; +INSERT INTO mcs(a,b) VALUES (1,2),(2,3),(4,5); +INSERT INTO idb(a,b) VALUES (1,2),(2,3),(4,5); +UPDATE idb dest JOIN mcs src ON dest.a=src.a SET dest.b = dest.b + src.b + 100; +SELECT * FROM idb; +a b +1 104 +2 106 +4 110 +UPDATE idb dest JOIN mcs src ON dest.a=src.a SET dest.b = dest.b + src.b + 100; +SELECT * FROM idb; +a b +1 206 +2 209 +4 215 DROP USER 'cejuser'@'localhost'; DROP DATABASE mcs45_db; diff --git a/mysql-test/columnstore/basic/t/mcs45_write_crossengine_join.test b/mysql-test/columnstore/basic/t/mcs45_write_crossengine_join.test index b97abccf9..2ebaadbc9 100644 --- a/mysql-test/columnstore/basic/t/mcs45_write_crossengine_join.test +++ b/mysql-test/columnstore/basic/t/mcs45_write_crossengine_join.test @@ -38,6 +38,7 @@ FLUSH PRIVILEGES; # Create tables with Innodb and Columnstore engines CREATE TABLE t1 (t1_int INT, t1_char CHAR(5))ENGINE=Innodb; CREATE TABLE t2 (t2_int INT, t2_char CHAR(5))ENGINE=Columnstore; +CREATE VIEW v1 AS SELECT * FROM t1; INSERT INTO t1 VALUES (NULL,''),(1,'aaa'),(2,'bbb'),(3,'ccc'),(4,'ddd'),(5,'eee'),(6,'ffff'),(7,'ggggg'); INSERT INTO t2 VALUES (NULL,''),(1,'hhhh'),(3,'iii'),(5,'jjj'),(7,'kkkk'),(9,'lll'),(11,'m'),(13,'nnn'); @@ -46,19 +47,36 @@ UPDATE t2, t1 SET t2.t2_char = 'zzz' WHERE t1.t1_int = t2.t2_int AND t1.t1_int = SELECT * FROM t1, t2 WHERE t1.t1_int = t2.t2_int AND t1.t1_int = 3; UPDATE t1 JOIN t2 on t1.t1_int=t2.t2_int SET t2.t2_char='sssss'; SELECT * FROM t1, t2 WHERE t1.t1_int = t2.t2_int; + # MCOL-1482 ---error ER_INTERNAL_ERROR UPDATE t1 JOIN t2 on t1.t1_int=t2.t2_int SET t1.t1_char='s'; +SELECT * FROM t1; +# Update foreign view +UPDATE v1 JOIN t2 on v1.t1_int=t2.t2_int SET v1.t1_char='t'; +SELECT * FROM t1; +# Update foreign table with a subquery as the source +UPDATE t1 JOIN (SELECT * FROM t2 WHERE t2_int < 5) d_t2 on t1.t1_int=d_t2.t2_int SET t1.t1_char='u'; SELECT * FROM t1; SELECT * FROM t2; DELETE t2 FROM t2 JOIN t1 ON t1.t1_int = t2.t2_int AND t1.t1_int = 7; SELECT * FROM t1; SELECT * FROM t2; -# Similar error as MCOL-1482 +# Similar error as MCOL-1482, but for a foreign engine DELETE. --error ER_INTERNAL_ERROR DELETE t1 FROM t1 JOIN t2 ON t1.t1_int = t2.t2_int AND t1.t1_int = 5; +# Test case from MCOL-1482 issue description +CREATE TABLE mcs(a INT, b INT)ENGINE=Columnstore; +CREATE TABLE idb(a INT, b INT)ENGINE=Innodb; + +INSERT INTO mcs(a,b) VALUES (1,2),(2,3),(4,5); +INSERT INTO idb(a,b) VALUES (1,2),(2,3),(4,5); +UPDATE idb dest JOIN mcs src ON dest.a=src.a SET dest.b = dest.b + src.b + 100; +SELECT * FROM idb; +UPDATE idb dest JOIN mcs src ON dest.a=src.a SET dest.b = dest.b + src.b + 100; +SELECT * FROM idb; + # Clean UP DROP USER 'cejuser'@'localhost'; DROP DATABASE mcs45_db;