Commit 77225fd2 authored by Rich Prohaska's avatar Rich Prohaska

Merge branch 'keepcard'

parents c6f720db 9cbde61b
drop table if exists tt;
create table tt (a int, b int, c int, d int, key(a), key(b), key(c));
insert into tt values (0,0,0,0),(1,0,0,0),(2,0,1,0),(3,0,1,0);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 a 1 a A NULL NULL NULL YES BTREE
tt 1 b 1 b A NULL NULL NULL YES BTREE
tt 1 c 1 c A NULL NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
alter table tt drop key b, add key (d);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
tt 1 d 1 d A NULL NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
tt 1 d 1 d A 1 NULL NULL YES BTREE
flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
tt 1 d 1 d A 1 NULL NULL YES BTREE
drop table tt;
drop table if exists tt;
create table tt (a int, b int, c int, primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
alter table tt add key (b);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A NULL NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
alter table tt add key (c);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
tt 1 c 1 c A NULL NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
drop table tt;
drop table if exists tt;
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A NULL NULL NULL YES BTREE
tt 1 c 1 c A NULL NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
alter table tt drop key b;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
alter table tt drop key c;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
drop table tt;
drop table if exists tt;
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A NULL NULL NULL YES BTREE
tt 1 c 1 c A NULL NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 1 NULL NULL YES BTREE
tt 1 c 1 c A 2 NULL NULL YES BTREE
alter table tt drop primary key;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 b 1 b A NULL NULL NULL YES BTREE
tt 1 c 1 c A NULL NULL NULL YES BTREE
flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 b 1 b A NULL NULL NULL YES BTREE
tt 1 c 1 c A NULL NULL NULL YES BTREE
drop table tt;
# test that add and drop works
source include/have_tokudb.inc;
disable_warnings;
drop table if exists tt;
enable_warnings;
create table tt (a int, b int, c int, d int, key(a), key(b), key(c));
insert into tt values (0,0,0,0),(1,0,0,0),(2,0,1,0),(3,0,1,0);
# test that analyze computes the correcK
show indexes from tt;
analyze table tt;
show indexes from tt;
# drop b, add d
alter table tt drop key b, add key (d);
show indexes from tt;
analyze table tt;
show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
drop table tt;
# test that add index keeps cardinality for older indexes
source include/have_tokudb.inc;
disable_warnings;
drop table if exists tt;
enable_warnings;
create table tt (a int, b int, c int, primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
# test that analyze computes the correct cardinality for the PK
show indexes from tt;
analyze table tt;
show indexes from tt;
# add a key(b)
alter table tt add key (b);
show indexes from tt;
analyze table tt;
show indexes from tt;
# add a key(c)
alter table tt add key (c);
show indexes from tt;
analyze table tt;
show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
drop table tt;
# test that add index keeps cardinality for older indexes
source include/have_tokudb.inc;
disable_warnings;
drop table if exists tt;
enable_warnings;
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
# compute cardinality
show indexes from tt;
analyze table tt;
show indexes from tt;
# drop key b
alter table tt drop key b;
show indexes from tt;
# drop key c
alter table tt drop key c;
show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
drop table tt;
# test that add index keeps cardinality for older indexes
source include/have_tokudb.inc;
disable_warnings;
drop table if exists tt;
enable_warnings;
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
# compute cardinality
show indexes from tt;
analyze table tt;
show indexes from tt;
# drop key a
alter table tt drop primary key;
show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
drop table tt;
......@@ -55,7 +55,10 @@ int ha_tokudb::analyze(THD *thd, HA_CHECK_OPT *check_opt) {
struct analyze_progress_extra analyze_progress_extra = {
thd, share, table_share, i, key_name, time(0), write_status_msg
};
int error = tokudb::analyze_card(share->key_file[i], txn, false, num_key_parts, &rec_per_key[next_key_part],
bool is_unique = false;
if (i == primary_key || (key_info->flags & HA_NOSAME))
is_unique = true;
int error = tokudb::analyze_card(share->key_file[i], txn, is_unique, num_key_parts, &rec_per_key[next_key_part],
tokudb_cmp_dbt_key_parts, analyze_progress, &analyze_progress_extra);
if (error != 0 && error != ETIME) {
result = HA_ADMIN_FAILED;
......
......@@ -22,6 +22,7 @@ public:
alter_txn(NULL),
add_index_changed(false),
drop_index_changed(false),
reset_card(false),
compression_changed(false),
expand_varchar_update_needed(false),
expand_fixed_update_needed(false),
......@@ -38,6 +39,7 @@ public:
bool add_index_changed;
bool incremented_num_DBs, modified_DBs;
bool drop_index_changed;
bool reset_card;
bool compression_changed;
enum toku_compression_method orig_compression_method;
bool expand_varchar_update_needed;
......@@ -366,7 +368,6 @@ bool ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha
}
if (error == 0 && (ctx->handler_flags & Alter_inplace_info::CHANGE_CREATE_OPTION) && (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) {
// Get the current compression
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
DB *db = share->key_file[0];
error = db->get_compression_method(db, &ctx->orig_compression_method);
assert(error == 0);
......@@ -388,6 +389,9 @@ bool ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha
if (error == 0 && ctx->expand_fixed_update_needed)
error = alter_table_expand_columns(altered_table, ha_alter_info);
if (error == 0 && ctx->reset_card)
tokudb::set_card_from_status(share->status_block, ctx->alter_txn, table->s, altered_table->s);
bool result = false; // success
if (error) {
print_error(error, MYF(0));
......@@ -422,7 +426,7 @@ int ha_tokudb::alter_table_add_index(TABLE *altered_table, Alter_inplace_info *h
my_free(key_info);
if (error == 0)
tokudb::delete_card_from_status(share->status_block, ctx->alter_txn);
ctx->reset_card = true;
return error;
}
......@@ -469,7 +473,7 @@ int ha_tokudb::alter_table_drop_index(TABLE *altered_table, Alter_inplace_info *
int error = drop_indexes(table, index_drop_offsets, ha_alter_info->index_drop_count, key_info, ctx->alter_txn);
if (error == 0)
tokudb::delete_card_from_status(share->status_block, ctx->alter_txn);
ctx->reset_card = true;
return error;
}
......
......@@ -4,9 +4,9 @@ CHECKS = $(patsubst %,%.check,$(TARGETS))
CPPFLAGS = -I.. -D__STDC_FORMAT_MACROS
CXXFLAGS = -g -Wall -Wextra -Wno-missing-field-initializers -Wshadow
FRACTALTREE_BASE_DIR = ../../../../tokudb
FRACTALTREE_DIR = $(FRACTALTREE_BASE_DIR)/release
VALGRIND = valgrind -q --leak-check=full --show-reachable=yes --suppressions=$(FRACTALTREE_BASE_DIR)/build.debug/valgrind.suppressions --soname-synonyms=somalloc=*tokuportability*
FRACTALTREE_BASE_DIR = ../ft-index
FRACTALTREE_INSTALL_DIR = $(FRACTALTREE_BASE_DIR)/install.debug
VALGRIND = valgrind -q --leak-check=full --show-reachable=yes --suppressions=$(FRACTALTREE_BASE_DIR)/ft/valgrind.suppressions --soname-synonyms=somalloc=*tokuportability*
ifeq ($(GCOV),1)
CXXFLAGS += -fprofile-arcs -ftest-coverage
......@@ -21,7 +21,7 @@ check: $(CHECKS)
true
%.check: %
LD_LIBRARY_PATH=$(FRACTALTREE_DIR)/lib $(VALGRIND) ./$<
LD_LIBRARY_PATH=$(FRACTALTREE_INSTALL_DIR)/lib $(VALGRIND) ./$<
card.check: card_test.check card_1.check card_inf.check card_inf_1.check card_random_1.check card_etime.check
true
......@@ -33,4 +33,4 @@ max_test.check: max_test
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -g -o $@ $<
card_%: card_%.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -g -o $@ $< -I.. -I$(FRACTALTREE_DIR)/include -L$(FRACTALTREE_DIR)/lib -ltokudb -ltokuportability
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -g -o $@ $< -I.. -I$(FRACTALTREE_INSTALL_DIR)/include -L$(FRACTALTREE_INSTALL_DIR)/lib -ltokufractaltree -ltokuportability
......@@ -19,27 +19,9 @@
typedef unsigned long long ulonglong;
#include "tokudb_status.h"
#include "tokudb_buffer.h"
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint64_t *rec_per_key;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
#include "fake_mysql.h"
#if __APPLE__
typedef unsigned long ulong;
#endif
......@@ -111,6 +93,11 @@ static void test_card(DB_ENV *env, DB *db, uint64_t expect_card) {
assert(rec_per_key[0] == expect_card);
r = tokudb::analyze_card(db, txn, true, num_key_parts, rec_per_key, analyze_key_compare, NULL, NULL);
assert(r == 0);
assert(rec_per_key[0] == expect_card);
r = txn->commit(txn, 0);
assert(r == 0);
}
......
......@@ -20,27 +20,7 @@
typedef unsigned long long ulonglong;
#include "tokudb_status.h"
#include "tokudb_buffer.h"
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint64_t *rec_per_key;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
#include "fake_mysql.h"
#if __APPLE__
typedef unsigned long ulong;
#endif
......
......@@ -18,27 +18,7 @@
typedef unsigned long long ulonglong;
#include "tokudb_status.h"
#include "tokudb_buffer.h"
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint64_t *rec_per_key;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
#include "fake_mysql.h"
#if __APPLE__
typedef unsigned long ulong;
#endif
......
......@@ -18,27 +18,7 @@
typedef unsigned long long ulonglong;
#include "tokudb_status.h"
#include "tokudb_buffer.h"
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint64_t *rec_per_key;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
#include "fake_mysql.h"
#if __APPLE__
typedef unsigned long ulong;
#endif
......
......@@ -19,27 +19,7 @@
typedef unsigned long long ulonglong;
#include "tokudb_status.h"
#include "tokudb_buffer.h"
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint64_t *rec_per_key;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
#include "fake_mysql.h"
#if __APPLE__
typedef unsigned long ulong;
#endif
......
......@@ -11,27 +11,8 @@ typedef unsigned long long ulonglong;
#include <tokudb_status.h>
#include <tokudb_buffer.h>
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint64_t *rec_per_key;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
#include "fake_mysql.h"
#if __APPLE__
typedef unsigned long ulong;
#endif
......
// Provide some mimimal MySQL classes just to compile the tokudb cardinality functions
class KEY_INFO {
public:
uint flags;
uint key_parts;
uint64_t *rec_per_key;
char *name;
};
#define HA_NOSAME 1
class TABLE_SHARE {
public:
uint primary_key;
uint keys, key_parts;
KEY_INFO *key_info;
};
class TABLE {
public:
TABLE_SHARE *s;
KEY_INFO *key_info;
};
uint get_key_parts(KEY_INFO *key_info) {
assert(key_info);
return 0;
}
......@@ -66,6 +66,51 @@ namespace tokudb {
assert(error == 0);
}
bool find_index_of_key(const char *key_name, TABLE_SHARE *table_share, uint *index_offset_ptr) {
for (uint i = 0; i < table_share->keys; i++) {
if (strcmp(key_name, table_share->key_info[i].name) == 0) {
*index_offset_ptr = i;
return true;
}
}
return false;
}
// Altered table cardinality = select cardinality data from current table cardinality for keys that exist
// in the altered table and the current table.
void set_card_from_status(DB *status_db, DB_TXN *txn, TABLE_SHARE *table_share, TABLE_SHARE *altered_table_share) {
int error;
// read existing cardinality data from status
uint64_t rec_per_key[table_share->key_parts];
error = get_card_from_status(status_db, txn, table_share->key_parts, rec_per_key);
// set altered records per key to unknown
uint64_t altered_rec_per_key[altered_table_share->key_parts];
for (uint i = 0; i < altered_table_share->key_parts; i++)
altered_rec_per_key[i] = 0;
// compute the beginning of the key offsets in the original table
uint orig_key_offset[table_share->keys];
uint orig_key_parts = 0;
for (uint i = 0; i < table_share->keys; i++) {
orig_key_offset[i] = orig_key_parts;
orig_key_parts += table_share->key_info[i].key_parts;
}
// if orig card data exists, then use it to compute new card data
if (error == 0) {
uint key_parts = 0;
for (uint i = 0; error == 0 && i < altered_table_share->keys; i++) {
uint orig_key_index;
if (find_index_of_key(altered_table_share->key_info[i].name, table_share, &orig_key_index)) {
memcpy(&altered_rec_per_key[key_parts], &rec_per_key[orig_key_offset[orig_key_index]], altered_table_share->key_info[i].key_parts);
}
key_parts += altered_table_share->key_info[i].key_parts;
}
}
if (error == 0)
set_card_in_status(status_db, txn, altered_table_share->key_parts, altered_rec_per_key);
else
delete_card_from_status(status_db, txn);
}
// Compute records per key for all key parts of the ith key of the table.
// For each key part, put records per key part in *rec_per_key_part[key_part_index].
// Returns 0 if success, otherwise an error number.
......@@ -74,66 +119,71 @@ namespace tokudb {
int (*key_compare)(DB *, const DBT *, const DBT *, uint),
int (*analyze_progress)(void *extra, uint64_t rows), void *progress_extra) {
int error = 0;
DBC *cursor = NULL;
error = db->cursor(db, txn, &cursor, 0);
if (error == 0) {
uint64_t rows = 0;
uint64_t unique_rows[num_key_parts];
for (uint64_t i = 0; i < num_key_parts; i++)
unique_rows[i] = 1;
// stop looking when the entire dictionary was analyzed, or a cap on execution time was reached, or the analyze was killed.
DBT key = {}; key.flags = DB_DBT_REALLOC;
DBT prev_key = {}; prev_key.flags = DB_DBT_REALLOC;
while (1) {
error = cursor->c_get(cursor, &key, 0, DB_NEXT);
if (error != 0) {
if (error == DB_NOTFOUND)
uint64_t rows = 0;
uint64_t unique_rows[num_key_parts];
if (is_unique && num_key_parts == 1) {
// dont compute for unique keys with a single part. we already know the answer.
rows = unique_rows[0] = 1;
} else {
DBC *cursor = NULL;
error = db->cursor(db, txn, &cursor, 0);
if (error == 0) {
for (uint64_t i = 0; i < num_key_parts; i++)
unique_rows[i] = 1;
// stop looking when the entire dictionary was analyzed, or a cap on execution time was reached, or the analyze was killed.
DBT key = {}; key.flags = DB_DBT_REALLOC;
DBT prev_key = {}; prev_key.flags = DB_DBT_REALLOC;
while (1) {
error = cursor->c_get(cursor, &key, 0, DB_NEXT);
if (error != 0) {
if (error == DB_NOTFOUND)
error = 0; // eof is not an error
break;
}
rows++;
// first row is a unique row, otherwise compare with the previous key
bool copy_key = false;
if (rows == 1) {
copy_key = true;
} else {
// compare this key with the previous key. ignore appended PK for SK's.
// TODO if a prefix is different, then all larger keys that include the prefix are also different.
// TODO if we are comparing the entire primary key or the entire unique secondary key, then the cardinality must be 1,
// so we can avoid computing it.
for (uint64_t i = 0; i < num_key_parts; i++) {
int cmp = key_compare(db, &prev_key, &key, i+1);
if (cmp != 0) {
unique_rows[i]++;
copy_key = true;
break;
}
rows++;
// first row is a unique row, otherwise compare with the previous key
bool copy_key = false;
if (rows == 1) {
copy_key = true;
} else {
// compare this key with the previous key. ignore appended PK for SK's.
// TODO if a prefix is different, then all larger keys that include the prefix are also different.
// TODO if we are comparing the entire primary key or the entire unique secondary key, then the cardinality must be 1,
// so we can avoid computing it.
for (uint64_t i = 0; i < num_key_parts; i++) {
int cmp = key_compare(db, &prev_key, &key, i+1);
if (cmp != 0) {
unique_rows[i]++;
copy_key = true;
}
}
}
// prev_key = key
if (copy_key) {
prev_key.data = realloc(prev_key.data, key.size);
assert(prev_key.data);
prev_key.size = key.size;
memcpy(prev_key.data, key.data, prev_key.size);
}
// check for limit
if (analyze_progress && (rows % 1000) == 0) {
error = analyze_progress(progress_extra, rows);
if (error)
break;
}
}
// prev_key = key
if (copy_key) {
prev_key.data = realloc(prev_key.data, key.size);
assert(prev_key.data);
prev_key.size = key.size;
memcpy(prev_key.data, key.data, prev_key.size);
}
// check for limit
if (analyze_progress && (rows % 1000) == 0) {
error = analyze_progress(progress_extra, rows);
if (error)
break;
}
}
// cleanup
free(key.data);
free(prev_key.data);
int close_error = cursor->c_close(cursor);
assert(close_error == 0);
// return cardinality
if (error == 0 || error == ETIME) {
for (uint64_t i = 0; i < num_key_parts; i++)
rec_per_key_part[i] = rows / unique_rows[i];
// cleanup
free(key.data);
free(prev_key.data);
int close_error = cursor->c_close(cursor);
assert(close_error == 0);
}
}
// return cardinality
if (error == 0 || error == ETIME) {
for (uint64_t i = 0; i < num_key_parts; i++)
rec_per_key_part[i] = rows / unique_rows[i];
}
return error;
}
}
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