mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge mysql.com:/opt/local/work/mysql-4.1-root
into mysql.com:/media/sda1/mysql/mysql-5.0-merge
This commit is contained in:
commit
8e72214d74
10 changed files with 150 additions and 48 deletions
|
@ -775,3 +775,28 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
|
|||
select ? from t1;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t1' at line 1
|
||||
drop table t1;
|
||||
prepare stmt from "select @@time_zone";
|
||||
execute stmt;
|
||||
@@time_zone
|
||||
SYSTEM
|
||||
set @@time_zone:='Japan';
|
||||
execute stmt;
|
||||
@@time_zone
|
||||
Japan
|
||||
prepare stmt from "select @@tx_isolation";
|
||||
execute stmt;
|
||||
@@tx_isolation
|
||||
REPEATABLE-READ
|
||||
set transaction isolation level read committed;
|
||||
execute stmt;
|
||||
@@tx_isolation
|
||||
READ-COMMITTED
|
||||
set transaction isolation level serializable;
|
||||
execute stmt;
|
||||
@@tx_isolation
|
||||
SERIALIZABLE
|
||||
set @@tx_isolation=default;
|
||||
execute stmt;
|
||||
@@tx_isolation
|
||||
REPEATABLE-READ
|
||||
deallocate prepare stmt;
|
||||
|
|
|
@ -2746,3 +2746,14 @@ WHERE
|
|||
COUNT(*)
|
||||
4
|
||||
drop table t1,t2,t3;
|
||||
create table t1 (f1 int);
|
||||
insert into t1 values (1),(NULL);
|
||||
create table t2 (f2 int, f3 int, f4 int);
|
||||
create index idx1 on t2 (f4);
|
||||
insert into t2 values (1,2,3),(2,4,6);
|
||||
select A.f2 from t1 left join t2 A on A.f2 = f1 where A.f3=(select min(f3)
|
||||
from t2 C where A.f4 = C.f4) or A.f3 IS NULL;
|
||||
f2
|
||||
1
|
||||
NULL
|
||||
drop table t1,t2;
|
||||
|
|
|
@ -811,3 +811,20 @@ select ??;
|
|||
select ? from t1;
|
||||
--enable_ps_protocol
|
||||
drop table t1;
|
||||
#
|
||||
# Bug#9359 "Prepared statements take snapshot of system vars at PREPARE
|
||||
# time"
|
||||
#
|
||||
prepare stmt from "select @@time_zone";
|
||||
execute stmt;
|
||||
set @@time_zone:='Japan';
|
||||
execute stmt;
|
||||
prepare stmt from "select @@tx_isolation";
|
||||
execute stmt;
|
||||
set transaction isolation level read committed;
|
||||
execute stmt;
|
||||
set transaction isolation level serializable;
|
||||
execute stmt;
|
||||
set @@tx_isolation=default;
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
|
|
|
@ -2330,3 +2330,14 @@ WHERE
|
|||
|
||||
drop table t1,t2,t3;
|
||||
|
||||
#
|
||||
# Bug #11482 4.1.12 produces different resultset for a complex query
|
||||
# than in previous 4.1.x
|
||||
create table t1 (f1 int);
|
||||
insert into t1 values (1),(NULL);
|
||||
create table t2 (f2 int, f3 int, f4 int);
|
||||
create index idx1 on t2 (f4);
|
||||
insert into t2 values (1,2,3),(2,4,6);
|
||||
select A.f2 from t1 left join t2 A on A.f2 = f1 where A.f3=(select min(f3)
|
||||
from t2 C where A.f4 = C.f4) or A.f3 IS NULL;
|
||||
drop table t1,t2;
|
||||
|
|
|
@ -4217,6 +4217,36 @@ void Item_user_var_as_out_param::print(String *str)
|
|||
}
|
||||
|
||||
|
||||
Item_func_get_system_var::
|
||||
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
|
||||
LEX_STRING *component_arg, const char *name_arg,
|
||||
size_t name_len_arg)
|
||||
:var(var_arg), var_type(var_type_arg), component(*component_arg)
|
||||
{
|
||||
/* set_name() will allocate the name */
|
||||
set_name(name_arg, name_len_arg, system_charset_info);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_func_get_system_var::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
Item *item= var->item(thd, var_type, &component);
|
||||
DBUG_ENTER("Item_func_get_system_var::fix_fields");
|
||||
/*
|
||||
Evaluate the system variable and substitute the result (a basic constant)
|
||||
instead of this item. If the variable can not be evaluated,
|
||||
the error is reported in sys_var::item().
|
||||
*/
|
||||
if (item == 0)
|
||||
DBUG_RETURN(1); // Impossible
|
||||
item->set_name(name, 0, system_charset_info); // don't allocate a new name
|
||||
thd->change_item_tree(ref, item);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_inet_aton::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
@ -4563,22 +4593,21 @@ longlong Item_func_bit_xor::val_int()
|
|||
0 error
|
||||
# constant item
|
||||
*/
|
||||
|
||||
|
||||
|
||||
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
||||
LEX_STRING component)
|
||||
{
|
||||
sys_var *var;
|
||||
char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
|
||||
LEX_STRING *base_name, *component_name;
|
||||
|
||||
if (component.str == 0 &&
|
||||
!my_strcasecmp(system_charset_info, name.str, "VERSION"))
|
||||
return new Item_string("@@VERSION", server_version,
|
||||
(uint) strlen(server_version),
|
||||
system_charset_info, DERIVATION_SYSCONST);
|
||||
|
||||
Item *item;
|
||||
sys_var *var;
|
||||
char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
|
||||
LEX_STRING *base_name, *component_name;
|
||||
|
||||
if (component.str)
|
||||
{
|
||||
base_name= &component;
|
||||
|
@ -4600,9 +4629,8 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
if (!(item=var->item(thd, var_type, component_name)))
|
||||
return 0; // Impossible
|
||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
|
||||
buff[0]='@';
|
||||
buff[1]='@';
|
||||
pos=buff+2;
|
||||
|
@ -4623,28 +4651,8 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
|||
memcpy(pos, base_name->str, base_name->length);
|
||||
pos+= base_name->length;
|
||||
|
||||
// set_name() will allocate the name
|
||||
item->set_name(buff,(uint) (pos-buff), system_charset_info);
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
|
||||
uint length, const char *item_name)
|
||||
{
|
||||
Item *item;
|
||||
sys_var *var;
|
||||
LEX_STRING null_lex_string;
|
||||
|
||||
null_lex_string.str= 0;
|
||||
|
||||
var= find_sys_var(var_name, length);
|
||||
DBUG_ASSERT(var != 0);
|
||||
if (!(item=var->item(thd, var_type, &null_lex_string)))
|
||||
return 0; // Impossible
|
||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
item->set_name(item_name, 0, system_charset_info); // Will use original name
|
||||
return item;
|
||||
return new Item_func_get_system_var(var, var_type, component_name,
|
||||
buff, pos - buff);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1199,6 +1199,29 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/* A system variable */
|
||||
|
||||
class Item_func_get_system_var :public Item_func
|
||||
{
|
||||
sys_var *var;
|
||||
enum_var_type var_type;
|
||||
LEX_STRING component;
|
||||
public:
|
||||
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
|
||||
LEX_STRING *component_arg, const char *name_arg,
|
||||
size_t name_len_arg);
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
/*
|
||||
Stubs for pure virtual methods. Should never be called: this
|
||||
item is always substituted with a constant in fix_fields().
|
||||
*/
|
||||
double val() { DBUG_ASSERT(0); return 0.0; }
|
||||
longlong val_int() { DBUG_ASSERT(0); return 0; }
|
||||
String* val_str(String*) { DBUG_ASSERT(0); return 0; }
|
||||
void fix_length_and_dec() { DBUG_ASSERT(0); }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_inet_aton : public Item_int_func
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -475,6 +475,11 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
|
|||
#include "protocol.h"
|
||||
#include "sql_udf.h"
|
||||
class user_var_entry;
|
||||
enum enum_var_type
|
||||
{
|
||||
OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL
|
||||
};
|
||||
class sys_var;
|
||||
#include "item.h"
|
||||
extern my_decimal decimal_zero;
|
||||
typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
|
||||
|
@ -1329,12 +1334,9 @@ extern bool sql_cache_init();
|
|||
extern void sql_cache_free();
|
||||
extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
|
||||
|
||||
/* item.cc */
|
||||
/* item_func.cc */
|
||||
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
||||
LEX_STRING component);
|
||||
Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
|
||||
uint length, const char *item_name);
|
||||
/* item_func.cc */
|
||||
int get_var_with_binlog(THD *thd, LEX_STRING &name,
|
||||
user_var_entry **out_entry);
|
||||
/* log.cc */
|
||||
|
|
|
@ -1652,15 +1652,7 @@ err:
|
|||
|
||||
/*
|
||||
Return an Item for a variable. Used with @@[global.]variable_name
|
||||
|
||||
If type is not given, return local value if exists, else global
|
||||
|
||||
We have to use netprintf() instead of my_error() here as this is
|
||||
called on the parsing stage.
|
||||
|
||||
TODO:
|
||||
With prepared statements/stored procedures this has to be fixed
|
||||
to create an item that gets the current value at fix_fields() stage.
|
||||
*/
|
||||
|
||||
Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
|
||||
|
|
|
@ -30,11 +30,6 @@ class set_var;
|
|||
typedef struct system_variables SV;
|
||||
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib;
|
||||
|
||||
enum enum_var_type
|
||||
{
|
||||
OPT_DEFAULT= 0, OPT_SESSION, OPT_GLOBAL
|
||||
};
|
||||
|
||||
typedef int (*sys_check_func)(THD *, set_var *);
|
||||
typedef bool (*sys_update_func)(THD *, set_var *);
|
||||
typedef void (*sys_after_update_func)(THD *,enum_var_type);
|
||||
|
|
|
@ -5138,7 +5138,23 @@ inline void add_cond_and_fix(Item **e1, Item *e2)
|
|||
(where othertbl is a non-const table and othertbl.field may be NULL)
|
||||
and add them to conditions on correspoding tables (othertbl in this
|
||||
example).
|
||||
|
||||
|
||||
Exception from that is the case when referred_tab->join != join.
|
||||
I.e. don't add NOT NULL constraints from any embedded subquery.
|
||||
Consider this query:
|
||||
SELECT A.f2 FROM t1 LEFT JOIN t2 A ON A.f2 = f1
|
||||
WHERE A.f3=(SELECT MIN(f3) FROM t2 C WHERE A.f4 = C.f4) OR A.f3 IS NULL;
|
||||
Here condition A.f3 IS NOT NULL is going to be added to the WHERE
|
||||
condition of the embedding query.
|
||||
Another example:
|
||||
SELECT * FROM t10, t11 WHERE (t10.a < 10 OR t10.a IS NULL)
|
||||
AND t11.b <=> t10.b AND (t11.a = (SELECT MAX(a) FROM t12
|
||||
WHERE t12.b = t10.a ));
|
||||
Here condition t10.a IS NOT NULL is going to be added.
|
||||
In both cases addition of NOT NULL condition will erroneously reject
|
||||
some rows of the result set.
|
||||
referred_tab->join != join constraint would disallow such additions.
|
||||
|
||||
This optimization doesn't affect the choices that ref, range, or join
|
||||
optimizer make. This was intentional because this was added after 4.1
|
||||
was GA.
|
||||
|
@ -5169,6 +5185,8 @@ static void add_not_null_conds(JOIN *join)
|
|||
DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
|
||||
Item_field *not_null_item= (Item_field*)item;
|
||||
JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab;
|
||||
if (referred_tab->join != join)
|
||||
continue;
|
||||
Item *notnull;
|
||||
if (!(notnull= new Item_func_isnotnull(not_null_item)))
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
Loading…
Reference in a new issue