summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <dlenev@mysql.com>2003-11-23 00:48:59 +0300
committerunknown <dlenev@mysql.com>2003-11-23 00:48:59 +0300
commitc1dd9540a4e397668040ab4027500138c238081b (patch)
tree8789c0bab356766145012382440d8b916135777c
parentd0d8ba7815fc75164d79a9758a01e7efbe1b8022 (diff)
parent00ddd4e56a90f04f7c2b515ff26b7ab0af08d599 (diff)
downloadmariadb-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.cc7
-rw-r--r--sql/item.h19
-rw-r--r--sql/item_func.cc13
-rw-r--r--tests/client_test.c112
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);