Commit c1dd9540 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into mysql.com:/home/dlenev/src/mysql-4.1-bg1500-2


sql/item.cc:
  Auto merged
sql/item.h:
  Auto merged
sql/item_func.cc:
  Auto merged
parents d0d8ba78 00ddd4e5
......@@ -512,7 +512,7 @@ String *Item_null::val_str(String *str)
void Item_param::set_null()
{
DBUG_ENTER("Item_param::set_null");
maybe_null= null_value= 1;
maybe_null= null_value= value_is_set= 1;
DBUG_VOID_RETURN;
}
......@@ -521,6 +521,7 @@ void Item_param::set_int(longlong i)
DBUG_ENTER("Item_param::set_int");
int_value= (longlong)i;
item_type= INT_ITEM;
value_is_set= 1;
DBUG_PRINT("info", ("integer: %lld", int_value));
DBUG_VOID_RETURN;
}
......@@ -530,6 +531,7 @@ void Item_param::set_double(double value)
DBUG_ENTER("Item_param::set_double");
real_value=value;
item_type= REAL_ITEM;
value_is_set= 1;
DBUG_PRINT("info", ("double: %lg", real_value));
DBUG_VOID_RETURN;
}
......@@ -540,6 +542,7 @@ void Item_param::set_value(const char *str, uint length)
DBUG_ENTER("Item_param::set_value");
str_value.copy(str,length,default_charset());
item_type= STRING_ITEM;
value_is_set= 1;
DBUG_PRINT("info", ("string: %s", str_value.ptr()));
DBUG_VOID_RETURN;
}
......@@ -561,6 +564,7 @@ void Item_param::set_time(TIME *tm, timestamp_type type)
item_is_time= true;
item_type= STRING_ITEM;
value_is_set= 1;
}
......@@ -568,6 +572,7 @@ void Item_param::set_longdata(const char *str, ulong length)
{
str_value.append(str,length);
long_data_supplied= 1;
value_is_set= 1;
}
......
......@@ -173,7 +173,17 @@ class Item {
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
/*
Returns true if this is constant (during query execution, i.e. its value
will not change until next fix_fields) and its value is known.
*/
virtual bool const_item() const { return used_tables() == 0; }
/*
Returns true if this is constant but its value may be not known yet.
(Can be used for parameters of prep. stmts or of stored procedures.)
*/
virtual bool const_during_execution() const
{ return (used_tables() & ~PARAM_TABLE_BIT) == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); }
void print_item_w_name(String *);
virtual void update_used_tables() {}
......@@ -318,6 +328,7 @@ class Item_null :public Item
class Item_param :public Item
{
public:
bool value_is_set;
longlong int_value;
double real_value;
TIME ltime;
......@@ -336,6 +347,7 @@ class Item_param :public Item
item_result_type = STRING_RESULT;
item_is_time= false;
long_data_supplied= false;
value_is_set= 0;
}
enum Type type() const { return item_type; }
double val();
......@@ -363,6 +375,13 @@ class Item_param :public Item
String *query_val_str(String *str);
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
Item *new_item() { return new Item_param(pos_in_query); }
/*
If value for parameter was not set we treat it as non-const
so noone will use parameters value in fix_fields still
parameter is constant during execution.
*/
virtual table_map used_tables() const
{ return value_is_set ? (table_map)0 : PARAM_TABLE_BIT; }
void print(String *str) { str->append('?'); }
};
......
......@@ -2711,7 +2711,8 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
modifications to find_best and auto_close as complement to auto_init code
above.
*/
if (Item_func::fix_fields(thd, tlist, ref) || !args[0]->const_item())
if (Item_func::fix_fields(thd, tlist, ref) ||
!args[0]->const_during_execution())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
return 1;
......@@ -2725,11 +2726,15 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
args[i]= item= *((Item_ref *)item)->ref;
if (item->type() != Item::FIELD_ITEM)
key=NO_SUCH_KEY;
used_tables_cache|=item->used_tables();
}
/* check that all columns come from the same table */
if (my_count_bits(used_tables_cache) != 1)
/*
Check that all columns come from the same table.
We've already checked that columns in MATCH are fields so
PARAM_TABLE_BIT can only appear from AGAINST argument.
*/
if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
key=NO_SUCH_KEY;
if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
......
......@@ -7953,6 +7953,117 @@ static void test_ts()
}
}
/*
Test for bug #1500.
*/
static void test_bug1500()
{
MYSQL_STMT *stmt;
MYSQL_BIND bind[3];
int rc;
long int_data[3]= {2,3,4};
char *data;
myheader("test_bug1500");
rc= mysql_query(mysql,"DROP TABLE IF EXISTS test_bg1500");
myquery(rc);
rc= mysql_query(mysql,"CREATE TABLE test_bg1500 (i INT)");
myquery(rc);
rc= mysql_query(mysql,"INSERT INTO test_bg1500 VALUES (1),(2)");
myquery(rc);
rc= mysql_commit(mysql);
myquery(rc);
stmt= mysql_prepare(mysql,"SELECT i FROM test_bg1500 WHERE i IN (?,?,?)",44);
mystmt_init(stmt);
verify_param_count(stmt,3);
bind[0].buffer= (char *)int_data;
bind[0].buffer_type= FIELD_TYPE_LONG;
bind[0].is_null= 0;
bind[2]= bind[1]= bind[0];
bind[1].buffer= (char *)(int_data + 1);
bind[2].buffer= (char *)(int_data + 2);
rc= mysql_bind_param(stmt, bind);
mystmt(stmt,rc);
rc= mysql_execute(stmt);
mystmt(stmt,rc);
assert(1 == my_process_stmt_result(stmt));
/* FIXME If we comment out next string server will crash :( */
mysql_stmt_close(stmt);
rc= mysql_query(mysql,"DROP TABLE test_bg1500");
myquery(rc);
rc= mysql_query(mysql,"CREATE TABLE test_bg1500 (s VARCHAR(25), FULLTEXT(s))");
myquery(rc);
rc= mysql_query(mysql,
"INSERT INTO test_bg1500 VALUES ('Gravedigger'), ('Greed'),('Hollow Dogs')");
myquery(rc);
rc= mysql_commit(mysql);
myquery(rc);
stmt= mysql_prepare(mysql,
"SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)",53);
mystmt_init(stmt);
verify_param_count(stmt,1);
data= "Dogs";
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= data;
bind[0].buffer_length= strlen(data);
bind[0].is_null= 0;
bind[0].length= 0;
rc= mysql_bind_param(stmt, bind);
mystmt(stmt,rc);
rc= mysql_execute(stmt);
mystmt(stmt,rc);
assert(1 == my_process_stmt_result(stmt));
/*
FIXME If we comment out next string server will crash too :(
This is another manifestation of bug #1663
*/
mysql_stmt_close(stmt);
/* This should work too */
stmt= mysql_prepare(mysql,
"SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?,'digger'))", 70);
mystmt_init(stmt);
verify_param_count(stmt,1);
data= "Grave";
bind[0].buffer_type= MYSQL_TYPE_STRING;
bind[0].buffer= data;
bind[0].buffer_length= strlen(data);
bind[0].is_null= 0;
bind[0].length= 0;
rc= mysql_bind_param(stmt, bind);
mystmt(stmt,rc);
rc= mysql_execute(stmt);
mystmt(stmt,rc);
assert(1 == my_process_stmt_result(stmt));
mysql_stmt_close(stmt);
}
/*
Read and parse arguments and MySQL options from my.cnf
......@@ -8194,6 +8305,7 @@ int main(int argc, char **argv)
test_ts(); /* test for timestamp BR#819 */
test_bug1115(); /* BUG#1115 */
test_bug1180(); /* BUG#1180 */
test_bug1500(); /* BUG#1500 */
test_bug1644(); /* BUG#1644 */
end_time= time((time_t *)0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment