summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <serg@serg.mysql.com>2001-04-07 00:18:33 +0200
committerunknown <serg@serg.mysql.com>2001-04-07 00:18:33 +0200
commit7006b51823cc6c1f69f42f3c1599385414e6c5b4 (patch)
treeea2aec8b968cfcac8454af4f7651fb7718a0a3fd
parent50007b28e9d472c363ec3e516975769567fb99ef (diff)
downloadmariadb-git-7006b51823cc6c1f69f42f3c1599385414e6c5b4.tar.gz
Preliminary commit of HANDLER syntax (w/o LIMIT or column-list)
-rw-r--r--mysql-test/r/handler.result26
-rw-r--r--mysql-test/t/handler.test32
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/lex.h7
-rw-r--r--sql/mysql_priv.h8
-rw-r--r--sql/sql_base.cc6
-rw-r--r--sql/sql_class.cc5
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_handler.cc172
-rw-r--r--sql/sql_lex.h5
-rw-r--r--sql/sql_parse.cc19
-rw-r--r--sql/sql_yacc.yy88
12 files changed, 352 insertions, 22 deletions
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
new file mode 100644
index 00000000000..b13199ba96d
--- /dev/null
+++ b/mysql-test/r/handler.result
@@ -0,0 +1,26 @@
+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
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
new file mode 100644
index 00000000000..18f1d37fee4
--- /dev/null
+++ b/mysql-test/t/handler.test
@@ -0,0 +1,32 @@
+#
+# test of HANDLER ...
+#
+
+drop table if exists t1;
+create table t1 (a int, b char(10), key a(a));
+insert into t1 values
+(14,"aaa"),(15,"bbb"),(16,"ccc"),
+(17,"ddd"),(18,"eee"),(19,"fff"),
+(20,"ggg"),(21,"hhh"),(22,"iii");
+handler t1 open;
+handler t1 read a first;
+handler t1 read a next;
+handler t1 read a next;
+handler t1 read a prev;
+handler t1 read a last;
+handler t1 read a prev;
+handler t1 read a prev;
+
+handler t1 read a first;
+handler t1 read a prev;
+
+handler t1 read a last;
+handler t1 read a prev;
+handler t1 read a next;
+handler t1 read a next;
+
+handler t1 read a=(15);
+
+handler t1 close;
+drop table if exists t1;
+
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 7ddb88f26ed..5114ff581f7 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -54,7 +54,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\
lex.h lex_symbol.h sql_acl.h sql_crypt.h md5.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_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
thr_malloc.cc item_create.cc \
diff --git a/sql/lex.h b/sql/lex.h
index 3b43922e21f..896c9d40be9 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -82,6 +82,7 @@ static SYMBOL symbols[] = {
{ "CHANGED", SYM(CHANGED),0,0},
{ "CHECK", SYM(CHECK_SYM),0,0},
{ "CHECKSUM", SYM(CHECKSUM_SYM),0,0},
+ { "CLOSE", SYM(CLOSE_SYM),0,0},
{ "COLUMN", SYM(COLUMN_SYM),0,0},
{ "COLUMNS", SYM(COLUMNS),0,0},
{ "COMMENT", SYM(COMMENT_SYM),0,0},
@@ -152,6 +153,7 @@ static SYMBOL symbols[] = {
{ "GRANTS", SYM(GRANTS),0,0},
{ "GROUP", SYM(GROUP),0,0},
{ "HAVING", SYM(HAVING),0,0},
+ { "HANDLER", SYM(HANDLER_SYM),0,0},
{ "HEAP", SYM(HEAP_SYM),0,0},
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY),0,0},
{ "HOUR", SYM(HOUR_SYM),0,0},
@@ -184,6 +186,7 @@ static SYMBOL symbols[] = {
{ "KEY", SYM(KEY_SYM),0,0},
{ "KEYS", SYM(KEYS),0,0},
{ "KILL", SYM(KILL_SYM),0,0},
+ { "LAST", SYM(LAST_SYM),0,0},
{ "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0},
{ "LEADING", SYM(LEADING),0,0},
{ "LEFT", SYM(LEFT),0,0},
@@ -225,11 +228,12 @@ static SYMBOL symbols[] = {
{ "MYISAM", SYM(MYISAM_SYM),0,0},
{ "NATURAL", SYM(NATURAL),0,0},
{ "NATIONAL", SYM(NATIONAL_SYM),0,0},
+ { "NEXT", SYM(NEXT_SYM),0,0},
{ "NCHAR", SYM(NCHAR_SYM),0,0},
- { "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "NO", SYM(NO_SYM),0,0},
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
+ { "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
@@ -244,6 +248,7 @@ static SYMBOL symbols[] = {
{ "PASSWORD", SYM(PASSWORD),0,0},
{ "PURGE", SYM(PURGE),0,0},
{ "PRECISION", SYM(PRECISION),0,0},
+ { "PREV", SYM(PREV_SYM),0,0},
{ "PRIMARY", SYM(PRIMARY_SYM),0,0},
{ "PROCEDURE", SYM(PROCEDURE),0,0},
{ "PROCESS" , SYM(PROCESS),0,0},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 9af7012f0bc..27fc5d02988 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -381,6 +381,12 @@ int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild);
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);
+
/* sql_base.cc */
void set_item_name(Item *item,char *pos,uint length);
bool add_field_to_list(char *field_name, enum enum_field_types type,
@@ -402,6 +408,8 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error);
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);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
bool set_query_id,List<Item> *sum_func_list);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 0024e80219b..7eb26e6fb1a 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -34,8 +34,6 @@ HASH open_cache; /* Used by mysql_test */
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
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 mysql_rm_tmp_tables(void);
static key_map get_key_map_from_key_list(TABLE *table,
@@ -409,7 +407,7 @@ void close_thread_tables(THD *thd, bool locked)
{
DBUG_ENTER("close_thread_tables");
- if (thd->locked_tables)
+ if (thd->locked_tables || thd->manual_open)
DBUG_VOID_RETURN; // LOCK TABLES in use
TABLE *table,*next;
@@ -1807,7 +1805,7 @@ static key_map get_key_map_from_key_list(TABLE *table,
** Returns pointer to last inserted field if ok
****************************************************************************/
-static bool
+bool
insert_fields(THD *thd,TABLE_LIST *tables, const char *table_name,
List_iterator<Item> *it)
{
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index d4c7f77f94a..85a19d31210 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -76,7 +76,7 @@ static void free_var(user_var_entry *entry)
****************************************************************************/
THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
- insert_id_used(0),in_lock_tables(0),
+ insert_id_used(0),in_lock_tables(0),manual_open(0),
global_read_lock(0),bootstrap(0)
{
host=user=priv_user=db=query=ip=0;
@@ -158,9 +158,10 @@ THD::~THD()
net_end(&net);
}
ha_rollback(this);
- if (locked_tables)
+ if (locked_tables || manual_open)
{
lock=locked_tables; locked_tables=0;
+ manual_open=0;
close_thread_tables(this);
}
close_temporary_tables(this);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 297b6acbad5..1ad7b3b6110 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -24,7 +24,7 @@
class Query_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_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
@@ -278,7 +278,7 @@ public:
bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
- bool query_start_used,last_insert_id_used,insert_id_used;
+ bool query_start_used,last_insert_id_used,insert_id_used,manual_open;
bool system_thread,in_lock_tables,global_read_lock;
bool query_error, bootstrap;
bool volatile killed;
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
new file mode 100644
index 00000000000..df6734c5fd3
--- /dev/null
+++ b/sql/sql_handler.cc
@@ -0,0 +1,172 @@
+/* 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 "mysql_priv.h"
+#include "sql_select.h"
+
+static TABLE *find_table_by_name(THD *thd, char *db, char *table_name);
+
+int mysql_ha_open(THD *thd, TABLE_LIST *tables)
+{
+ int err=open_tables(thd,tables);
+ if (!err)
+ {
+ thd->manual_open=1;
+ send_ok(&thd->net);
+ }
+}
+
+int mysql_ha_close(THD *thd, TABLE_LIST *tables)
+{
+ send_ok(&thd->net);
+ return 0;
+}
+
+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)
+{
+ int err;
+ 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");
+ // send_error(&thd->net,ER_UNKNOWN_TABLE);
+ // send_ok(&thd->net);
+ return -1;
+ }
+ tables->table=table;
+
+ int keyno=find_type(keyname, &table->keynames, 1+2)-1;
+ if (keyno<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);
+
+ switch(mode)
+ {
+ case RFIRST:
+ err=table->file->index_first(table->record[0]);
+ break;
+ case RLAST:
+ err=table->file->index_last(table->record[0]);
+ break;
+ case RNEXT:
+ err=table->file->index_next(table->record[0]);
+ break;
+ case RPREV:
+ err=table->file->index_prev(table->record[0]);
+ break;
+ case RKEY:
+ {
+ KEY *keyinfo=table->key_info+keyno;
+ uint key_len=0, i;
+ byte *key, *buf;
+ for (i=0; i < key_expr->elements; i++)
+ key_len+=keyinfo->key_part[i].store_length;
+ if (!(key=sql_calloc(ALIGN_SIZE(key_len))))
+ {
+ send_error(&thd->net,ER_OUTOFMEMORY);
+ exit(-1);
+ }
+ List_iterator<Item> it_ke(*key_expr);
+ for (i=0, buf=key; i < key_expr->elements; i++)
+ {
+ uint maybe_null= test(keyinfo->key_part[i].null_bit);
+ store_key_item ski=store_key_item(keyinfo->key_part[i].field,
+ (char*)buf+maybe_null,maybe_null ? (char*) buf : 0,
+ keyinfo->key_part[i].length, it_ke++);
+ ski.copy();
+ buf+=keyinfo->key_part[i].store_length;
+ }
+ err=table->file->index_read(table->record[0],
+ key,key_len,ha_rkey_mode);
+ break;
+ }
+ default:
+ send_error(&thd->net,ER_ILLEGAL_HA);
+ exit(-1);
+ }
+
+ if (err && 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));
+ return -1;
+ }
+ send_fields(thd,list,1);
+ 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));
+ return -1;
+ }
+ }
+ my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
+ }
+ send_eof(&thd->net);
+ return 0;
+}
+
+/**************************************************************************
+ 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->open_tables; table ; table=table->next)
+ {
+ if (!memcmp(table->table_cache_key, db, dblen) &&
+ !my_strcasecmp(table->table_name,table_name))
+ return table;
+ }
+ return(0);
+}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 10a99f920bd..f505b870d67 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -53,7 +53,8 @@ enum enum_sql_command {
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
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,
@@ -141,6 +142,8 @@ typedef struct st_lex {
enum lex_states next_state;
enum enum_duplicates duplicates;
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;
thr_lock_type lock_option;
bool create_refs,drop_primary,drop_if_exists,local_file;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 5ed17d76dff..0789f2c07bf 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1996,6 +1996,23 @@ mysql_execute_command(void)
res = mysql_show_grants(thd,lex->grant_user);
}
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);
+ break;
+
case SQLCOM_BEGIN:
if (end_active_trans(thd))
{
@@ -2041,7 +2058,7 @@ mysql_execute_command(void)
}
thd->proc_info="query end"; // QQ
if (res < 0)
- send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0, 0);
error:
DBUG_VOID_RETURN;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 1196d279e5c..a2de97534b7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -142,6 +142,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CASCADE
%token CHECKSUM_SYM
%token CHECK_SYM
+%token CLOSE_SYM
%token COMMITTED_SYM
%token COLUMNS
%token COLUMN_SYM
@@ -176,6 +177,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GREATEST_SYM
%token GROUP
%token HAVING
+%token HANDLER_SYM
%token HEAP_SYM
%token HEX_NUM
%token HIGH_PRIORITY
@@ -193,6 +195,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token JOIN_SYM
%token KEYS
%token KEY_SYM
+%token LAST_SYM
%token LEADING
%token LEAST_SYM
%token LEVEL_SYM
@@ -220,6 +223,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NATIONAL_SYM
%token NATURAL
%token NCHAR_SYM
+%token NEXT_SYM
%token NOT
%token NO_SYM
%token NULL_SYM
@@ -236,6 +240,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DUMPFILE
%token PACK_KEYS_SYM
%token PARTIAL
+%token PREV_SYM
%token PRIMARY_SYM
%token PRIVILEGES
%token PROCESS
@@ -516,13 +521,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
select_item_list select_item values_list no_braces
limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
- when_list2 expr_list2
+ when_list2 expr_list2 handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock varchar
references opt_on_delete opt_on_delete_list opt_on_delete_item use
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_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list
@@ -530,7 +535,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
- END_OF_INPUT
+ handler_read_function handler_rkey_mode END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
@@ -579,6 +584,7 @@ verb_clause:
| slave
| show
| truncate
+ | handler
| unlock
| update
| use
@@ -2003,10 +2009,10 @@ drop:
table_list:
- table
- | table_list ',' table
+ table_name
+ | table_list ',' table_name
-table:
+table_name:
table_ident
{ if (!add_table_to_list($1,NULL,1)) YYABORT; }
@@ -2039,7 +2045,7 @@ insert2:
| insert_table {}
insert_table:
- table
+ table_name
{
Lex->field_list.empty();
Lex->many_values.empty();
@@ -2128,7 +2134,7 @@ values:
/* Update rows in a table */
update:
- UPDATE_SYM opt_low_priority opt_ignore table SET update_list where_clause delete_limit_clause
+ UPDATE_SYM opt_low_priority opt_ignore table_name SET update_list where_clause delete_limit_clause
{ Lex->sql_command = SQLCOM_UPDATE; }
update_list:
@@ -2155,7 +2161,7 @@ delete:
Lex->sql_command= SQLCOM_DELETE; Lex->options=0;
Lex->lock_option= current_thd->update_lock_default;
}
- opt_delete_options FROM table
+ opt_delete_options FROM table_name
where_clause delete_limit_clause
@@ -2168,7 +2174,7 @@ opt_delete_option:
| LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
truncate:
- TRUNCATE_SYM opt_table_sym table
+ TRUNCATE_SYM opt_table_sym table_name
{ Lex->sql_command= SQLCOM_TRUNCATE; Lex->options=0;
Lex->lock_option= current_thd->update_lock_default; }
@@ -2519,6 +2525,7 @@ keyword:
| CHANGED {}
| CHECKSUM_SYM {}
| CHECK_SYM {}
+ | CLOSE_SYM {}
| COMMENT_SYM {}
| COMMIT_SYM {}
| COMMITTED_SYM {}
@@ -2544,12 +2551,14 @@ keyword:
| GEMINI_SYM {}
| GLOBAL_SYM {}
| HEAP_SYM {}
+ | HANDLER_SYM {}
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
| ISOLATION {}
| ISAM_SYM {}
| INNOBASE_SYM {}
+ | LAST_SYM {}
| LEVEL_SYM {}
| LOCAL_SYM {}
| LOGS_SYM {}
@@ -2572,10 +2581,12 @@ keyword:
| MYISAM_SYM {}
| NATIONAL_SYM {}
| NCHAR_SYM {}
+ | NEXT_SYM {}
| NO_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PASSWORD {}
+ | PREV_SYM {}
| PROCESS {}
| PROCESSLIST_SYM {}
| QUICK {}
@@ -2832,6 +2843,63 @@ unlock:
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
+/*
+** Table: 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 ident handler_read_function
+ {
+ Lex->sql_command = SQLCOM_HA_READ;
+ Lex->backup_dir= $4.str;
+ if (!add_table_to_list($2,0,0))
+ YYABORT;
+ }
+
+handler_read_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 */
revoke: