summaryrefslogtreecommitdiff
path: root/sql/ha_berkeley.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/ha_berkeley.cc')
-rw-r--r--sql/ha_berkeley.cc585
1 files changed, 337 insertions, 248 deletions
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 33f7b6238b0..72af402a0dc 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -103,7 +103,39 @@ static int write_status(DB *status_block, char *buff, uint length);
static void update_status(BDB_SHARE *share, TABLE *table);
static void berkeley_noticecall(DB_ENV *db_env, db_notices notice);
-
+static int berkeley_close_connection(THD *thd);
+static int berkeley_commit(THD *thd, bool all);
+static int berkeley_rollback(THD *thd, bool all);
+
+handlerton berkeley_hton = {
+ "BerkeleyDB",
+ SHOW_OPTION_YES,
+ "Supports transactions and page-level locking",
+ DB_TYPE_BERKELEY_DB,
+ berkeley_init,
+ 0, /* slot */
+ 0, /* savepoint size */
+ berkeley_close_connection,
+ NULL, /* savepoint_set */
+ NULL, /* savepoint_rollback */
+ NULL, /* savepoint_release */
+ berkeley_commit,
+ berkeley_rollback,
+ NULL, /* prepare */
+ NULL, /* recover */
+ NULL, /* commit_by_xid */
+ NULL, /* rollback_by_xid */
+ NULL, /* create_cursor_read_view */
+ NULL, /* set_cursor_read_view */
+ NULL, /* close_cursor_read_view */
+ HTON_CLOSE_CURSORS_AT_COMMIT
+};
+
+typedef struct st_berkeley_trx_data {
+ DB_TXN *all;
+ DB_TXN *stmt;
+ uint bdb_lock_count;
+} berkeley_trx_data;
/* General functions */
@@ -111,6 +143,9 @@ bool berkeley_init(void)
{
DBUG_ENTER("berkeley_init");
+ if (have_berkeley_db != SHOW_OPTION_YES)
+ goto error;
+
if (!berkeley_tmpdir)
berkeley_tmpdir=mysql_tmpdir;
if (!berkeley_home)
@@ -136,7 +171,7 @@ bool berkeley_init(void)
berkeley_log_file_size= max(berkeley_log_file_size, 10*1024*1024L);
if (db_env_create(&db_env,0))
- DBUG_RETURN(1); /* purecov: inspected */
+ goto error;
db_env->set_errcall(db_env,berkeley_print_error);
db_env->set_errpfx(db_env,"bdb");
db_env->set_noticecall(db_env, berkeley_noticecall);
@@ -164,16 +199,18 @@ bool berkeley_init(void)
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN |
DB_CREATE | DB_THREAD, 0666))
{
- db_env->close(db_env,0); /* purecov: inspected */
- db_env=0; /* purecov: inspected */
- goto err;
+ db_env->close(db_env,0);
+ db_env=0;
+ goto error;
}
(void) hash_init(&bdb_open_tables,system_charset_info,32,0,0,
(hash_get_key) bdb_get_key,0,0);
pthread_mutex_init(&bdb_mutex,MY_MUTEX_INIT_FAST);
-err:
- DBUG_RETURN(db_env == 0);
+ DBUG_RETURN(FALSE);
+error:
+ have_berkeley_db= SHOW_OPTION_DISABLED; // If we couldn't use handler
+ DBUG_RETURN(TRUE);
}
@@ -191,6 +228,12 @@ bool berkeley_end(void)
DBUG_RETURN(error != 0);
}
+static int berkeley_close_connection(THD *thd)
+{
+ my_free((gptr)thd->ha_data[berkeley_hton.slot], MYF(0));
+ return 0;
+}
+
bool berkeley_flush_logs()
{
int error;
@@ -209,26 +252,29 @@ bool berkeley_flush_logs()
DBUG_RETURN(result);
}
-
-int berkeley_commit(THD *thd, void *trans)
+static int berkeley_commit(THD *thd, bool all)
{
DBUG_ENTER("berkeley_commit");
- DBUG_PRINT("trans",("ending transaction %s",
- trans == thd->transaction.stmt.bdb_tid ? "stmt" : "all"));
- int error=txn_commit((DB_TXN*) trans,0);
+ DBUG_PRINT("trans",("ending transaction %s", all ? "all" : "stmt"));
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DB_TXN **txn= all ? &trx->all : &trx->stmt;
+ int error=txn_commit(*txn,0);
+ *txn=0;
#ifndef DBUG_OFF
if (error)
- DBUG_PRINT("error",("error: %d",error)); /* purecov: inspected */
+ DBUG_PRINT("error",("error: %d",error));
#endif
DBUG_RETURN(error);
}
-int berkeley_rollback(THD *thd, void *trans)
+static int berkeley_rollback(THD *thd, bool all)
{
DBUG_ENTER("berkeley_rollback");
- DBUG_PRINT("trans",("aborting transaction %s",
- trans == thd->transaction.stmt.bdb_tid ? "stmt" : "all"));
- int error=txn_abort((DB_TXN*) trans);
+ DBUG_PRINT("trans",("aborting transaction %s", all ? "all" : "stmt"));
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DB_TXN **txn= all ? &trx->all : &trx->stmt;
+ int error=txn_abort(*txn);
+ *txn=0;
DBUG_RETURN(error);
}
@@ -262,7 +308,7 @@ int berkeley_show_logs(Protocol *protocol)
{
protocol->prepare_for_resend();
protocol->store(*a, system_charset_info);
- protocol->store("BDB", 3, system_charset_info);
+ protocol->store(STRING_WITH_LEN("BDB"), system_charset_info);
if (f && *f && strcmp(*a, *f) == 0)
{
f++;
@@ -341,11 +387,27 @@ void berkeley_cleanup_log_files(void)
** Berkeley DB tables
*****************************************************************************/
-static const char *ha_bdb_bas_exts[]= { ha_berkeley_ext, NullS };
-const char **ha_berkeley::bas_ext() const
-{ return ha_bdb_bas_exts; }
+ha_berkeley::ha_berkeley(TABLE *table_arg)
+ :handler(&berkeley_hton, table_arg), alloc_ptr(0), rec_buff(0), file(0),
+ int_table_flags(HA_REC_NOT_IN_SEQ | HA_FAST_KEY_READ |
+ HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED |
+ HA_CAN_GEOMETRY |
+ HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
+ changed_rows(0), last_dup_key((uint) -1), version(0), using_ignore(0)
+{}
+static const char *ha_berkeley_exts[] = {
+ ha_berkeley_ext,
+ NullS
+};
+
+const char **ha_berkeley::bas_ext() const
+{
+ return ha_berkeley_exts;
+}
+
ulong ha_berkeley::index_flags(uint idx, uint part, bool all_parts) const
{
ulong flags= (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_KEYREAD_ONLY
@@ -360,7 +422,8 @@ ulong ha_berkeley::index_flags(uint idx, uint part, bool all_parts) const
}
switch (table->key_info[idx].key_part[i].field->key_type()) {
case HA_KEYTYPE_TEXT:
- case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
/*
As BDB stores only one copy of equal strings, we can't use key read
on these. Binary collations do support key read though.
@@ -395,9 +458,11 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
KEY_PART_INFO *key_part= key->key_part, *end=key_part+key->key_parts;
uint key_length=new_key->size;
+ DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
+ uint length;
if (key_part->null_bit)
{
if (*new_key_ptr != *saved_key_ptr++)
@@ -406,11 +471,12 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
if (!*new_key_ptr++)
continue;
}
- if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,
- key_part->length)))
+ if ((cmp= key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,
+ key_part->length,
+ key->table->insert_or_update)))
return cmp;
- uint length=key_part->field->packed_col_length(new_key_ptr,
- key_part->length);
+ length= key_part->field->packed_col_length(new_key_ptr,
+ key_part->length);
new_key_ptr+=length;
key_length-=length;
saved_key_ptr+=key_part->field->packed_col_length(saved_key_ptr,
@@ -436,7 +502,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
for (; key_part != end && (int) key_length > 0 ; key_part++)
{
int cmp;
- if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0)))
+ if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0,0)))
return cmp;
new_key_ptr+=key_part->length;
key_length-= key_part->length;
@@ -446,6 +512,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
}
#endif
+
/* Compare key against row */
static bool
@@ -457,6 +524,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
+ uint length;
if (key_part->null_bit)
{
key_length--;
@@ -470,27 +538,34 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
if (!*key++) // Null value
continue;
}
- if ((cmp=key_part->field->pack_cmp(key,key_part->length)))
+ /*
+ Last argument has to be 0 as we are also using this to function to see
+ if a key like 'a ' matched a row with 'a'
+ */
+ if ((cmp= key_part->field->pack_cmp(key, key_part->length, 0)))
return cmp;
- uint length=key_part->field->packed_col_length(key,key_part->length);
- key+=length;
- key_length-=length;
+ length= key_part->field->packed_col_length(key,key_part->length);
+ key+= length;
+ key_length-= length;
}
return 0; // Identical keys
}
+
int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
uint open_mode=(mode == O_RDONLY ? DB_RDONLY : 0) | DB_THREAD;
+ uint max_key_length;
int error;
+ TABLE_SHARE *table_share= table->s;
DBUG_ENTER("ha_berkeley::open");
/* Open primary key */
hidden_primary_key=0;
- if ((primary_key=table->primary_key) >= MAX_KEY)
+ if ((primary_key= table_share->primary_key) >= MAX_KEY)
{ // No primary key
- primary_key=table->keys;
+ primary_key= table_share->keys;
key_used_on_scan=MAX_KEY;
ref_length=hidden_primary_key=BDB_HIDDEN_PRIMARY_KEY_LENGTH;
}
@@ -498,18 +573,18 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
key_used_on_scan=primary_key;
/* Need some extra memory in case of packed keys */
- uint max_key_length= table->max_key_length + MAX_REF_PARTS*3;
+ max_key_length= table_share->max_key_length + MAX_REF_PARTS*3;
if (!(alloc_ptr=
my_multi_malloc(MYF(MY_WME),
&key_buff, max_key_length,
&key_buff2, max_key_length,
&primary_key_buff,
(hidden_primary_key ? 0 :
- table->key_info[table->primary_key].key_length),
+ table->key_info[table_share->primary_key].key_length),
NullS)))
DBUG_RETURN(1); /* purecov: inspected */
if (!(rec_buff= (byte*) my_malloc((alloced_rec_buff_length=
- table->rec_buff_length),
+ table_share->rec_buff_length),
MYF(MY_WME))))
{
my_free(alloc_ptr,MYF(0)); /* purecov: inspected */
@@ -517,7 +592,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
}
/* Init shared structure */
- if (!(share=get_share(name,table)))
+ if (!(share= get_share(name,table)))
{
my_free((char*) rec_buff,MYF(0)); /* purecov: inspected */
my_free(alloc_ptr,MYF(0)); /* purecov: inspected */
@@ -530,7 +605,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
/* Fill in shared structure, if needed */
pthread_mutex_lock(&share->mutex);
- file = share->file;
+ file= share->file;
if (!share->use_count++)
{
if ((error=db_create(&file, db_env, 0)))
@@ -541,13 +616,13 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
my_errno=error; /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
- share->file = file;
+ share->file= file;
file->set_bt_compare(file,
(hidden_primary_key ? berkeley_cmp_hidden_key :
berkeley_cmp_packed_key));
if (!hidden_primary_key)
- file->app_private= (void*) (table->key_info+table->primary_key);
+ file->app_private= (void*) (table->key_info + table_share->primary_key);
if ((error= txn_begin(db_env, 0, (DB_TXN**) &transaction, 0)) ||
(error= (file->open(file, transaction,
fn_format(name_buff, name, "", ha_berkeley_ext,
@@ -555,7 +630,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
"main", DB_BTREE, open_mode, 0))) ||
(error= transaction->commit(transaction, 0)))
{
- free_share(share,table, hidden_primary_key,1); /* purecov: inspected */
+ free_share(share, table, hidden_primary_key,1); /* purecov: inspected */
my_free((char*) rec_buff,MYF(0)); /* purecov: inspected */
my_free(alloc_ptr,MYF(0)); /* purecov: inspected */
my_errno=error; /* purecov: inspected */
@@ -567,7 +642,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
key_type[primary_key]=DB_NOOVERWRITE;
DB **ptr=key_file;
- for (uint i=0, used_keys=0; i < table->keys ; i++, ptr++)
+ for (uint i=0, used_keys=0; i < table_share->keys ; i++, ptr++)
{
char part[7];
if (i != primary_key)
@@ -599,7 +674,7 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
}
}
/* Calculate pack_length of primary key */
- share->fixed_length_primary_key=1;
+ share->fixed_length_primary_key= 1;
if (!hidden_primary_key)
{
ref_length=0;
@@ -609,18 +684,19 @@ int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
ref_length+= key_part->field->max_packed_col_length(key_part->length);
share->fixed_length_primary_key=
(ref_length == table->key_info[primary_key].key_length);
- share->status|=STATUS_PRIMARY_KEY_INIT;
+ share->status|= STATUS_PRIMARY_KEY_INIT;
}
- share->ref_length=ref_length;
+ share->ref_length= ref_length;
}
- ref_length=share->ref_length; // If second open
+ ref_length= share->ref_length; // If second open
pthread_mutex_unlock(&share->mutex);
transaction=0;
cursor=0;
key_read=0;
block_size=8192; // Berkeley DB block size
- share->fixed_length_row=!(table->db_create_options & HA_OPTION_PACK_RECORD);
+ share->fixed_length_row= !(table_share->db_create_options &
+ HA_OPTION_PACK_RECORD);
get_status();
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
@@ -660,9 +736,15 @@ bool ha_berkeley::fix_rec_buff_for_blob(ulong length)
ulong ha_berkeley::max_row_length(const byte *buf)
{
- ulong length=table->reclength + table->fields*2;
- for (Field_blob **ptr=table->blob_field ; *ptr ; ptr++)
- length+= (*ptr)->get_length((char*) buf+(*ptr)->offset())+2;
+ ulong length= table->s->reclength + table->s->fields*2;
+ uint *ptr, *end;
+ for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
+ ptr != end ;
+ ptr++)
+ {
+ Field_blob *blob= ((Field_blob*) table->field[*ptr]);
+ length+= blob->get_length((char*) buf + blob->offset())+2;
+ }
return length;
}
@@ -678,29 +760,30 @@ ulong ha_berkeley::max_row_length(const byte *buf)
int ha_berkeley::pack_row(DBT *row, const byte *record, bool new_row)
{
+ byte *ptr;
bzero((char*) row,sizeof(*row));
if (share->fixed_length_row)
{
row->data=(void*) record;
- row->size=table->reclength+hidden_primary_key;
+ row->size= table->s->reclength+hidden_primary_key;
if (hidden_primary_key)
{
if (new_row)
get_auto_primary_key(current_ident);
- memcpy_fixed((char*) record+table->reclength, (char*) current_ident,
+ memcpy_fixed((char*) record+table->s->reclength, (char*) current_ident,
BDB_HIDDEN_PRIMARY_KEY_LENGTH);
}
return 0;
}
- if (table->blob_fields)
+ if (table->s->blob_fields)
{
if (fix_rec_buff_for_blob(max_row_length(record)))
return HA_ERR_OUT_OF_MEM; /* purecov: inspected */
}
/* Copy null bits */
- memcpy(rec_buff, record, table->null_bytes);
- byte *ptr=rec_buff + table->null_bytes;
+ memcpy(rec_buff, record, table->s->null_bytes);
+ ptr= rec_buff + table->s->null_bytes;
for (Field **field=table->field ; *field ; field++)
ptr=(byte*) (*field)->pack((char*) ptr,
@@ -723,13 +806,13 @@ int ha_berkeley::pack_row(DBT *row, const byte *record, bool new_row)
void ha_berkeley::unpack_row(char *record, DBT *row)
{
if (share->fixed_length_row)
- memcpy(record,(char*) row->data,table->reclength+hidden_primary_key);
+ memcpy(record,(char*) row->data,table->s->reclength+hidden_primary_key);
else
{
/* Copy null bits */
const char *ptr= (const char*) row->data;
- memcpy(record, ptr, table->null_bytes);
- ptr+=table->null_bytes;
+ memcpy(record, ptr, table->s->null_bytes);
+ ptr+= table->s->null_bytes;
for (Field **field=table->field ; *field ; field++)
ptr= (*field)->unpack(record + (*field)->offset(), ptr);
}
@@ -740,11 +823,11 @@ void ha_berkeley::unpack_row(char *record, DBT *row)
void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
{
- KEY *key_info=table->key_info+index;
+ KEY *key_info= table->key_info+index;
KEY_PART_INFO *key_part= key_info->key_part,
- *end=key_part+key_info->key_parts;
+ *end= key_part+key_info->key_parts;
+ char *pos= (char*) key->data;
- char *pos=(char*) key->data;
for (; key_part != end; key_part++)
{
if (key_part->null_bit)
@@ -768,8 +851,10 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
/*
- Create a packed key from from a row
- This will never fail as the key buffer is pre allocated.
+ Create a packed key from a row. This key will be written as such
+ to the index tree.
+
+ This will never fail as the key buffer is pre-allocated.
*/
DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
@@ -815,7 +900,10 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
/*
- Create a packed key from from a MySQL unpacked key
+ Create a packed key from from a MySQL unpacked key (like the one that is
+ sent from the index_read()
+
+ This key is to be used to read a row
*/
DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff,
@@ -861,7 +949,7 @@ int ha_berkeley::write_row(byte * record)
int error;
DBUG_ENTER("write_row");
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && record == table->record[0])
@@ -869,7 +957,8 @@ int ha_berkeley::write_row(byte * record)
if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */
- if (table->keys + test(hidden_primary_key) == 1)
+ table->insert_or_update= 1; // For handling of VARCHAR
+ if (table->s->keys + test(hidden_primary_key) == 1)
{
error=file->put(file, transaction, create_key(&prim_key, primary_key,
key_buff, record),
@@ -880,22 +969,15 @@ int ha_berkeley::write_row(byte * record)
{
DB_TXN *sub_trans = transaction;
/* Don't use sub transactions in temporary tables */
- ulong thd_options = table->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
key_map changed_keys(0);
- if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
- break; /* purecov: deadcode */
- DBUG_PRINT("trans",("starting subtransaction")); /* purecov: deadcode */
- }
if (!(error=file->put(file, sub_trans, create_key(&prim_key, primary_key,
key_buff, record),
&row, key_type[primary_key])))
{
changed_keys.set_bit(primary_key);
- for (uint keynr=0 ; keynr < table->keys ; keynr++)
+ for (uint keynr=0 ; keynr < table->s->keys ; keynr++)
{
if (keynr == primary_key)
continue;
@@ -919,15 +1001,11 @@ int ha_berkeley::write_row(byte * record)
if (using_ignore)
{
int new_error = 0;
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- DBUG_PRINT("trans",("aborting subtransaction")); /* purecov: deadcode */
- new_error=txn_abort(sub_trans); /* purecov: deadcode */
- }
- else if (!changed_keys.is_clear_all())
+ if (!changed_keys.is_clear_all())
{
new_error = 0;
- for (uint keynr=0 ; keynr < table->keys+test(hidden_primary_key) ;
+ for (uint keynr=0;
+ keynr < table->s->keys+test(hidden_primary_key);
keynr++)
{
if (changed_keys.is_set(keynr))
@@ -945,15 +1023,11 @@ int ha_berkeley::write_row(byte * record)
}
}
}
- else if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- DBUG_PRINT("trans",("committing subtransaction")); /* purecov: deadcode */
- error=txn_commit(sub_trans, 0); /* purecov: deadcode */
- }
if (error != DB_LOCK_DEADLOCK)
break;
}
}
+ table->insert_or_update= 0;
if (error == DB_KEYEXIST)
error=HA_ERR_FOUND_DUPP_KEY;
else if (!error)
@@ -978,7 +1052,7 @@ int ha_berkeley::key_cmp(uint keynr, const byte * old_row,
(new_row[key_part->null_offset] & key_part->null_bit))
return 1;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
if (key_part->field->cmp_binary((char*) (old_row + key_part->offset),
@@ -1005,7 +1079,7 @@ int ha_berkeley::key_cmp(uint keynr, const byte * old_row,
int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
const byte * old_row, DBT *old_key,
const byte * new_row, DBT *new_key,
- ulong thd_options, bool local_using_ignore)
+ bool local_using_ignore)
{
DBT row;
int error;
@@ -1024,8 +1098,7 @@ int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
{
// Probably a duplicated key; restore old key and row if needed
last_dup_key=primary_key;
- if (local_using_ignore &&
- !(thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
+ if (local_using_ignore)
{
int new_error;
if ((new_error=pack_row(&row, old_row, 0)) ||
@@ -1055,8 +1128,7 @@ int ha_berkeley::update_primary_key(DB_TXN *trans, bool primary_key_changed,
int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
uint primary_key,
const byte *old_row, DBT *old_key,
- const byte *new_row, DBT *new_key,
- ulong thd_options)
+ const byte *new_row, DBT *new_key)
{
int error;
DBT tmp_key;
@@ -1066,7 +1138,7 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
/* Restore the old primary key, and the old row, but don't ignore
duplicate key failure */
if ((error=update_primary_key(trans, TRUE, new_row, new_key,
- old_row, old_key, thd_options, FALSE)))
+ old_row, old_key, FALSE)))
goto err; /* purecov: inspected */
/* Remove the new key, and put back the old key
@@ -1076,7 +1148,7 @@ int ha_berkeley::restore_keys(DB_TXN *trans, key_map *changed_keys,
that one just put back the old value. */
if (!changed_keys->is_clear_all())
{
- for (keynr=0 ; keynr < table->keys+test(hidden_primary_key) ; keynr++)
+ for (keynr=0 ; keynr < table->s->keys+test(hidden_primary_key) ; keynr++)
{
if (changed_keys->is_set(keynr))
{
@@ -1103,15 +1175,15 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
DBT prim_key, key, old_prim_key;
int error;
DB_TXN *sub_trans;
- ulong thd_options = table->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
bool primary_key_changed;
DBUG_ENTER("update_row");
LINT_INIT(error);
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
+ table->insert_or_update= 1; // For handling of VARCHAR
if (hidden_primary_key)
{
primary_key_changed=0;
@@ -1134,20 +1206,14 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
key_map changed_keys(0);
- if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
- break; /* purecov: deadcode */
- DBUG_PRINT("trans",("starting subtransaction")); /* purecov: deadcode */
- }
/* Start by updating the primary key */
if (!(error=update_primary_key(sub_trans, primary_key_changed,
old_row, &old_prim_key,
new_row, &prim_key,
- thd_options, using_ignore)))
+ using_ignore)))
{
// Update all other keys
- for (uint keynr=0 ; keynr < table->keys ; keynr++)
+ for (uint keynr=0 ; keynr < table->s->keys ; keynr++)
{
if (keynr == primary_key)
continue;
@@ -1155,15 +1221,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
{
if ((error=remove_key(sub_trans, keynr, old_row, &old_prim_key)))
{
- if (using_ignore && /* purecov: inspected */
- (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- int new_error;
- DBUG_PRINT("trans",("aborting subtransaction"));
- new_error=txn_abort(sub_trans);
- if (new_error)
- error = new_error;
- }
+ table->insert_or_update= 0;
DBUG_RETURN(error); // Fatal error /* purecov: inspected */
}
changed_keys.set_bit(keynr);
@@ -1185,30 +1243,21 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
if (using_ignore)
{
int new_error = 0;
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- DBUG_PRINT("trans",("aborting subtransaction")); /* purecov: deadcode */
- new_error=txn_abort(sub_trans); /* purecov: deadcode */
- }
- else if (!changed_keys.is_clear_all())
+ if (!changed_keys.is_clear_all())
new_error=restore_keys(transaction, &changed_keys, primary_key,
- old_row, &old_prim_key, new_row, &prim_key,
- thd_options);
+ old_row, &old_prim_key, new_row, &prim_key);
if (new_error)
{
- error=new_error; // This shouldn't happen /* purecov: inspected */
- break; /* purecov: inspected */
+ /* This shouldn't happen */
+ error=new_error; /* purecov: inspected */
+ break; /* purecov: inspected */
}
}
}
- else if (using_ignore && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- DBUG_PRINT("trans",("committing subtransaction")); /* purecov: deadcode */
- error=txn_commit(sub_trans, 0); /* purecov: deadcode */
- }
if (error != DB_LOCK_DEADLOCK)
break;
}
+ table->insert_or_update= 0;
if (error == DB_KEYEXIST)
error=HA_ERR_FOUND_DUPP_KEY;
DBUG_RETURN(error);
@@ -1275,7 +1324,9 @@ int ha_berkeley::remove_keys(DB_TXN *trans, const byte *record,
DBT *new_record, DBT *prim_key, key_map *keys)
{
int result = 0;
- for (uint keynr=0 ; keynr < table->keys+test(hidden_primary_key) ; keynr++)
+ for (uint keynr=0;
+ keynr < table->s->keys+test(hidden_primary_key);
+ keynr++)
{
if (keys->is_set(keynr))
{
@@ -1295,10 +1346,9 @@ int ha_berkeley::delete_row(const byte * record)
{
int error;
DBT row, prim_key;
- key_map keys=table->keys_in_use;
- ulong thd_options = table->tmp_table == NO_TMP_TABLE ? table->in_use->options : 0;
+ key_map keys= table->s->keys_in_use;
DBUG_ENTER("delete_row");
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
if ((error=pack_row(&row, record, 0)))
DBUG_RETURN((error)); /* purecov: inspected */
@@ -1311,34 +1361,11 @@ int ha_berkeley::delete_row(const byte * record)
DB_TXN *sub_trans = transaction;
for (uint retry=0 ; retry < berkeley_trans_retry ; retry++)
{
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- if ((error=txn_begin(db_env, transaction, &sub_trans, 0))) /* purecov: deadcode */
- break; /* purecov: deadcode */
- DBUG_PRINT("trans",("starting sub transaction")); /* purecov: deadcode */
- }
error=remove_keys(sub_trans, record, &row, &prim_key, &keys);
- if (!error && (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS))
- {
- DBUG_PRINT("trans",("ending sub transaction")); /* purecov: deadcode */
- error=txn_commit(sub_trans, 0); /* purecov: deadcode */
- }
if (error)
{ /* purecov: inspected */
DBUG_PRINT("error",("Got error %d",error));
- if (thd_options & OPTION_INTERNAL_SUBTRANSACTIONS)
- {
- /* retry */
- int new_error;
- DBUG_PRINT("trans",("aborting subtransaction"));
- if ((new_error=txn_abort(sub_trans)))
- {
- error=new_error; // This shouldn't happen
- break;
- }
- }
- else
- break; // No retry - return error
+ break; // No retry - return error
}
if (error != DB_LOCK_DEADLOCK)
break;
@@ -1355,7 +1382,7 @@ int ha_berkeley::index_init(uint keynr)
{
int error;
DBUG_ENTER("ha_berkeley::index_init");
- DBUG_PRINT("enter",("table: '%s' key: %d", table->real_name, keynr));
+ DBUG_PRINT("enter",("table: '%s' key: %d", table->s->table_name, keynr));
/*
Under some very rare conditions (like full joins) we may already have
@@ -1382,7 +1409,7 @@ int ha_berkeley::index_end()
DBUG_ENTER("ha_berkely::index_end");
if (cursor)
{
- DBUG_PRINT("enter",("table: '%s'", table->real_name));
+ DBUG_PRINT("enter",("table: '%s'", table->s->table_name));
error=cursor->c_close(cursor);
cursor=0;
}
@@ -1445,7 +1472,7 @@ int ha_berkeley::read_row(int error, char *buf, uint keynr, DBT *row,
int ha_berkeley::index_read_idx(byte * buf, uint keynr, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(ha_read_key_count,&LOCK_status);
+ table->in_use->status_var.ha_read_key_count++;
DBUG_ENTER("index_read_idx");
current_row.flags=DB_DBT_REALLOC;
active_index=MAX_KEY;
@@ -1466,7 +1493,7 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
int do_prev= 0;
DBUG_ENTER("ha_berkeley::index_read");
- statistic_increment(ha_read_key_count,&LOCK_status);
+ table->in_use->status_var.ha_read_key_count++;
bzero((char*) &row,sizeof(row));
if (find_flag == HA_READ_BEFORE_KEY)
{
@@ -1478,7 +1505,8 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
find_flag= HA_READ_AFTER_KEY;
do_prev= 1;
}
- if (key_len == key_info->key_length)
+ if (key_len == key_info->key_length &&
+ !(table->key_info[active_index].flags & HA_END_SPACE_KEY))
{
if (find_flag == HA_READ_AFTER_KEY)
key_info->handler.bdb_return_if_eq= 1;
@@ -1535,7 +1563,8 @@ int ha_berkeley::index_read_last(byte * buf, const byte * key, uint key_len)
KEY *key_info= &table->key_info[active_index];
DBUG_ENTER("ha_berkeley::index_read");
- statistic_increment(ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
/* read of partial key */
@@ -1559,7 +1588,8 @@ int ha_berkeley::index_next(byte * buf)
{
DBT row;
DBUG_ENTER("index_next");
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT),
(char*) buf, active_index, &row, &last_key, 1));
@@ -1570,9 +1600,11 @@ int ha_berkeley::index_next_same(byte * buf, const byte *key, uint keylen)
DBT row;
int error;
DBUG_ENTER("index_next_same");
- statistic_increment(ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
- if (keylen == table->key_info[active_index].key_length)
+ if (keylen == table->key_info[active_index].key_length &&
+ !(table->key_info[active_index].flags & HA_END_SPACE_KEY))
error=read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT_DUP),
(char*) buf, active_index, &row, &last_key, 1);
else
@@ -1590,7 +1622,8 @@ int ha_berkeley::index_prev(byte * buf)
{
DBT row;
DBUG_ENTER("index_prev");
- statistic_increment(ha_read_prev_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_PREV),
(char*) buf, active_index, &row, &last_key, 1));
@@ -1601,7 +1634,8 @@ int ha_berkeley::index_first(byte * buf)
{
DBT row;
DBUG_ENTER("index_first");
- statistic_increment(ha_read_first_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_FIRST),
(char*) buf, active_index, &row, &last_key, 1));
@@ -1611,7 +1645,8 @@ int ha_berkeley::index_last(byte * buf)
{
DBT row;
DBUG_ENTER("index_last");
- statistic_increment(ha_read_last_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_LAST),
(char*) buf, active_index, &row, &last_key, 0));
@@ -1633,7 +1668,8 @@ int ha_berkeley::rnd_next(byte *buf)
{
DBT row;
DBUG_ENTER("rnd_next");
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
bzero((char*) &row,sizeof(row));
DBUG_RETURN(read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT),
(char*) buf, primary_key, &row, &last_key, 1));
@@ -1657,6 +1693,7 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos)
pos+=key_part->field->packed_col_length((char*) pos,key_part->length);
to->size= (uint) (pos- (byte*) to->data);
}
+ DBUG_DUMP("key", (char*) to->data, to->size);
return to;
}
@@ -1664,9 +1701,10 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos)
int ha_berkeley::rnd_pos(byte * buf, byte *pos)
{
DBT db_pos;
- statistic_increment(ha_read_rnd_count,&LOCK_status);
+
DBUG_ENTER("ha_berkeley::rnd_pos");
-
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
active_index= MAX_KEY;
DBUG_RETURN(read_row(file->get(file, transaction,
get_pos(&db_pos, pos),
@@ -1726,14 +1764,14 @@ void ha_berkeley::info(uint flag)
if ((flag & HA_STATUS_CONST) || version != share->version)
{
version=share->version;
- for (uint i=0 ; i < table->keys ; i++)
+ for (uint i=0 ; i < table->s->keys ; i++)
{
table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]=
share->rec_per_key[i];
}
}
/* Don't return key if we got an error for the internal primary key */
- if (flag & HA_STATUS_ERRKEY && last_dup_key < table->keys)
+ if (flag & HA_STATUS_ERRKEY && last_dup_key < table->s->keys)
errkey= last_dup_key;
DBUG_VOID_RETURN;
}
@@ -1795,61 +1833,65 @@ int ha_berkeley::reset(void)
int ha_berkeley::external_lock(THD *thd, int lock_type)
{
int error=0;
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
DBUG_ENTER("ha_berkeley::external_lock");
+ if (!trx)
+ {
+ thd->ha_data[berkeley_hton.slot]= trx= (berkeley_trx_data *)
+ my_malloc(sizeof(*trx), MYF(MY_ZEROFILL));
+ if (!trx)
+ DBUG_RETURN(1);
+ }
if (lock_type != F_UNLCK)
{
- if (!thd->transaction.bdb_lock_count++)
+ if (!trx->bdb_lock_count++)
{
- DBUG_ASSERT(thd->transaction.stmt.bdb_tid == 0);
+ DBUG_ASSERT(trx->stmt == 0);
transaction=0; // Safety
/* First table lock, start transaction */
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
- OPTION_TABLE_LOCK)) &&
- !thd->transaction.all.bdb_tid)
+ OPTION_TABLE_LOCK)) && !trx->all)
{
/* We have to start a master transaction */
- DBUG_PRINT("trans",("starting transaction all"));
- if ((error=txn_begin(db_env, 0,
- (DB_TXN**) &thd->transaction.all.bdb_tid,
- 0)))
+ DBUG_PRINT("trans",("starting transaction all: options: 0x%lx",
+ (ulong) thd->options));
+ if ((error=txn_begin(db_env, 0, &trx->all, 0)))
{
- thd->transaction.bdb_lock_count--; // We didn't get the lock /* purecov: inspected */
- DBUG_RETURN(error); /* purecov: inspected */
+ trx->bdb_lock_count--; // We didn't get the lock
+ DBUG_RETURN(error);
}
+ trans_register_ha(thd, TRUE, &berkeley_hton);
if (thd->in_lock_tables)
DBUG_RETURN(0); // Don't create stmt trans
}
DBUG_PRINT("trans",("starting transaction stmt"));
- if ((error=txn_begin(db_env,
- (DB_TXN*) thd->transaction.all.bdb_tid,
- (DB_TXN**) &thd->transaction.stmt.bdb_tid,
- 0)))
+ if ((error=txn_begin(db_env, trx->all, &trx->stmt, 0)))
{
/* We leave the possible master transaction open */
- thd->transaction.bdb_lock_count--; // We didn't get the lock /* purecov: inspected */
- DBUG_RETURN(error); /* purecov: inspected */
+ trx->bdb_lock_count--; // We didn't get the lock
+ DBUG_RETURN(error);
}
+ trans_register_ha(thd, FALSE, &berkeley_hton);
}
- transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid;
+ transaction= trx->stmt;
}
else
{
lock.type=TL_UNLOCK; // Unlocked
thread_safe_add(share->rows, changed_rows, &share->mutex);
changed_rows=0;
- if (!--thd->transaction.bdb_lock_count)
+ if (!--trx->bdb_lock_count)
{
- if (thd->transaction.stmt.bdb_tid)
+ if (trx->stmt)
{
/*
- F_UNLOCK is done without a transaction commit / rollback.
+ F_UNLCK is done without a transaction commit / rollback.
This happens if the thread didn't update any rows
We must in this case commit the work to keep the row locks
*/
DBUG_PRINT("trans",("commiting non-updating transaction"));
- error=txn_commit((DB_TXN*) thd->transaction.stmt.bdb_tid,0);
- thd->transaction.stmt.bdb_tid=0;
- transaction=0;
+ error= txn_commit(trx->stmt,0);
+ trx->stmt= transaction= 0;
}
}
}
@@ -1863,18 +1905,24 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
Under LOCK TABLES, each used tables will force a call to start_stmt.
*/
-int ha_berkeley::start_stmt(THD *thd)
+int ha_berkeley::start_stmt(THD *thd, thr_lock_type lock_type)
{
int error=0;
DBUG_ENTER("ha_berkeley::start_stmt");
- if (!thd->transaction.stmt.bdb_tid)
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DBUG_ASSERT(trx);
+ /*
+ note that trx->stmt may have been already initialized as start_stmt()
+ is called for *each table* not for each storage engine,
+ and there could be many bdb tables referenced in the query
+ */
+ if (!trx->stmt)
{
DBUG_PRINT("trans",("starting transaction stmt"));
- error=txn_begin(db_env, (DB_TXN*) thd->transaction.all.bdb_tid,
- (DB_TXN**) &thd->transaction.stmt.bdb_tid,
- 0);
+ error=txn_begin(db_env, trx->all, &trx->stmt, 0);
+ trans_register_ha(thd, FALSE, &berkeley_hton);
}
- transaction= (DB_TXN*) thd->transaction.stmt.bdb_tid;
+ transaction= trx->stmt;
DBUG_RETURN(error);
}
@@ -1918,9 +1966,7 @@ THR_LOCK_DATA **ha_berkeley::store_lock(THD *thd, THR_LOCK_DATA **to,
lock_type <= TL_WRITE) &&
!thd->in_lock_tables)
lock_type = TL_WRITE_ALLOW_WRITE;
- lock.type=lock_type;
- lock_on_read= ((table->reginfo.lock_type > TL_WRITE_ALLOW_READ) ? DB_RMW :
- 0);
+ lock.type= lock_type;
}
*to++= &lock;
return to;
@@ -1974,9 +2020,9 @@ int ha_berkeley::create(const char *name, register TABLE *form,
if ((error= create_sub_table(name_buff,"main",DB_BTREE,0)))
DBUG_RETURN(error); /* purecov: inspected */
- primary_key=table->primary_key;
+ primary_key= table->s->primary_key;
/* Create the keys */
- for (uint i=0; i < form->keys; i++)
+ for (uint i=0; i < form->s->keys; i++)
{
if (i != primary_key)
{
@@ -1998,7 +2044,7 @@ int ha_berkeley::create(const char *name, register TABLE *form,
"status", DB_BTREE, DB_CREATE, 0))))
{
char rec_buff[4+MAX_KEY*4];
- uint length= 4+ table->keys*4;
+ uint length= 4+ table->s->keys*4;
bzero(rec_buff, length);
error= write_status(status_block, rec_buff, length);
status_block->close(status_block,0);
@@ -2062,19 +2108,35 @@ ha_rows ha_berkeley::records_in_range(uint keynr, key_range *start_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 && kfile->key_range(kfile,transaction,
- pack_key(&key, keynr, key_buff,
- start_key->key,
- start_key->length),
- &start_range,0)) ||
- (end_key && kfile->key_range(kfile,transaction,
- pack_key(&key, keynr, key_buff,
- end_key->key,
- end_key->length),
- &end_range,0)))
- DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); // Better than returning an error /* purecov: inspected */
+ bool error;
+ KEY *key_info= &table->key_info[keynr];
+ DBUG_ENTER("ha_berkeley::records_in_range");
+
+ /* Ensure we get maximum range, even for varchar keys with different space */
+ key_info->handler.bdb_return_if_eq= -1;
+ error= ((start_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff,
+ start_key->key,
+ start_key->length),
+ &start_range,0)));
+ if (error)
+ {
+ key_info->handler.bdb_return_if_eq= 0;
+ // Better than returning an error
+ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); /* purecov: inspected */
+ }
+ key_info->handler.bdb_return_if_eq= 1;
+ error= (end_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff,
+ end_key->key,
+ end_key->length),
+ &end_range,0));
+ key_info->handler.bdb_return_if_eq= 0;
+ if (error)
+ {
+ // Better than returning an error
+ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); /* purecov: inspected */
+ }
if (!start_key)
start_pos= 0.0;
@@ -2091,20 +2153,20 @@ ha_rows ha_berkeley::records_in_range(uint keynr, key_range *start_key,
end_pos=end_range.less+end_range.equal;
rows=(end_pos-start_pos)*records;
DBUG_PRINT("exit",("rows: %g",rows));
- DBUG_RETURN(rows <= 1.0 ? (ha_rows) 1 : (ha_rows) rows);
+ DBUG_RETURN((ha_rows)(rows <= 1.0 ? 1 : rows));
}
-longlong ha_berkeley::get_auto_increment()
+ulonglong ha_berkeley::get_auto_increment()
{
- longlong nr=1; // Default if error or new key
+ ulonglong nr=1; // Default if error or new key
int error;
(void) ha_berkeley::extra(HA_EXTRA_KEYREAD);
/* Set 'active_index' */
- ha_berkeley::index_init(table->next_number_index);
+ ha_berkeley::index_init(table->s->next_number_index);
- if (!table->next_number_key_offset)
+ if (!table->s->next_number_key_offset)
{ // Autoincrement at key-start
error=ha_berkeley::index_last(table->record[1]);
}
@@ -2117,7 +2179,7 @@ longlong ha_berkeley::get_auto_increment()
/* Reading next available number for a sub key */
ha_berkeley::create_key(&last_key, active_index,
key_buff, table->record[0],
- table->next_number_key_offset);
+ table->s->next_number_key_offset);
/* Store for compare */
memcpy(old_key.data=key_buff2, key_buff, (old_key.size=last_key.size));
old_key.app_private=(void*) key_info;
@@ -2146,8 +2208,8 @@ longlong ha_berkeley::get_auto_increment()
}
}
if (!error)
- nr=(longlong)
- table->next_number_field->val_int_offset(table->rec_buff_length)+1;
+ nr= (ulonglong)
+ table->next_number_field->val_int_offset(table->s->rec_buff_length)+1;
ha_berkeley::index_end();
(void) ha_berkeley::extra(HA_EXTRA_NO_KEYREAD);
return nr;
@@ -2185,7 +2247,7 @@ static void print_msg(THD *thd, const char *table_name, const char *op_name,
protocol->store(msg_type);
protocol->store(msgbuf);
if (protocol->write())
- thd->killed=1;
+ thd->killed=THD::KILL_CONNECTION;
}
#endif
@@ -2194,6 +2256,8 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
uint i;
DB_BTREE_STAT *stat=0;
DB_TXN_STAT *txn_stat_ptr= 0;
+ berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+ DBUG_ASSERT(trx);
/*
Original bdb documentation says:
@@ -2208,13 +2272,10 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
txn_stat_ptr && txn_stat_ptr->st_nactive>=2)
{
DB_TXN_ACTIVE *atxn_stmt= 0, *atxn_all= 0;
-
- DB_TXN *txn_all= (DB_TXN*) thd->transaction.all.bdb_tid;
- u_int32_t all_id= txn_all->id(txn_all);
-
- DB_TXN *txn_stmt= (DB_TXN*) thd->transaction.stmt.bdb_tid;
- u_int32_t stmt_id= txn_stmt->id(txn_stmt);
-
+
+ u_int32_t all_id= trx->all->id(trx->all);
+ u_int32_t stmt_id= trx->stmt->id(trx->stmt);
+
DB_TXN_ACTIVE *cur= txn_stat_ptr->st_txnarray;
DB_TXN_ACTIVE *end= cur + txn_stat_ptr->st_nactive;
for (; cur!=end && (!atxn_stmt || !atxn_all); cur++)
@@ -2222,7 +2283,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
if (cur->txnid==all_id) atxn_all= cur;
if (cur->txnid==stmt_id) atxn_stmt= cur;
}
-
+
if (atxn_stmt && atxn_all &&
log_compare(&atxn_stmt->lsn,&atxn_all->lsn))
{
@@ -2232,7 +2293,7 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
free(txn_stat_ptr);
}
- for (i=0 ; i < table->keys ; i++)
+ for (i=0 ; i < table->s->keys ; i++)
{
if (stat)
{
@@ -2367,14 +2428,15 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table)
char *tmp_name;
DB **key_file;
u_int32_t *key_type;
+ uint keys= table->s->keys;
if ((share=(BDB_SHARE *)
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
&share, sizeof(*share),
- &rec_per_key, table->keys * sizeof(ha_rows),
+ &rec_per_key, keys * sizeof(ha_rows),
&tmp_name, length+1,
- &key_file, (table->keys+1) * sizeof(*key_file),
- &key_type, (table->keys+1) * sizeof(u_int32_t),
+ &key_file, (keys+1) * sizeof(*key_file),
+ &key_type, (keys+1) * sizeof(u_int32_t),
NullS)))
{
share->rec_per_key = rec_per_key;
@@ -2401,7 +2463,7 @@ static int free_share(BDB_SHARE *share, TABLE *table, uint hidden_primary_key,
bool mutex_is_locked)
{
int error, result = 0;
- uint keys=table->keys + test(hidden_primary_key);
+ uint keys= table->s->keys + test(hidden_primary_key);
pthread_mutex_lock(&bdb_mutex);
if (mutex_is_locked)
pthread_mutex_unlock(&share->mutex); /* purecov: inspected */
@@ -2465,8 +2527,8 @@ void ha_berkeley::get_status()
}
if (!(share->status & STATUS_ROW_COUNT_INIT) && share->status_block)
{
- share->org_rows=share->rows=
- table->max_rows ? table->max_rows : HA_BERKELEY_MAX_ROWS;
+ share->org_rows= share->rows=
+ table->s->max_rows ? table->s->max_rows : HA_BERKELEY_MAX_ROWS;
if (!share->status_block->cursor(share->status_block, 0, &cursor, 0))
{
DBT row;
@@ -2481,9 +2543,10 @@ void ha_berkeley::get_status()
uint i;
uchar *pos=(uchar*) row.data;
share->org_rows=share->rows=uint4korr(pos); pos+=4;
- for (i=0 ; i < table->keys ; i++)
+ for (i=0 ; i < table->s->keys ; i++)
{
- share->rec_per_key[i]=uint4korr(pos); pos+=4;
+ share->rec_per_key[i]=uint4korr(pos);
+ pos+=4;
}
}
cursor->c_close(cursor);
@@ -2541,7 +2604,7 @@ static void update_status(BDB_SHARE *share, TABLE *table)
{
char rec_buff[4+MAX_KEY*4], *pos=rec_buff;
int4store(pos,share->rows); pos+=4;
- for (uint i=0 ; i < table->keys ; i++)
+ for (uint i=0 ; i < table->s->keys ; i++)
{
int4store(pos,share->rec_per_key[i]); pos+=4;
}
@@ -2557,6 +2620,7 @@ end:
DBUG_VOID_RETURN;
}
+
/*
Return an estimated of the number of rows in the table.
Used when sorting to allocate buffers and by the optimizer.
@@ -2567,4 +2631,29 @@ ha_rows ha_berkeley::estimate_rows_upper_bound()
return share->rows + HA_BERKELEY_EXTRA_ROWS;
}
+int ha_berkeley::cmp_ref(const byte *ref1, const byte *ref2)
+{
+ if (hidden_primary_key)
+ return memcmp(ref1, ref2, BDB_HIDDEN_PRIMARY_KEY_LENGTH);
+
+ int result;
+ Field *field;
+ KEY *key_info=table->key_info+table->s->primary_key;
+ KEY_PART_INFO *key_part=key_info->key_part;
+ KEY_PART_INFO *end=key_part+key_info->key_parts;
+
+ for (; key_part != end; key_part++)
+ {
+ field= key_part->field;
+ result= field->pack_cmp((const char*)ref1, (const char*)ref2,
+ key_part->length, 0);
+ if (result)
+ return result;
+ ref1+= field->packed_col_length((const char*)ref1, key_part->length);
+ ref2+= field->packed_col_length((const char*)ref2, key_part->length);
+ }
+
+ return 0;
+}
+
#endif /* HAVE_BERKELEY_DB */