summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/des_key_file.cc45
-rw-r--r--sql/item_create.cc3
-rw-r--r--sql/item_strfunc.cc150
-rw-r--r--sql/item_strfunc.h13
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/lex.h1
-rw-r--r--sql/mysql_priv.h6
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/sql_parse.cc28
-rw-r--r--sql/sql_yacc.yy58
10 files changed, 202 insertions, 106 deletions
diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc
index c6ac9ab6059..d9c924b5a3c 100644
--- a/sql/des_key_file.cc
+++ b/sql/des_key_file.cc
@@ -19,25 +19,37 @@
#ifdef HAVE_OPENSSL
+struct st_des_keyschedule des_keyschedule[10];
+uint des_default_key;
+pthread_mutex_t LOCK_des_key_file;
+static int initialized;
+
/*
Function which loads DES keys from plaintext file into memory on MySQL
- server startup and on command FLUSH DES_KEYS. Blame tonu@spam.ee on bugs ;)
-*/
+ server startup and on command FLUSH DES_KEY_FILE.
+ Blame tonu@spam.ee on bugs ;)
-struct st_des_keyschedule des_keyschedule[10];
-uint des_default_key;
+ RETURN
+ 0 ok
+ 1 Error
+*/
-void
+bool
load_des_key_file(const char *file_name)
{
+ bool result=1;
File file;
- des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- char offset;
IO_CACHE io;
DBUG_ENTER("load_des_key_file");
DBUG_PRINT("enter",("name: %s",file_name));
- VOID(pthread_mutex_lock(&LOCK_open));
+ if (!initialized)
+ {
+ initialized=1;
+ pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST);
+ }
+
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
if ((file=my_open(file_name,O_RDONLY | O_BINARY ,MYF(MY_WME))) < 0 ||
init_io_cache(&io, file, IO_SIZE*2, READ_CACHE, 0, 0, MYF(MY_WME)))
goto error;
@@ -47,7 +59,7 @@ load_des_key_file(const char *file_name)
for (;;)
{
char *start, *end;
- char buf[1024];
+ char buf[1024], offset;
st_des_keyblock keyblock;
uint length;
@@ -60,10 +72,12 @@ load_des_key_file(const char *file_name)
// Remove newline and possible other control characters
for (start=buf+1 ; isspace(*start) ; start++) ;
end=buf+length;
- for (end=strend(buf) ; end > start && iscntrl(end[-1]) ; end--) ;
+ for (end=strend(buf) ; end > start && !isgraph(end[-1]) ; end--) ;
if (start != end)
{
+ des_cblock ivec;
+ bzero((char*) &ivec,sizeof(ivec));
// We make good 24-byte (168 bit) key from given plaintext key with MD5
EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar *) start, (int) (end-start),1,
@@ -76,11 +90,10 @@ load_des_key_file(const char *file_name)
des_default_key= (uint) offset; // use first as def.
}
}
- else
- {
- DBUG_PRINT("des",("wrong offset: %c",offset));
- }
+ else if (offset != '#')
+ sql_print_error("load_des_file: Found wrong key_number: %c",offset);
}
+ result=0;
error:
if (file >= 0)
@@ -88,7 +101,7 @@ error:
my_close(file,MYF(0));
end_io_cache(&io);
}
- VOID(pthread_mutex_unlock(&LOCK_open));
- DBUG_VOID_RETURN;
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
+ DBUG_RETURN(result);
}
#endif /* HAVE_OPENSSL */
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 71dc99f2558..a9567414b0b 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -151,8 +151,7 @@ Item *create_func_get_lock(Item* a, Item *b)
Item *create_func_hex(Item *a)
{
- return new Item_func_conv(a,new Item_int((int32) 10,2),
- new Item_int((int32) 16,2));
+ return new Item_func_hex(a);
}
Item *create_func_inet_ntoa(Item* a)
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 792c76ebc0d..c64fdc7a049 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -209,78 +209,84 @@ void Item_func_concat::fix_length_and_dec()
Function des_encrypt() by tonu@spam.ee & monty
Works only if compiled with OpenSSL library support.
This returns a binary string where first character is
- CHAR(128 | tail-length << 4 | key-number).
- If one uses a string key key_number is 0.
+ CHAR(128 | key-number).
+ If one uses a string key key_number is 127.
Encryption result is longer than original by formula:
- new_length= (8-(original_length % 8))+1
+ new_length= org_length + (8-(org_length % 8))+1
*/
String *Item_func_des_encrypt::val_str(String *str)
{
#ifdef HAVE_OPENSSL
- des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ des_cblock ivec;
struct st_des_keyblock keyblock;
struct st_des_keyschedule keyschedule;
- struct st_des_keyschedule *keyschedule_ptr;
const char *append_str="********";
uint key_number, res_length, tail;
String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
- if (res->length() == 0)
+ if ((res_length=res->length()) == 0)
return &empty_string;
if (arg_count == 1)
- keyschedule_ptr= &des_keyschedule[key_number=des_default_key];
+ {
+ /* Protect against someone doing FLUSH DES_KEY_FILE */
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ keyschedule= des_keyschedule[key_number=des_default_key];
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
+ }
else if (args[1]->result_type() == INT_RESULT)
{
key_number= (uint) args[1]->val_int();
if (key_number > 9)
goto error;
- keyschedule_ptr= &des_keyschedule[key_number];
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ keyschedule= des_keyschedule[key_number];
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
}
else
{
- uint tail,res_length;
String *keystr=args[1]->val_str(&tmp_value);
if (!keystr)
goto error;
- key_number=15; // User key string
+ key_number=127; // User key string
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
- keyschedule_ptr= &keyschedule;
+ bzero((char*) &ivec,sizeof(ivec));
EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar*) keystr->ptr(), (int) keystr->length(),
1, (uchar*) &keyblock,ivec);
- des_set_key_unchecked(&keyblock.key1,keyschedule_ptr->ks1);
- des_set_key_unchecked(&keyblock.key2,keyschedule_ptr->ks2);
- des_set_key_unchecked(&keyblock.key3,keyschedule_ptr->ks3);
+ des_set_key_unchecked(&keyblock.key1,keyschedule.ks1);
+ des_set_key_unchecked(&keyblock.key2,keyschedule.ks2);
+ des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
}
/*
The problem: DES algorithm requires original data to be in 8-bytes
- chunks. Missing bytes get filled with zeros and result of encryption
- can be up to 7 bytes longer than original string. When decrypted,
+ chunks. Missing bytes get filled with '*'s and result of encryption
+ can be up to 8 bytes longer than original string. When decrypted,
we do not know the size of original string :(
- We add one byte with value 0x1..0x8 as the second byte to original
- plaintext marking change of string length.
+ We add one byte with value 0x1..0x8 as the last byte of the padded
+ string marking change of string length.
*/
- tail= (7-(res->length()+7) % 8); // 0..7 marking extra length
- res_length=res->length()+tail+1;
- if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length))
+ tail= (8-(res_length) % 8); // 1..8 marking extra length
+ res_length+=tail;
+ if (tail && res->append(append_str, tail) || tmp_value.alloc(res_length+1))
goto error;
-
- tmp_value.length(res_length);
- tmp_value[0]=(char) (128 | tail << 4 | key_number);
+ (*res)[res_length-1]=tail; // save extra length
+ tmp_value.length(res_length+1);
+ tmp_value[0]=(char) (128 | key_number);
// Real encryption
+ bzero((char*) &ivec,sizeof(ivec));
des_ede3_cbc_encrypt((const uchar*) (res->ptr()),
(uchar*) (tmp_value.ptr()+1),
- res->length(),
- keyschedule_ptr->ks1,
- keyschedule_ptr->ks2,
- keyschedule_ptr->ks3,
+ res_length,
+ keyschedule.ks1,
+ keyschedule.ks2,
+ keyschedule.ks3,
&ivec, TRUE);
return &tmp_value;
@@ -295,24 +301,27 @@ String *Item_func_des_decrypt::val_str(String *str)
{
#ifdef HAVE_OPENSSL
des_key_schedule ks1, ks2, ks3;
- des_cblock ivec={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ des_cblock ivec;
struct st_des_keyblock keyblock;
struct st_des_keyschedule keyschedule;
- struct st_des_keyschedule *keyschedule_ptr;
String *res= args[0]->val_str(str);
+ uint length=res->length(),tail;
if ((null_value=args[0]->null_value))
return 0;
- if (res->length() < 9 || (res->length() % 8) != 1 || !((*res)[0] & 128))
+ length=res->length();
+ if (length < 9 || (length % 8) != 1 || !((*res)[0] & 128))
return res; // Skip decryption if not encrypted
if (arg_count == 1) // If automatic uncompression
{
- uint key_number=(uint) (*res)[0] & 15;
+ uint key_number=(uint) (*res)[0] & 127;
// Check if automatic key and that we have privilege to uncompress using it
if (!(current_thd->master_access & PROCESS_ACL) || key_number > 9)
goto error;
- keyschedule_ptr= &des_keyschedule[key_number];
+ VOID(pthread_mutex_lock(&LOCK_des_key_file));
+ keyschedule= des_keyschedule[key_number];
+ VOID(pthread_mutex_unlock(&LOCK_des_key_file));
}
else
{
@@ -321,26 +330,30 @@ String *Item_func_des_decrypt::val_str(String *str)
if (!keystr)
goto error;
- keyschedule_ptr= &keyschedule;
+ bzero((char*) &ivec,sizeof(ivec));
EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar*) keystr->ptr(),(int) keystr->length(),
1,(uchar*) &keyblock,ivec);
// Here we set all 64-bit keys (56 effective) one by one
- des_set_key_unchecked(&keyblock.key1,keyschedule_ptr->ks1);
- des_set_key_unchecked(&keyblock.key2,keyschedule_ptr->ks2);
- des_set_key_unchecked(&keyblock.key3,keyschedule_ptr->ks3);
+ des_set_key_unchecked(&keyblock.key1,keyschedule.ks1);
+ des_set_key_unchecked(&keyblock.key2,keyschedule.ks2);
+ des_set_key_unchecked(&keyblock.key3,keyschedule.ks3);
}
- if (tmp_value.alloc(res->length()-1))
+ if (tmp_value.alloc(length-1))
goto error;
- /* Restore old length of key */
- tmp_value.length(res->length()-1-(((uchar) (*res)[0] >> 4) & 7));
+
+ bzero((char*) &ivec,sizeof(ivec));
des_ede3_cbc_encrypt((const uchar*) res->ptr()+1,
(uchar*) (tmp_value.ptr()),
- res->length()-1,
- keyschedule_ptr->ks1,
- keyschedule_ptr->ks2,
- keyschedule_ptr->ks3,
+ length-1,
+ keyschedule.ks1,
+ keyschedule.ks2,
+ keyschedule.ks3,
&ivec, FALSE);
+ /* Restore old length of key */
+ if ((tail=(uint) (uchar) tmp_value[length-2]) > 8)
+ goto error; // Wrong key
+ tmp_value.length(length-1-tail);
return &tmp_value;
error:
@@ -1274,9 +1287,9 @@ String *Item_func_soundex::val_str(String *str)
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
- if (str_value.alloc(max(res->length(),4)))
+ if (tmp_value.alloc(max(res->length(),4)))
return str; /* purecov: inspected */
- char *to= (char *) str_value.ptr();
+ char *to= (char *) tmp_value.ptr();
char *from= (char *) res->ptr(), *end=from+res->length();
while (from != end && isspace(*from)) // Skip pre-space
@@ -1300,11 +1313,11 @@ String *Item_func_soundex::val_str(String *str)
last_ch = ch; // save code of last input letter
} // for next double-letter check
}
- for (end=(char*) str_value.ptr()+4 ; to < end ; to++)
+ for (end=(char*) tmp_value.ptr()+4 ; to < end ; to++)
*to = '0';
*to=0; // end string
- str_value.length((uint) (to-str_value.ptr()));
- return &str_value;
+ tmp_value.length((uint) (to-tmp_value.ptr()));
+ return &tmp_value;
}
@@ -1759,6 +1772,45 @@ String *Item_func_conv::val_str(String *str)
return str;
}
+
+String *Item_func_hex::val_str(String *str)
+{
+ if (args[0]->result_type() != STRING_RESULT)
+ {
+ /* Return hex of unsigned longlong value */
+ longlong dec= args[0]->val_int();
+ char ans[65],*ptr;
+ if ((null_value= args[0]->null_value))
+ return 0;
+ ptr= longlong2str(dec,ans,16);
+ if (str->copy(ans,(uint32) (ptr-ans)))
+ return &empty_string; // End of memory
+ return str;
+ }
+
+ /* Convert given string to a hex string, character by character */
+ String *res= args[0]->val_str(str);
+ const char *from, *end;
+ char *to;
+ if (!res || tmp_value.alloc(res->length()*2))
+ {
+ null_value=1;
+ return 0;
+ }
+ null_value=0;
+ tmp_value.length(res->length()*2);
+ for (from=res->ptr(), end=from+res->length(), to= (char*) tmp_value.ptr();
+ from != end ;
+ from++, to+=2)
+ {
+ uint tmp=(uint) (uchar) *from;
+ to[0]=_dig_vec[tmp >> 4];
+ to[1]=_dig_vec[tmp & 15];
+ }
+ return &tmp_value;
+}
+
+
#include <my_dir.h> // For my_stat
String *Item_load_file::val_str(String *str)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index ba2d6ffc3f0..e92dcf806db 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -297,6 +297,7 @@ public:
class Item_func_soundex :public Item_str_func
{
+ String tmp_value;
public:
Item_func_soundex(Item *a) :Item_str_func(a) {}
String *val_str(String *);
@@ -412,6 +413,18 @@ public:
void fix_length_and_dec() { decimals=0; max_length=64; }
};
+
+class Item_func_hex :public Item_str_func
+{
+ String tmp_value;
+public:
+ Item_func_hex(Item *a) :Item_str_func(a) {}
+ const char *func_name() const { return "hex"; }
+ String *val_str(String *);
+ void fix_length_and_dec() { decimals=0; max_length=args[0]->max_length*2; }
+};
+
+
class Item_func_binary :public Item_str_func
{
public:
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index e65f7679cae..2b1bb9cae0e 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -672,7 +672,7 @@ String *Item_func_date_format::val_str(String *str)
else
size=format_length(format);
if (format == str)
- str=&str_value; // Save result here
+ str= &str_value; // Save result here
if (str->alloc(size))
{
null_value=1;
diff --git a/sql/lex.h b/sql/lex.h
index d20141a560e..d72d2ff63a4 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -111,6 +111,7 @@ static SYMBOL symbols[] = {
{ "DAY_SECOND", SYM(DAY_SECOND_SYM),0,0},
{ "DEC", SYM(DECIMAL_SYM),0,0},
{ "DECIMAL", SYM(DECIMAL_SYM),0,0},
+ { "DES_KEY_FILE", SYM(DES_KEY_FILE),0,0},
{ "DEFAULT", SYM(DEFAULT),0,0},
{ "DELAYED", SYM(DELAYED_SYM),0,0},
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a6859e31bde..fece60dd49c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -263,7 +263,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
bool mysql_change_db(THD *thd,const char *name);
void mysql_parse(THD *thd,char *inBuf,uint length);
void mysql_init_select(LEX *lex);
-void mysql_new_select(LEX *lex);
+bool mysql_new_select(LEX *lex);
void init_max_user_conn(void);
void free_max_user_conn(void);
pthread_handler_decl(handle_one_connection,arg);
@@ -405,9 +405,11 @@ struct st_des_keyschedule
{
des_key_schedule ks1, ks2, ks3;
};
+extern char *des_key_file;
extern struct st_des_keyschedule des_keyschedule[10];
extern uint des_default_key;
-void load_des_key_file(const char *file_name);
+extern pthread_mutex_t LOCK_des_key_file;
+bool load_des_key_file(const char *file_name);
#endif /* HAVE_OPENSSL */
/* sql_list.c */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a8b9a799c56..786c0c2ad38 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -242,7 +242,7 @@ static char glob_hostname[FN_REFLEN];
#include "sslopt-vars.h"
#ifdef HAVE_OPENSSL
-static char * des_key_file = 0;
+char *des_key_file = 0;
struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0;
#endif /* HAVE_OPENSSL */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 12646f0737f..ebe8fc979bf 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2431,9 +2431,10 @@ mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex = lex->select;
select_lex->where=select_lex->having=0;
- select_lex->select_limit=current_thd->default_select_limit;
+ select_lex->select_limit=lex->thd->default_select_limit;
select_lex->offset_limit=0;
- select_lex->options=0; select_lex->linkage=UNSPECIFIED_TYPE;
+ select_lex->options=0;
+ select_lex->linkage=UNSPECIFIED_TYPE;
lex->exchange = 0;
lex->proc_list.first=0;
select_lex->order_list.elements=select_lex->group_list.elements=0;
@@ -2444,18 +2445,25 @@ mysql_init_select(LEX *lex)
select_lex->next = (SELECT_LEX *)NULL;
}
-void
+bool
mysql_new_select(LEX *lex)
{
SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
+ if (!select_lex)
+ return 1;
lex->select->next=select_lex;
lex->select=select_lex;
select_lex->table_list.next= (byte**) &select_lex->table_list.first;
- select_lex->item_list.empty(); select_lex->when_list.empty();
- select_lex->expr_list.empty(); select_lex->interval_list.empty();
- select_lex->use_index.empty(); select_lex->ftfunc_list.empty();
+ select_lex->item_list.empty();
+ select_lex->when_list.empty();
+ select_lex->expr_list.empty();
+ select_lex->interval_list.empty();
+ select_lex->use_index.empty();
+ select_lex->ftfunc_list.empty();
+ return 0;
}
+
void
mysql_parse(THD *thd,char *inBuf,uint length)
{
@@ -3035,7 +3043,13 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
reset_master();
if (options & REFRESH_SLAVE)
reset_slave();
-
+#ifdef OPENSSL
+ if (options & REFRESH_DES_KEY_FILE)
+ {
+ if (des_key_file)
+ result=load_des_key_file(des_key_file);
+ }
+#endif
return result;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ea105f3be50..e76998e9d7d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -171,13 +171,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DEMAND_SYM
%token DESC
%token DESCRIBE
-%token DIRECTORY_SYM
-%token DISTINCT
+%token DES_KEY_FILE
%token DISABLE_SYM
+%token DISTINCT
%token DYNAMIC_SYM
%token ENABLE_SYM
%token ENCLOSED
%token ESCAPED
+%token DIRECTORY_SYM
%token ESCAPE_SYM
%token EXISTS
%token EXTENDED_SYM
@@ -2106,13 +2107,7 @@ order_dir:
limit_clause:
- /* empty */
- {
- SELECT_LEX *sel=Select;
- sel->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ?
- 1 : current_thd->default_select_limit;
- sel->offset_limit= 0L;
- }
+ /* empty */ {}
| LIMIT ULONG_NUM
{
SELECT_LEX *sel=Select;
@@ -2511,13 +2506,14 @@ show_param:
TEXT_STRING AND MASTER_LOG_POS_SYM EQ ulonglong_num AND
MASTER_LOG_SEQ_SYM EQ ULONG_NUM AND MASTER_SERVER_ID_SYM EQ
ULONG_NUM
- {
- Lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
- Lex->mi.log_file_name = $8.str;
- Lex->mi.pos = $12;
- Lex->mi.last_log_seq = $16;
- Lex->mi.server_id = $20;
- }
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SHOW_NEW_MASTER;
+ lex->mi.log_file_name = $8.str;
+ lex->mi.pos = $12;
+ lex->mi.last_log_seq = $16;
+ lex->mi.server_id = $20;
+ }
| MASTER_SYM LOGS_SYM
{
Lex->sql_command = SQLCOM_SHOW_BINLOGS;
@@ -2526,10 +2522,13 @@ show_param:
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_HOSTS;
}
- | BINLOG_SYM EVENTS_SYM binlog_in binlog_from limit_clause
+ | BINLOG_SYM EVENTS_SYM binlog_in binlog_from
{
- Lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS;
- }
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SHOW_BINLOG_EVENTS;
+ lex->select->select_limit= lex->thd->default_select_limit;
+ lex->select->offset_limit= 0L;
+ } limit_clause
| keys_or_index FROM table_ident opt_db
{
Lex->sql_command= SQLCOM_SHOW_KEYS;
@@ -2642,6 +2641,7 @@ flush_option:
| STATUS_SYM { Lex->type|= REFRESH_STATUS; }
| SLAVE { Lex->type|= REFRESH_SLAVE; }
| MASTER_SYM { Lex->type|= REFRESH_MASTER; }
+ | DES_KEY_FILE { Lex->type|= REFRESH_DES_KEY_FILE; }
opt_table_list:
/* empty */ {}
@@ -2912,27 +2912,28 @@ keyword:
| CIPHER_SYM {}
| CLOSE_SYM {}
| COMMENT_SYM {}
- | COMMIT_SYM {}
| COMMITTED_SYM {}
+ | COMMIT_SYM {}
| COMPRESSED_SYM {}
| CONCURRENT {}
| DATA_SYM {}
| DATETIME {}
| DATE_SYM {}
| DAY_SYM {}
- | DIRECTORY_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DEMAND_SYM {}
- | DISABLE_SYM {}
+ | DES_KEY_FILE {}
+ | DIRECTORY_SYM {}
| DUMPFILE {}
| DYNAMIC_SYM {}
- | ENABLE_SYM {}
| END {}
| ENUM {}
| ESCAPE_SYM {}
| EVENTS_SYM {}
| EXTENDED_SYM {}
| FAST_SYM {}
+ | DISABLE_SYM {}
+ | ENABLE_SYM {}
| FULL {}
| FILE_SYM {}
| FIRST_SYM {}
@@ -3296,6 +3297,8 @@ handler:
LEX *lex=Lex;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
+ lex->select->select_limit= 1;
+ lex->select->offset_limit= 0L;
if (!add_table_to_list($2,0,0))
YYABORT;
}
@@ -3581,9 +3584,8 @@ union_list:
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
YYABORT;
}
- if (lex->select->linkage == NOT_A_SELECT)
+ if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex))
YYABORT;
- mysql_new_select(lex);
lex->select->linkage=UNION_TYPE;
}
select_init
@@ -3597,11 +3599,11 @@ optional_order_or_limit:
|
{
LEX *lex=Lex;
- if (!lex->select->braces)
- YYABORT;
- mysql_new_select(lex);
+ if (!lex->select->braces || mysql_new_select(lex))
+ YYABORT;
mysql_init_select(lex);
lex->select->linkage=NOT_A_SELECT;
+ lex->select->select_limit=lex->thd->default_select_limit;
}
opt_order_clause limit_clause