Commit 703ed504 authored by unknown's avatar unknown

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


Docs/manual.texi:
  Update of UDF functions
mysql-test/mysql-test-run.sh:
  Added option --user
mysql-test/r/bdb.result:
  Added more test to get better coverage
mysql-test/t/bdb.test:
  Added more test to get better coverage
sql/field.cc:
  Fixes for key packing in BDB
sql/field.h:
  Fixes for key packing in BDB
sql/ha_berkeley.cc:
  Fixed for bugs that was found when getting full code coverage
sql/ha_heap.cc:
  Fixed problem with HEAP tables on windows
sql/log.cc:
  Safety fix
sql/sql_select.cc:
  Fixed bug with HAVING on empty tables
sql/table.cc:
  Fixed problem with HEAP tables on windows
parent ad996362
...@@ -31588,17 +31588,22 @@ message to less than 80 characters so that it fits the width of a standard ...@@ -31588,17 +31588,22 @@ message to less than 80 characters so that it fits the width of a standard
terminal screen. terminal screen.
The return value of the main function @code{xxx()} is the function value, for The return value of the main function @code{xxx()} is the function value, for
@code{long long} and @code{double} functions. For string functions, the @code{long long} and @code{double} functions. A string functions should
string is returned in the @code{result} and @code{length} arguments. return a pointer to the result and store the length of the string in the
@code{result} is a buffer at least 255 bytes long. Set these to the contents @code{length} arguments. @code{result} is a buffer at least 255 bytes long.
and length of the return value. For example: Set these to the contents and length of the return value. For example:
@example @example
memcpy(result, "result string", 13); memcpy(result, "result string", 13);
*length = 13; *length = 13;
@end example @end example
The string function return value normally also points to the result. If your string functions that needs to return a string longer than 255
bytes, you must allocate the space for it with @code{malloc()} in your
@code{xxx_init()} function or your @code{xxx()} function and free it in
your @code{xxx_deinit()} function. You can store the allocated memory
in the @code{ptr} slot in the @code{UDF_INIT} structure for reuse by
future @code{xxx()} calls. @xref{UDF calling sequences}.
To indicate a return value of @code{NULL} in the main function, set To indicate a return value of @code{NULL} in the main function, set
@code{is_null} to @code{1}: @code{is_null} to @code{1}:
...@@ -40403,6 +40408,12 @@ though, so Version 3.23 is not released as a stable version yet. ...@@ -40403,6 +40408,12 @@ though, so Version 3.23 is not released as a stable version yet.
@appendixsubsec Changes in release 3.23.31 @appendixsubsec Changes in release 3.23.31
@itemize @bullet @itemize @bullet
@item @item
Using @code{HAVING} on an empty table could produce one result row.
@item
Fixed that the @strong{MySQL} RPM is not depending on perl5 anymore.
@item
Fixed some problems with @code{HEAP} tables on windows.
@item
@code{SHOW TABLE STATUS} didn't show correct average row length for tables @code{SHOW TABLE STATUS} didn't show correct average row length for tables
bigger than 4G. bigger than 4G.
@item @item
...@@ -40412,15 +40423,16 @@ Added option @code{MEDIUM} to @code{CHECK TABLE}. ...@@ -40412,15 +40423,16 @@ Added option @code{MEDIUM} to @code{CHECK TABLE}.
@item @item
Fixed problem when using @code{DECIMAL()} keys on negative numbers. Fixed problem when using @code{DECIMAL()} keys on negative numbers.
@item @item
@code{HOUR()} on a @code{CHAR} column always returned @code{NULL}. @code{HOUR()} (and some other @code{TIME} functions) on a @code{CHAR} column
always returned @code{NULL}.
@item @item
Fixed security bug in something (please upgrade if you are using a earlier Fixed security bug in something (please upgrade if you are using a earlier
MySQL 3.23 version). MySQL 3.23 version).
@item @item
Fixed buffer overflow bug when writing a certain error message. Fixed buffer overflow bug when writing a certain error message.
@item @item
Added usage of @code{getrlimit()} on Linux to get @code{-O --open-files-limit=#} Added usage of @code{getrlimit()} on Linux to get @code{-O
to work on Linux. --open-files-limit=#} to work on Linux.
@item @item
Added new mysqld variable: bdb_version. Added new mysqld variable: bdb_version.
@item @item
...@@ -100,10 +100,12 @@ DO_GCOV="" ...@@ -100,10 +100,12 @@ DO_GCOV=""
DO_GDB="" DO_GDB=""
DO_DDD="" DO_DDD=""
SLEEP_TIME=2 SLEEP_TIME=2
DBUSER=""
while test $# -gt 0; do while test $# -gt 0; do
case "$1" in case "$1" in
--force ) FORCE=1 ;; --user=*) DBUSER=`$ECHO "$1" | $SED -e "s;--user=;;"` ;;
--force) FORCE=1 ;;
--local) USE_RUNNING_SERVER="" ;; --local) USE_RUNNING_SERVER="" ;;
--tmpdir=*) MYSQL_TMP_DIR=`$ECHO "$1" | $SED -e "s;--tmpdir=;;"` ;; --tmpdir=*) MYSQL_TMP_DIR=`$ECHO "$1" | $SED -e "s;--tmpdir=;;"` ;;
--master_port=*) MASTER_MYPORT=`$ECHO "$1" | $SED -e "s;--master_port=;;"` ;; --master_port=*) MASTER_MYPORT=`$ECHO "$1" | $SED -e "s;--master_port=;;"` ;;
...@@ -209,9 +211,9 @@ fi ...@@ -209,9 +211,9 @@ fi
if [ -n "$USE_RUNNING_SERVER" ] if [ -n "$USE_RUNNING_SERVER" ]
then then
MASTER_MYSOCK="/tmp/mysql.sock" MASTER_MYSOCK="/tmp/mysql.sock"
DBUSER=test DBUSER=${DBUSER:-test}
else else
DBUSER=root # We want to do FLUSH xxx commands DBUSER=${DBUSER:-root} # We want to do FLUSH xxx commands
fi fi
if [ -w / ] if [ -w / ]
......
...@@ -147,6 +147,12 @@ Table Op Msg_type Msg_text ...@@ -147,6 +147,12 @@ Table Op Msg_type Msg_text
test.t1 check error The handler for the table doesn't support check/repair test.t1 check error The handler for the table doesn't support check/repair
a b a b
2 testing 2 testing
Table Op Msg_type Msg_text
test.t1 analyze status OK
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
t1 1 skr 1 a A 3 NULL NULL
a b
1
a b a b
a 1 a 1
a 2 a 2
...@@ -429,6 +435,8 @@ count(*) ...@@ -429,6 +435,8 @@ count(*)
count(*) count(*)
1 1
count(*) count(*)
0
count(*)
1 1
count(*) count(*)
1 1
...@@ -468,4 +476,4 @@ hello 1 ...@@ -468,4 +476,4 @@ hello 1
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 optimize status OK test.t1 optimize status OK
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Comment
t1 0 PRIMARY 1 a A 1 NULL NULL t1 0 PRIMARY 1 a A 2 NULL NULL
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Small basic test with ignore # Small basic test with ignore
# #
drop table if exists t1; drop table if exists t1,t2;
create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=bdb; create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=bdb;
insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt'); insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
...@@ -81,6 +81,17 @@ create table t1 (a int,b varchar(20)) type=bdb; ...@@ -81,6 +81,17 @@ create table t1 (a int,b varchar(20)) type=bdb;
insert into t1 values (1,""), (2,"testing"); insert into t1 values (1,""), (2,"testing");
delete from t1 where a = 1; delete from t1 where a = 1;
select * from t1; select * from t1;
create index skr on t1 (a);
insert into t1 values (3,""), (4,"testing");
analyze table t1;
show keys from t1;
drop table t1;
# Test of reading on secondary key with may be null
create table t1 (a int,b varchar(20),key(a)) type=bdb;
insert into t1 values (1,""), (2,"testing");
select * from t1 where a = 1;
drop table t1; drop table t1;
# #
...@@ -352,12 +363,15 @@ CREATE TABLE t1 ( ...@@ -352,12 +363,15 @@ CREATE TABLE t1 (
INDEX sca_pic (sca_pic) INDEX sca_pic (sca_pic)
) type = bdb ; ) type = bdb ;
INSERT INTO t1 ( sca_code, cat_code, sca_desc, lan_code, sca_pic, sca_sdesc, sca_sch_desc) VALUES ( 'PD', 'J', 'PENDANT', 'EN', NULL, NULL, 'PENDANT'),( 'RI', 'J', 'RING', 'EN', NULL, NULL, 'RING'),( 'QQ', 'J', 'RING', 'EN', 'not null', NULL, 'RING'); INSERT INTO t1 ( sca_code, cat_code, sca_desc, lan_code, sca_pic, sca_sdesc, sca_sch_desc) VALUES ( 'PD', 'J', 'PENDANT', 'EN', NULL, NULL, 'PENDANT'),( 'RI', 'J', 'RING', 'EN', NULL, NULL, 'RING'),( 'QQ', 'N', 'RING', 'EN', 'not null', NULL, 'RING');
select count(*) from t1 where sca_code = 'PD'; select count(*) from t1 where sca_code = 'PD';
select count(*) from t1 where sca_code <= 'PD'; select count(*) from t1 where sca_code <= 'PD';
select count(*) from t1 where sca_pic is null; select count(*) from t1 where sca_pic is null;
alter table t1 drop index sca_pic, add index sca_pic (cat_code, sca_pic); alter table t1 drop index sca_pic, add index sca_pic (cat_code, sca_pic);
select count(*) from t1 where sca_code='PD' and sca_pic is null; select count(*) from t1 where sca_code='PD' and sca_pic is null;
select count(*) from t1 where cat_code='E';
alter table t1 drop index sca_pic, add index (sca_pic, cat_code); alter table t1 drop index sca_pic, add index (sca_pic, cat_code);
select count(*) from t1 where sca_code='PD' and sca_pic is null; select count(*) from t1 where sca_code='PD' and sca_pic is null;
select count(*) from t1 where sca_pic >= 'n'; select count(*) from t1 where sca_pic >= 'n';
...@@ -385,7 +399,7 @@ flush logs; ...@@ -385,7 +399,7 @@ flush logs;
# #
# Test key on blob with null values # Test key on blob with null values
# #
create table t1 (b blob, i int, key (b(100)), key (i), key (i, b(20))); create table t1 (b blob, i int, key (b(100)), key (i), key (i, b(20))) type=bdb;
insert into t1 values ('this is a blob', 1), (null, -1), (null, null),("",1),("",2),("",3); insert into t1 values ('this is a blob', 1), (null, -1), (null, null),("",1),("",2),("",3);
select b from t1 where b = 'this is a blob'; select b from t1 where b = 'this is a blob';
select * from t1 where b like 't%'; select * from t1 where b like 't%';
...@@ -399,7 +413,7 @@ drop table t1; ...@@ -399,7 +413,7 @@ drop table t1;
# #
# Test with variable length primary key # Test with variable length primary key
# #
create table t1 (a varchar(100) not null, primary key(a), b int not null); create table t1 (a varchar(100) not null, primary key(a), b int not null) type=bdb;
insert into t1 values("hello",1),("world",2); insert into t1 values("hello",1),("world",2);
select * from t1 order by b desc; select * from t1 order by b desc;
optimize table t1; optimize table t1;
......
# test of problems with having (Reported by Mark Rogers)
#
drop table if exists t1;
create table t1 (a int);
select count(a) as b from t1 where a=0 having b > 0;
insert into t1 values (null);
select count(a) as b from t1 where a=0 having b > 0;
select count(a) as b from t1 where a=0 having b >=0;
drop table t1;
...@@ -3599,7 +3599,7 @@ void Field_varstring::sql_type(String &res) const ...@@ -3599,7 +3599,7 @@ void Field_varstring::sql_type(String &res) const
char *Field_varstring::pack(char *to, const char *from, uint max_length) char *Field_varstring::pack(char *to, const char *from, uint max_length)
{ {
uint length=uint2korr(to); uint length=uint2korr(from);
if (length > max_length) if (length > max_length)
length=max_length; length=max_length;
*to++= (length & 255); *to++= (length & 255);
...@@ -4037,6 +4037,43 @@ void Field_blob::sql_type(String &res) const ...@@ -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 */ /* Keys for blobs are like keys on varchars */
int Field_blob::pack_cmp(const char *a, const char *b, uint key_length) 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) ...@@ -4087,10 +4124,33 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
return my_sortncmp(a,a_length, b,b_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) 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) if (length > max_length)
length=max_length; length=max_length;
*to++= (length & 255); *to++= (length & 255);
...@@ -4101,6 +4161,7 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) ...@@ -4101,6 +4161,7 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
return to+length; return to+length;
} }
/**************************************************************************** /****************************************************************************
** enum type. ** enum type.
** This is a string which only can have a selection of different values. ** This is a string which only can have a selection of different values.
......
...@@ -166,7 +166,12 @@ class Field { ...@@ -166,7 +166,12 @@ class Field {
memcpy(to,from,length); memcpy(to,from,length);
return 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); return pack(to,from,max_length);
} }
...@@ -861,39 +866,10 @@ class Field_blob :public Field_str { ...@@ -861,39 +866,10 @@ class Field_blob :public Field_str {
tmp=(char*) value.ptr(); memcpy_fixed(ptr+packlength,&tmp,sizeof(char*)); tmp=(char*) value.ptr(); memcpy_fixed(ptr+packlength,&tmp,sizeof(char*));
return 0; return 0;
} }
char *pack(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);
ulong length=get_length(); char *pack_key(char *to, const char *from, uint max_length);
if (length > max_length) char *pack_key_from_key_image(char* to, const char *from, uint 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);
int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *a, const char *b, uint key_length);
int pack_cmp(const char *b, uint key_length); int pack_cmp(const char *b, uint key_length);
uint packed_col_length(const char *col_ptr) uint packed_col_length(const char *col_ptr)
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
Testing of: Testing of:
- LOCK TABLES - LOCK TABLES
- BLOBS
- Mark tables that participate in a transaction so that they are not - Mark tables that participate in a transaction so that they are not
closed during the transaction. We need to test what happens if closed during the transaction. We need to test what happens if
MySQL closes a table that is updated by a not commit transaction. 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) ...@@ -290,7 +289,7 @@ static void berkeley_noticecall(DB_ENV *db_env, db_notices notice)
{ {
switch (notice) switch (notice)
{ {
case DB_NOTICE_LOGFILE_CHANGED: case DB_NOTICE_LOGFILE_CHANGED: /* purecov: tested */
pthread_mutex_lock(&LOCK_manager); pthread_mutex_lock(&LOCK_manager);
manager_status |= MANAGER_BERKELEY_LOG_CLEANUP; manager_status |= MANAGER_BERKELEY_LOG_CLEANUP;
pthread_mutex_unlock(&LOCK_manager); pthread_mutex_unlock(&LOCK_manager);
...@@ -418,6 +417,10 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length) ...@@ -418,6 +417,10 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
if (key_part->null_bit) if (key_part->null_bit)
{ {
key_length--; 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] & if (*key != (table->record[0][key_part->null_offset] &
key_part->null_bit) ? 0 : 1) key_part->null_bit) ? 0 : 1)
return 1; return 1;
...@@ -731,7 +734,6 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff, ...@@ -731,7 +734,6 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
DBUG_ENTER("create_key"); DBUG_ENTER("create_key");
key->data=buff; key->data=buff;
for ( ; key_part != end && key_length > 0; key_part++) for ( ; key_part != end && key_length > 0; key_part++)
{ {
if (key_part->null_bit) if (key_part->null_bit)
...@@ -745,8 +747,8 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff, ...@@ -745,8 +747,8 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
} }
*buff++ = 1; // Store NOT NULL marker *buff++ = 1; // Store NOT NULL marker
} }
buff=key_part->field->pack(buff,record + key_part->offset, buff=key_part->field->pack_key(buff,record + key_part->offset,
key_part->length); key_part->length);
key_length-=key_part->length; key_length-=key_part->length;
} }
key->size= (buff - (char*) key->data); key->size= (buff - (char*) key->data);
...@@ -783,7 +785,8 @@ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff, ...@@ -783,7 +785,8 @@ DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff,
} }
key_ptr++; 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_ptr+=key_part->store_length;
key_length-=key_part->store_length; key_length-=key_part->store_length;
} }
...@@ -807,7 +810,7 @@ int ha_berkeley::write_row(byte * record) ...@@ -807,7 +810,7 @@ int ha_berkeley::write_row(byte * record)
if ((error=pack_row(&row, record,1))) if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */ 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, error=file->put(file, transaction, create_key(&prim_key, primary_key,
key_buff, record), key_buff, record),
...@@ -859,8 +862,8 @@ int ha_berkeley::write_row(byte * record) ...@@ -859,8 +862,8 @@ int ha_berkeley::write_row(byte * record)
int new_error = 0; int new_error = 0;
if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS) if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
{ {
DBUG_PRINT("trans",("aborting subtransaction")); DBUG_PRINT("trans",("aborting subtransaction")); /* purecov: deadcode */
new_error=txn_abort(sub_trans); new_error=txn_abort(sub_trans); /* purecov: deadcode */
} }
else if (changed_keys) else if (changed_keys)
{ {
...@@ -871,14 +874,14 @@ int ha_berkeley::write_row(byte * record) ...@@ -871,14 +874,14 @@ int ha_berkeley::write_row(byte * record)
{ {
if ((new_error = remove_key(sub_trans, keynr, record, if ((new_error = remove_key(sub_trans, keynr, record,
(DBT*) 0, &prim_key))) (DBT*) 0, &prim_key)))
break; break; /* purecov: inspected */
} }
} }
} }
if (new_error) if (new_error)
{ {
error=new_error; // This shouldn't happen error=new_error; // This shouldn't happen /* purecov: inspected */
break; break; /* purecov: inspected */
} }
} }
} }
...@@ -1185,7 +1188,8 @@ int ha_berkeley::remove_key(DB_TXN *trans, uint keynr, const byte *record, ...@@ -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); dbug_assert(keynr != primary_key && prim_key->data != key_buff2);
DBC *tmp_cursor; 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, if (!(error=cursor->c_get(tmp_cursor,
(keynr == primary_key ? (keynr == primary_key ?
...@@ -1294,9 +1298,10 @@ int ha_berkeley::index_init(uint keynr) ...@@ -1294,9 +1298,10 @@ int ha_berkeley::index_init(uint keynr)
DBUG_ENTER("index_init"); DBUG_ENTER("index_init");
active_index=keynr; active_index=keynr;
dbug_assert(cursor == 0); dbug_assert(cursor == 0);
if ((error=file->cursor(key_file[keynr], transaction, &cursor, if ((error=key_file[keynr]->cursor(key_file[keynr], transaction, &cursor,
table->reginfo.lock_type > TL_WRITE_ALLOW_READ ? table->reginfo.lock_type >
0 : 0))) TL_WRITE_ALLOW_READ ?
0 : 0)))
cursor=0; // Safety /* purecov: inspected */ cursor=0; // Safety /* purecov: inspected */
bzero((char*) &last_key,sizeof(last_key)); bzero((char*) &last_key,sizeof(last_key));
DBUG_RETURN(error); DBUG_RETURN(error);
...@@ -1353,8 +1358,8 @@ int ha_berkeley::read_row(int error, char *buf, uint keynr, DBT *row, ...@@ -1353,8 +1358,8 @@ int ha_berkeley::read_row(int error, char *buf, uint keynr, DBT *row,
current_row.flags=DB_DBT_REALLOC; current_row.flags=DB_DBT_REALLOC;
if ((error=file->get(file, transaction, &key, &current_row, 0))) if ((error=file->get(file, transaction, &key, &current_row, 0)))
{ {
table->status=STATUS_NOT_FOUND; table->status=STATUS_NOT_FOUND; /* purecov: inspected */
DBUG_RETURN(error == DB_NOTFOUND ? HA_ERR_CRASHED : error); DBUG_RETURN(error == DB_NOTFOUND ? HA_ERR_CRASHED : error); /* purecov: inspected */
} }
row= &current_row; row= &current_row;
} }
...@@ -1371,7 +1376,7 @@ int ha_berkeley::index_read_idx(byte * buf, uint keynr, const byte * key, ...@@ -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); statistic_increment(ha_read_key_count,&LOCK_status);
DBUG_ENTER("index_read_idx"); DBUG_ENTER("index_read_idx");
current_row.flags=DB_DBT_REALLOC; 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, pack_key(&last_key, keynr, key_buff, key,
key_len), key_len),
&current_row,0), &current_row,0),
...@@ -1389,13 +1394,15 @@ int ha_berkeley::index_read(byte * buf, const byte * key, ...@@ -1389,13 +1394,15 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
statistic_increment(ha_read_key_count,&LOCK_status); statistic_increment(ha_read_key_count,&LOCK_status);
bzero((char*) &row,sizeof(row)); 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, error=read_row(cursor->c_get(cursor, pack_key(&last_key,
active_index, active_index,
key_buff, key_buff,
key, key_len), 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); buf, active_index, &row, (DBT*) 0, 0);
} }
else else
...@@ -1840,16 +1847,18 @@ ha_rows ha_berkeley::records_in_range(int keynr, ...@@ -1840,16 +1847,18 @@ ha_rows ha_berkeley::records_in_range(int keynr,
{ {
DBT key; DBT key;
DB_KEY_RANGE start_range, end_range; DB_KEY_RANGE start_range, end_range;
DB *kfile=key_file[keynr];
double start_pos,end_pos,rows; double start_pos,end_pos,rows;
DBUG_ENTER("records_in_range"); DBUG_ENTER("records_in_range");
if ((start_key && file->key_range(key_file[keynr],transaction,
pack_key(&key, keynr, key_buff, start_key, if ((start_key && kfile->key_range(kfile,transaction,
start_key_len), pack_key(&key, keynr, key_buff, start_key,
&start_range,0)) || start_key_len),
(end_key && file->key_range(key_file[keynr],transaction, &start_range,0)) ||
pack_key(&key, keynr, key_buff, end_key, (end_key && kfile->key_range(kfile,transaction,
end_key_len), pack_key(&key, keynr, key_buff, end_key,
&end_range,0))) end_key_len),
&end_range,0)))
DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); // Better than returning an error /* purecov: inspected */ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); // Better than returning an error /* purecov: inspected */
if (!start_key) if (!start_key)
...@@ -1969,8 +1978,8 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1969,8 +1978,8 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
free(stat); free(stat);
stat=0; stat=0;
} }
if (file->stat(key_file[i], (void*) &stat, 0, 0)) if (key_file[i]->stat(key_file[i], (void*) &stat, 0, 0))
goto err; goto err; /* purecov: inspected */
share->rec_per_key[i]= (stat->bt_ndata / share->rec_per_key[i]= (stat->bt_ndata /
(stat->bt_nkeys ? stat->bt_nkeys : 1)); (stat->bt_nkeys ? stat->bt_nkeys : 1));
} }
...@@ -1983,7 +1992,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1983,7 +1992,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
stat=0; stat=0;
} }
if (file->stat(file, (void*) &stat, 0, 0)) if (file->stat(file, (void*) &stat, 0, 0))
goto err; goto err; /* purecov: inspected */
} }
pthread_mutex_lock(&share->mutex); pthread_mutex_lock(&share->mutex);
share->rows=stat->bt_ndata; share->rows=stat->bt_ndata;
...@@ -1997,9 +2006,9 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -1997,9 +2006,9 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
HA_ADMIN_OK); HA_ADMIN_OK);
err: err:
if (stat) if (stat) /* purecov: inspected */
free(stat); free(stat); /* purecov: inspected */
return HA_ADMIN_FAILED; return HA_ADMIN_FAILED; /* purecov: inspected */
} }
int ha_berkeley::optimize(THD* thd, HA_CHECK_OPT* check_opt) 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) ...@@ -2036,7 +2045,7 @@ int ha_berkeley::check(THD* thd, HA_CHECK_OPT* check_opt)
tmp_file->set_bt_compare(tmp_file, tmp_file->set_bt_compare(tmp_file,
(hidden_primary_key ? berkeley_cmp_hidden_key : (hidden_primary_key ? berkeley_cmp_hidden_key :
berkeley_cmp_packed_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); fn_format(name_buff,share->table_name,"", ha_berkeley_ext, 2 | 4);
if ((error=tmp_file->verify(tmp_file, name_buff, NullS, (FILE*) 0, if ((error=tmp_file->verify(tmp_file, name_buff, NullS, (FILE*) 0,
hidden_primary_key ? 0 : DB_NOORDERCHK))) hidden_primary_key ? 0 : DB_NOORDERCHK)))
...@@ -2196,7 +2205,7 @@ void ha_berkeley::get_status() ...@@ -2196,7 +2205,7 @@ void ha_berkeley::get_status()
{ {
share->org_rows=share->rows= share->org_rows=share->rows=
table->max_rows ? table->max_rows : HA_BERKELEY_MAX_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; DBT row;
char rec_buff[64]; char rec_buff[64];
......
...@@ -70,7 +70,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) ...@@ -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*)); mem_per_row += MY_ALIGN(table->reclength+1, sizeof(char*));
max_rows = (ulong) (max_heap_table_size / mem_per_row); 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->keys,keydef,
table->reclength, table->reclength,
((table->max_rows < max_rows && table->max_rows) ? ((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) ...@@ -278,5 +278,5 @@ int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
{ {
char buff[FN_REFLEN]; char buff[FN_REFLEN];
return heap_create(fn_format(buff,name,"","",2)); return heap_create(fn_format(buff,name,"","",4+2));
} }
...@@ -952,7 +952,7 @@ void sql_print_error(const char *format,...) ...@@ -952,7 +952,7 @@ void sql_print_error(const char *format,...)
#ifndef DBUG_OFF #ifndef DBUG_OFF
{ {
char buff[1024]; char buff[1024];
vsnprintf(buff,sizeof(buff)-1,format,args); my_vsnprintf(buff,sizeof(buff)-1,format,args);
DBUG_PRINT("error",("%s",buff)); DBUG_PRINT("error",("%s",buff));
} }
#endif #endif
......
...@@ -314,7 +314,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -314,7 +314,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ /* Impossible cond */ { /* Impossible cond */
error=return_zero_rows(result, tables, fields, error=return_zero_rows(result, tables, fields,
join.tmp_table_param.sum_func_count != 0 && !group, join.tmp_table_param.sum_func_count != 0 && !group,
select_options,"Impossible WHERE",join.having, select_options,"Impossible WHERE",having,
procedure); procedure);
delete procedure; delete procedure;
DBUG_RETURN(error); DBUG_RETURN(error);
...@@ -330,7 +330,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -330,7 +330,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ {
error=return_zero_rows(result, tables, fields, !group, error=return_zero_rows(result, tables, fields, !group,
select_options,"No matching min/max row", select_options,"No matching min/max row",
join.having,procedure); having,procedure);
delete procedure; delete procedure;
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -383,7 +383,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -383,7 +383,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
{ {
error=return_zero_rows(result,tables,fields, error=return_zero_rows(result,tables,fields,
join.tmp_table_param.sum_func_count != 0 && join.tmp_table_param.sum_func_count != 0 &&
!group,0,"",join.having,procedure); !group,0,"",having,procedure);
goto err; goto err;
} }
if (!(thd->options & OPTION_BIG_SELECTS) && if (!(thd->options & OPTION_BIG_SELECTS) &&
...@@ -414,7 +414,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds, ...@@ -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, join.tmp_table_param.sum_func_count != 0 && !group,
select_options, select_options,
"Impossible WHERE noticed after reading const tables", "Impossible WHERE noticed after reading const tables",
join.having,procedure); having,procedure);
goto err; goto err;
} }
......
...@@ -531,7 +531,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -531,7 +531,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
{ {
int err; int err;
if ((err=(outparam->file-> 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_READ_ONLY ? O_RDONLY : O_RDWR),
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
((db_stat & HA_WAIT_IF_LOCKED) || ((db_stat & HA_WAIT_IF_LOCKED) ||
......
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