diff options
author | unknown <tomas@poseidon.ndb.mysql.com> | 2005-06-04 19:26:35 +0200 |
---|---|---|
committer | unknown <tomas@poseidon.ndb.mysql.com> | 2005-06-04 19:26:35 +0200 |
commit | 84f89641cfc6acff016b973c3bfa12ef0a31fe12 (patch) | |
tree | 5a32b384f0388487fb7fee12035b2f2e36fb75d9 /sql | |
parent | 7b3cd08e9bb71e57102a5aa5ab2237980bf92b02 (diff) | |
parent | dab1b26b1d3ec57e11681459282de2fe81e362f3 (diff) | |
download | mariadb-git-84f89641cfc6acff016b973c3bfa12ef0a31fe12.tar.gz |
Merge
BitKeeper/etc/logging_ok:
auto-union
libmysqld/Makefile.am:
Auto merged
sql/field.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
sql/ha_ndbcluster.h:
Auto merged
sql/item.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
storage/ndb/src/mgmclient/CommandInterpreter.cpp:
Auto merged
sql/sql_bitmap.h:
merge
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 15 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 22 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 1229 | ||||
-rw-r--r-- | sql/ha_ndbcluster.h | 36 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item.h | 8 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 33 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 30 | ||||
-rw-r--r-- | sql/item_func.cc | 47 | ||||
-rw-r--r-- | sql/item_func.h | 10 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 7 | ||||
-rw-r--r-- | sql/set_var.cc | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 5 | ||||
-rw-r--r-- | sql/sql_bitmap.h | 24 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 10 | ||||
-rw-r--r-- | sql/sql_union.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 6 |
20 files changed, 904 insertions, 594 deletions
diff --git a/sql/field.cc b/sql/field.cc index ed9d3e1ecd9..08a785b2780 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5859,31 +5859,32 @@ int Field_str::store(double nr) char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; uint length; bool use_scientific_notation= TRUE; + uint char_length= field_length / charset()->mbmaxlen; /* Check fabs(nr) against longest value that can be stored in field, which depends on whether the value is < 1 or not, and negative or not */ double anr= fabs(nr); int neg= (nr < 0.0) ? 1 : 0; - if (field_length > 4 && field_length < 32 && - (anr < 1.0 ? anr > 1/(log_10[max(0,(int) field_length-neg-2)]) /* -2 for "0." */ - : anr < log_10[field_length-neg]-1)) + if (char_length > 4 && char_length < 32 && + (anr < 1.0 ? anr > 1/(log_10[max(0,(int) char_length-neg-2)]) /* -2 for "0." */ + : anr < log_10[char_length-neg]-1)) use_scientific_notation= FALSE; length= (uint) my_sprintf(buff, (buff, "%-.*g", (use_scientific_notation ? - max(0, (int)field_length-neg-5) : - field_length), + max(0, (int)char_length-neg-5) : + char_length), nr)); /* +1 below is because "precision" in %g above means the max. number of significant digits, not the output width. Thus the width can be larger than number of significant digits by 1 (for decimal point) - the test for field_length < 5 is for extreme cases, + the test for char_length < 5 is for extreme cases, like inserting 500.0 in char(1) */ - DBUG_ASSERT(field_length < 5 || length <= field_length+1); + DBUG_ASSERT(char_length < 5 || length <= char_length+1); return store((const char *) buff, length, charset()); } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 5f4027c1a88..d2652b242ce 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5964,11 +5964,14 @@ ha_innobase::external_lock( TABLES if AUTOCOMMIT=1. It does not make much sense to acquire an InnoDB table lock if it is released immediately at the end of LOCK TABLES, and InnoDB's table locks in that case cause - VERY easily deadlocks. */ + VERY easily deadlocks. We do not set InnoDB table locks when + MySQL sets them at the start of a stored procedure call + (MySQL does have thd->in_lock_tables TRUE there). */ if (prebuilt->select_lock_type != LOCK_NONE) { if (thd->in_lock_tables && + thd->lex->sql_command != SQLCOM_CALL && thd->variables.innodb_table_locks && (thd->options & OPTION_NOT_AUTOCOMMIT)) { @@ -6479,11 +6482,21 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { + /* Starting from 5.0.7, we weaken also the table locks + set at the start of a MySQL stored procedure call, just like + we weaken the locks set at the start of an SQL statement. + MySQL does set thd->in_lock_tables TRUE there, but in reality + we do not need table locks to make the execution of a + single transaction stored procedure call deterministic + (if it does not use a consistent read). */ + /* If we are not doing a LOCK TABLE or DISCARD/IMPORT TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) && !thd->in_lock_tables + lock_type <= TL_WRITE) + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL) && !thd->tablespace_op && thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { @@ -6497,7 +6510,10 @@ ha_innobase::store_lock( to t2. Convert the lock to a normal read lock to allow concurrent inserts to t2. */ - if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) { + if (lock_type == TL_READ_NO_INSERT + && (!thd->in_lock_tables + || thd->lex->sql_command == SQLCOM_CALL)) { + lock_type = TL_READ; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index fc21a634b00..2bd0e992ae4 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -6077,572 +6077,778 @@ void ndb_serialize_cond(const Item *item, void *arg) context->supported= FALSE; break; } - + DBUG_VOID_RETURN; } if (context->supported) { - Ndb_cond_stack *ndb_stack= context->stack_ptr; - Ndb_cond *prev_cond= context->cond_ptr; - Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond(); - if (!ndb_stack->ndb_cond) - ndb_stack->ndb_cond= curr_cond; - curr_cond->prev= prev_cond; - if (prev_cond) prev_cond->next= curr_cond; - - // Check for end of AND/OR expression - if (!item) + Ndb_rewrite_context *rewrite_context= context->rewrite_stack; + const Item_func *func_item; + // Check if we are rewriting some unsupported function call + if (rewrite_context && + (func_item= rewrite_context->func_item) && + rewrite_context->count++ == 0) { - // End marker for condition group - DBUG_PRINT("info", ("End of condition group")); - curr_cond->ndb_item= new Ndb_item(NDB_END_COND); - } - else - switch(item->type()) { - case(Item::FIELD_ITEM): { - Item_field *field_item= (Item_field *) item; - Field *field= field_item->field; - enum_field_types type= field->type(); + switch(func_item->functype()) { + case(Item_func::BETWEEN): /* - Check that the field is part of the table of the handler - instance and that we expect a field with of this result type. + Rewrite + <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2> + to <field>|<const> > <const1>|<field1> AND + <field>|<const> < <const2>|<field2> + or actually in prefix format + BEGIN(AND) GT(<field>|<const>, <const1>|<field1>), + LT(<field>|<const>, <const2>|<field2>), END() */ - if (context->table == field->table) - { - const NDBTAB *tab= (const NDBTAB *) context->ndb_table; - DBUG_PRINT("info", ("FIELD_ITEM")); - DBUG_PRINT("info", ("table %s", tab->getName())); - DBUG_PRINT("info", ("column %s", field->field_name)); - DBUG_PRINT("info", ("result type %d", field->result_type())); - - // Check that we are expecting a field and with the correct - // result type - if(context->expecting(Item::FIELD_ITEM) && - (context->expecting_field_result(field->result_type()) || - // Date and year can be written as strings - (type == MYSQL_TYPE_TIME || - type == MYSQL_TYPE_DATE || - type == MYSQL_TYPE_YEAR || - type == MYSQL_TYPE_DATETIME) - ? context->expecting_field_result(STRING_RESULT) : true) - // Bit fields no yet supported in scan filter - && type != MYSQL_TYPE_BIT) + case(Item_func::IN_FUNC): { + /* + Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..) + to <field>|<const> = <const1>|<field1> OR + <field> = <const2>|<field2> ... + or actually in prefix format + BEGIN(OR) EQ(<field>|<const>, <const1><field1>), + EQ(<field>|<const>, <const2>|<field2>), ... END() + Each part of the disjunction is added for each call + to ndb_serialize_cond and end of rewrite statement + is wrapped in end of ndb_serialize_cond + */ + if (context->expecting(item->type())) + { + // This is the <field>|<const> item, save it in the rewrite context + rewrite_context->left_hand_item= item; + if (item->type() == Item::FUNC_ITEM) { - const NDBCOL *col= tab->getColumn(field->field_name); - DBUG_ASSERT(col); - curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo()); - context->dont_expect(Item::FIELD_ITEM); - context->expect_no_field_result(); - if (context->expect_mask) + Item_func *func_item= (Item_func *) item; + if (func_item->functype() == Item_func::UNKNOWN_FUNC && + func_item->const_item()) { - // We have not seen second argument yet - if (type == MYSQL_TYPE_TIME || - type == MYSQL_TYPE_DATE || - type == MYSQL_TYPE_YEAR || - type == MYSQL_TYPE_DATETIME) - { - context->expect_only(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - } - else - switch(field->result_type()) { - case(STRING_RESULT): - // Expect char string or binary string - context->expect_only(Item::STRING_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect_collation(field_item->collation.collation); - break; - case(REAL_RESULT): - context->expect_only(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - break; - case(INT_RESULT): - context->expect_only(Item::INT_ITEM); - context->expect(Item::VARBIN_ITEM); - break; - case(DECIMAL_RESULT): - context->expect_only(Item::DECIMAL_ITEM); - context->expect(Item::REAL_ITEM); - break; - default: - break; - } + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); } else { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - // Check that field and string constant collations are the same - if ((field->result_type() == STRING_RESULT) && - !context->expecting_collation(item->collation.collation)) - { - DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; - } + DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN")); + context->supported= FALSE; + DBUG_VOID_RETURN; + } - break; } } - DBUG_PRINT("info", ("Was not expecting field of type %u", - field->result_type())); - context->supported= FALSE; - break; - } - case(Item::FUNC_ITEM): { - Item_func *func_item= (Item_func *) item; - // Check that we expect a function or functional expression here - if (context->expecting(Item::FUNC_ITEM) || - func_item->functype() == Item_func::UNKNOWN_FUNC) - context->expect_nothing(); else { - // Did not expect function here + // Non-supported BETWEEN|IN expression + DBUG_PRINT("info", ("Found unexpected item of type %u in BETWEEN|IN", + item->type())); context->supported= FALSE; - break; + DBUG_VOID_RETURN; } - + break; + } + default: + context->supported= FALSE; + break; + } + DBUG_VOID_RETURN; + } + else + { + Ndb_cond_stack *ndb_stack= context->stack_ptr; + Ndb_cond *prev_cond= context->cond_ptr; + Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond(); + if (!ndb_stack->ndb_cond) + ndb_stack->ndb_cond= curr_cond; + curr_cond->prev= prev_cond; + if (prev_cond) prev_cond->next= curr_cond; + // Check if we are rewriting some unsupported function call + if (context->rewrite_stack) + { + Ndb_rewrite_context *rewrite_context= context->rewrite_stack; + const Item_func *func_item= rewrite_context->func_item; switch(func_item->functype()) { - case(Item_func::EQ_FUNC): { - DBUG_PRINT("info", ("EQ_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::NE_FUNC): { - DBUG_PRINT("info", ("NE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::LT_FUNC): { - DBUG_PRINT("info", ("LT_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::LE_FUNC): { - DBUG_PRINT("info", ("LE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::GE_FUNC): { - DBUG_PRINT("info", ("GE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::GT_FUNC): { - DBUG_PRINT("info", ("GT_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::REAL_ITEM); - context->expect(Item::DECIMAL_ITEM); - context->expect(Item::INT_ITEM); - context->expect(Item::VARBIN_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); - break; - } - case(Item_func::LIKE_FUNC): { - DBUG_PRINT("info", ("LIKE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - break; - } - case(Item_func::NOTLIKE_FUNC): { - DBUG_PRINT("info", ("NOTLIKE_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::STRING_ITEM); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - break; - } - case(Item_func::ISNULL_FUNC): { - DBUG_PRINT("info", ("ISNULL_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); + case(Item_func::BETWEEN): { + /* + Rewrite + <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2> + to <field>|<const> > <const1>|<field1> AND + <field>|<const> < <const2>|<field2> + or actually in prefix format + BEGIN(AND) GT(<field>|<const>, <const1>|<field1>), + LT(<field>|<const>, <const2>|<field2>), END() + */ + if (rewrite_context->count == 2) + { + // Lower limit of BETWEEN + DBUG_PRINT("info", ("GE_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::GE_FUNC, 2); + } + else if (rewrite_context->count == 3) + { + // Upper limit of BETWEEN + DBUG_PRINT("info", ("LE_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::LE_FUNC, 2); + } + else + { + // Illegal BETWEEN expression + DBUG_PRINT("info", ("Illegal BETWEEN expression")); + context->supported= FALSE; + DBUG_VOID_RETURN; + } break; } - case(Item_func::ISNOTNULL_FUNC): { - DBUG_PRINT("info", ("ISNOTNULL_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::FIELD_ITEM); - context->expect_field_result(STRING_RESULT); - context->expect_field_result(REAL_RESULT); - context->expect_field_result(INT_RESULT); - context->expect_field_result(DECIMAL_RESULT); + case(Item_func::IN_FUNC): { + /* + Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..) + to <field>|<const> = <const1>|<field1> OR + <field> = <const2>|<field2> ... + or actually in prefix format + BEGIN(OR) EQ(<field>|<const>, <const1><field1>), + EQ(<field>|<const>, <const2>|<field2>), ... END() + Each part of the disjunction is added for each call + to ndb_serialize_cond and end of rewrite statement + is wrapped in end of ndb_serialize_cond + */ + DBUG_PRINT("info", ("EQ_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::EQ_FUNC, 2); break; } - case(Item_func::NOT_FUNC): { - DBUG_PRINT("info", ("NOT_FUNC")); - curr_cond->ndb_item= new Ndb_item(func_item->functype(), - func_item); - context->expect(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - break; + default: + context->supported= FALSE; } - case(Item_func::UNKNOWN_FUNC): { - DBUG_PRINT("info", ("UNKNOWN_FUNC %s", - func_item->const_item()?"const":"")); - DBUG_PRINT("info", ("result type %d", func_item->result_type())); - if (func_item->const_item()) - switch(func_item->result_type()) { - case(STRING_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::STRING_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + // Handle left hand <field>|<const> + context->rewrite_stack= NULL; // Disable rewrite mode + context->expect_only(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + context->expect(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + ndb_serialize_cond(rewrite_context->left_hand_item, arg); + context->skip= 0; // Any FUNC_ITEM expression has already been parsed + context->rewrite_stack= rewrite_context; // Enable rewrite mode + if (!context->supported) + DBUG_VOID_RETURN; + + prev_cond= context->cond_ptr; + curr_cond= context->cond_ptr= new Ndb_cond(); + prev_cond->next= curr_cond; + } + + // Check for end of AND/OR expression + if (!item) + { + // End marker for condition group + DBUG_PRINT("info", ("End of condition group")); + curr_cond->ndb_item= new Ndb_item(NDB_END_COND); + } + else + switch(item->type()) { + case(Item::FIELD_ITEM): { + Item_field *field_item= (Item_field *) item; + Field *field= field_item->field; + enum_field_types type= field->type(); + /* + Check that the field is part of the table of the handler + instance and that we expect a field with of this result type. + */ + if (context->table == field->table) + { + const NDBTAB *tab= (const NDBTAB *) context->ndb_table; + DBUG_PRINT("info", ("FIELD_ITEM")); + DBUG_PRINT("info", ("table %s", tab->getName())); + DBUG_PRINT("info", ("column %s", field->field_name)); + DBUG_PRINT("info", ("result type %d", field->result_type())); + + // Check that we are expecting a field and with the correct + // result type + if (context->expecting(Item::FIELD_ITEM) && + (context->expecting_field_result(field->result_type()) || + // Date and year can be written as strings + ((type == MYSQL_TYPE_TIME || + type == MYSQL_TYPE_DATE || + type == MYSQL_TYPE_YEAR || + type == MYSQL_TYPE_DATETIME) + ? context->expecting_field_result(STRING_RESULT) : true)) && + // Bit fields no yet supported in scan filter + type != MYSQL_TYPE_BIT) + { + const NDBCOL *col= tab->getColumn(field->field_name); + DBUG_ASSERT(col); + curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo()); + context->dont_expect(Item::FIELD_ITEM); + context->expect_no_field_result(); + if (context->expect_mask) { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); - context->expect_collation(func_item->collation.collation); + // We have not seen second argument yet + if (type == MYSQL_TYPE_TIME || + type == MYSQL_TYPE_DATE || + type == MYSQL_TYPE_YEAR || + type == MYSQL_TYPE_DATETIME) + { + context->expect_only(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + } + else + switch(field->result_type()) { + case(STRING_RESULT): + // Expect char string or binary string + context->expect_only(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect_collation(field_item->collation.collation); + break; + case(REAL_RESULT): + context->expect_only(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + break; + case(INT_RESULT): + context->expect_only(Item::INT_ITEM); + context->expect(Item::VARBIN_ITEM); + break; + case(DECIMAL_RESULT): + context->expect_only(Item::DECIMAL_ITEM); + context->expect(Item::REAL_ITEM); + break; + default: + break; + } } else { // Expect another logical expression context->expect_only(Item::FUNC_ITEM); context->expect(Item::COND_ITEM); - // Check that string result have correct collation - if (!context->expecting_collation(item->collation.collation)) + // Check that field and string constant collations are the same + if ((field->result_type() == STRING_RESULT) && + !context->expecting_collation(item->collation.collation) + && type != MYSQL_TYPE_TIME + && type != MYSQL_TYPE_DATE + && type != MYSQL_TYPE_YEAR + && type != MYSQL_TYPE_DATETIME) { DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; + item->collation.collation->name)); + context->supported= FALSE; } } - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case(REAL_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::REAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); break; } - case(INT_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::INT_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(INT_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - case(DECIMAL_RESULT): { - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::DECIMAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(DECIMAL_RESULT); - } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - } - // Skip any arguments since we will evaluate function instead - DBUG_PRINT("info", ("Skip until end of arguments marker")); - context->skip= func_item->argument_count(); - break; - } - default: - break; + else + { + DBUG_PRINT("info", ("Was not expecting field of type %u", + field->result_type())); + context->supported= FALSE; } + } else - // Function does not return constant expression + { + DBUG_PRINT("info", ("Was not expecting field from table %s(%s)", + context->table->s->table_name, + field->table->s->table_name)); context->supported= FALSE; + } break; } - default: { - DBUG_PRINT("info", ("Found func_item of type %d", - func_item->functype())); - context->supported= FALSE; - } - } - break; - } - case(Item::STRING_ITEM): - DBUG_PRINT("info", ("STRING_ITEM")); - if (context->expecting(Item::STRING_ITEM)) - { -#ifndef DBUG_OFF - char buff[256]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - str.length(0); - Item_string *string_item= (Item_string *) item; - DBUG_PRINT("info", ("value \"%s\"", - string_item->val_str(&str)->ptr())); -#endif - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::STRING_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + case(Item::FUNC_ITEM): { + Item_func *func_item= (Item_func *) item; + // Check that we expect a function or functional expression here + if (context->expecting(Item::FUNC_ITEM) || + func_item->functype() == Item_func::UNKNOWN_FUNC) + context->expect_nothing(); + else { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); - context->expect_collation(item->collation.collation); + // Did not expect function here + context->supported= FALSE; + break; } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); - // Check that we are comparing with a field with same collation - if (!context->expecting_collation(item->collation.collation)) - { - DBUG_PRINT("info", ("Found non-matching collation %s", - item->collation.collation->name)); - context->supported= FALSE; - } + + switch(func_item->functype()) { + case(Item_func::EQ_FUNC): { + DBUG_PRINT("info", ("EQ_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; } - } - else - context->supported= FALSE; - break; - case(Item::INT_ITEM): - DBUG_PRINT("info", ("INT_ITEM")); - if (context->expecting(Item::INT_ITEM)) - { - Item_int *int_item= (Item_int *) item; - DBUG_PRINT("info", ("value %d", int_item->value)); - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::INT_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(INT_RESULT); + case(Item_func::NE_FUNC): { + DBUG_PRINT("info", ("NE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); + case(Item_func::LT_FUNC): { + DBUG_PRINT("info", ("LT_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::LE_FUNC): { + DBUG_PRINT("info", ("LE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::GE_FUNC): { + DBUG_PRINT("info", ("GE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::GT_FUNC): { + DBUG_PRINT("info", ("GT_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::REAL_ITEM); + context->expect(Item::DECIMAL_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::LIKE_FUNC): { + DBUG_PRINT("info", ("LIKE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect(Item::FUNC_ITEM); + break; + } + case(Item_func::NOTLIKE_FUNC): { + DBUG_PRINT("info", ("NOTLIKE_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::STRING_ITEM); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect(Item::FUNC_ITEM); + break; + } + case(Item_func::ISNULL_FUNC): { + DBUG_PRINT("info", ("ISNULL_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::ISNOTNULL_FUNC): { + DBUG_PRINT("info", ("ISNOTNULL_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::FIELD_ITEM); + context->expect_field_result(STRING_RESULT); + context->expect_field_result(REAL_RESULT); + context->expect_field_result(INT_RESULT); + context->expect_field_result(DECIMAL_RESULT); + break; + } + case(Item_func::NOT_FUNC): { + DBUG_PRINT("info", ("NOT_FUNC")); + curr_cond->ndb_item= new Ndb_item(func_item->functype(), + func_item); + context->expect(Item::FUNC_ITEM); context->expect(Item::COND_ITEM); + break; } - } - else - context->supported= FALSE; - break; - case(Item::REAL_ITEM): - DBUG_PRINT("info", ("REAL_ITEM %s")); - if (context->expecting(Item::REAL_ITEM)) - { - Item_float *float_item= (Item_float *) item; - DBUG_PRINT("info", ("value %f", float_item->value)); - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::REAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) - { - // We have not seen the field argument yet + case(Item_func::BETWEEN) : { + DBUG_PRINT("info", ("BETWEEN, rewriting using AND")); + Ndb_rewrite_context *rewrite_context= + new Ndb_rewrite_context(func_item); + rewrite_context->next= context->rewrite_stack; + context->rewrite_stack= rewrite_context; + DBUG_PRINT("info", ("COND_AND_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC, + func_item->argument_count() - 1); context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); + context->expect(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + break; } - else - { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); + case(Item_func::IN_FUNC) : { + DBUG_PRINT("info", ("IN_FUNC, rewriting using OR")); + Ndb_rewrite_context *rewrite_context= + new Ndb_rewrite_context(func_item); + rewrite_context->next= context->rewrite_stack; + context->rewrite_stack= rewrite_context; + DBUG_PRINT("info", ("COND_OR_FUNC")); + curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC, + func_item->argument_count() - 1); + context->expect_only(Item::FIELD_ITEM); + context->expect(Item::INT_ITEM); + context->expect(Item::STRING_ITEM); + context->expect(Item::VARBIN_ITEM); + context->expect(Item::FUNC_ITEM); + break; } + case(Item_func::UNKNOWN_FUNC): { + DBUG_PRINT("info", ("UNKNOWN_FUNC %s", + func_item->const_item()?"const":"")); + DBUG_PRINT("info", ("result type %d", func_item->result_type())); + if (func_item->const_item()) + switch(func_item->result_type()) { + case(STRING_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::STRING_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + context->expect_collation(func_item->collation.collation); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + // Check that string result have correct collation + if (!context->expecting_collation(item->collation.collation)) + { + DBUG_PRINT("info", ("Found non-matching collation %s", + item->collation.collation->name)); + context->supported= FALSE; + } + } + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + case(REAL_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::REAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + case(INT_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::INT_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(INT_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + case(DECIMAL_RESULT): { + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::DECIMAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(DECIMAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } + // Skip any arguments since we will evaluate function instead + DBUG_PRINT("info", ("Skip until end of arguments marker")); + context->skip= func_item->argument_count(); + break; + } + default: + break; + } + else + // Function does not return constant expression + context->supported= FALSE; + break; + } + default: { + DBUG_PRINT("info", ("Found func_item of type %d", + func_item->functype())); + context->supported= FALSE; + } + } + break; } - else - context->supported= FALSE; - break; - case(Item::VARBIN_ITEM): - DBUG_PRINT("info", ("VARBIN_ITEM")); - if (context->expecting(Item::VARBIN_ITEM)) - { + case(Item::STRING_ITEM): + DBUG_PRINT("info", ("STRING_ITEM")); + if (context->expecting(Item::STRING_ITEM)) + { #ifndef DBUG_OFF - char buff[256]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - str.length(0); - Item_hex_string *varbin_item= (Item_hex_string *) item; - DBUG_PRINT("info", ("value \"%s\"", - varbin_item->val_str(&str)->ptr())); + char buff[256]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + str.length(0); + Item_string *string_item= (Item_string *) item; + DBUG_PRINT("info", ("value \"%s\"", + string_item->val_str(&str)->ptr())); #endif - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::VARBIN_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::STRING_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + context->expect_collation(item->collation.collation); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + // Check that we are comparing with a field with same collation + if (!context->expecting_collation(item->collation.collation)) + { + DBUG_PRINT("info", ("Found non-matching collation %s", + item->collation.collation->name)); + context->supported= FALSE; + } + } + } + else + context->supported= FALSE; + break; + case(Item::INT_ITEM): + DBUG_PRINT("info", ("INT_ITEM")); + if (context->expecting(Item::INT_ITEM)) { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(STRING_RESULT); + Item_int *int_item= (Item_int *) item; + DBUG_PRINT("info", ("value %d", int_item->value)); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::INT_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(INT_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } else + context->supported= FALSE; + break; + case(Item::REAL_ITEM): + DBUG_PRINT("info", ("REAL_ITEM %s")); + if (context->expecting(Item::REAL_ITEM)) { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); + Item_float *float_item= (Item_float *) item; + DBUG_PRINT("info", ("value %f", float_item->value)); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::REAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } - } - else - context->supported= FALSE; - break; - case(Item::DECIMAL_ITEM): - DBUG_PRINT("info", ("DECIMAL_ITEM %s")); - if (context->expecting(Item::DECIMAL_ITEM)) - { - Item_decimal *decimal_item= (Item_decimal *) item; - DBUG_PRINT("info", ("value %f", decimal_item->val_real())); - NDB_ITEM_QUALIFICATION q; - q.value_type= Item::DECIMAL_ITEM; - curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); - if (context->expect_field_result_mask) + else + context->supported= FALSE; + break; + case(Item::VARBIN_ITEM): + DBUG_PRINT("info", ("VARBIN_ITEM")); + if (context->expecting(Item::VARBIN_ITEM)) { - // We have not seen the field argument yet - context->expect_only(Item::FIELD_ITEM); - context->expect_only_field_result(REAL_RESULT); - context->expect_field_result(DECIMAL_RESULT); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::VARBIN_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(STRING_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } else + context->supported= FALSE; + break; + case(Item::DECIMAL_ITEM): + DBUG_PRINT("info", ("DECIMAL_ITEM %s")); + if (context->expecting(Item::DECIMAL_ITEM)) { - // Expect another logical expression - context->expect_only(Item::FUNC_ITEM); - context->expect(Item::COND_ITEM); + Item_decimal *decimal_item= (Item_decimal *) item; + DBUG_PRINT("info", ("value %f", decimal_item->val_real())); + NDB_ITEM_QUALIFICATION q; + q.value_type= Item::DECIMAL_ITEM; + curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); + if (context->expect_field_result_mask) + { + // We have not seen the field argument yet + context->expect_only(Item::FIELD_ITEM); + context->expect_only_field_result(REAL_RESULT); + context->expect_field_result(DECIMAL_RESULT); + } + else + { + // Expect another logical expression + context->expect_only(Item::FUNC_ITEM); + context->expect(Item::COND_ITEM); + } } + else + context->supported= FALSE; + break; + case(Item::COND_ITEM): { + Item_cond *cond_item= (Item_cond *) item; + + if (context->expecting(Item::COND_ITEM)) + switch(cond_item->functype()) { + case(Item_func::COND_AND_FUNC): + DBUG_PRINT("info", ("COND_AND_FUNC")); + curr_cond->ndb_item= new Ndb_item(cond_item->functype(), + cond_item); + break; + case(Item_func::COND_OR_FUNC): + DBUG_PRINT("info", ("COND_OR_FUNC")); + curr_cond->ndb_item= new Ndb_item(cond_item->functype(), + cond_item); + break; + default: + DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype())); + context->supported= FALSE; + break; + } + else + // Did not expect condition + context->supported= FALSE; + break; } - else + default: { + DBUG_PRINT("info", ("Found item of type %d", item->type())); context->supported= FALSE; - break; - case(Item::COND_ITEM): { - Item_cond *cond_item= (Item_cond *) item; - - if (context->expecting(Item::COND_ITEM)) - switch(cond_item->functype()) { - case(Item_func::COND_AND_FUNC): - DBUG_PRINT("info", ("COND_AND_FUNC")); - curr_cond->ndb_item= new Ndb_item(cond_item->functype(), - cond_item); - break; - case(Item_func::COND_OR_FUNC): - DBUG_PRINT("info", ("COND_OR_FUNC")); - curr_cond->ndb_item= new Ndb_item(cond_item->functype(), - cond_item); - break; - default: - DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype())); - context->supported= FALSE; - break; - } - else - // Did not expect condition - context->supported= FALSE; - break; - } - default: { - DBUG_PRINT("info", ("Found item of type %d", item->type())); - context->supported= FALSE; - } + } + } + + if (context->supported && context->rewrite_stack) + { + Ndb_rewrite_context *rewrite_context= context->rewrite_stack; + if (rewrite_context->count == + rewrite_context->func_item->argument_count()) + { + // Rewrite is done, wrap an END() at the en + DBUG_PRINT("info", ("End of condition group")); + prev_cond= curr_cond; + curr_cond= context->cond_ptr= new Ndb_cond(); + prev_cond->next= curr_cond; + curr_cond->ndb_item= new Ndb_item(NDB_END_COND); + // Pop rewrite stack + context->rewrite_stack= context->rewrite_stack->next; + } } + } } - + DBUG_VOID_RETURN; } @@ -6925,8 +7131,10 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) break; } case(Item_func::NOT_FUNC): { + DBUG_PRINT("info", ("Generating negated query")); cond= cond->next; negated= TRUE; + break; } default: @@ -6942,12 +7150,14 @@ ha_ndbcluster::build_scan_filter_group(Ndb_cond* &cond, NdbScanFilter *filter) if (cond) cond= cond->next; if (filter->end() == -1) DBUG_RETURN(1); - break; + if (!negated) + break; + // else fall through (NOT END is an illegal condition) default: { DBUG_PRINT("info", ("Illegal scan filter")); } } - } while (level > 0); + } while (level > 0 || negated); DBUG_RETURN(0); } @@ -6958,14 +7168,20 @@ ha_ndbcluster::build_scan_filter(Ndb_cond * &cond, NdbScanFilter *filter) bool simple_cond= TRUE; DBUG_ENTER("build_scan_filter"); - switch(cond->ndb_item->type) { - case(Item_func::COND_AND_FUNC): - case(Item_func::COND_OR_FUNC): - simple_cond= FALSE; - break; - default: - break; - } + switch(cond->ndb_item->type) { + case(NDB_FUNCTION): + switch(cond->ndb_item->qualification.function_type) { + case(Item_func::COND_AND_FUNC): + case(Item_func::COND_OR_FUNC): + simple_cond= FALSE; + break; + default: + break; + } + break; + default: + break; + } if (simple_cond && filter->begin() == -1) DBUG_RETURN(1); if (build_scan_filter_group(cond, filter)) @@ -6983,6 +7199,7 @@ ha_ndbcluster::generate_scan_filter(Ndb_cond_stack *ndb_cond_stack, DBUG_ENTER("generate_scan_filter"); if (ndb_cond_stack) { + DBUG_PRINT("info", ("Generating scan filter")); NdbScanFilter filter(op); bool multiple_cond= FALSE; // Wrap an AND group around multiple conditions diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 01e7bea057f..f73ca8a974e 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -86,6 +86,7 @@ typedef struct ndb_item_field_value { typedef union ndb_item_value { const Item *item; NDB_ITEM_FIELD_VALUE *field_value; + uint arg_count; } NDB_ITEM_VALUE; struct negated_function_mapping @@ -144,6 +145,7 @@ class Ndb_item { } case(NDB_FUNCTION): value.item= item_value; + value.arg_count= ((Item_func *) item_value)->argument_count(); break; case(NDB_END_COND): break; @@ -162,6 +164,13 @@ class Ndb_item { { qualification.function_type= func_type; value.item= item_value; + value.arg_count= ((Item_func *) item_value)->argument_count(); + }; + Ndb_item(Item_func::Functype func_type, uint no_args) + : type(NDB_FUNCTION) + { + qualification.function_type= func_type; + value.arg_count= no_args; }; ~Ndb_item() { @@ -194,7 +203,7 @@ class Ndb_item { int argument_count() { - return ((Item_func *) value.item)->argument_count(); + return value.arg_count; }; const char* get_val() @@ -273,12 +282,28 @@ class Ndb_cond_stack { if (ndb_cond) delete ndb_cond; ndb_cond= NULL; + if (next) delete next; next= NULL; }; Ndb_cond *ndb_cond; Ndb_cond_stack *next; }; +class Ndb_rewrite_context +{ +public: + Ndb_rewrite_context(Item_func *func) + : func_item(func), left_hand_item(NULL), count(0) {}; + ~Ndb_rewrite_context() + { + if (next) delete next; + } + const Item_func *func_item; + const Item *left_hand_item; + uint count; + Ndb_rewrite_context *next; +}; + /* This class is used for storing the context when traversing the Item tree. It stores a reference to the table the condition @@ -292,11 +317,16 @@ class Ndb_cond_traverse_context Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack) : table(tab), ndb_table(ndb_tab), supported(TRUE), stack_ptr(stack), cond_ptr(NULL), - expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL) + expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL), + rewrite_stack(NULL) { if (stack) cond_ptr= stack->ndb_cond; }; + ~Ndb_cond_traverse_context() + { + if (rewrite_stack) delete rewrite_stack; + } void expect(Item::Type type) { expect_mask|= (1 << type); @@ -357,7 +387,7 @@ class Ndb_cond_traverse_context uint expect_field_result_mask; uint skip; CHARSET_INFO* collation; - + Ndb_rewrite_context *rewrite_stack; }; /* diff --git a/sql/item.cc b/sql/item.cc index 913c01f5992..5fef75a6e30 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1027,7 +1027,7 @@ Item_field::Item_field(THD *thd, Field *f) structure can go away and pop up again between subsequent executions of a prepared statement). */ - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) { if (db_name) orig_db_name= thd->strdup(db_name); diff --git a/sql/item.h b/sql/item.h index f2e8e582780..4f5ed9934c5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -585,10 +585,12 @@ public: } /* For error printing */ - inline void my_name(char **strp, uint *lengthp) + inline LEX_STRING *my_name(LEX_STRING *get_name) { - *strp= m_name.str; - *lengthp= m_name.length; + if (!get_name) + return &m_name; + (*get_name)= m_name; + return get_name; } bool is_splocal() { return 1; } /* Needed for error checking */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a7abb5f9be8..3f25d473792 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1116,8 +1116,8 @@ Item_func_ifnull::fix_length_and_dec() max_length= (max(args[0]->max_length - args[0]->decimals, args[1]->max_length - args[1]->decimals) + decimals); - agg_result_type(&cached_result_type, args, 2); - switch (cached_result_type) { + agg_result_type(&hybrid_type, args, 2); + switch (hybrid_type) { case STRING_RESULT: agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); break; @@ -1155,7 +1155,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table) } double -Item_func_ifnull::val_real() +Item_func_ifnull::real_op() { DBUG_ASSERT(fixed == 1); double value= args[0]->val_real(); @@ -1171,7 +1171,7 @@ Item_func_ifnull::val_real() } longlong -Item_func_ifnull::val_int() +Item_func_ifnull::int_op() { DBUG_ASSERT(fixed == 1); longlong value=args[0]->val_int(); @@ -1187,7 +1187,7 @@ Item_func_ifnull::val_int() } -my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) +my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); my_decimal *value= args[0]->val_decimal(decimal_value); @@ -1204,7 +1204,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) String * -Item_func_ifnull::val_str(String *str) +Item_func_ifnull::str_op(String *str) { DBUG_ASSERT(fixed == 1); String *res =args[0]->val_str(str); @@ -1227,9 +1227,16 @@ Item_func_if::fix_length_and_dec() { maybe_null=args[1]->maybe_null || args[2]->maybe_null; decimals= max(args[1]->decimals, args[2]->decimals); - max_length= (max(args[1]->max_length - args[1]->decimals, + if (decimals == NOT_FIXED_DEC) + { + max_length= max(args[1]->max_length, args[2]->max_length); + } + else + { + max_length= (max(args[1]->max_length - args[1]->decimals, args[2]->max_length - args[2]->decimals) + decimals); + } enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); bool null1=args[1]->const_item() && args[1]->null_value; @@ -1678,7 +1685,7 @@ void Item_func_case::print(String *str) Coalesce - return first not NULL argument. */ -String *Item_func_coalesce::val_str(String *str) +String *Item_func_coalesce::str_op(String *str) { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1692,7 +1699,7 @@ String *Item_func_coalesce::val_str(String *str) return 0; } -longlong Item_func_coalesce::val_int() +longlong Item_func_coalesce::int_op() { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1706,7 +1713,7 @@ longlong Item_func_coalesce::val_int() return 0; } -double Item_func_coalesce::val_real() +double Item_func_coalesce::real_op() { DBUG_ASSERT(fixed == 1); null_value=0; @@ -1721,7 +1728,7 @@ double Item_func_coalesce::val_real() } -my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) +my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); null_value= 0; @@ -1738,8 +1745,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) void Item_func_coalesce::fix_length_and_dec() { - agg_result_type(&cached_result_type, args, arg_count); - switch (cached_result_type) { + agg_result_type(&hybrid_type, args, arg_count); + switch (hybrid_type) { case STRING_RESULT: count_only_length(); decimals= NOT_FIXED_DEC; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a929d509723..7a22e76b217 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -453,23 +453,19 @@ public: }; -class Item_func_coalesce :public Item_func +class Item_func_coalesce :public Item_func_numhybrid { protected: - enum Item_result cached_result_type; - Item_func_coalesce(Item *a, Item *b) - :Item_func(a, b), cached_result_type(INT_RESULT) - {} + Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {} public: - Item_func_coalesce(List<Item> &list) - :Item_func(list),cached_result_type(INT_RESULT) - {} - double val_real(); - longlong val_int(); - String *val_str(String *); - my_decimal *val_decimal(my_decimal *); + Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {} + double real_op(); + longlong int_op(); + String *str_op(String *); + my_decimal *decimal_op(my_decimal *); void fix_length_and_dec(); - enum Item_result result_type () const { return cached_result_type; } + void find_num_type() {} + enum Item_result result_type () const { return hybrid_type; } const char *func_name() const { return "coalesce"; } table_map not_null_tables() const { return 0; } }; @@ -482,10 +478,10 @@ protected: bool field_type_defined; public: Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} - double val_real(); - longlong val_int(); - String *val_str(String *str); - my_decimal *val_decimal(my_decimal *); + double real_op(); + longlong int_op(); + String *str_op(String *str); + my_decimal *decimal_op(my_decimal *); enum_field_types field_type() const; void fix_length_and_dec(); const char *func_name() const { return "ifnull"; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 3767844e200..5af99cb8132 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -695,8 +695,8 @@ String *Item_int_func::val_str(String *str) /* - Check arguments here to determine result's type for function with two - arguments. + Check arguments here to determine result's type for a numeric + function of two arguments. SYNOPSIS Item_num_op::find_num_type() @@ -722,8 +722,9 @@ void Item_num_op::find_num_type(void) hybrid_type= DECIMAL_RESULT; result_precision(); } - else if (r0 == INT_RESULT && r1 == INT_RESULT) + else { + DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT); decimals= 0; hybrid_type=INT_RESULT; result_precision(); @@ -738,7 +739,9 @@ void Item_num_op::find_num_type(void) /* - Set result type of function if it (type) is depends only on first argument + Set result type for a numeric function of one argument + (can be also used by a numeric function of many arguments, if the result + type depends only on the first argument) SYNOPSIS Item_func_num1::find_num_type() @@ -817,6 +820,8 @@ String *Item_func_numhybrid::val_str(String *str) str->set(nr,decimals,&my_charset_bin); break; } + case STRING_RESULT: + return str_op(&str_value); default: DBUG_ASSERT(0); } @@ -841,6 +846,14 @@ double Item_func_numhybrid::val_real() return (double)int_op(); case REAL_RESULT: return real_op(); + case STRING_RESULT: + { + char *end_not_used; + int err_not_used; + String *res= str_op(&str_value); + return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(), + &end_not_used, &err_not_used) : 0.0); + } default: DBUG_ASSERT(0); } @@ -865,6 +878,15 @@ longlong Item_func_numhybrid::val_int() return int_op(); case REAL_RESULT: return (longlong)real_op(); + case STRING_RESULT: + { + char *end_not_used; + int err_not_used; + String *res= str_op(&str_value); + CHARSET_INFO *cs= str_value.charset(); + return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used, + &err_not_used) : 0); + } default: DBUG_ASSERT(0); } @@ -893,6 +915,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) break; } case STRING_RESULT: + { + String *res= str_op(&str_value); + str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(), + res->length(), res->charset(), decimal_value); + break; + } case ROW_RESULT: default: DBUG_ASSERT(0); @@ -2325,9 +2353,6 @@ longlong Item_func_field::val_int() { DBUG_ASSERT(fixed == 1); - if (args[0]->is_null()) - return 0; - if (cmp_type == STRING_RESULT) { String *field; @@ -2343,6 +2368,8 @@ longlong Item_func_field::val_int() else if (cmp_type == INT_RESULT) { longlong val= args[0]->val_int(); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count ; i++) { if (!args[i]->is_null() && val == args[i]->val_int()) @@ -2353,6 +2380,8 @@ longlong Item_func_field::val_int() { my_decimal dec_arg_buf, *dec_arg, dec_buf, *dec= args[0]->val_decimal(&dec_buf); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count; i++) { dec_arg= args[i]->val_decimal(&dec_arg_buf); @@ -2363,6 +2392,8 @@ longlong Item_func_field::val_int() else { double val= args[0]->val_real(); + if (args[0]->null_value) + return 0; for (uint i=1; i < arg_count ; i++) { if (!args[i]->is_null() && val == args[i]->val_real()) @@ -4509,7 +4540,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name, !my_strcasecmp(system_charset_info, name.str, "VERSION")) return new Item_string("@@VERSION", server_version, (uint) strlen(server_version), - system_charset_info); + system_charset_info, DERIVATION_SYSCONST); Item *item; sys_var *var; diff --git a/sql/item_func.h b/sql/item_func.h index b53f2a0b9c6..f0c7e25ad53 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -189,10 +189,13 @@ class Item_func_numhybrid: public Item_func protected: Item_result hybrid_type; public: - Item_func_numhybrid(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) + Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT) {} Item_func_numhybrid(Item *a,Item *b) - :Item_func(a,b),hybrid_type(REAL_RESULT) + :Item_func(a,b), hybrid_type(REAL_RESULT) + {} + Item_func_numhybrid(List<Item> &list) + :Item_func(list), hybrid_type(REAL_RESULT) {} enum Item_result result_type () const { return hybrid_type; } @@ -208,6 +211,7 @@ public: virtual longlong int_op()= 0; virtual double real_op()= 0; virtual my_decimal *decimal_op(my_decimal *)= 0; + virtual String *str_op(String *)= 0; bool is_null() { (void) val_real(); return null_value; } }; @@ -220,6 +224,7 @@ public: void fix_num_length_and_dec(); void find_num_type(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } }; @@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid virtual void result_precision()= 0; void print(String *str) { print_op(str); } void find_num_type(); + String *str_op(String *str) { DBUG_ASSERT(0); return 0; } }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b7aefdd6f2e..4f1e5b9a290 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -362,7 +362,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) because we do not rollback this changes TODO: make rollback for it, or special name resolving mode in 5.0. */ - !arena->is_stmt_prepare() + !arena->is_stmt_prepare_or_first_sp_execute() ) { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 0f2c9a2907d..76b0fa6afcf 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -499,7 +499,6 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, timestamp_type type, String *str) { char intbuff[15]; - uint days_i; uint hours_i; uint weekday; ulong length; @@ -602,8 +601,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, break; case 'h': case 'I': - days_i= l_time->hour/24; - hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + hours_i= (l_time->hour%24 + 11)%12+1; length= int10_to_str(hours_i, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 2, '0'); break; @@ -624,8 +622,7 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time, str->append_with_prefill(intbuff, length, 1, '0'); break; case 'l': - days_i= l_time->hour/24; - hours_i= (l_time->hour%24 + 11)%12+1 + 24*days_i; + hours_i= (l_time->hour%24 + 11)%12+1; length= int10_to_str(hours_i, intbuff, 10) - intbuff; str->append_with_prefill(intbuff, length, 1, '0'); break; diff --git a/sql/set_var.cc b/sql/set_var.cc index 5f0db0bd2d5..0d743f99b73 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1715,7 +1715,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) Item_string *tmp; pthread_mutex_lock(&LOCK_global_system_variables); char *str= (char*) value_ptr(thd, var_type, base); - tmp= new Item_string(str, strlen(str), system_charset_info); + tmp= new Item_string(str, strlen(str), + system_charset_info, DERIVATION_SYSCONST); pthread_mutex_unlock(&LOCK_global_system_variables); return tmp; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a07927547c6..f68a06a80e5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3224,7 +3224,8 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, if (!(*leaves)) make_leaves_list(leaves, tables); - for (TABLE_LIST *table_list= *leaves; + TABLE_LIST *table_list; + for (table_list= *leaves; table_list; table_list= table_list->next_leaf, tablenr++) { @@ -3263,7 +3264,7 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds, my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES); DBUG_RETURN(1); } - for (TABLE_LIST *table_list= tables; + for (table_list= tables; table_list; table_list= table_list->next_local) { diff --git a/sql/sql_bitmap.h b/sql/sql_bitmap.h index bd137e15b90..5e5bb1d8d3b 100644 --- a/sql/sql_bitmap.h +++ b/sql/sql_bitmap.h @@ -28,7 +28,7 @@ template <uint default_width> class Bitmap uint32 buffer[(default_width+31)/32]; public: Bitmap() { init(); } - Bitmap(Bitmap& from) { *this=from; } + Bitmap(const Bitmap& from) { *this=from; } explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); } void init() { bitmap_init(&map, buffer, default_width, 0); } void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); } @@ -61,19 +61,17 @@ public: my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); } char *print(char *buf) const { - char *s=buf; int i; - uchar *uchar_buffer= (uchar*)&buffer; - for (i=sizeof(buffer)-1; i>=0 ; i--) + char *s=buf; + const uchar *e=buffer, *b=e+sizeof(buffer)-1; + while (!*b && b>e) + b--; + if ((*s=_dig_vec_upper[*b >> 4]) != '0') + s++; + *s++=_dig_vec_upper[*b & 15]; + while (--b>=e) { - if ((*s=_dig_vec_upper[uchar_buffer[i] >> 4]) != '0') - break; - if ((*s=_dig_vec_upper[uchar_buffer[i] & 15]) != '0') - break; - } - for (s++, i-- ; i>=0 ; i--) - { - *s++=_dig_vec_upper[uchar_buffer[i] >> 4]; - *s++=_dig_vec_upper[uchar_buffer[i] & 15]; + *s++=_dig_vec_upper[*b >> 4]; + *s++=_dig_vec_upper[*b & 15]; } *s=0; return buf; diff --git a/sql/sql_class.h b/sql/sql_class.h index 1a014e2151b..8f8ba9e2d8e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -696,7 +696,8 @@ public: virtual Type type() const; virtual ~Item_arena() {}; - inline bool is_stmt_prepare() const { return (int)state < (int)PREPARED; } + inline bool is_stmt_prepare_or_first_sp_execute() const + { return (int)state < (int)PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_stmt_execute() const { return state == PREPARED || state == EXECUTED; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3947ed2ba27..c374890c717 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5898,7 +5898,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->db= empty_c_string; ptr->db_length= 0; } - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) ptr->db= thd->strdup(ptr->db); ptr->alias= alias_str; @@ -6976,7 +6976,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, against the opened tables to ensure we don't use a table that is part of the view (which can only be done after the table has been opened). */ - if (thd->current_arena->is_stmt_prepare()) + if (thd->current_arena->is_stmt_prepare_or_first_sp_execute()) { /* For temporary tables we don't have to check if the created table exists diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 403d20f3ddb..5e8b6cb49e9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5217,7 +5217,10 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) tmp= new Item_func_trig_cond(tmp, &tab->found); } if (tmp) + { tmp->quick_fix_field(); + tmp->update_used_tables(); + } return tmp; } @@ -5445,11 +5448,13 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0))) DBUG_RETURN(1); tab->select_cond=sel->cond=tmp; + /* Push condition to storage engine if this is enabled + and the condition is not guarded */ + tab->table->file->pushed_cond= NULL; if (thd->variables.engine_condition_pushdown) { COND *push_cond= - make_cond_for_table(cond,current_map,current_map); - tab->table->file->pushed_cond= NULL; + make_cond_for_table(tmp, current_map, current_map); if (push_cond) { /* Push condition to handler */ @@ -5790,6 +5795,7 @@ make_join_readinfo(JOIN *join, uint options) if (!table->no_keyread) { if (tab->select && tab->select->quick && + tab->select->quick->index != MAX_KEY && //not index_merge table->used_keys.is_set(tab->select->quick->index)) { table->key_read=1; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 8d36889df76..56401ced67c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -323,7 +323,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } if (tmp_arena) thd->restore_backup_item_arena(tmp_arena, &backup); - if (arena->is_stmt_prepare()) + if (arena->is_stmt_prepare_or_first_sp_execute()) { /* prepare fake select to initialize it correctly */ init_prepare_fake_select_lex(thd); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a6e77edaa84..2a7237c7fc2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4346,11 +4346,11 @@ simple_expr: { if ($3->is_splocal()) { - LEX_STRING name; + LEX_STRING *name; Item_splocal *il= static_cast<Item_splocal *>($3); - il->my_name(&name.str, &name.length); - my_error(ER_WRONG_COLUMN_NAME, MYF(0), name.str); + name= il->my_name(NULL); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str); YYABORT; } $$= new Item_default_value($3); |