Databases Reference
In-Depth Information
What we need here is to make these two
NULL
values unique in some way, to be
able to distinguish between them and provide a stable sorting order. The trick we
use in our engine is to use combined keys. Remember that the task of secondary
key indexes is to map a secondary key to a corresponding primary key?
NULL
is not
a problem for primary keys, as all primary key columns are always
NOT
NULL
. But,
for every secondary key, instead of using {secondary key, primary key} as a key/
value pair in the Tokyo Cabinet B+trees, we will use {secondary key concatenated
with primary key, empty string} as a key/value pair. This immediately solves
our problem—if two secondary keys are exactly identical, but should be reported
as different because they are both
NULL
, we return -1 or 1 depending on the
corresponding primary keys, which are guaranteed to be unique. But the key buffer
needs to be big enough to hold the largest secondary key and the primary key
together. It is exactly how we allocated it above.
if (key_buffer == 0)
return HA_ERR_OUT_OF_MEM;
share = find_or_create_share(name, table);
if (share->use_count == 0) {
share->dbh = open_tcdb(name, table, &err);
if (err) {
free(key_buffer);
key_buffer = 0;
return err;
}
thr_lock_init(&share->lock);
}
As usual, in the
open()
method we find (or create) a
TOCAB_SHARE
structure, and
if this share was created we initialize its
THR_LOCK
member. But we also open our
.tocab
table file here, because we decided to store its handle in the share.
share->use_count++;
thr_lock_data_init(&share->lock,&lock,NULL);
dbcur = tcbdbcurnew(share->dbh);
if (!dbcur) {
close();
return HA_ERR_OUT_OF_MEM;
}
keyread = false;
return 0;
}