summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <tomas@poseidon.ndb.mysql.com>2005-06-04 19:26:35 +0200
committerunknown <tomas@poseidon.ndb.mysql.com>2005-06-04 19:26:35 +0200
commit84f89641cfc6acff016b973c3bfa12ef0a31fe12 (patch)
tree5a32b384f0388487fb7fee12035b2f2e36fb75d9 /sql
parent7b3cd08e9bb71e57102a5aa5ab2237980bf92b02 (diff)
parentdab1b26b1d3ec57e11681459282de2fe81e362f3 (diff)
downloadmariadb-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.cc15
-rw-r--r--sql/ha_innodb.cc22
-rw-r--r--sql/ha_ndbcluster.cc1229
-rw-r--r--sql/ha_ndbcluster.h36
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_cmpfunc.cc33
-rw-r--r--sql/item_cmpfunc.h30
-rw-r--r--sql/item_func.cc47
-rw-r--r--sql/item_func.h10
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_timefunc.cc7
-rw-r--r--sql/set_var.cc3
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_bitmap.h24
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_yacc.yy6
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);