diff options
author | unknown <dlenev@mysql.com> | 2003-11-23 00:48:59 +0300 |
---|---|---|
committer | unknown <dlenev@mysql.com> | 2003-11-23 00:48:59 +0300 |
commit | c1dd9540a4e397668040ab4027500138c238081b (patch) | |
tree | 8789c0bab356766145012382440d8b916135777c | |
parent | d0d8ba7815fc75164d79a9758a01e7efbe1b8022 (diff) | |
parent | 00ddd4e56a90f04f7c2b515ff26b7ab0af08d599 (diff) | |
download | mariadb-git-c1dd9540a4e397668040ab4027500138c238081b.tar.gz |
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
-rw-r--r-- | sql/item.cc | 7 | ||||
-rw-r--r-- | sql/item.h | 19 | ||||
-rw-r--r-- | sql/item_func.cc | 13 | ||||
-rw-r--r-- | tests/client_test.c | 112 |
4 files changed, 146 insertions, 5 deletions
diff --git a/sql/item.cc b/sql/item.cc index 9684fd3e518..1d43351688b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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; } diff --git a/sql/item.h b/sql/item.h index 907b9ea5ad4..53db177b360 100644 --- a/sql/item.h +++ b/sql/item.h @@ -173,7 +173,17 @@ public: 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 @@ public: class Item_param :public Item { public: + bool value_is_set; longlong int_value; double real_value; TIME ltime; @@ -336,6 +347,7 @@ public: 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 @@ public: 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('?'); } }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 2a07341d97a..4e845a654f1 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -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"); diff --git a/tests/client_test.c b/tests/client_test.c index 517cac39d1b..637f6c4ede1 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -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); |