summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormonty@donna.mysql.com <>2001-01-17 03:15:20 +0200
committermonty@donna.mysql.com <>2001-01-17 03:15:20 +0200
commit0732f7475eb4775fcfff20257bbe386b38e51a99 (patch)
tree256b185f833ce2fac42471efe65aa7bde9b9a8da /sql
parent5f4a3f51675240ac05daaba50926740e380e5016 (diff)
downloadmariadb-git-0732f7475eb4775fcfff20257bbe386b38e51a99.tar.gz
Fixed for bugs that was found when getting full code coverage of BDB
Fixed bug with HEAP tables on windows Fixed bug with HAVING on empty tables
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc65
-rw-r--r--sql/field.h44
-rw-r--r--sql/ha_berkeley.cc83
-rw-r--r--sql/ha_heap.cc4
-rw-r--r--sql/log.cc2
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/table.cc2
7 files changed, 127 insertions, 81 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 1c6aa32e167..225189a1098 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3599,7 +3599,7 @@ void Field_varstring::sql_type(String &res) const
char *Field_varstring::pack(char *to, const char *from, uint max_length)
{
- uint length=uint2korr(to);
+ uint length=uint2korr(from);
if (length > max_length)
length=max_length;
*to++= (length & 255);
@@ -4037,6 +4037,43 @@ void Field_blob::sql_type(String &res) const
}
+char *Field_blob::pack(char *to, const char *from, uint max_length)
+{
+ char *save=ptr;
+ ptr=(char*) from;
+ ulong length=get_length(); // Length of from string
+ if (length > max_length)
+ {
+ ptr=to;
+ length=max_length;
+ store_length(length); // Store max length
+ ptr=(char*) from;
+ }
+ else
+ memcpy(to,from,packlength); // Copy length
+ if (length)
+ {
+ get_ptr((char**) &from);
+ memcpy(to+packlength, from,length);
+ }
+ ptr=save; // Restore org row pointer
+ return to+packlength+length;
+}
+
+
+const char *Field_blob::unpack(char *to, const char *from)
+{
+ memcpy(to,from,packlength);
+ from+=packlength;
+ ulong length=get_length();
+ if (length)
+ memcpy_fixed(to+packlength, &from, sizeof(from));
+ else
+ bzero(to+packlength,sizeof(from));
+ return from+length;
+}
+
+
/* Keys for blobs are like keys on varchars */
int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
@@ -4087,10 +4124,33 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
return my_sortncmp(a,a_length, b,b_length);
}
+/* Create a packed key that will be used for storage from a MySQL row */
char *Field_blob::pack_key(char *to, const char *from, uint max_length)
{
- uint length=uint2korr(to);
+ char *save=ptr;
+ ptr=(char*) from;
+ ulong length=get_length(); // Length of from string
+ if (length > max_length)
+ length=max_length;
+ *to++= (uchar) length;
+ if (max_length > 255) // 2 byte length
+ *to++= (uchar) (length >> 8);
+ if (length)
+ {
+ get_ptr((char**) &from);
+ memcpy(to, from, length);
+ }
+ ptr=save; // Restore org row pointer
+ return to+length;
+}
+
+/* Create a packed key that will be used for storage from a MySQL key */
+
+char *Field_blob::pack_key_from_key_image(char *to, const char *from,
+ uint max_length)
+{
+ uint length=uint2korr(from);
if (length > max_length)
length=max_length;
*to++= (length & 255);
@@ -4101,6 +4161,7 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
return to+length;
}
+
/****************************************************************************
** enum type.
** This is a string which only can have a selection of different values.
diff --git a/sql/field.h b/sql/field.h
index 4af7c17486a..21fd9ebffd9 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -166,7 +166,12 @@ public:
memcpy(to,from,length);
return from+length;
}
- virtual char *keypack(char* to, const char *from, uint max_length=~(uint) 0)
+ virtual char *pack_key(char* to, const char *from, uint max_length)
+ {
+ return pack(to,from,max_length);
+ }
+ virtual char *pack_key_from_key_image(char* to, const char *from,
+ uint max_length)
{
return pack(to,from,max_length);
}
@@ -861,39 +866,10 @@ public:
tmp=(char*) value.ptr(); memcpy_fixed(ptr+packlength,&tmp,sizeof(char*));
return 0;
}
- char *pack(char *to, const char *from, uint max_length= ~(uint) 0)
- {
- ulong length=get_length();
- if (length > max_length)
- {
- length=max_length;
- char *save=ptr;
- ptr=to;
- store_length(length);
- ptr=save;
- }
- else
- memcpy(to,from,packlength);
- if (length)
- {
- get_ptr((char**) &from);
- memcpy(to+packlength, from,length);
- return to+packlength+length;
- }
- return to+packlength;
- }
- const char *unpack(char *to, const char *from)
- {
- memcpy(to,from,packlength);
- from+=packlength;
- ulong length=get_length();
- if (length)
- memcpy_fixed(to+packlength, &from, sizeof(from));
- else
- bzero(to+packlength,sizeof(from));
- return from+length;
- }
- char *pack_key(char *to, const char *from, uint max_length=~(uint) 0);
+ char *pack(char *to, const char *from, uint max_length= ~(uint) 0);
+ const char *unpack(char *to, const char *from);
+ char *pack_key(char *to, const char *from, uint max_length);
+ char *pack_key_from_key_image(char* to, const char *from, uint max_length);
int pack_cmp(const char *a, const char *b, uint key_length);
int pack_cmp(const char *b, uint key_length);
uint packed_col_length(const char *col_ptr)
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index b26c3ad31de..a2057382e62 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -42,7 +42,6 @@
Testing of:
- LOCK TABLES
- - BLOBS
- Mark tables that participate in a transaction so that they are not
closed during the transaction. We need to test what happens if
MySQL closes a table that is updated by a not commit transaction.
@@ -290,7 +289,7 @@ static void berkeley_noticecall(DB_ENV *db_env, db_notices notice)
{
switch (notice)
{
- case DB_NOTICE_LOGFILE_CHANGED:
+ case DB_NOTICE_LOGFILE_CHANGED: /* purecov: tested */
pthread_mutex_lock(&LOCK_manager);
manager_status |= MANAGER_BERKELEY_LOG_CLEANUP;
pthread_mutex_unlock(&LOCK_manager);
@@ -418,6 +417,10 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
if (key_part->null_bit)
{
key_length--;
+ /*
+ With the current usage, the following case will always be FALSE,
+ because NULL keys are sorted before any other key
+ */
if (*key != (table->record[0][key_part->null_offset] &
key_part->null_bit) ? 0 : 1)
return 1;
@@ -731,7 +734,6 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
DBUG_ENTER("create_key");
key->data=buff;
-
for ( ; key_part != end && key_length > 0; key_part++)
{
if (key_part->null_bit)
@@ -745,8 +747,8 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
}
*buff++ = 1; // Store NOT NULL marker
}
- buff=key_part->field->pack(buff,record + key_part->offset,
- key_part->length);
+ buff=key_part->field->pack_key(buff,record + key_part->offset,
+ key_part->length);
key_length-=key_part->length;
}
key->size= (buff - (char*) key->data);
@@ -783,7 +785,8 @@ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff,
}
key_ptr++;
}
- buff=key_part->field->keypack(buff,key_ptr,key_part->length);
+ buff=key_part->field->pack_key_from_key_image(buff,key_ptr,
+ key_part->length);
key_ptr+=key_part->store_length;
key_length-=key_part->store_length;
}
@@ -807,7 +810,7 @@ int ha_berkeley::write_row(byte * record)
if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */
- if (table->keys == 1)
+ if (table->keys + test(hidden_primary_key) == 1)
{
error=file->put(file, transaction, create_key(&prim_key, primary_key,
key_buff, record),
@@ -859,8 +862,8 @@ int ha_berkeley::write_row(byte * record)
int new_error = 0;
if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
{
- DBUG_PRINT("trans",("aborting subtransaction"));
- new_error=txn_abort(sub_trans);
+ DBUG_PRINT("trans",("aborting subtransaction")); /* purecov: deadcode */
+ new_error=txn_abort(sub_trans); /* purecov: deadcode */
}
else if (changed_keys)
{
@@ -871,14 +874,14 @@ int ha_berkeley::write_row(byte * record)
{
if ((new_error = remove_key(sub_trans, keynr, record,
(DBT*) 0, &prim_key)))
- break;
+ break; /* purecov: inspected */
}
}
}
if (new_error)
{
- error=new_error; // This shouldn't happen
- break;
+ error=new_error; // This shouldn't happen /* purecov: inspected */
+ break; /* purecov: inspected */
}
}
}
@@ -1185,7 +1188,8 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record,
*/
dbug_assert(keynr != primary_key && prim_key->data != key_buff2);
DBC *tmp_cursor;
- if (!(error=file->cursor(key_file[keynr], trans, &tmp_cursor, 0)))
+ if (!(error=key_file[keynr]->cursor(key_file[keynr], trans,
+ &tmp_cursor, 0)))
{
if (!(error=cursor->c_get(tmp_cursor,
(keynr == primary_key ?
@@ -1294,9 +1298,10 @@ int ha_berkeley::index_init(uint keynr)
DBUG_ENTER("index_init");
active_index=keynr;
dbug_assert(cursor == 0);
- if ((error=file->cursor(key_file[keynr], transaction, &cursor,
- table->reginfo.lock_type > TL_WRITE_ALLOW_READ ?
- 0 : 0)))
+ if ((error=key_file[keynr]->cursor(key_file[keynr], transaction, &cursor,
+ table->reginfo.lock_type >
+ TL_WRITE_ALLOW_READ ?
+ 0 : 0)))
cursor=0; // Safety /* purecov: inspected */
bzero((char*) &last_key,sizeof(last_key));
DBUG_RETURN(error);
@@ -1353,8 +1358,8 @@ int ha_berkeley::read_row(int error, char *buf, uint keynr, DBT *row,
current_row.flags=DB_DBT_REALLOC;
if ((error=file->get(file, transaction, &key, &current_row, 0)))
{
- table->status=STATUS_NOT_FOUND;
- DBUG_RETURN(error == DB_NOTFOUND ? HA_ERR_CRASHED : error);
+ table->status=STATUS_NOT_FOUND; /* purecov: inspected */
+ DBUG_RETURN(error == DB_NOTFOUND ? HA_ERR_CRASHED : error); /* purecov: inspected */
}
row= &current_row;
}
@@ -1371,7 +1376,7 @@ int ha_berkeley::index_read_idx(byte * buf, uint keynr, const byte * key,
statistic_increment(ha_read_key_count,&LOCK_status);
DBUG_ENTER("index_read_idx");
current_row.flags=DB_DBT_REALLOC;
- DBUG_RETURN(read_row(file->get(key_file[keynr], transaction,
+ DBUG_RETURN(read_row(key_file[keynr]->get(key_file[keynr], transaction,
pack_key(&last_key, keynr, key_buff, key,
key_len),
&current_row,0),
@@ -1389,13 +1394,15 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
statistic_increment(ha_read_key_count,&LOCK_status);
bzero((char*) &row,sizeof(row));
- if (key_len == key_info->key_length)
+ if (key_len == key_info->key_length + key_info->extra_length)
{
error=read_row(cursor->c_get(cursor, pack_key(&last_key,
active_index,
key_buff,
key, key_len),
- &row, DB_SET),
+ &row,
+ (find_flag == HA_READ_KEY_EXACT ?
+ DB_SET : DB_SET_RANGE)),
buf, active_index, &row, (DBT*) 0, 0);
}
else
@@ -1840,16 +1847,18 @@ ha_rows ha_berkeley::records_in_range(int keynr,
{
DBT key;
DB_KEY_RANGE start_range, end_range;
+ DB *kfile=key_file[keynr];
double start_pos,end_pos,rows;
DBUG_ENTER("records_in_range");
- if ((start_key && file->key_range(key_file[keynr],transaction,
- pack_key(&key, keynr, key_buff, start_key,
- start_key_len),
- &start_range,0)) ||
- (end_key && file->key_range(key_file[keynr],transaction,
- pack_key(&key, keynr, key_buff, end_key,
- end_key_len),
- &end_range,0)))
+
+ if ((start_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff, start_key,
+ start_key_len),
+ &start_range,0)) ||
+ (end_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff, end_key,
+ end_key_len),
+ &end_range,0)))
DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); // Better than returning an error /* purecov: inspected */
if (!start_key)
@@ -1969,8 +1978,8 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
free(stat);
stat=0;
}
- if (file->stat(key_file[i], (void*) &stat, 0, 0))
- goto err;
+ if (key_file[i]->stat(key_file[i], (void*) &stat, 0, 0))
+ goto err; /* purecov: inspected */
share->rec_per_key[i]= (stat->bt_ndata /
(stat->bt_nkeys ? stat->bt_nkeys : 1));
}
@@ -1983,7 +1992,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
stat=0;
}
if (file->stat(file, (void*) &stat, 0, 0))
- goto err;
+ goto err; /* purecov: inspected */
}
pthread_mutex_lock(&share->mutex);
share->rows=stat->bt_ndata;
@@ -1997,9 +2006,9 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
HA_ADMIN_OK);
err:
- if (stat)
- free(stat);
- return HA_ADMIN_FAILED;
+ if (stat) /* purecov: inspected */
+ free(stat); /* purecov: inspected */
+ return HA_ADMIN_FAILED; /* purecov: inspected */
}
int ha_berkeley::optimize(THD* thd, HA_CHECK_OPT* check_opt)
@@ -2036,7 +2045,7 @@ int ha_berkeley::check(THD* thd, HA_CHECK_OPT* check_opt)
tmp_file->set_bt_compare(tmp_file,
(hidden_primary_key ? berkeley_cmp_hidden_key :
berkeley_cmp_packed_key));
- file->app_private= (void*) (table->key_info+table->primary_key);
+ tmp_file->app_private= (void*) (table->key_info+table->primary_key);
fn_format(name_buff,share->table_name,"", ha_berkeley_ext, 2 | 4);
if ((error=tmp_file->verify(tmp_file, name_buff, NullS, (FILE*) 0,
hidden_primary_key ? 0 : DB_NOORDERCHK)))
@@ -2196,7 +2205,7 @@ void ha_berkeley::get_status()
{
share->org_rows=share->rows=
table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS;
- if (!file->cursor(share->status_block, 0, &cursor, 0))
+ if (!share->status_block->cursor(share->status_block, 0, &cursor, 0))
{
DBT row;
char rec_buff[64];
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 0a8f55bc5bb..13dccc2bf64 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -70,7 +70,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
}
mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
max_rows = (ulong) (max_heap_table_size / mem_per_row);
- file=heap_open(table->path,mode,
+ file=heap_open(name,mode,
table->keys,keydef,
table->reclength,
((table->max_rows < max_rows && table->max_rows) ?
@@ -278,5 +278,5 @@ int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
{
char buff[FN_REFLEN];
- return heap_create(fn_format(buff,name,"","",2));
+ return heap_create(fn_format(buff,name,"","",4+2));
}
diff --git a/sql/log.cc b/sql/log.cc
index df3168c02cf..45e4c1620b5 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -952,7 +952,7 @@ void sql_print_error(const char *format,...)
#ifndef DBUG_OFF
{
char buff[1024];
- vsnprintf(buff,sizeof(buff)-1,format,args);
+ my_vsnprintf(buff,sizeof(buff)-1,format,args);
DBUG_PRINT("error",("%s",buff));
}
#endif
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 7cbd022a7b7..2d8373ec067 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -314,7 +314,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ /* Impossible cond */
error=return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 && !group,
- select_options,"Impossible WHERE",join.having,
+ select_options,"Impossible WHERE",having,
procedure);
delete procedure;
DBUG_RETURN(error);
@@ -330,7 +330,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{
error=return_zero_rows(result, tables, fields, !group,
select_options,"No matching min/max row",
- join.having,procedure);
+ having,procedure);
delete procedure;
DBUG_RETURN(error);
}
@@ -383,7 +383,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{
error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 &&
- !group,0,"",join.having,procedure);
+ !group,0,"",having,procedure);
goto err;
}
if (!(thd->options & OPTION_BIG_SELECTS) &&
@@ -414,7 +414,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
join.tmp_table_param.sum_func_count != 0 && !group,
select_options,
"Impossible WHERE noticed after reading const tables",
- join.having,procedure);
+ having,procedure);
goto err;
}
diff --git a/sql/table.cc b/sql/table.cc
index 70efd41425c..762c28b0fbf 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -531,7 +531,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{
int err;
if ((err=(outparam->file->
- ha_open(index_file,
+ ha_open(unpack_filename(index_file,index_file),
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
((db_stat & HA_WAIT_IF_LOCKED) ||