Commit 83af1d42 authored by unknown's avatar unknown

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

into mysql.com:/opt/local/work/mysql-5.0-7306-final

parents 1531ab87 edb38786
...@@ -174,11 +174,8 @@ where a=2 ...@@ -174,11 +174,8 @@ where a=2
limit 1'; limit 1';
execute stmt1 ; execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
# currently (May 2004, Version 4.1) it is impossible prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
-- error 1064 execute stmt1 using @arg00;
prepare stmt1 from 'update t1 set b=''bla''
where a=2
limit ?';
--disable_query_log --disable_query_log
select '------ insert tests ------' as test_sequence ; select '------ insert tests ------' as test_sequence ;
......
...@@ -300,10 +300,8 @@ set @arg00=1; ...@@ -300,10 +300,8 @@ set @arg00=1;
prepare stmt1 from ' select a,b from t1 order by a prepare stmt1 from ' select a,b from t1 order by a
limit 1 '; limit 1 ';
execute stmt1 ; execute stmt1 ;
# currently (May 2004, Version 4.1) it is impossible prepare stmt1 from ' select a,b from t1 limit ? ';
-- error 1064 execute stmt1 using @arg00;
prepare stmt1 from ' select a,b from t1
limit ? ';
##### parameter used in many places ##### parameter used in many places
set @arg00='b' ; set @arg00='b' ;
......
...@@ -634,3 +634,44 @@ id ...@@ -634,3 +634,44 @@ id
3 3
deallocate prepare stmt; deallocate prepare stmt;
drop table t1, t2; drop table t1, t2;
create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
prepare stmt from "select * from t1 limit ?, ?";
set @offset=0, @limit=1;
execute stmt using @offset, @limit;
a
1
select * from t1 limit 0, 1;
a
1
set @offset=3, @limit=2;
execute stmt using @offset, @limit;
a
4
5
select * from t1 limit 3, 2;
a
4
5
prepare stmt from "select * from t1 limit ?";
execute stmt using @limit;
a
1
2
prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
ERROR 42000: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
set @offset=9;
set @limit=2;
execute stmt using @offset, @limit;
a
10
1
prepare stmt from "(select * from t1 limit ?, ?) union all
(select * from t1 limit ?, ?) order by a limit ?";
execute stmt using @offset, @limit, @offset, @limit, @limit;
a
10
10
drop table t1;
deallocate prepare stmt;
...@@ -444,9 +444,10 @@ limit 1 '; ...@@ -444,9 +444,10 @@ limit 1 ';
execute stmt1 ; execute stmt1 ;
a b a b
1 one 1 one
prepare stmt1 from ' select a,b from t1 prepare stmt1 from ' select a,b from t1 limit ? ';
limit ? '; execute stmt1 using @arg00;
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 '?' at line 2 a b
1 one
set @arg00='b' ; set @arg00='b' ;
set @arg01=0 ; set @arg01=0 ;
set @arg02=2 ; set @arg02=2 ;
...@@ -1381,10 +1382,8 @@ execute stmt1 ; ...@@ -1381,10 +1382,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
......
...@@ -444,9 +444,10 @@ limit 1 '; ...@@ -444,9 +444,10 @@ limit 1 ';
execute stmt1 ; execute stmt1 ;
a b a b
1 one 1 one
prepare stmt1 from ' select a,b from t1 prepare stmt1 from ' select a,b from t1 limit ? ';
limit ? '; execute stmt1 using @arg00;
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 '?' at line 2 a b
1 one
set @arg00='b' ; set @arg00='b' ;
set @arg01=0 ; set @arg01=0 ;
set @arg02=2 ; set @arg02=2 ;
...@@ -1364,10 +1365,8 @@ execute stmt1 ; ...@@ -1364,10 +1365,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
......
...@@ -445,9 +445,10 @@ limit 1 '; ...@@ -445,9 +445,10 @@ limit 1 ';
execute stmt1 ; execute stmt1 ;
a b a b
1 one 1 one
prepare stmt1 from ' select a,b from t1 prepare stmt1 from ' select a,b from t1 limit ? ';
limit ? '; execute stmt1 using @arg00;
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 '?' at line 2 a b
1 one
set @arg00='b' ; set @arg00='b' ;
set @arg01=0 ; set @arg01=0 ;
set @arg02=2 ; set @arg02=2 ;
...@@ -1365,10 +1366,8 @@ execute stmt1 ; ...@@ -1365,10 +1366,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
......
...@@ -487,9 +487,10 @@ limit 1 '; ...@@ -487,9 +487,10 @@ limit 1 ';
execute stmt1 ; execute stmt1 ;
a b a b
1 one 1 one
prepare stmt1 from ' select a,b from t1 prepare stmt1 from ' select a,b from t1 limit ? ';
limit ? '; execute stmt1 using @arg00;
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 '?' at line 2 a b
1 one
set @arg00='b' ; set @arg00='b' ;
set @arg01=0 ; set @arg01=0 ;
set @arg02=2 ; set @arg02=2 ;
...@@ -1407,10 +1408,8 @@ execute stmt1 ; ...@@ -1407,10 +1408,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
...@@ -3500,9 +3499,10 @@ limit 1 '; ...@@ -3500,9 +3499,10 @@ limit 1 ';
execute stmt1 ; execute stmt1 ;
a b a b
1 one 1 one
prepare stmt1 from ' select a,b from t1 prepare stmt1 from ' select a,b from t1 limit ? ';
limit ? '; execute stmt1 using @arg00;
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 '?' at line 2 a b
1 one
set @arg00='b' ; set @arg00='b' ;
set @arg01=0 ; set @arg01=0 ;
set @arg02=2 ; set @arg02=2 ;
...@@ -4420,10 +4420,8 @@ execute stmt1 ; ...@@ -4420,10 +4420,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
......
...@@ -444,9 +444,10 @@ limit 1 '; ...@@ -444,9 +444,10 @@ limit 1 ';
execute stmt1 ; execute stmt1 ;
a b a b
1 one 1 one
prepare stmt1 from ' select a,b from t1 prepare stmt1 from ' select a,b from t1 limit ? ';
limit ? '; execute stmt1 using @arg00;
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 '?' at line 2 a b
1 one
set @arg00='b' ; set @arg00='b' ;
set @arg01=0 ; set @arg01=0 ;
set @arg02=2 ; set @arg02=2 ;
...@@ -1364,10 +1365,8 @@ execute stmt1 ; ...@@ -1364,10 +1365,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
......
use test; use test; drop table if exists t1, t9 ; create table t1
drop table if exists t1, t9 ;
create table t1
( (
a int, b varchar(30), a int, b varchar(30),
primary key(a) primary key(a)
...@@ -1364,10 +1362,8 @@ execute stmt1 ; ...@@ -1364,10 +1362,8 @@ execute stmt1 ;
select a,b from t1 where b = 'bla' ; select a,b from t1 where b = 'bla' ;
a b a b
2 bla 2 bla
prepare stmt1 from 'update t1 set b=''bla'' prepare stmt1 from 'update t1 set b=''bla'' where a=2 limit ?';
where a=2 execute stmt1 using @arg00;
limit ?';
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 '?' at line 3
test_sequence test_sequence
------ insert tests ------ ------ insert tests ------
delete from t1 ; delete from t1 ;
......
...@@ -664,3 +664,32 @@ select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id); ...@@ -664,3 +664,32 @@ select t2.id from t2, t1 where (t1.id=1 and t2.t1_id=t1.id);
deallocate prepare stmt; deallocate prepare stmt;
drop table t1, t2; drop table t1, t2;
#
# Bug#7306 LIMIT ?, ? and also WL#1785 " Prepared statements: implement
# support for placeholders in LIMIT clause."
# Add basic test coverage for the feature.
#
create table t1 (a int);
insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
prepare stmt from "select * from t1 limit ?, ?";
set @offset=0, @limit=1;
execute stmt using @offset, @limit;
select * from t1 limit 0, 1;
set @offset=3, @limit=2;
execute stmt using @offset, @limit;
select * from t1 limit 3, 2;
prepare stmt from "select * from t1 limit ?";
execute stmt using @limit;
--error 1235
prepare stmt from "select * from t1 where a in (select a from t1 limit ?)";
prepare stmt from "select * from t1 union all select * from t1 limit ?, ?";
set @offset=9;
set @limit=2;
execute stmt using @offset, @limit;
prepare stmt from "(select * from t1 limit ?, ?) union all
(select * from t1 limit ?, ?) order by a limit ?";
execute stmt using @offset, @limit, @offset, @limit, @limit;
drop table t1;
deallocate prepare stmt;
...@@ -336,6 +336,11 @@ public: ...@@ -336,6 +336,11 @@ public:
If value is not null null_value flag will be reset to FALSE. If value is not null null_value flag will be reset to FALSE.
*/ */
virtual longlong val_int()=0; virtual longlong val_int()=0;
/*
This is just a shortcut to avoid the cast. You should still use
unsigned_flag to check the sign of the item.
*/
inline ulonglong val_uint() { return (ulonglong) val_int(); }
/* /*
Return string representation of this item object. Return string representation of this item object.
...@@ -980,10 +985,10 @@ public: ...@@ -980,10 +985,10 @@ public:
longlong value; longlong value;
Item_int(int32 i,uint length=11) :value((longlong) i) Item_int(int32 i,uint length=11) :value((longlong) i)
{ max_length=length; fixed= 1; } { max_length=length; fixed= 1; }
#ifdef HAVE_LONG_LONG
Item_int(longlong i,uint length=21) :value(i) Item_int(longlong i,uint length=21) :value(i)
{ max_length=length; fixed= 1; } { max_length=length; fixed= 1; }
#endif Item_int(ulonglong i, uint length= 21) :value((longlong)i)
{ max_length=length; fixed= 1; unsigned_flag= 1; }
Item_int(const char *str_arg,longlong i,uint length) :value(i) Item_int(const char *str_arg,longlong i,uint length) :value(i)
{ max_length=length; name=(char*) str_arg; fixed= 1; } { max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(const char *str_arg, uint length=64); Item_int(const char *str_arg, uint length=64);
...@@ -1021,9 +1026,8 @@ class Item_uint :public Item_int ...@@ -1021,9 +1026,8 @@ class Item_uint :public Item_int
{ {
public: public:
Item_uint(const char *str_arg, uint length); Item_uint(const char *str_arg, uint length);
Item_uint(uint32 i) :Item_int((ulonglong) i, 10) {}
Item_uint(const char *str_arg, longlong i, uint length); Item_uint(const char *str_arg, longlong i, uint length);
Item_uint(uint32 i) :Item_int((longlong) i, 10)
{ unsigned_flag= 1; }
double val_real() double val_real()
{ DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); } { DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
String *val_str(String*); String *val_str(String*);
......
...@@ -600,8 +600,8 @@ void Item_exists_subselect::fix_length_and_dec() ...@@ -600,8 +600,8 @@ void Item_exists_subselect::fix_length_and_dec()
decimals= 0; decimals= 0;
max_length= 1; max_length= 1;
max_columns= engine->cols(); max_columns= engine->cols();
/* We need only 1 row to determinate existence */ /* We need only 1 row to determine existence */
unit->global_parameters->select_limit= 1; unit->global_parameters->select_limit= new Item_int(1);
} }
double Item_exists_subselect::val_real() double Item_exists_subselect::val_real()
......
...@@ -319,7 +319,7 @@ sp_head::sp_head() ...@@ -319,7 +319,7 @@ sp_head::sp_head()
*sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first); *sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first);
DBUG_ENTER("sp_head::sp_head"); DBUG_ENTER("sp_head::sp_head");
state= INITIALIZED; state= INITIALIZED_FOR_SP;
m_backpatch.empty(); m_backpatch.empty();
m_lex.empty(); m_lex.empty();
hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
...@@ -1077,7 +1077,7 @@ sp_head::restore_thd_mem_root(THD *thd) ...@@ -1077,7 +1077,7 @@ sp_head::restore_thd_mem_root(THD *thd)
DBUG_ENTER("sp_head::restore_thd_mem_root"); DBUG_ENTER("sp_head::restore_thd_mem_root");
Item *flist= free_list; // The old list Item *flist= free_list; // The old list
set_item_arena(thd); // Get new free_list and mem_root set_item_arena(thd); // Get new free_list and mem_root
state= INITIALIZED; state= INITIALIZED_FOR_SP;
DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx", DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
(ulong) &mem_root, (ulong) &thd->mem_root)); (ulong) &mem_root, (ulong) &thd->mem_root));
......
...@@ -661,8 +661,8 @@ public: ...@@ -661,8 +661,8 @@ public:
#endif #endif
enum enum_state enum enum_state
{ {
INITIALIZED= 0, PREPARED= 1, EXECUTED= 3, CONVENTIONAL_EXECUTION= 2, INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
ERROR= -1 CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
}; };
enum_state state; enum_state state;
...@@ -691,6 +691,7 @@ public: ...@@ -691,6 +691,7 @@ public:
virtual Type type() const; virtual Type type() const;
virtual ~Item_arena() {}; virtual ~Item_arena() {};
inline bool is_stmt_prepare() const { return state == INITIALIZED; }
inline bool is_stmt_prepare_or_first_sp_execute() const inline bool is_stmt_prepare_or_first_sp_execute() const
{ return (int)state < (int)PREPARED; } { return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; } inline bool is_first_stmt_execute() const { return state == PREPARED; }
......
...@@ -217,6 +217,8 @@ exit: ...@@ -217,6 +217,8 @@ exit:
queries defined. After temporary table is filled, if this is not EXPLAIN, queries defined. After temporary table is filled, if this is not EXPLAIN,
then the entire unit / node is deleted. unit is deleted if UNION is used then the entire unit / node is deleted. unit is deleted if UNION is used
for derived table and node is deleted is it is a simple SELECT. for derived table and node is deleted is it is a simple SELECT.
If you use this function, make sure it's not called at prepare.
Due to evaluation of LIMIT clause it can not be used at prepared stage.
RETURN RETURN
0 ok 0 ok
...@@ -245,11 +247,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) ...@@ -245,11 +247,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
} }
else else
{ {
unit->offset_limit_cnt= first_select->offset_limit; unit->set_limit(first_select);
unit->select_limit_cnt= first_select->select_limit+
first_select->offset_limit;
if (unit->select_limit_cnt < first_select->select_limit)
unit->select_limit_cnt= HA_POS_ERROR;
if (unit->select_limit_cnt == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
first_select->options&= ~OPTION_FOUND_ROWS; first_select->options&= ~OPTION_FOUND_ROWS;
......
...@@ -225,21 +225,21 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) ...@@ -225,21 +225,21 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
MYSQL_ERROR *err; MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex->select_lex; SELECT_LEX *sel= &thd->lex->select_lex;
ha_rows offset= sel->offset_limit, limit= sel->select_limit; SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows idx= 0;
Protocol *protocol=thd->protocol; Protocol *protocol=thd->protocol;
unit->set_limit(sel);
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++)) while ((err= it++))
{ {
/* Skip levels that the user is not interested in */ /* Skip levels that the user is not interested in */
if (!(levels_to_show & ((ulong) 1 << err->level))) if (!(levels_to_show & ((ulong) 1 << err->level)))
continue; continue;
if (offset) if (++idx <= unit->offset_limit_cnt)
{
offset--;
continue; continue;
} if (idx > unit->select_limit_cnt)
if (limit-- == 0)
break; break;
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(warning_level_names[err->level], protocol->store(warning_level_names[err->level],
......
...@@ -321,8 +321,8 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) ...@@ -321,8 +321,8 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
key_expr key_expr
ha_rkey_mode ha_rkey_mode
cond cond
select_limit select_limit_cnt
offset_limit offset_limit_cnt
RETURN RETURN
FALSE ok FALSE ok
...@@ -333,7 +333,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -333,7 +333,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode, char *keyname, enum enum_ha_read_modes mode, char *keyname,
List<Item> *key_expr, List<Item> *key_expr,
enum ha_rkey_function ha_rkey_mode, Item *cond, enum ha_rkey_function ha_rkey_mode, Item *cond,
ha_rows select_limit,ha_rows offset_limit) ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
{ {
TABLE_LIST *hash_tables; TABLE_LIST *hash_tables;
TABLE *table; TABLE *table;
...@@ -429,7 +429,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -429,7 +429,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0)) if (insert_fields(thd, tables, tables->db, tables->alias, &it, 0, 0))
goto err0; goto err0;
select_limit+=offset_limit;
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF); protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
HANDLER_TABLES_HACK(thd); HANDLER_TABLES_HACK(thd);
...@@ -447,7 +446,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -447,7 +446,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
table->file->init_table_handle_for_HANDLER(); table->file->init_table_handle_for_HANDLER();
for (num_rows=0; num_rows < select_limit; ) for (num_rows=0; num_rows < select_limit_cnt; )
{ {
switch (mode) { switch (mode) {
case RFIRST: case RFIRST:
...@@ -535,7 +534,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -535,7 +534,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
} }
if (cond && !cond->val_int()) if (cond && !cond->val_int())
continue; continue;
if (num_rows >= offset_limit) if (num_rows >= offset_limit_cnt)
{ {
Item *item; Item *item;
protocol->prepare_for_resend(); protocol->prepare_for_resend();
......
...@@ -1138,8 +1138,9 @@ void st_select_lex::init_select() ...@@ -1138,8 +1138,9 @@ void st_select_lex::init_select()
order_list.elements= 0; order_list.elements= 0;
order_list.first= 0; order_list.first= 0;
order_list.next= (byte**) &order_list.first; order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR; /* Set limit and offset to default values */
offset_limit= 0; select_limit= 0; /* denotes the default limit = HA_POS_ERROR */
offset_limit= 0; /* denotes the default offset = 0 */
with_sum_func= 0; with_sum_func= 0;
} }
...@@ -1363,7 +1364,7 @@ ulong st_select_lex_node::get_table_join_options() ...@@ -1363,7 +1364,7 @@ ulong st_select_lex_node::get_table_join_options()
*/ */
bool st_select_lex::test_limit() bool st_select_lex::test_limit()
{ {
if (select_limit != HA_POS_ERROR) if (select_limit != 0)
{ {
my_error(ER_NOT_SUPPORTED_YET, MYF(0), my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"LIMIT & IN/ALL/ANY/SOME subquery"); "LIMIT & IN/ALL/ANY/SOME subquery");
...@@ -1551,24 +1552,20 @@ void st_select_lex::print_limit(THD *thd, String *str) ...@@ -1551,24 +1552,20 @@ void st_select_lex::print_limit(THD *thd, String *str)
item->substype() == Item_subselect::IN_SUBS || item->substype() == Item_subselect::IN_SUBS ||
item->substype() == Item_subselect::ALL_SUBS)) item->substype() == Item_subselect::ALL_SUBS))
{ {
DBUG_ASSERT(!item->fixed || select_limit == 1L && offset_limit == 0L); DBUG_ASSERT(!item->fixed ||
select_limit->val_int() == LL(1) && offset_limit == 0);
return; return;
} }
if (explicit_limit) if (explicit_limit)
{ {
str->append(" limit ", 7); str->append(" limit ", 7);
char buff[20];
// latin1 is good enough for numbers
String st(buff, sizeof(buff), &my_charset_latin1);
st.set((ulonglong)select_limit, &my_charset_latin1);
str->append(st);
if (offset_limit) if (offset_limit)
{ {
offset_limit->print(str);
str->append(','); str->append(',');
st.set((ulonglong)select_limit, &my_charset_latin1);
str->append(st);
} }
select_limit->print(str);
} }
} }
...@@ -1619,7 +1616,7 @@ bool st_lex::can_be_merged() ...@@ -1619,7 +1616,7 @@ bool st_lex::can_be_merged()
select_lex.with_sum_func == 0 && select_lex.with_sum_func == 0 &&
select_lex.table_list.elements >= 1 && select_lex.table_list.elements >= 1 &&
!(select_lex.options & SELECT_DISTINCT) && !(select_lex.options & SELECT_DISTINCT) &&
select_lex.select_limit == HA_POS_ERROR); select_lex.select_limit == 0);
} }
...@@ -1756,11 +1753,15 @@ bool st_lex::need_correct_ident() ...@@ -1756,11 +1753,15 @@ bool st_lex::need_correct_ident()
values - SELECT_LEX with initial values for counters values - SELECT_LEX with initial values for counters
*/ */
void st_select_lex_unit::set_limit(SELECT_LEX *values) void st_select_lex_unit::set_limit(SELECT_LEX *sl)
{ {
offset_limit_cnt= values->offset_limit; ulonglong select_limit_val;
select_limit_cnt= values->select_limit+values->offset_limit;
if (select_limit_cnt < values->select_limit) select_limit_val= sl->select_limit ? sl->select_limit->val_uint() :
HA_POS_ERROR;
offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0);
select_limit_cnt= select_limit_val + offset_limit_cnt;
if (select_limit_cnt < select_limit_val)
select_limit_cnt= HA_POS_ERROR; // no limit select_limit_cnt= HA_POS_ERROR; // no limit
} }
......
...@@ -488,7 +488,7 @@ public: ...@@ -488,7 +488,7 @@ public:
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */ List<List_item> when_list; /* WHEN clause (expression) */
SQL_LIST *gorder_list; SQL_LIST *gorder_list;
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ Item *select_limit, *offset_limit; /* LIMIT clause parameters */
// Arrays of pointers to top elements of all_fields list // Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array; Item **ref_pointer_array;
......
...@@ -2351,7 +2351,8 @@ mysql_execute_command(THD *thd) ...@@ -2351,7 +2351,8 @@ mysql_execute_command(THD *thd)
{ {
SELECT_LEX *param= lex->unit.global_parameters; SELECT_LEX *param= lex->unit.global_parameters;
if (!param->explicit_limit) if (!param->explicit_limit)
param->select_limit= thd->variables.select_limit; param->select_limit=
new Item_int((ulonglong)thd->variables.select_limit);
} }
select_result *result=lex->result; select_result *result=lex->result;
...@@ -3141,13 +3142,15 @@ end_with_restore_list: ...@@ -3141,13 +3142,15 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (update_precheck(thd, all_tables)) if (update_precheck(thd, all_tables))
break; break;
DBUG_ASSERT(select_lex->offset_limit == 0);
unit->set_limit(select_lex);
res= (result= mysql_update(thd, all_tables, res= (result= mysql_update(thd, all_tables,
select_lex->item_list, select_lex->item_list,
lex->value_list, lex->value_list,
select_lex->where, select_lex->where,
select_lex->order_list.elements, select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
select_lex->select_limit, unit->select_limit_cnt,
lex->duplicates, lex->ignore)); lex->duplicates, lex->ignore));
/* mysql_update return 2 if we need to switch to multi-update */ /* mysql_update return 2 if we need to switch to multi-update */
if (result != 2) if (result != 2)
...@@ -3253,9 +3256,11 @@ end_with_restore_list: ...@@ -3253,9 +3256,11 @@ end_with_restore_list:
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= delete_precheck(thd, all_tables))) if ((res= delete_precheck(thd, all_tables)))
break; break;
DBUG_ASSERT(select_lex->offset_limit == 0);
unit->set_limit(select_lex);
res = mysql_delete(thd, all_tables, select_lex->where, res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list, &select_lex->order_list,
select_lex->select_limit, select_lex->options); unit->select_limit_cnt, select_lex->options);
break; break;
} }
case SQLCOM_DELETE_MULTI: case SQLCOM_DELETE_MULTI:
...@@ -3842,9 +3847,10 @@ end_with_restore_list: ...@@ -3842,9 +3847,10 @@ end_with_restore_list:
*/ */
if (check_db_used(thd, all_tables)) if (check_db_used(thd, all_tables))
goto error; goto error;
unit->set_limit(select_lex);
res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str, res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
lex->insert_list, lex->ha_rkey_mode, select_lex->where, lex->insert_list, lex->ha_rkey_mode, select_lex->where,
select_lex->select_limit, select_lex->offset_limit); unit->select_limit_cnt, unit->offset_limit_cnt);
break; break;
case SQLCOM_BEGIN: case SQLCOM_BEGIN:
...@@ -5126,7 +5132,6 @@ mysql_init_select(LEX *lex) ...@@ -5126,7 +5132,6 @@ mysql_init_select(LEX *lex)
{ {
SELECT_LEX *select_lex= lex->current_select; SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select(); select_lex->init_select();
select_lex->select_limit= HA_POS_ERROR;
lex->orig_sql_command= SQLCOM_END; lex->orig_sql_command= SQLCOM_END;
lex->wild= 0; lex->wild= 0;
if (select_lex == &lex->select_lex) if (select_lex == &lex->select_lex)
...@@ -5141,6 +5146,7 @@ bool ...@@ -5141,6 +5146,7 @@ bool
mysql_new_select(LEX *lex, bool move_down) mysql_new_select(LEX *lex, bool move_down)
{ {
SELECT_LEX *select_lex; SELECT_LEX *select_lex;
THD *thd;
DBUG_ENTER("mysql_new_select"); DBUG_ENTER("mysql_new_select");
if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX())) if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX()))
...@@ -5190,7 +5196,7 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -5190,7 +5196,7 @@ mysql_new_select(LEX *lex, bool move_down)
fake->select_number= INT_MAX; fake->select_number= INT_MAX;
fake->make_empty_select(); fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE; fake->linkage= GLOBAL_OPTIONS_TYPE;
fake->select_limit= HA_POS_ERROR; fake->select_limit= 0;
} }
} }
...@@ -5238,8 +5244,8 @@ void mysql_init_multi_delete(LEX *lex) ...@@ -5238,8 +5244,8 @@ void mysql_init_multi_delete(LEX *lex)
{ {
lex->sql_command= SQLCOM_DELETE_MULTI; lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex); mysql_init_select(lex);
lex->select_lex.select_limit= lex->unit.select_limit_cnt= lex->select_lex.select_limit= 0;
HA_POS_ERROR; lex->unit.select_limit_cnt= HA_POS_ERROR;
lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list); lex->select_lex.table_list.save_and_clear(&lex->auxilliary_table_list);
lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= using_update_log ? TL_READ_NO_INSERT : TL_READ;
lex->query_tables= 0; lex->query_tables= 0;
...@@ -6753,8 +6759,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) ...@@ -6753,8 +6759,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (select_lex->order_list.elements) if (select_lex->order_list.elements)
msg= "ORDER BY"; msg= "ORDER BY";
else if (select_lex->select_limit && select_lex->select_limit != else if (select_lex->select_limit)
HA_POS_ERROR)
msg= "LIMIT"; msg= "LIMIT";
if (msg) if (msg)
{ {
......
...@@ -1316,6 +1316,7 @@ bool mysql_show_binlog_events(THD* thd) ...@@ -1316,6 +1316,7 @@ bool mysql_show_binlog_events(THD* thd)
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
LEX_MASTER_INFO *lex_mi= &thd->lex->mi; LEX_MASTER_INFO *lex_mi= &thd->lex->mi;
SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows event_count, limit_start, limit_end; ha_rows event_count, limit_start, limit_end;
my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly
char search_file_name[FN_REFLEN], *name; char search_file_name[FN_REFLEN], *name;
...@@ -1324,8 +1325,9 @@ bool mysql_show_binlog_events(THD* thd) ...@@ -1324,8 +1325,9 @@ bool mysql_show_binlog_events(THD* thd)
LOG_INFO linfo; LOG_INFO linfo;
Log_event* ev; Log_event* ev;
limit_start= thd->lex->current_select->offset_limit; unit->set_limit(thd->lex->current_select);
limit_end= thd->lex->current_select->select_limit + limit_start; limit_start= unit->offset_limit_cnt;
limit_end= unit->select_limit_cnt;
name= search_file_name; name= search_file_name;
if (log_file_name) if (log_file_name)
......
...@@ -10077,7 +10077,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), ...@@ -10077,7 +10077,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{ {
join->do_send_rows= 0; join->do_send_rows= 0;
if (join->unit->fake_select_lex) if (join->unit->fake_select_lex)
join->unit->fake_select_lex->select_limit= HA_POS_ERROR; join->unit->fake_select_lex->select_limit= 0;
DBUG_RETURN(NESTED_LOOP_OK); DBUG_RETURN(NESTED_LOOP_OK);
} }
} }
......
...@@ -448,7 +448,7 @@ bool st_select_lex_unit::exec() ...@@ -448,7 +448,7 @@ bool st_select_lex_unit::exec()
table->no_keyread=1; table->no_keyread=1;
} }
res= sl->join->error; res= sl->join->error;
offset_limit_cnt= sl->offset_limit; offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : 0;
if (!res) if (!res)
{ {
examined_rows+= thd->examined_row_count; examined_rows+= thd->examined_row_count;
......
...@@ -1000,8 +1000,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) ...@@ -1000,8 +1000,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
we do not support updatable UNIONs in VIEW, so we can check just limit of we do not support updatable UNIONs in VIEW, so we can check just limit of
LEX::select_lex LEX::select_lex
*/ */
if ((!view->view && !view->belong_to_view) || thd->lex->sql_command == SQLCOM_INSERT || if ((!view->view && !view->belong_to_view) ||
thd->lex->select_lex.select_limit == HA_POS_ERROR) thd->lex->sql_command == SQLCOM_INSERT ||
thd->lex->select_lex.select_limit == 0)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */ DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table; table= view->table;
if (view->belong_to_view) if (view->belong_to_view)
......
...@@ -721,7 +721,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -721,7 +721,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
signed_literal now_or_signed_literal opt_escape signed_literal now_or_signed_literal opt_escape
sp_opt_default sp_opt_default
simple_ident_nospvar simple_ident_q simple_ident_nospvar simple_ident_q
field_or_var field_or_var limit_option
%type <item_num> %type <item_num>
NUM_literal NUM_literal
...@@ -5542,8 +5542,8 @@ opt_limit_clause_init: ...@@ -5542,8 +5542,8 @@ opt_limit_clause_init:
{ {
LEX *lex= Lex; LEX *lex= Lex;
SELECT_LEX *sel= lex->current_select; SELECT_LEX *sel= lex->current_select;
sel->offset_limit= 0L; sel->offset_limit= 0;
sel->select_limit= HA_POS_ERROR; sel->select_limit= 0;
} }
| limit_clause {} | limit_clause {}
; ;
...@@ -5558,21 +5558,21 @@ limit_clause: ...@@ -5558,21 +5558,21 @@ limit_clause:
; ;
limit_options: limit_options:
ulong_num limit_option
{ {
SELECT_LEX *sel= Select; SELECT_LEX *sel= Select;
sel->select_limit= $1; sel->select_limit= $1;
sel->offset_limit= 0L; sel->offset_limit= 0;
sel->explicit_limit= 1; sel->explicit_limit= 1;
} }
| ulong_num ',' ulong_num | limit_option ',' limit_option
{ {
SELECT_LEX *sel= Select; SELECT_LEX *sel= Select;
sel->select_limit= $3; sel->select_limit= $3;
sel->offset_limit= $1; sel->offset_limit= $1;
sel->explicit_limit= 1; sel->explicit_limit= 1;
} }
| ulong_num OFFSET_SYM ulong_num | limit_option OFFSET_SYM limit_option
{ {
SELECT_LEX *sel= Select; SELECT_LEX *sel= Select;
sel->select_limit= $1; sel->select_limit= $1;
...@@ -5580,18 +5580,23 @@ limit_options: ...@@ -5580,18 +5580,23 @@ limit_options:
sel->explicit_limit= 1; sel->explicit_limit= 1;
} }
; ;
limit_option:
param_marker
| ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); }
| LONG_NUM { $$= new Item_uint($1.str, $1.length); }
| NUM { $$= new Item_uint($1.str, $1.length); }
delete_limit_clause: delete_limit_clause:
/* empty */ /* empty */
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->current_select->select_limit= HA_POS_ERROR; lex->current_select->select_limit= 0;
} }
| LIMIT ulonglong_num | LIMIT limit_option
{ {
SELECT_LEX *sel= Select; SELECT_LEX *sel= Select;
sel->select_limit= (ha_rows) $2; sel->select_limit= $2;
sel->explicit_limit= 1; sel->explicit_limit= 1;
}; };
...@@ -7942,8 +7947,8 @@ handler: ...@@ -7942,8 +7947,8 @@ handler:
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_HA_READ; lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
lex->current_select->select_limit= 1; lex->current_select->select_limit= new Item_int(1);
lex->current_select->offset_limit= 0L; lex->current_select->offset_limit= 0;
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT; YYABORT;
} }
......
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