Commit ac221066 authored by unknown's avatar unknown

merged

parents 61d9206d 898bc3a2
This diff is collapsed.
a b
14 aaa
a b
15 bbb
a b
16 ccc
a b
15 bbb
a b
22 iii
a b
21 hhh
a b
20 ggg
a b
14 aaa
a b
a b
22 iii
a b
21 hhh
a b
22 iii
a b
a b
15 bbb
#
# test of HANDLER ...
#
drop table if exists t1;
create table t1 (a int, b char(10), key a(a), key b(a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(15,"bbb"),(16,"ccc"),(16,"xxx"),
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
handler t2 read a first;
handler t2 read a next;
handler t2 read a next;
handler t2 read a prev;
handler t2 read a last;
handler t2 read a prev;
handler t2 read a prev;
handler t2 read a first;
handler t2 read a prev;
handler t2 read a last;
handler t2 read a prev;
handler t2 read a next;
handler t2 read a next;
handler t2 read a=(15);
handler t2 read a=(16);
!$1070 handler t2 read a=(19,"fff");
handler t2 read b=(19,"fff");
handler t2 read b=(19,"yyy");
handler t2 read b=(19);
!$1109 handler t1 read a last;
handler t2 read a=(11);
handler t2 read a>=(11);
handler t2 read a=(18);
handler t2 read a>=(18);
handler t2 read a>(18);
handler t2 read a<=(18);
handler t2 read a<(18);
handler t2 read a first limit 5;
handler t2 read a next limit 3;
handler t2 read a prev limit 10;
handler t2 read a>=(16) limit 4;
handler t2 read a>=(16) limit 2,2;
handler t2 read a last limit 3;
handler t2 read a=(19);
handler t2 read a=(19) where b="yyy";
handler t2 read first;
handler t2 read next;
handler t2 read next;
handler t2 read last;
handler t2 close;
drop table if exists t1;
...@@ -56,7 +56,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ...@@ -56,7 +56,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\ sql_select.h structs.h table.h sql_udf.h hash_filo.h\
lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \ lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.h \
log_event.h mini_client.h sql_repl.h slave.h log_event.h mini_client.h sql_repl.h slave.h
mysqld_SOURCES = sql_lex.cc \ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
thr_malloc.cc item_create.cc \ thr_malloc.cc item_create.cc \
......
...@@ -82,6 +82,7 @@ static SYMBOL symbols[] = { ...@@ -82,6 +82,7 @@ static SYMBOL symbols[] = {
{ "CHANGED", SYM(CHANGED),0,0}, { "CHANGED", SYM(CHANGED),0,0},
{ "CHECK", SYM(CHECK_SYM),0,0}, { "CHECK", SYM(CHECK_SYM),0,0},
{ "CHECKSUM", SYM(CHECKSUM_SYM),0,0}, { "CHECKSUM", SYM(CHECKSUM_SYM),0,0},
{ "CLOSE", SYM(CLOSE_SYM),0,0},
{ "COLUMN", SYM(COLUMN_SYM),0,0}, { "COLUMN", SYM(COLUMN_SYM),0,0},
{ "COLUMNS", SYM(COLUMNS),0,0}, { "COLUMNS", SYM(COLUMNS),0,0},
{ "COMMENT", SYM(COMMENT_SYM),0,0}, { "COMMENT", SYM(COMMENT_SYM),0,0},
...@@ -152,6 +153,7 @@ static SYMBOL symbols[] = { ...@@ -152,6 +153,7 @@ static SYMBOL symbols[] = {
{ "GRANTS", SYM(GRANTS),0,0}, { "GRANTS", SYM(GRANTS),0,0},
{ "GROUP", SYM(GROUP),0,0}, { "GROUP", SYM(GROUP),0,0},
{ "HAVING", SYM(HAVING),0,0}, { "HAVING", SYM(HAVING),0,0},
{ "HANDLER", SYM(HANDLER_SYM),0,0},
{ "HEAP", SYM(HEAP_SYM),0,0}, { "HEAP", SYM(HEAP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0}, { "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0}, { "HOUR", SYM(HOUR_SYM),0,0},
...@@ -185,6 +187,7 @@ static SYMBOL symbols[] = { ...@@ -185,6 +187,7 @@ static SYMBOL symbols[] = {
{ "KEY", SYM(KEY_SYM),0,0}, { "KEY", SYM(KEY_SYM),0,0},
{ "KEYS", SYM(KEYS),0,0}, { "KEYS", SYM(KEYS),0,0},
{ "KILL", SYM(KILL_SYM),0,0}, { "KILL", SYM(KILL_SYM),0,0},
{ "LAST", SYM(LAST_SYM),0,0},
{ "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0}, { "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
{ "LEADING", SYM(LEADING),0,0}, { "LEADING", SYM(LEADING),0,0},
{ "LEFT", SYM(LEFT),0,0}, { "LEFT", SYM(LEFT),0,0},
...@@ -226,11 +229,12 @@ static SYMBOL symbols[] = { ...@@ -226,11 +229,12 @@ static SYMBOL symbols[] = {
{ "MYISAM", SYM(MYISAM_SYM),0,0}, { "MYISAM", SYM(MYISAM_SYM),0,0},
{ "NATURAL", SYM(NATURAL),0,0}, { "NATURAL", SYM(NATURAL),0,0},
{ "NATIONAL", SYM(NATIONAL_SYM),0,0}, { "NATIONAL", SYM(NATIONAL_SYM),0,0},
{ "NEXT", SYM(NEXT_SYM),0,0},
{ "NCHAR", SYM(NCHAR_SYM),0,0}, { "NCHAR", SYM(NCHAR_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "NO", SYM(NO_SYM),0,0}, { "NO", SYM(NO_SYM),0,0},
{ "NOT", SYM(NOT),0,0}, { "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0}, { "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "ON", SYM(ON),0,0}, { "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0}, { "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0}, { "OPTIMIZE", SYM(OPTIMIZE),0,0},
...@@ -245,6 +249,7 @@ static SYMBOL symbols[] = { ...@@ -245,6 +249,7 @@ static SYMBOL symbols[] = {
{ "PASSWORD", SYM(PASSWORD),0,0}, { "PASSWORD", SYM(PASSWORD),0,0},
{ "PURGE", SYM(PURGE),0,0}, { "PURGE", SYM(PURGE),0,0},
{ "PRECISION", SYM(PRECISION),0,0}, { "PRECISION", SYM(PRECISION),0,0},
{ "PREV", SYM(PREV_SYM),0,0},
{ "PRIMARY", SYM(PRIMARY_SYM),0,0}, { "PRIMARY", SYM(PRIMARY_SYM),0,0},
{ "PROCEDURE", SYM(PROCEDURE),0,0}, { "PROCEDURE", SYM(PROCEDURE),0,0},
{ "PROCESS" , SYM(PROCESS),0,0}, { "PROCESS" , SYM(PROCESS),0,0},
......
...@@ -385,6 +385,12 @@ int mysqld_show_status(THD *thd); ...@@ -385,6 +385,12 @@ int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild); int mysqld_show_variables(THD *thd,const char *wild);
int mysqld_show(THD *thd, const char *wild, show_var_st *variables); int mysqld_show(THD *thd, const char *wild, show_var_st *variables);
/* sql_handler.cc */
int mysql_ha_open(THD *thd, TABLE_LIST *tables);
int mysql_ha_close(THD *thd, TABLE_LIST *tables);
int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
/* sql_base.cc */ /* sql_base.cc */
void set_item_name(Item *item,char *pos,uint length); void set_item_name(Item *item,char *pos,uint length);
bool add_field_to_list(char *field_name, enum enum_field_types type, bool add_field_to_list(char *field_name, enum enum_field_types type,
...@@ -406,6 +412,8 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find); ...@@ -406,6 +412,8 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables, SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error); table_map read_tables, COND *conds, int *error);
Item ** find_item_in_list(Item *item,List<Item> &items); Item ** find_item_in_list(Item *item,List<Item> &items);
bool insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name,
List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables); bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item, int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
bool set_query_id,List<Item> *sum_func_list); bool set_query_id,List<Item> *sum_func_list);
......
...@@ -34,8 +34,6 @@ HASH open_cache; /* Used by mysql_test */ ...@@ -34,8 +34,6 @@ HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db, static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias, bool locked); const char *name, const char *alias, bool locked);
static bool insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name,
List_iterator<Item> *it);
static void free_cache_entry(TABLE *entry); static void free_cache_entry(TABLE *entry);
static void mysql_rm_tmp_tables(void); static void mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table, static key_map get_key_map_from_key_list(TABLE *table,
...@@ -1815,7 +1813,7 @@ static key_map get_key_map_from_key_list(TABLE *table, ...@@ -1815,7 +1813,7 @@ static key_map get_key_map_from_key_list(TABLE *table,
** Returns pointer to last inserted field if ok ** Returns pointer to last inserted field if ok
****************************************************************************/ ****************************************************************************/
static bool bool
insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name, insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name,
List_iterator<Item> *it) List_iterator<Item> *it)
{ {
......
...@@ -85,7 +85,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -85,7 +85,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
query_length=col_access=0; query_length=col_access=0;
query_error=0; query_error=0;
next_insert_id=last_insert_id=0; next_insert_id=last_insert_id=0;
open_tables=temporary_tables=0; open_tables=temporary_tables=handler_tables=0;
handler_items=0;
tmp_table=0; tmp_table=0;
lock=locked_tables=0; lock=locked_tables=0;
used_tables=0; used_tables=0;
...@@ -163,6 +164,11 @@ THD::~THD() ...@@ -163,6 +164,11 @@ THD::~THD()
lock=locked_tables; locked_tables=0; lock=locked_tables; locked_tables=0;
close_thread_tables(this); close_thread_tables(this);
} }
if (handler_tables)
{
open_tables=handler_tables; handler_tables=0;
close_thread_tables(this);
}
close_temporary_tables(this); close_temporary_tables(this);
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
if (opt_using_transactions) if (opt_using_transactions)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
class Query_log_event; class Query_log_event;
class Load_log_event; class Load_log_event;
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY };
enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE }; enum enum_duplicates { DUP_ERROR, DUP_REPLACE, DUP_IGNORE };
enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN }; enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
...@@ -231,7 +231,7 @@ class THD :public ilink { ...@@ -231,7 +231,7 @@ class THD :public ilink {
const char *proc_info; const char *proc_info;
uint client_capabilities,max_packet_length; uint client_capabilities,max_packet_length;
uint master_access,db_access; uint master_access,db_access;
TABLE *open_tables,*temporary_tables; TABLE *open_tables,*temporary_tables, *handler_tables;
MYSQL_LOCK *lock,*locked_tables; MYSQL_LOCK *lock,*locked_tables;
ULL *ull; ULL *ull;
struct st_my_thread_var *mysys_var; struct st_my_thread_var *mysys_var;
...@@ -253,7 +253,7 @@ class THD :public ilink { ...@@ -253,7 +253,7 @@ class THD :public ilink {
#ifdef HAVE_GEMINI_DB #ifdef HAVE_GEMINI_DB
struct st_gemini gemini; struct st_gemini gemini;
#endif #endif
Item *free_list; Item *free_list, *handler_items;
CONVERT *convert_set; CONVERT *convert_set;
Field *dupp_field; Field *dupp_field;
#ifndef __WIN__ #ifndef __WIN__
......
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* HANDLER ... commands - direct access to ISAM */
#include <assert.h>
#include "mysql_priv.h"
#include "sql_select.h"
/* TODO:
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
the most natural (easiest, fastest) way to do it is to
compute List<Item> field_list not in mysql_ha_read
but in mysql_ha_open, and then store it in TABLE structure.
The problem here is that mysql_parse calls free_item to free all the
items allocated at the end of every query. The workaround would to
keep two item lists per THD - normal free_list and handler_items.
The second is to be freeed only on thread end. mysql_ha_open should
then do { handler_items=concat(handler_items, free_list); free_list=0; }
But !!! do_cammand calls free_root at the end of every query and frees up
all the sql_alloc'ed memory. It's harder to work around...
*/
#define HANDLER_TABLES_HACK(thd) { \
TABLE *tmp=thd->open_tables; \
thd->open_tables=thd->handler_tables; \
thd->handler_tables=tmp; }
static TABLE *find_table_by_name(THD *thd, char *db, char *table_name);
int mysql_ha_open(THD *thd, TABLE_LIST *tables)
{
HANDLER_TABLES_HACK(thd);
int err=open_tables(thd,tables);
HANDLER_TABLES_HACK(thd);
if (err)
return -1;
send_ok(&thd->net);
return 0;
}
int mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
/* Perhaps, we should close table here.
But it's not easy - *tables is a single-linked list, designed
to be closed at all once.
So, why bother ? All the tables will be closed at thread exit.
*/
send_ok(&thd->net);
return 0;
}
static enum enum_ha_read_modes rkey_to_rnext[]=
{ RNEXT, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
int 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)
{
int err, keyno=-1;
TABLE *table=find_table_by_name(thd, tables->db, tables->name);
if (!table)
{
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
tables->name,"HANDLER");
return -1;
}
tables->table=table;
if (cond && cond->fix_fields(thd,tables))
return -1;
if (keyname)
{
if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0)
{
my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
keyname,tables->name);
return -1;
}
}
List<Item> list;
list.push_front(new Item_field(NULL,NULL,"*"));
List_iterator<Item> it(list);
it++;
insert_fields(thd,tables,tables->name,&it);
table->file->index_init(keyno);
select_limit+=offset_limit;
send_fields(thd,list,1);
MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
for (uint num_rows=0; num_rows < select_limit; )
{
switch(mode)
{
case RFIRST:
err=keyname ?
table->file->index_first(table->record[0]) :
table->file->rnd_init(1) ||
table->file->rnd_next(table->record[0]);
mode=RNEXT;
break;
case RLAST:
dbug_assert(keyname != 0);
err=table->file->index_last(table->record[0]);
mode=RPREV;
break;
case RNEXT:
err=keyname ?
table->file->index_next(table->record[0]) :
table->file->rnd_next(table->record[0]);
break;
case RPREV:
dbug_assert(keyname != 0);
err=table->file->index_prev(table->record[0]);
break;
case RKEY:
{
dbug_assert(keyname != 0);
KEY *keyinfo=table->key_info+keyno;
KEY_PART_INFO *key_part=keyinfo->key_part;
uint key_len;
byte *key;
if (key_expr->elements > keyinfo->key_parts)
{
my_printf_error(ER_TOO_MANY_KEY_PARTS,ER(ER_TOO_MANY_KEY_PARTS),
MYF(0),keyinfo->key_parts);
goto err;
}
List_iterator<Item> it_ke(*key_expr);
Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++)
{
item->save_in_field(key_part->field);
key_len+=key_part->store_length;
}
if (!(key=sql_calloc(ALIGN_SIZE(key_len))))
{
send_error(&thd->net,ER_OUTOFMEMORY);
goto err;
}
key_copy(key, table, keyno, key_len);
err=table->file->index_read(table->record[0],
key,key_len,ha_rkey_mode);
mode=rkey_to_rnext[(int)ha_rkey_mode];
break;
}
default:
send_error(&thd->net,ER_ILLEGAL_HA);
goto err;
}
if (err)
{
if (err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE)
{
sql_print_error("mysql_ha_read: Got error %d when reading table",
err);
table->file->print_error(err,MYF(0));
goto err;
}
goto ok;
}
if (cond)
{
err=err;
if(!cond->val_int())
continue;
}
if (num_rows>=offset_limit)
{
if (!err)
{
String *packet = &thd->packet;
Item *item;
packet->length(0);
it.rewind();
while ((item=it++))
{
if (item->send(packet))
{
packet->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0));
goto err;
}
}
my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
}
}
num_rows++;
}
ok:
mysql_unlock_tables(thd,lock);
send_eof(&thd->net);
return 0;
err:
mysql_unlock_tables(thd,lock);
return -1;
}
/**************************************************************************
2Monty: It could easily happen, that the following service functions are
already defined somewhere in the code, but I failed to find them.
If this is the case, just say a word and I'll use old functions here.
**************************************************************************/
/* Note: this function differs from find_locked_table() because we're looking
here for alias, not real table name
*/
static TABLE *find_table_by_name(THD *thd, char *db, char *table_name)
{
int dblen;
if (!db || ! *db) db=thd->db;
if (!db || ! *db) db="";
dblen=strlen(db);
for (TABLE *table=thd->handler_tables; table ; table=table->next)
{
if (!memcmp(table->table_cache_key, db, dblen) &&
!my_strcasecmp(table->table_name,table_name))
return table;
}
return(0);
}
...@@ -53,7 +53,8 @@ enum enum_sql_command { ...@@ -53,7 +53,8 @@ enum enum_sql_command {
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES SQLCOM_SHOW_OPEN_TABLES,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ
}; };
enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT,
...@@ -141,6 +142,8 @@ typedef struct st_lex { ...@@ -141,6 +142,8 @@ typedef struct st_lex {
enum lex_states next_state; enum lex_states next_state;
enum enum_duplicates duplicates; enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation; enum enum_tx_isolation tx_isolation;
enum enum_ha_read_modes ha_read_mode;
enum ha_rkey_function ha_rkey_mode;
uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default; uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default;
thr_lock_type lock_option; thr_lock_type lock_option;
bool create_refs,drop_primary,drop_if_exists,local_file; bool create_refs,drop_primary,drop_if_exists,local_file;
......
...@@ -2008,6 +2008,24 @@ mysql_execute_command(void) ...@@ -2008,6 +2008,24 @@ mysql_execute_command(void)
res = mysql_show_grants(thd,lex->grant_user); res = mysql_show_grants(thd,lex->grant_user);
} }
break; break;
case SQLCOM_HA_OPEN:
if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables))
goto error;
res = mysql_ha_open(thd, tables);
break;
case SQLCOM_HA_CLOSE:
if (check_db_used(thd,tables))
goto error;
res = mysql_ha_close(thd, tables);
break;
case SQLCOM_HA_READ:
if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables))
goto error;
res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir,
lex->insert_list, lex->ha_rkey_mode, lex->where,
lex->select_limit, lex->offset_limit);
break;
case SQLCOM_BEGIN: case SQLCOM_BEGIN:
if (end_active_trans(thd)) if (end_active_trans(thd))
{ {
......
...@@ -110,6 +110,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -110,6 +110,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CHECKSUM_SYM %token CHECKSUM_SYM
%token CHECK_SYM %token CHECK_SYM
%token COALESCE %token COALESCE
%token CLOSE_SYM
%token COLUMNS %token COLUMNS
%token COLUMN_SYM %token COLUMN_SYM
%token COMMENT_SYM %token COMMENT_SYM
...@@ -193,6 +194,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -193,6 +194,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GROUP_UNIQUE_USERS %token GROUP_UNIQUE_USERS
%token GT_SYM %token GT_SYM
%token HAVING %token HAVING
%token HANDLER_SYM
%token HEAP_SYM %token HEAP_SYM
%token HEX_NUM %token HEX_NUM
%token HIGH_PRIORITY %token HIGH_PRIORITY
...@@ -222,6 +224,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -222,6 +224,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token KEY_SYM %token KEY_SYM
%token KILL_SYM %token KILL_SYM
%token LAST_INSERT_ID %token LAST_INSERT_ID
%token LAST_SYM
%token LE %token LE
%token LEADING %token LEADING
%token LEAST_SYM %token LEAST_SYM
...@@ -271,6 +274,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -271,6 +274,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NATURAL %token NATURAL
%token NCHAR_SYM %token NCHAR_SYM
%token NE %token NE
%token NEXT_SYM
%token NOT %token NOT
%token NOW_SYM %token NOW_SYM
%token NO_SYM %token NO_SYM
...@@ -292,6 +296,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -292,6 +296,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token PASSWORD %token PASSWORD
%token POSITION_SYM %token POSITION_SYM
%token PRECISION %token PRECISION
%token PREV_SYM
%token PRIMARY_SYM %token PRIMARY_SYM
%token PRIVILEGES %token PRIVILEGES
%token PROCEDURE %token PROCEDURE
...@@ -403,6 +408,43 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -403,6 +408,43 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token USE_SYM %token USE_SYM
%token USING %token USING
%token VALUES %token VALUES
%token VARIABLES
%token WHERE
%token WITH
%token WRITE_SYM
%token COMPRESSED_SYM
%token BIGINT
%token BLOB_SYM
%token CHAR_SYM
%token CHANGED
%token DATETIME
%token DATE_SYM
%token DECIMAL_SYM
%token DOUBLE_SYM
%token ENUM
%token FAST_SYM
%token FLOAT_SYM
%token INT_SYM
%token LONGBLOB
%token LONGTEXT
%token MEDIUMBLOB
%token MEDIUMINT
%token MEDIUMTEXT
%token NUMERIC_SYM
%token PRECISION
%token QUICK
%token REAL
%token SMALLINT
%token STRING_SYM
%token TEXT_SYM
%token TIMESTAMP
%token TIME_SYM
%token TINYBLOB
%token TINYINT
%token TINYTEXT
%token UNSIGNED
>>>>>>> BitKeeper/tmp/sql_yacc.yy_serg@1.85
%token VARBINARY %token VARBINARY
%token VARCHAR %token VARCHAR
%token VARIABLES %token VARIABLES
...@@ -527,13 +569,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -527,13 +569,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
select_item_list select_item values_list no_braces select_item_list select_item values_list no_braces
limit_clause delete_limit_clause fields opt_values values limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item procedure_list procedure_list2 procedure_item
when_list2 expr_list2 when_list2 expr_list2 handler
opt_precision opt_ignore opt_column opt_restrict opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock varchar field_opt_list opt_binary table_lock_list table_lock varchar
references opt_on_delete opt_on_delete_list opt_on_delete_item use references opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option opt_delete_options opt_delete_option
opt_outer table_list table opt_option opt_place opt_low_priority opt_outer table_list table_name opt_option opt_place opt_low_priority
opt_attribute opt_attribute_list attribute column_list column_list_id opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges opt_table user_list grant_option opt_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list grant_privilege grant_privilege_list
...@@ -541,6 +583,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -541,6 +583,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
equal optional_braces opt_key_definition key_usage_list2 equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_rkey_mode handler_read_or_scan
END_OF_INPUT END_OF_INPUT
%type <NONE> %type <NONE>
...@@ -590,6 +633,7 @@ verb_clause: ...@@ -590,6 +633,7 @@ verb_clause:
| slave | slave
| show | show
| truncate | truncate
| handler
| unlock | unlock
| update | update
| use | use
...@@ -1910,7 +1954,8 @@ order_dir: ...@@ -1910,7 +1954,8 @@ order_dir:
limit_clause: limit_clause:
/* empty */ /* empty */
{ {
Lex->select_limit= current_thd->default_select_limit; Lex->select_limit= (Lex->sql_command == SQLCOM_HA_READ) ?
1 : current_thd->default_select_limit;
Lex->offset_limit= 0L; Lex->offset_limit= 0L;
} }
| LIMIT ULONG_NUM | LIMIT ULONG_NUM
...@@ -2015,10 +2060,10 @@ drop: ...@@ -2015,10 +2060,10 @@ drop:
table_list: table_list:
table table_name
| table_list ',' table | table_list ',' table_name
table: table_name:
table_ident table_ident
{ if (!add_table_to_list($1,NULL,1)) YYABORT; } { if (!add_table_to_list($1,NULL,1)) YYABORT; }
...@@ -2051,7 +2096,7 @@ insert2: ...@@ -2051,7 +2096,7 @@ insert2:
| insert_table {} | insert_table {}
insert_table: insert_table:
table table_name
{ {
Lex->field_list.empty(); Lex->field_list.empty();
Lex->many_values.empty(); Lex->many_values.empty();
...@@ -2550,6 +2595,7 @@ keyword: ...@@ -2550,6 +2595,7 @@ keyword:
| CHANGED {} | CHANGED {}
| CHECKSUM_SYM {} | CHECKSUM_SYM {}
| CHECK_SYM {} | CHECK_SYM {}
| CLOSE_SYM {}
| COMMENT_SYM {} | COMMENT_SYM {}
| COMMIT_SYM {} | COMMIT_SYM {}
| COMMITTED_SYM {} | COMMITTED_SYM {}
...@@ -2575,12 +2621,14 @@ keyword: ...@@ -2575,12 +2621,14 @@ keyword:
| GEMINI_SYM {} | GEMINI_SYM {}
| GLOBAL_SYM {} | GLOBAL_SYM {}
| HEAP_SYM {} | HEAP_SYM {}
| HANDLER_SYM {}
| HOSTS_SYM {} | HOSTS_SYM {}
| HOUR_SYM {} | HOUR_SYM {}
| IDENTIFIED_SYM {} | IDENTIFIED_SYM {}
| ISOLATION {} | ISOLATION {}
| ISAM_SYM {} | ISAM_SYM {}
| INNOBASE_SYM {} | INNOBASE_SYM {}
| LAST_SYM {}
| LEVEL_SYM {} | LEVEL_SYM {}
| LOCAL_SYM {} | LOCAL_SYM {}
| LOGS_SYM {} | LOGS_SYM {}
...@@ -2603,10 +2651,12 @@ keyword: ...@@ -2603,10 +2651,12 @@ keyword:
| MYISAM_SYM {} | MYISAM_SYM {}
| NATIONAL_SYM {} | NATIONAL_SYM {}
| NCHAR_SYM {} | NCHAR_SYM {}
| NEXT_SYM {}
| NO_SYM {} | NO_SYM {}
| OPEN_SYM {} | OPEN_SYM {}
| PACK_KEYS_SYM {} | PACK_KEYS_SYM {}
| PASSWORD {} | PASSWORD {}
| PREV_SYM {}
| PROCESS {} | PROCESS {}
| PROCESSLIST_SYM {} | PROCESSLIST_SYM {}
| QUICK {} | QUICK {}
...@@ -2863,6 +2913,58 @@ unlock: ...@@ -2863,6 +2913,58 @@ unlock:
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; } UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
/*
** Handler: direct access to ISAM functions
*/
handler:
HANDLER_SYM table_ident OPEN_SYM opt_table_alias
{
Lex->sql_command = SQLCOM_HA_OPEN;
if (!add_table_to_list($2,$4,0))
YYABORT;
}
| HANDLER_SYM table_ident CLOSE_SYM
{
Lex->sql_command = SQLCOM_HA_CLOSE;
if (!add_table_to_list($2,0,0))
YYABORT;
}
| HANDLER_SYM table_ident READ_SYM handler_read_or_scan
{
Lex->sql_command = SQLCOM_HA_READ;
if (!add_table_to_list($2,0,0))
YYABORT;
}
where_clause limit_clause { }
handler_read_or_scan:
handler_scan_function { Lex->backup_dir= 0; }
| ident handler_rkey_function { Lex->backup_dir= $1.str; }
handler_scan_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
| NEXT_SYM { Lex->ha_read_mode = RNEXT; }
handler_rkey_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; }
| NEXT_SYM { Lex->ha_read_mode = RNEXT; }
| PREV_SYM { Lex->ha_read_mode = RPREV; }
| LAST_SYM { Lex->ha_read_mode = RLAST; }
| handler_rkey_mode
{
Lex->ha_read_mode = RKEY;
if (!(Lex->insert_list = new List_item))
YYABORT;
} '(' values ')' { }
handler_rkey_mode:
EQ { Lex->ha_rkey_mode=HA_READ_KEY_EXACT; }
| GE { Lex->ha_rkey_mode=HA_READ_KEY_OR_NEXT; }
| LE { Lex->ha_rkey_mode=HA_READ_KEY_OR_PREV; }
| GT_SYM { Lex->ha_rkey_mode=HA_READ_AFTER_KEY; }
| LT { Lex->ha_rkey_mode=HA_READ_BEFORE_KEY; }
/* GRANT / REVOKE */ /* GRANT / REVOKE */
revoke: revoke:
......
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