Commit 7006b518 authored by unknown's avatar unknown

Preliminary commit of HANDLER syntax (w/o LIMIT or column-list)

parent 50007b28
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));
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;
......@@ -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 \
......
......@@ -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},
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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;
......
/* 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);
}
......@@ -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;
......
......@@ -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;
......
......@@ -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:
......
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