diff --git a/dbcon/execplan/simplefilter.cpp b/dbcon/execplan/simplefilter.cpp index 5a4fd996d..4916a129c 100644 --- a/dbcon/execplan/simplefilter.cpp +++ b/dbcon/execplan/simplefilter.cpp @@ -470,6 +470,27 @@ bool SimpleFilter::operator==(const SimpleFilter& t) const return true; } +bool SimpleFilter::semanticEq(const SimpleFilter& t) const +{ + if (fOp != NULL) + { + if (*fOp != *t.fOp) + return false; + } + if (fLhs != NULL) + { + if (*fLhs != t.fLhs && *fLhs != *t.fRhs) + return false; + } + if (fRhs != NULL) + { + if (*fRhs != t.fRhs && *fRhs != *t.fLhs) + return false; + } + + return true; +} + bool SimpleFilter::operator==(const TreeNode* t) const { const SimpleFilter* o; diff --git a/dbcon/execplan/simplefilter.h b/dbcon/execplan/simplefilter.h index f1711082e..f29d505e3 100644 --- a/dbcon/execplan/simplefilter.h +++ b/dbcon/execplan/simplefilter.h @@ -138,28 +138,36 @@ public: /** @brief Do a deep, strict (as opposed to semantic) equivalence test * * Do a deep, strict (as opposed to semantic) equivalence test. - * @return true iff every member of t is a duplicate copy of every member of this; false otherwise + * @return true if every member of t is a duplicate copy of every member of this; false otherwise */ virtual bool operator==(const TreeNode* t) const; /** @brief Do a deep, strict (as opposed to semantic) equivalence test * * Do a deep, strict (as opposed to semantic) equivalence test. - * @return true iff every member of t is a duplicate copy of every member of this; false otherwise + * @return true if every member of t is a duplicate copy of every member of this; false otherwise */ bool operator==(const SimpleFilter& t) const; + /** @brief Do a semantic equivalence test + * + * Do a semantic equivalence test. + * @return true if filter operation are the same and + * the sets of arguments are the same; false otherwise + */ + bool semanticEq(const SimpleFilter& t) const; + /** @brief Do a deep, strict (as opposed to semantic) equivalence test * * Do a deep, strict (as opposed to semantic) equivalence test. - * @return false iff every member of t is a duplicate copy of every member of this; true otherwise + * @return false if every member of t is a duplicate copy of every member of this; true otherwise */ virtual bool operator!=(const TreeNode* t) const; /** @brief Do a deep, strict (as opposed to semantic) equivalence test * * Do a deep, strict (as opposed to semantic) equivalence test. - * @return false iff every member of t is a duplicate copy of every member of this; true otherwise + * @return false if every member of t is a duplicate copy of every member of this; true otherwise */ bool operator!=(const SimpleFilter& t) const; diff --git a/dbcon/mysql/ha_calpont_dml.cpp b/dbcon/mysql/ha_calpont_dml.cpp index cb1f3853e..e3c23274b 100644 --- a/dbcon/mysql/ha_calpont_dml.cpp +++ b/dbcon/mysql/ha_calpont_dml.cpp @@ -88,109 +88,6 @@ inline uint32_t tid2sid(const uint32_t tid) } //StopWatch timer; -int buildBuffer(uchar* buf, string& buffer, int& columns, TABLE* table) -{ - char attribute_buffer[1024]; - String attribute(attribute_buffer, sizeof(attribute_buffer), - &my_charset_bin); - - std::string cols = " ("; - std::string vals = " values ("; - columns = 0; - - for (Field** field = table->field; *field; field++) - { - const char* ptr; - const char* end_ptr; - - if ((*field)->is_null()) - ptr = end_ptr = 0; - else - { - bitmap_set_bit(table->read_set, (*field)->field_index); - (*field)->val_str(&attribute, &attribute); - ptr = attribute.ptr(); - end_ptr = attribute.length() + ptr; - } - - if (columns > 0) - { - cols.append(","); - vals.append(","); - } - - columns++; - - cols.append((*field)->field_name.str); - - if (ptr == end_ptr) - { - vals.append ("NULL"); - } - else - { - - if ( (*field)->type() == MYSQL_TYPE_VARCHAR || - /*FIXME: (*field)->type() == MYSQL_TYPE_VARBINARY || */ - (*field)->type() == MYSQL_TYPE_VAR_STRING || - (*field)->type() == MYSQL_TYPE_STRING || - (*field)->type() == MYSQL_TYPE_DATE || - (*field)->type() == MYSQL_TYPE_DATETIME || - (*field)->type() == MYSQL_TYPE_DATETIME2 || - (*field)->type() == MYSQL_TYPE_TIMESTAMP || - (*field)->type() == MYSQL_TYPE_TIMESTAMP2 || - (*field)->type() == MYSQL_TYPE_TIME ) - vals.append("'"); - - while (ptr < end_ptr) - { - - if (*ptr == '\r') - { - ptr++; - } - else if (*ptr == '\n') - { - ptr++; - } - else if (*ptr == '\'' ) - { - //@Bug 1820. Replace apostrophe with strange character to pass parser. - vals += '\252'; - ptr++; - } - else - vals += *ptr++; - } - - if ( (*field)->type() == MYSQL_TYPE_VARCHAR || - /*FIXME: (*field)->type() == MYSQL_TYPE_VARBINARY || */ - (*field)->type() == MYSQL_TYPE_VAR_STRING || - (*field)->type() == MYSQL_TYPE_STRING || - (*field)->type() == MYSQL_TYPE_DATE || - (*field)->type() == MYSQL_TYPE_DATETIME || - (*field)->type() == MYSQL_TYPE_DATETIME2 || - (*field)->type() == MYSQL_TYPE_TIMESTAMP || - (*field)->type() == MYSQL_TYPE_TIMESTAMP2 || - (*field)->type() == MYSQL_TYPE_TIME ) - vals.append("'"); - } - } - - if (columns) - { - cols.append(") "); - vals.append(") "); - buffer = "INSERT INTO "; - buffer.append(table->s->table_name.str); - buffer.append(cols); - buffer.append(vals); - } - - return columns; -} - - uint32_t buildValueList (TABLE* table, cal_connection_info& ci ) { char attribute_buffer[1024]; diff --git a/dbcon/mysql/ha_calpont_execplan.cpp b/dbcon/mysql/ha_calpont_execplan.cpp index f9bd19d4e..c536a5950 100644 --- a/dbcon/mysql/ha_calpont_execplan.cpp +++ b/dbcon/mysql/ha_calpont_execplan.cpp @@ -395,6 +395,40 @@ ReturnedColumn* buildAggFrmTempField(Item* item, gp_walk_info& gwi) return result; } +/*@brief isDuplicateSF - search for a duplicate SimpleFilter*/ +/*********************************************************** + * DESCRIPTION: + * As of 1.4 CS potentially has duplicate filter predicates + * in both join->conds and join->cond_equal. This utility f() + * searches for semantically equal SF in the list of already + * applied equi predicates. + * TODO + * We must move find_select_handler to either future or + * later execution phase. + * PARAMETERS: + * gwi main structure + * sf SimpleFilter * to find + * RETURNS + * true if sf has been found in the applied SF list + * false otherwise + * USED + * buildPredicateItem() + ***********************************************************/ +bool isDuplicateSF(gp_walk_info *gwip, execplan::SimpleFilter *sfp) +{ + List_iterator it(gwip->equiCondSFList); + execplan::SimpleFilter *isfp; + while((isfp = it++)) + { + if (sfp->semanticEq(*isfp)) + { + return true; + } + } + + return false; +} + string getViewName(TABLE_LIST* table_ptr) { string viewName = ""; @@ -1941,34 +1975,35 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip) } else if (ifp->functype() == Item_func::MULT_EQUAL_FUNC) { -#if 0 // MYSQL_5.6 - Item_equal* item_eq = (Item_equal*)ifp; - // This code is for mysql 5.6. Need to convert to MariaDB 10.1 - List_iterator_fast it(item_eq->fields); - idbassert(item_eq->fields.elements == 2); - - // @todo handle more than 2 equal fields - Item* item_field = it++; - ReturnedColumn* lhs = buildReturnedColumn(item_field, *gwip, gwip->fatalParseError); - item_field = it++; - ReturnedColumn* rhs = buildReturnedColumn(item_field, *gwip, gwip->fatalParseError); - - if (!rhs || !lhs) + Item_equal *cur_item_eq = (Item_equal*)ifp; + Item *lhs_item, *rhs_item; + // There must be at least two items + Item_equal_fields_iterator lhs_it(*cur_item_eq); + Item_equal_fields_iterator rhs_it(*cur_item_eq); rhs_it++; + while ((lhs_item = lhs_it++) && (rhs_item = rhs_it++)) { - gwip->fatalParseError = true; - gwip->parseErrorText = "Unsupport elements in MULT_EQUAL item"; - delete rhs; - delete lhs; - return false; + ReturnedColumn* lhs = buildReturnedColumn(lhs_item, *gwip, gwip->fatalParseError); + ReturnedColumn* rhs = buildReturnedColumn(rhs_item, *gwip, gwip->fatalParseError); + if (!rhs || !lhs) + { + gwip->fatalParseError = true; + gwip->parseErrorText = "Unsupport elements in MULT_EQUAL item"; + delete rhs; + delete lhs; + return false; + } + PredicateOperator* po = new PredicateOperator("="); + boost::shared_ptr sop(po); + sop->setOpType(lhs->resultType(), rhs->resultType()); + SimpleFilter* sf = new SimpleFilter(sop, lhs, rhs); + // Search in ptWorkStack for duplicates of the SF + // before we push the SF + if (!isDuplicateSF(gwip, sf)) + { + ParseTree* pt = new ParseTree(sf); + gwip->ptWorkStack.push(pt); + } } - - PredicateOperator* po = new PredicateOperator("="); - boost::shared_ptr sop(po); - sop->setOpType(lhs->resultType(), rhs->resultType()); - SimpleFilter* sf = new SimpleFilter(sop, lhs, rhs); - ParseTree* pt = new ParseTree(sf); - gwip->ptWorkStack.push(pt); -#endif } else if (ifp->functype() == Item_func::EQUAL_FUNC) { @@ -2189,6 +2224,11 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip) } } + if (ifp->functype() == Item_func::EQ_FUNC) + { + gwip->equiCondSFList.push_back(sf); + } + ParseTree* ptp = new ParseTree(sf); gwip->ptWorkStack.push(ptp); } @@ -3570,7 +3610,7 @@ ReturnedColumn* buildFunctionColumn( return rc; } - // TODO MariaDB 10.1: Until we figure out what to do with this + // Item_equal is supported by buildPredicateItem() if (funcName == "multiple equal") return NULL; @@ -5077,9 +5117,7 @@ void gp_walk(const Item* item, void* arg) string aliasTableName(scp->tableAlias()); scp->tableAlias(lower(aliasTableName)); gwip->rcWorkStack.push(scp->clone()); - //gwip->rcWorkStack.push(scp); boost::shared_ptr scsp(scp); - //boost::shared_ptr scsp(scp->clone()); gwip->scsp = scsp; gwip->funcName.clear(); @@ -6257,6 +6295,27 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, #ifdef DEBUG_WALK_COND cerr << "------------------ WHERE -----------------------" << endl; icp->traverse_cond(debug_walk, &gwi, Item::POSTFIX); + if (join && join->cond_equal) + { + List_iterator li(join->cond_equal->current_level); + Item_equal *cur_item_eq; + while ((cur_item_eq= li++)) + { + // WIP replace the block with + //cur_item_eq->traverse_cond(debug_walk, gwip, Item::POSTFIX); + std::cerr << "item_equal("; + Item *item; + Item_equal_fields_iterator it(*cur_item_eq); + while ((item= it++)) + { + std::ostringstream ostream; + std::ostringstream& osr = ostream; + getColNameFromItem(osr, item); + std::cerr << osr.str() << ","; + } + std::cerr << ")" << std::endl; + } + } cerr << "------------------------------------------------\n" << endl; #endif @@ -6279,6 +6338,19 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText, gwi); return ER_INTERNAL_ERROR; } + + // MCOL-3416 support for EQUAL_COND in MDB >= 10.1 + if (join && join->cond_equal) + { + // TODO MCOL-3416 This must traverse all levels not current_level only + List_iterator li(join->cond_equal->current_level); + Item_equal *cur_item_eq; + while ((cur_item_eq= li++)) + { + cur_item_eq->traverse_cond(gp_walk, &gwi, Item::POSTFIX); + } + } + } else if (join && join->zero_result_cause) { diff --git a/dbcon/mysql/ha_calpont_impl_if.h b/dbcon/mysql/ha_calpont_impl_if.h index ed467527b..967299aaf 100644 --- a/dbcon/mysql/ha_calpont_impl_if.h +++ b/dbcon/mysql/ha_calpont_impl_if.h @@ -143,6 +143,9 @@ struct gp_walk_info std::map derivedTbFilterMap; uint32_t derivedTbCnt; std::vector subselectList; + // Workaround for duplicate equi-JOIN predicates + // See isDuplicateSF() for more info. + List equiCondSFList; // Kludge for Bug 750 int32_t recursionLevel;