summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-06-07 14:11:36 +0400
committerunknown <konstantin@mysql.com>2005-06-07 14:11:36 +0400
commit5188f031ae9b8b7eca9092b82d454a567154737a (patch)
treed2686d80a3486e1912b96a6e6774bd3f77da0022 /sql
parenta9ccff554a9c6ae44a833e156e0010cba6e3362d (diff)
downloadmariadb-git-5188f031ae9b8b7eca9092b82d454a567154737a.tar.gz
Patch two (the final one) for Bug#7306 "the server side preparedStatement
error for LIMIT placeholder". The patch adds grammar support for LIMIT ?, ? and changes the type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*, so that it can point to Item_param. mysql-test/include/ps_modify.inc: Fix existing tests: now LIMIT can contain placeholders. mysql-test/include/ps_query.inc: Fix existing tests: now LIMIT can contain placeholders. mysql-test/r/ps.result: Add basic test coverage for LIMIT ?, ? and fix test results. mysql-test/r/ps_2myisam.result: Fix test results: now LIMIT can contain placeholders. mysql-test/r/ps_3innodb.result: Fix test results: now LIMIT can contain placeholders. mysql-test/r/ps_4heap.result: Fix test results: now LIMIT can contain placeholders. mysql-test/r/ps_5merge.result: Fix test results: now LIMIT can contain placeholders. mysql-test/r/ps_6bdb.result: Fix test results: now LIMIT can contain placeholders. mysql-test/r/ps_7ndb.result: Fix test results: now LIMIT can contain placeholders. mysql-test/t/ps.test: Add basic test coverage for LIMIT ?, ?. sql/item.h: Add a short-cut for (ulonglong) val_int() to Item. Add a constructor to Item_int() that accepts ulonglong. Simplify Item_uint constructor by using the c-tor above. sql/item_subselect.cc: Now select_limit has type Item *. We can safely create an Item in Item_exists_subselect::fix_length_and_dec(): it will be allocated in runtime memory root and freed in the end of execution. sql/sp_head.cc: Add a special initalization state for stored procedures to be able to easily distinguish the first execution of a stored procedure from prepared statement prepare. sql/sql_class.h: Introduce new state 'INITIALIZED_FOR_SP' to be able to easily distinguish the first execution of a stored procedure from prepared statement prepare. sql/sql_derived.cc: - use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt evreryplace. Add a warning about use of set_limit in mysql_derived_filling. sql/sql_error.cc: - use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt evreryplace. - this change is also aware of bug#11095 "show warnings limit 0 returns all rows instead of zero rows", so the one who merges the bugfix from 4.1 can use local version of sql_error.cc. sql/sql_handler.cc: - use unit->set_limit() to initalize unit->select_limit_cnt,offset_limit_cnt everyplace. sql/sql_lex.cc: Now ST_SELECT_LEX::select_limit, offset_limit have type Item * sql/sql_lex.h: Now ST_SELECT_LEX::select_limit, offset_limit have type Item * sql/sql_parse.cc: - use unit->set_limit() to initalize unit->select_limit_cnt,offset_limit_cnt everyplace. - we can create an Item_int to set global limit of a statement: it will be created in the runtime mem root and freed in the end of execution. sql/sql_repl.cc: Use unit->set_limit to initialize limits. sql/sql_select.cc: - select_limit is now Item* so the proper way to check for default value is to compare it with NULL. sql/sql_union.cc: Evaluate offset_limit_cnt using the new type of ST_SELECT_LEX::offset_limit sql/sql_view.cc: Now ST_SELECT_LEX::select_limit, offset_limit have type Item * sql/sql_yacc.yy: Add grammar support for LIMIT ?, ? clause.
Diffstat (limited to 'sql')
-rw-r--r--sql/item.h12
-rw-r--r--sql/item_subselect.cc4
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sql_class.h5
-rw-r--r--sql/sql_derived.cc8
-rw-r--r--sql/sql_error.cc16
-rw-r--r--sql/sql_handler.cc11
-rw-r--r--sql/sql_lex.cc33
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc25
-rw-r--r--sql/sql_repl.cc6
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_view.cc5
-rw-r--r--sql/sql_yacc.yy29
15 files changed, 90 insertions, 74 deletions
diff --git a/sql/item.h b/sql/item.h
index 4f5ed9934c5..4a7dd5b6390 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -335,6 +335,11 @@ public:
*/
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.
SYNOPSIS
@@ -978,10 +983,10 @@ public:
longlong value;
Item_int(int32 i,uint length=11) :value((longlong) i)
{ max_length=length; fixed= 1; }
-#ifdef HAVE_LONG_LONG
Item_int(longlong i,uint length=21) :value(i)
{ 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)
{ max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(const char *str_arg, uint length=64);
@@ -1019,9 +1024,8 @@ class Item_uint :public Item_int
{
public:
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(uint32 i) :Item_int((longlong) i, 10)
- { unsigned_flag= 1; }
double val_real()
{ DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
String *val_str(String*);
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4f1e5b9a290..7b83cbcd53a 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -602,8 +602,8 @@ void Item_exists_subselect::fix_length_and_dec()
decimals= 0;
max_length= 1;
max_columns= engine->cols();
- /* We need only 1 row to determinate existence */
- unit->global_parameters->select_limit= 1;
+ /* We need only 1 row to determine existence */
+ unit->global_parameters->select_limit= new Item_int(1);
}
double Item_exists_subselect::val_real()
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c17c8b81cb2..a72128a54da 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -320,7 +320,7 @@ sp_head::sp_head()
*sp_lex_sp_key(const byte *ptr, uint *plen, my_bool first);
DBUG_ENTER("sp_head::sp_head");
- state= INITIALIZED;
+ state= INITIALIZED_FOR_SP;
m_backpatch.empty();
m_lex.empty();
hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
@@ -1078,7 +1078,7 @@ sp_head::restore_thd_mem_root(THD *thd)
DBUG_ENTER("sp_head::restore_thd_mem_root");
Item *flist= free_list; // The old list
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",
(ulong) &mem_root, (ulong) &thd->mem_root));
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7c8ead7558e..a976407322f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -665,8 +665,8 @@ public:
#endif
enum enum_state
{
- INITIALIZED= 0, PREPARED= 1, EXECUTED= 3, CONVENTIONAL_EXECUTION= 2,
- ERROR= -1
+ INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
+ CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
};
enum_state state;
@@ -695,6 +695,7 @@ public:
virtual Type type() const;
virtual ~Item_arena() {};
+ inline bool is_stmt_prepare() const { return state == INITIALIZED; }
inline bool is_stmt_prepare_or_first_sp_execute() const
{ return (int)state < (int)PREPARED; }
inline bool is_first_stmt_execute() const { return state == PREPARED; }
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 2ae293c1bff..e1d701936cf 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -217,6 +217,8 @@ exit:
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
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
0 ok
@@ -245,11 +247,7 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
}
else
{
- unit->offset_limit_cnt= first_select->offset_limit;
- 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;
+ unit->set_limit(first_select);
if (unit->select_limit_cnt == HA_POS_ERROR)
first_select->options&= ~OPTION_FOUND_ROWS;
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 3bda16202b9..8a12339ccee 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -225,20 +225,22 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
MYSQL_ERROR *err;
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;
-
+
+ unit->set_limit(sel);
+
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++))
{
/* Skip levels that the user is not interested in */
if (!(levels_to_show & ((ulong) 1 << err->level)))
continue;
- if (offset)
- {
- offset--;
+ if (++idx <= unit->offset_limit_cnt)
continue;
- }
+ if (idx > unit->select_limit_cnt)
+ break;
protocol->prepare_for_resend();
protocol->store(warning_level_names[err->level],
warning_level_length[err->level], system_charset_info);
@@ -246,8 +248,6 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
protocol->store(err->msg, strlen(err->msg), system_charset_info);
if (protocol->write())
DBUG_RETURN(TRUE);
- if (!--limit)
- break;
}
send_eof(thd);
DBUG_RETURN(FALSE);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 1aa034ce61c..aca53db0ec8 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -321,8 +321,8 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
key_expr
ha_rkey_mode
cond
- select_limit
- offset_limit
+ select_limit_cnt
+ offset_limit_cnt
RETURN
FALSE ok
@@ -333,7 +333,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
enum enum_ha_read_modes mode, char *keyname,
List<Item> *key_expr,
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 *table;
@@ -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))
goto err0;
- select_limit+=offset_limit;
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
HANDLER_TABLES_HACK(thd);
@@ -447,7 +446,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
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) {
case RFIRST:
@@ -535,7 +534,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
if (cond && !cond->val_int())
continue;
- if (num_rows >= offset_limit)
+ if (num_rows >= offset_limit_cnt)
{
Item *item;
protocol->prepare_for_resend();
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 574c9966c63..6b9330182d6 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1138,8 +1138,9 @@ void st_select_lex::init_select()
order_list.elements= 0;
order_list.first= 0;
order_list.next= (byte**) &order_list.first;
- select_limit= HA_POS_ERROR;
- offset_limit= 0;
+ /* Set limit and offset to default values */
+ select_limit= 0; /* denotes the default limit = HA_POS_ERROR */
+ offset_limit= 0; /* denotes the default offset = 0 */
with_sum_func= 0;
}
@@ -1363,7 +1364,7 @@ ulong st_select_lex_node::get_table_join_options()
*/
bool st_select_lex::test_limit()
{
- if (select_limit != HA_POS_ERROR)
+ if (select_limit != 0)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"LIMIT & IN/ALL/ANY/SOME subquery");
@@ -1551,24 +1552,20 @@ void st_select_lex::print_limit(THD *thd, String *str)
item->substype() == Item_subselect::IN_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;
}
if (explicit_limit)
{
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)
{
+ offset_limit->print(str);
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()
select_lex.with_sum_func == 0 &&
select_lex.table_list.elements >= 1 &&
!(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()
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;
- select_limit_cnt= values->select_limit+values->offset_limit;
- if (select_limit_cnt < values->select_limit)
+ ulonglong select_limit_val;
+
+ 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
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index e297d303f3d..5022392565c 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -488,7 +488,7 @@ public:
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
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
Item **ref_pointer_array;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a9e68de3705..1a3a03012eb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2351,7 +2351,8 @@ mysql_execute_command(THD *thd)
{
SELECT_LEX *param= lex->unit.global_parameters;
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;
@@ -3146,13 +3147,15 @@ unsent_create_error:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (update_precheck(thd, all_tables))
break;
+ DBUG_ASSERT(select_lex->offset_limit == 0);
+ unit->set_limit(select_lex);
res= (result= mysql_update(thd, all_tables,
select_lex->item_list,
lex->value_list,
select_lex->where,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
+ unit->select_limit_cnt,
lex->duplicates, lex->ignore));
/* mysql_update return 2 if we need to switch to multi-update */
if (result != 2)
@@ -3258,9 +3261,11 @@ unsent_create_error:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= delete_precheck(thd, all_tables)))
break;
+ DBUG_ASSERT(select_lex->offset_limit == 0);
+ unit->set_limit(select_lex);
res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list,
- select_lex->select_limit, select_lex->options);
+ unit->select_limit_cnt, select_lex->options);
break;
}
case SQLCOM_DELETE_MULTI:
@@ -3847,9 +3852,10 @@ unsent_create_error:
*/
if (check_db_used(thd, all_tables))
goto error;
+ unit->set_limit(select_lex);
res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
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;
case SQLCOM_BEGIN:
@@ -5130,7 +5136,6 @@ mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
- select_lex->select_limit= HA_POS_ERROR;
lex->orig_sql_command= SQLCOM_END;
lex->wild= 0;
if (select_lex == &lex->select_lex)
@@ -5145,6 +5150,7 @@ bool
mysql_new_select(LEX *lex, bool move_down)
{
SELECT_LEX *select_lex;
+ THD *thd;
DBUG_ENTER("mysql_new_select");
if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX()))
@@ -5194,7 +5200,7 @@ mysql_new_select(LEX *lex, bool move_down)
fake->select_number= INT_MAX;
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
- fake->select_limit= HA_POS_ERROR;
+ fake->select_limit= 0;
}
}
@@ -5242,8 +5248,8 @@ void mysql_init_multi_delete(LEX *lex)
{
lex->sql_command= SQLCOM_DELETE_MULTI;
mysql_init_select(lex);
- lex->select_lex.select_limit= lex->unit.select_limit_cnt=
- HA_POS_ERROR;
+ lex->select_lex.select_limit= 0;
+ lex->unit.select_limit_cnt= HA_POS_ERROR;
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->query_tables= 0;
@@ -6757,8 +6763,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (select_lex->order_list.elements)
msg= "ORDER BY";
- else if (select_lex->select_limit && select_lex->select_limit !=
- HA_POS_ERROR)
+ else if (select_lex->select_limit)
msg= "LIMIT";
if (msg)
{
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 71cebb61ae6..0b5ac63dd0b 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1316,6 +1316,7 @@ bool mysql_show_binlog_events(THD* thd)
if (mysql_bin_log.is_open())
{
LEX_MASTER_INFO *lex_mi= &thd->lex->mi;
+ SELECT_LEX_UNIT *unit= &thd->lex->unit;
ha_rows event_count, limit_start, limit_end;
my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly
char search_file_name[FN_REFLEN], *name;
@@ -1324,8 +1325,9 @@ bool mysql_show_binlog_events(THD* thd)
LOG_INFO linfo;
Log_event* ev;
- limit_start= thd->lex->current_select->offset_limit;
- limit_end= thd->lex->current_select->select_limit + limit_start;
+ unit->set_limit(thd->lex->current_select);
+ limit_start= unit->offset_limit_cnt;
+ limit_end= unit->select_limit_cnt;
name= search_file_name;
if (log_file_name)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 27ef3fcea6f..d07dd523f75 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -10051,7 +10051,7 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
join->do_send_rows= 0;
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);
}
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 56401ced67c..912636b6cf3 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -448,7 +448,7 @@ bool st_select_lex_unit::exec()
table->no_keyread=1;
}
res= sl->join->error;
- offset_limit_cnt= sl->offset_limit;
+ offset_limit_cnt= sl->offset_limit ? sl->offset_limit->val_uint() : 0;
if (!res)
{
examined_rows+= thd->examined_row_count;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 289bf9d28a3..9f0c3260d8f 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -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
LEX::select_lex
*/
- if ((!view->view && !view->belong_to_view) || thd->lex->sql_command == SQLCOM_INSERT ||
- thd->lex->select_lex.select_limit == HA_POS_ERROR)
+ if ((!view->view && !view->belong_to_view) ||
+ thd->lex->sql_command == SQLCOM_INSERT ||
+ thd->lex->select_lex.select_limit == 0)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table;
if (view->belong_to_view)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 2f584bc6b4e..47a2b098538 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -721,7 +721,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
signed_literal now_or_signed_literal opt_escape
sp_opt_default
simple_ident_nospvar simple_ident_q
- field_or_var
+ field_or_var limit_option
%type <item_num>
NUM_literal
@@ -5542,8 +5542,8 @@ opt_limit_clause_init:
{
LEX *lex= Lex;
SELECT_LEX *sel= lex->current_select;
- sel->offset_limit= 0L;
- sel->select_limit= HA_POS_ERROR;
+ sel->offset_limit= 0;
+ sel->select_limit= 0;
}
| limit_clause {}
;
@@ -5558,21 +5558,21 @@ limit_clause:
;
limit_options:
- ulong_num
+ limit_option
{
SELECT_LEX *sel= Select;
sel->select_limit= $1;
- sel->offset_limit= 0L;
+ sel->offset_limit= 0;
sel->explicit_limit= 1;
}
- | ulong_num ',' ulong_num
+ | limit_option ',' limit_option
{
SELECT_LEX *sel= Select;
sel->select_limit= $3;
sel->offset_limit= $1;
sel->explicit_limit= 1;
}
- | ulong_num OFFSET_SYM ulong_num
+ | limit_option OFFSET_SYM limit_option
{
SELECT_LEX *sel= Select;
sel->select_limit= $1;
@@ -5580,18 +5580,23 @@ limit_options:
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:
/* empty */
{
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;
- sel->select_limit= (ha_rows) $2;
+ sel->select_limit= $2;
sel->explicit_limit= 1;
};
@@ -7942,8 +7947,8 @@ handler:
LEX *lex=Lex;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
- lex->current_select->select_limit= 1;
- lex->current_select->offset_limit= 0L;
+ lex->current_select->select_limit= new Item_int(1);
+ lex->current_select->offset_limit= 0;
if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
YYABORT;
}