summaryrefslogtreecommitdiff
path: root/sql/sql_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_handler.cc')
-rw-r--r--sql/sql_handler.cc151
1 files changed, 88 insertions, 63 deletions
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 28e94d1a477..12acf344c31 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -1,5 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+/* Copyright (C) 2000-2004 MySQL 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
@@ -65,7 +64,7 @@
#define HANDLER_TABLES_HASH_SIZE 120
static enum enum_ha_read_modes rkey_to_rnext[]=
- { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
+ { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
#define HANDLER_TABLES_HACK(thd) { \
TABLE *tmp=thd->open_tables; \
@@ -148,12 +147,8 @@ static void mysql_ha_hash_free(TABLE_LIST *tables)
int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
TABLE_LIST *hash_tables;
- char *db;
- char *name;
- char *alias;
- uint dblen;
- uint namelen;
- uint aliaslen;
+ char *db, *name, *alias;
+ uint dblen, namelen, aliaslen, counter;
int err;
DBUG_ENTER("mysql_ha_open");
DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
@@ -165,7 +160,8 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
/*
HASH entries are of type TABLE_LIST.
*/
- if (hash_init(&thd->handler_tables_hash, HANDLER_TABLES_HASH_SIZE, 0, 0,
+ if (hash_init(&thd->handler_tables_hash, &my_charset_latin1,
+ HANDLER_TABLES_HASH_SIZE, 0, 0,
(hash_get_key) mysql_ha_hash_get_key,
(hash_free_key) mysql_ha_hash_free, 0))
goto err;
@@ -189,7 +185,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
*/
DBUG_ASSERT(! tables->table);
HANDLER_TABLES_HACK(thd);
- err=open_tables(thd,tables);
+ err=open_tables(thd, tables, &counter);
HANDLER_TABLES_HACK(thd);
if (err)
goto err;
@@ -226,7 +222,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
memcpy(hash_tables->alias, tables->alias, aliaslen);
/* add to hash */
- if (hash_insert(&thd->handler_tables_hash, (byte*) hash_tables))
+ if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables))
{
mysql_ha_close(thd, tables);
goto err;
@@ -234,7 +230,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
}
if (! reopen)
- send_ok(&thd->net);
+ send_ok(thd);
DBUG_PRINT("exit",("OK"));
DBUG_RETURN(0);
@@ -294,6 +290,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
if (*table_ptr)
{
+ (*table_ptr)->file->ha_index_or_rnd_end();
VOID(pthread_mutex_lock(&LOCK_open));
if (close_thread_table(thd, table_ptr))
{
@@ -325,7 +322,7 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
DBUG_RETURN(-1);
}
- send_ok(&thd->net);
+ send_ok(thd);
DBUG_PRINT("exit", ("OK"));
DBUG_RETURN(0);
}
@@ -359,15 +356,22 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
TABLE_LIST *hash_tables;
TABLE **table_ptr;
TABLE *table;
- int err;
- int keyno=-1;
- uint num_rows;
MYSQL_LOCK *lock;
+ List<Item> list;
+ Protocol *protocol= thd->protocol;
+ char buff[MAX_FIELD_WIDTH];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ int err, keyno= -1;
+ uint num_rows;
+ byte *key;
+ uint key_len;
DBUG_ENTER("mysql_ha_read");
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
tables->db, tables->real_name, tables->alias));
- List<Item> list;
+ LINT_INIT(key);
+ LINT_INIT(key_len);
+
list.push_front(new Item_field(NULL,NULL,"*"));
List_iterator<Item> it(list);
it++;
@@ -447,11 +451,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
}
tables->table=table;
- if (cond && cond->fix_fields(thd,tables))
+ if (cond && ((!cond->fixed &&
+ cond->fix_fields(thd, tables, &cond)) || cond->check_cols(1)))
goto err0;
- table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
-
if (keyname)
{
if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0)
@@ -460,55 +463,71 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
keyname,tables->alias);
goto err0;
}
- table->file->index_init(keyno);
}
if (insert_fields(thd,tables,tables->db,tables->alias,&it))
goto err0;
select_limit+=offset_limit;
- send_fields(thd,list,1);
+ protocol->send_fields(&list,1);
HANDLER_TABLES_HACK(thd);
lock= mysql_lock_tables(thd, &tables->table, 1, 0);
HANDLER_TABLES_HACK(thd);
-
- byte *key;
- uint key_len;
- LINT_INIT(key);
- LINT_INIT(key_len);
+
if (!lock)
goto err0; // mysql_lock_tables() printed error message already
- table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
+ /*
+ In ::external_lock InnoDB resets the fields which tell it that
+ the handle is used in the HANDLER interface. Tell it again that
+ we are using it for HANDLER.
+ */
+
+ table->file->init_table_handle_for_HANDLER();
for (num_rows=0; num_rows < select_limit; )
{
- switch(mode) {
+ switch (mode) {
+ case RNEXT:
+ if (table->file->inited != handler::NONE)
+ {
+ err=keyname ?
+ table->file->index_next(table->record[0]) :
+ table->file->rnd_next(table->record[0]);
+ break;
+ }
+ /* else fall through */
case RFIRST:
if (keyname)
+ {
+ table->file->ha_index_or_rnd_end();
+ table->file->ha_index_init(keyno);
err=table->file->index_first(table->record[0]);
+ }
else
{
- if (!(err=table->file->rnd_init(1)))
+ table->file->ha_index_or_rnd_end();
+ if (!(err=table->file->ha_rnd_init(1)))
err=table->file->rnd_next(table->record[0]);
}
mode=RNEXT;
break;
+ case RPREV:
+ DBUG_ASSERT(keyname != 0);
+ if (table->file->inited != handler::NONE)
+ {
+ err=table->file->index_prev(table->record[0]);
+ break;
+ }
+ /* else fall through */
case RLAST:
DBUG_ASSERT(keyname != 0);
+ table->file->ha_index_or_rnd_end();
+ table->file->ha_index_init(keyno);
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 RNEXT_SAME:
/* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */
DBUG_ASSERT(keyname != 0);
@@ -521,37 +540,42 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
KEY_PART_INFO *key_part=keyinfo->key_part;
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;
+ my_printf_error(ER_TOO_MANY_KEY_PARTS,ER(ER_TOO_MANY_KEY_PARTS),
+ MYF(0),keyinfo->key_parts);
+ goto err;
}
- List_iterator_fast<Item> it_ke(*key_expr);
+ List_iterator<Item> it_ke(*key_expr);
Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++)
{
- if (item->fix_fields(thd, tables))
- goto err;
- if (item->used_tables() & ~RAND_TABLE_BIT)
+ // 'item' can be changed by fix_fields() call
+ if ((!item->fixed &&
+ item->fix_fields(thd, tables, it_ke.ref())) ||
+ (item= *it_ke.ref())->check_cols(1))
+ goto err;
+ if (item->used_tables() & ~RAND_TABLE_BIT)
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"HANDLER ... READ");
- goto err;
+ goto err;
}
- item->save_in_field(key_part->field, 1);
- key_len+=key_part->store_length;
+ (void) item->save_in_field(key_part->field, 1);
+ key_len+=key_part->store_length;
}
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
{
- send_error(&thd->net,ER_OUTOFMEMORY);
- goto err;
+ send_error(thd,ER_OUTOFMEMORY);
+ goto err;
}
key_copy(key, table, keyno, key_len);
+ table->file->ha_index_or_rnd_end();
+ table->file->ha_index_init(keyno);
err=table->file->index_read(table->record[0],
- key,key_len,ha_rkey_mode);
+ key,key_len,ha_rkey_mode);
mode=rkey_to_rnext[(int)ha_rkey_mode];
break;
}
default:
- send_error(&thd->net,ER_ILLEGAL_HA);
+ send_error(thd,ER_ILLEGAL_HA);
goto err;
}
@@ -572,26 +596,25 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
continue;
if (num_rows >= offset_limit)
{
- String *packet = &thd->packet;
Item *item;
- packet->length(0);
+ protocol->prepare_for_resend();
it.rewind();
while ((item=it++))
{
- if (item->send(thd,packet))
+ if (item->send(thd->protocol, &buffer))
{
- packet->free(); // Free used
+ protocol->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0));
goto err;
}
}
- my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
+ protocol->write();
}
num_rows++;
}
ok:
mysql_unlock_tables(thd,lock);
- send_eof(&thd->net);
+ send_eof(thd);
DBUG_PRINT("exit",("OK"));
DBUG_RETURN(0);
@@ -654,8 +677,10 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
while (*table_ptr)
{
if ((! *tmp_tables->db ||
- ! my_strcasecmp((*table_ptr)->table_cache_key, tmp_tables->db)) &&
- ! my_strcasecmp((*table_ptr)->real_name, tmp_tables->real_name))
+ ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->table_cache_key,
+ tmp_tables->db)) &&
+ ! my_strcasecmp(&my_charset_latin1, (*table_ptr)->real_name,
+ tmp_tables->real_name))
{
DBUG_PRINT("info",("*table_ptr '%s'.'%s' as '%s'",
(*table_ptr)->table_cache_key,
@@ -749,6 +774,7 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
}
safe_mutex_assert_owner(&LOCK_open);
+ (*table_ptr)->file->ha_index_or_rnd_end();
if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
@@ -757,4 +783,3 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
DBUG_RETURN(0);
}
-