summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorserg@serg.mysql.com <>2001-04-13 16:18:44 +0200
committerserg@serg.mysql.com <>2001-04-13 16:18:44 +0200
commitca0ba8e0ab4c765178d7dc3e703e70919f83bfa1 (patch)
treef12dcf690b5fcec38c52c0128c2854c62729ee9d /sql
parenta981cfbdcb534675cc4cf92fd583826d746e68c8 (diff)
downloadmariadb-git-ca0ba8e0ab4c765178d7dc3e703e70919f83bfa1.tar.gz
this won't be pushed
Diffstat (limited to 'sql')
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.cc13
-rw-r--r--sql/sql_class.h6
-rw-r--r--sql/sql_handler.cc225
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_yacc.yy57
7 files changed, 185 insertions, 128 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 89bb69f6d92..4a0ec80077f 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -384,8 +384,8 @@ 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,ha_rows,ha_rows);
+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 */
void set_item_name(Item *item,char *pos,uint length);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 7eb26e6fb1a..35d8749b452 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -407,7 +407,7 @@ void close_thread_tables(THD *thd, bool locked)
{
DBUG_ENTER("close_thread_tables");
- if (thd->locked_tables || thd->manual_open)
+ if (thd->locked_tables)
DBUG_VOID_RETURN; // LOCK TABLES in use
TABLE *table,*next;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 85a19d31210..567f1e1281e 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),manual_open(0),
+ insert_id_used(0),in_lock_tables(0),
global_read_lock(0),bootstrap(0)
{
host=user=priv_user=db=query=ip=0;
@@ -85,7 +85,8 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
query_length=col_access=0;
query_error=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;
lock=locked_tables=0;
used_tables=0;
@@ -158,10 +159,14 @@ THD::~THD()
net_end(&net);
}
ha_rollback(this);
- if (locked_tables || manual_open)
+ if (locked_tables)
{
lock=locked_tables; locked_tables=0;
- manual_open=0;
+ close_thread_tables(this);
+ }
+ if (handler_tables)
+ {
+ open_tables=handler_tables; handler_tables=0;
close_thread_tables(this);
}
close_temporary_tables(this);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 1ad7b3b6110..e9d5bc82fd3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -231,7 +231,7 @@ public:
const char *proc_info;
uint client_capabilities,max_packet_length;
uint master_access,db_access;
- TABLE *open_tables,*temporary_tables;
+ TABLE *open_tables,*temporary_tables, *handler_tables;
MYSQL_LOCK *lock,*locked_tables;
ULL *ull;
struct st_my_thread_var *mysys_var;
@@ -253,7 +253,7 @@ public:
#ifdef HAVE_GEMINI_DB
struct st_gemini gemini;
#endif
- Item *free_list;
+ Item *free_list, *handler_items;
CONVERT *convert_set;
Field *dupp_field;
#ifndef __WIN__
@@ -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,manual_open;
+ bool query_start_used,last_insert_id_used,insert_id_used;
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
index 0d82fda8844..9dbfc6f8626 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -17,23 +17,53 @@
/* 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);
- if (!err)
- {
- thd->manual_open=1;
- send_ok(&thd->net);
- }
+ 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;
}
@@ -43,27 +73,30 @@ static enum enum_ha_read_modes rkey_to_rnext[]=
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,
+ enum ha_rkey_function ha_rkey_mode, Item *cond,
ha_rows select_limit,ha_rows offset_limit)
{
- int err;
+ 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");
- // send_error(&thd->net,ER_UNKNOWN_TABLE);
- // send_ok(&thd->net);
+ tables->name,"HANDLER");
return -1;
}
tables->table=table;
+
+ if (cond && cond->fix_fields(thd,tables))
+ return -1;
- int keyno=find_type(keyname, &table->keynames, 1+2)-1;
- if (keyno<0)
+ if (keyname)
{
- my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
- keyname,tables->name);
- return -1;
+ 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;
@@ -72,99 +105,121 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
it++;
insert_fields(thd,tables,tables->name,&it);
-
+
table->file->index_init(keyno);
+
+ select_limit+=offset_limit;
+ send_fields(thd,list,1);
- if (select_limit == thd->default_select_limit) select_limit=1;
+ MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
- select_limit+=offset_limit;
- for (uint num_rows=0; num_rows < select_limit; num_rows++)
+ for (uint num_rows=0; num_rows < select_limit; )
{
switch(mode)
{
case RFIRST:
- err=table->file->index_first(table->record[0]);
- mode=RNEXT;
- break;
+ 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:
- err=table->file->index_last(table->record[0]);
- mode=RPREV;
- break;
+ dbug_assert(keyname != 0);
+ err=table->file->index_last(table->record[0]);
+ mode=RPREV;
+ break;
case RNEXT:
- err=table->file->index_next(table->record[0]);
- break;
+ err=keyname ?
+ table->file->index_next(table->record[0]) :
+ table->file->rnd_next(table->record[0]);
+ break;
case RPREV:
- err=table->file->index_prev(table->record[0]);
- break;
+ dbug_assert(keyname != 0);
+ 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;
- 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);
- return -1;
- }
- 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);
- return -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);
- mode=rkey_to_rnext[(int)ha_rkey_mode];
- break;
- }
+ {
+ 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);
- return -1;
+ send_error(&thd->net,ER_ILLEGAL_HA);
+ goto err;
}
- if (err && err != HA_ERR_KEY_NOT_FOUND && err != HA_ERR_END_OF_FILE)
+ if (err)
{
- sql_print_error("mysql_ha_read: Got error %d when reading table",
- err);
- table->file->print_error(err,MYF(0));
- return -1;
+ 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 (num_rows==offset_limit) 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());
+ 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;
}
/**************************************************************************
@@ -184,10 +239,10 @@ static TABLE *find_table_by_name(THD *thd, char *db, char *table_name)
if (!db || ! *db) db="";
dblen=strlen(db);
- for (TABLE *table=thd->open_tables; table ; table=table->next)
+ 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))
+ !my_strcasecmp(table->table_name,table_name))
return table;
}
return(0);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 72f163ec677..ea0531fb765 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2009,8 +2009,8 @@ mysql_execute_command(void)
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,
+ 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;
@@ -2059,7 +2059,7 @@ mysql_execute_command(void)
}
thd->proc_info="query end"; // QQ
if (res < 0)
- send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0, 0);
+ send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0);
error:
DBUG_VOID_RETURN;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 9942be1506f..214227ba063 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -535,7 +535,8 @@ 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
- handler_read_function handler_rkey_mode END_OF_INPUT
+ handler_rkey_function handler_rkey_mode handler_read_or_scan
+ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
@@ -1904,7 +1905,8 @@ order_dir:
limit_clause:
/* 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;
}
| LIMIT ULONG_NUM
@@ -2844,7 +2846,7 @@ unlock:
/*
-** Table: direct access to ISAM functions
+** Handler: direct access to ISAM functions
*/
handler:
@@ -2860,45 +2862,40 @@ handler:
if (!add_table_to_list($2,0,0))
YYABORT;
}
- | HANDLER_SYM table_ident READ_SYM ident handler_read_function limit_clause
+ | HANDLER_SYM table_ident READ_SYM handler_read_or_scan
{
Lex->sql_command = SQLCOM_HA_READ;
- Lex->backup_dir= $4.str;
if (!add_table_to_list($2,0,0))
YYABORT;
- }
+ }
+ where_clause limit_clause { }
-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_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 ')' { }
+ } '(' 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; }
+ 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 */