mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-10-21 02:57:42 +08:00
query planner stuff
some gcc -Wall fixes added suport for _ in identifier names in SQL gmdb2 manual additions
This commit is contained in:
@@ -112,10 +112,11 @@ int did_first;
|
||||
|
||||
char *mdb_get_coltype_string(MdbBackend *backend, int col_type)
|
||||
{
|
||||
char buf[100];
|
||||
static char buf[100];
|
||||
|
||||
if (col_type > 0x10) {
|
||||
// return NULL;
|
||||
sprintf(buf,"type %04x", col_type);
|
||||
sprintf(buf,"type %04x", col_type);
|
||||
return buf;
|
||||
} else {
|
||||
return backend->types_table[col_type];
|
||||
@@ -167,11 +168,12 @@ MdbBackend *backend;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_first (MdbHandle *mdb)
|
||||
static void
|
||||
do_first (MdbHandle *mdb)
|
||||
{
|
||||
int i, j, k;
|
||||
static char text[255];
|
||||
mdb_read_catalog (mdb, MDB_TABLE);
|
||||
int i, k;
|
||||
|
||||
mdb_read_catalog (mdb, MDB_TABLE);
|
||||
|
||||
/* loop over each entry in the catalog */
|
||||
for (i=0; i < mdb->num_catalog; i++) {
|
||||
|
@@ -27,6 +27,7 @@ char *mdb_money_to_string(MdbHandle *mdb, int start, char *s);
|
||||
static int _mdb_attempt_bind(MdbHandle *mdb,
|
||||
MdbColumn *col, unsigned char isnull, int offset, int len);
|
||||
char *mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale);
|
||||
int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size);
|
||||
|
||||
|
||||
void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr)
|
||||
@@ -155,21 +156,23 @@ int ret;
|
||||
}
|
||||
int mdb_read_row(MdbTableDef *table, int row)
|
||||
{
|
||||
MdbHandle *mdb = table->entry->mdb;
|
||||
MdbFormatConstants *fmt = mdb->fmt;
|
||||
MdbColumn *col;
|
||||
int i, j, rc;
|
||||
int num_cols, var_cols, fixed_cols;
|
||||
int row_start, row_end;
|
||||
int fixed_cols_found, var_cols_found;
|
||||
int col_start, len, next_col;
|
||||
int num_of_jumps=0, jumps_used=0;
|
||||
int eod; /* end of data */
|
||||
int delflag, lookupflag;
|
||||
int bitmask_sz;
|
||||
int col_ptr, deleted_columns=0;
|
||||
unsigned char null_mask[33]; /* 256 columns max / 8 bits per byte */
|
||||
unsigned char isnull;
|
||||
MdbHandle *mdb = table->entry->mdb;
|
||||
MdbFormatConstants *fmt = mdb->fmt;
|
||||
MdbColumn *col;
|
||||
int i, j, rc;
|
||||
int num_cols, var_cols, fixed_cols;
|
||||
int row_start, row_end;
|
||||
int fixed_cols_found, var_cols_found;
|
||||
int col_start, len, next_col;
|
||||
int num_of_jumps=0, jumps_used=0;
|
||||
int eod; /* end of data */
|
||||
int delflag, lookupflag;
|
||||
int bitmask_sz;
|
||||
int col_ptr, deleted_columns=0;
|
||||
unsigned char null_mask[33]; /* 256 columns max / 8 bits per byte */
|
||||
unsigned char isnull;
|
||||
MdbField fields[256];
|
||||
int num_fields;
|
||||
|
||||
row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (row*2));
|
||||
row_end = mdb_find_end_of_row(mdb, row);
|
||||
@@ -184,6 +187,13 @@ unsigned char isnull;
|
||||
lookupflag ? "[lookup]" : "",
|
||||
delflag ? "[delflag]" : "");
|
||||
#endif
|
||||
num_fields = mdb_crack_row(table, row_start, row_end, &fields);
|
||||
if (!mdb_test_sargs(table, &fields, num_fields)) return 0;
|
||||
for (i=0; i < num_fields; i++) {
|
||||
//col = g_ptr_array_index (table->columns, fields[i].colnum - 1);
|
||||
//rc = _mdb_attempt_bind(mdb, col, fields[i].is_null,
|
||||
//row_start + col_start, col->col_size);
|
||||
}
|
||||
//if (!table->noskip_del && (delflag || lookupflag)) {
|
||||
if (!table->noskip_del && delflag) {
|
||||
row_end = row_start-1;
|
||||
@@ -357,9 +367,9 @@ static int _mdb_attempt_bind(MdbHandle *mdb,
|
||||
} else if (isnull) {
|
||||
mdb_xfer_bound_data(mdb, 0, col, 0);
|
||||
} else {
|
||||
if (!mdb_test_sargs(mdb, col, offset, len)) {
|
||||
return 0;
|
||||
}
|
||||
//if (!mdb_test_sargs(mdb, col, offset, len)) {
|
||||
//return 0;
|
||||
//}
|
||||
mdb_xfer_bound_data(mdb, offset, col, len);
|
||||
}
|
||||
return 1;
|
||||
@@ -395,7 +405,6 @@ mdb_read_next_dpg_by_map1(MdbTableDef *table)
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
guint32 pgnum, i, j, bitn, map_pg;
|
||||
unsigned char map_byte;
|
||||
|
||||
pgnum = 0;
|
||||
//printf("map size %ld\n", table->map_sz);
|
||||
@@ -468,6 +477,7 @@ MdbHandle *mdb = table->entry->mdb;
|
||||
MdbFormatConstants *fmt = mdb->fmt;
|
||||
int rows;
|
||||
int rc;
|
||||
guint32 pg;
|
||||
|
||||
if (table->num_rows==0)
|
||||
return 0;
|
||||
@@ -476,19 +486,29 @@ int rc;
|
||||
if (!table->cur_pg_num) {
|
||||
table->cur_pg_num=1;
|
||||
table->cur_row=0;
|
||||
mdb_read_next_dpg(table);
|
||||
if (table->strategy!=MDB_INDEX_SCAN)
|
||||
if (!mdb_read_next_dpg(table)) return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
rows = mdb_get_int16(mdb,fmt->row_count_offset);
|
||||
|
||||
/* if at end of page, find a new page */
|
||||
if (table->cur_row >= rows) {
|
||||
table->cur_row=0;
|
||||
|
||||
if (!mdb_read_next_dpg(table)) {
|
||||
do {
|
||||
if (table->strategy==MDB_INDEX_SCAN) {
|
||||
|
||||
if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, &(table->cur_row))) {
|
||||
mdb_index_scan_free(table);
|
||||
return 0;
|
||||
}
|
||||
mdb_read_pg(mdb, pg);
|
||||
} else {
|
||||
rows = mdb_get_int16(mdb,fmt->row_count_offset);
|
||||
|
||||
/* if at end of page, find a new page */
|
||||
if (table->cur_row >= rows) {
|
||||
table->cur_row=0;
|
||||
|
||||
if (!mdb_read_next_dpg(table)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* printf("page %d row %d\n",table->cur_phys_pg, table->cur_row); */
|
||||
@@ -500,9 +520,7 @@ int rc;
|
||||
}
|
||||
void mdb_data_dump(MdbTableDef *table)
|
||||
{
|
||||
MdbHandle *mdb = table->entry->mdb;
|
||||
int i, j, pg_num;
|
||||
int rows;
|
||||
int i, j;
|
||||
char *bound_values[MDB_MAX_COLS];
|
||||
|
||||
for (i=0;i<table->num_cols;i++) {
|
||||
@@ -524,6 +542,7 @@ int mdb_is_fixed_col(MdbColumn *col)
|
||||
{
|
||||
return col->is_fixed;
|
||||
}
|
||||
#if 0
|
||||
static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size)
|
||||
{
|
||||
int i;
|
||||
@@ -535,6 +554,7 @@ int i;
|
||||
|
||||
return text;
|
||||
}
|
||||
#endif
|
||||
int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
|
||||
{
|
||||
guint16 ole_len;
|
||||
@@ -751,20 +771,21 @@ int i;
|
||||
return text;
|
||||
#endif
|
||||
}
|
||||
char *mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale)
|
||||
char *
|
||||
mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale)
|
||||
{
|
||||
/* FIX ME -- not thread safe */
|
||||
static char text[MDB_BIND_SIZE];
|
||||
char tmpbuf[MDB_BIND_SIZE];
|
||||
char mask[20];
|
||||
gint32 l, whole, fraction;
|
||||
gint32 l;
|
||||
|
||||
l = mdb->pg_buf[start+16] * 256 * 256 * 256 +
|
||||
mdb->pg_buf[start+15] * 256 * 256 +
|
||||
mdb->pg_buf[start+14] * 256 +
|
||||
mdb->pg_buf[start+13];
|
||||
|
||||
sprintf(mask,"%%0%ldld",prec);
|
||||
sprintf(mask,"%%0%dld",prec);
|
||||
sprintf(tmpbuf,mask,l);
|
||||
//strcpy(text, tmpbuf);
|
||||
//return text;
|
||||
@@ -776,21 +797,14 @@ gint32 l, whole, fraction;
|
||||
strcat(text,".");
|
||||
strcat(text,&tmpbuf[strlen(tmpbuf)-scale]);
|
||||
}
|
||||
/*
|
||||
for (i=0;i<size;i++) {
|
||||
fprintf(stdout, "%c %02x ", isprint(mdb->pg_buf[start+i]) ? mdb->pg_buf[start+i] : '.', mdb->pg_buf[start+i]);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
*/
|
||||
return text;
|
||||
return text;
|
||||
}
|
||||
char *mdb_col_to_string(MdbHandle *mdb, int start, int datatype, int size)
|
||||
{
|
||||
/* FIX ME -- not thread safe */
|
||||
static char text[MDB_BIND_SIZE];
|
||||
char tmpbuf[10];
|
||||
time_t t;
|
||||
int i,j;
|
||||
int i;
|
||||
|
||||
switch (datatype) {
|
||||
case MDB_BOOL:
|
||||
|
@@ -138,7 +138,8 @@ MdbHandle *mdb_open(char *filename)
|
||||
return _mdb_open(filename, FALSE);
|
||||
}
|
||||
|
||||
void mdb_close(MdbHandle *mdb)
|
||||
void
|
||||
mdb_close(MdbHandle *mdb)
|
||||
{
|
||||
if (mdb->f) {
|
||||
mdb->f->refs--;
|
||||
@@ -173,7 +174,11 @@ size_t mdb_read_pg(MdbHandle *mdb, unsigned long pg)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (pg && mdb->cur_pg == pg) return mdb->fmt->pg_size;
|
||||
|
||||
len = _mdb_read_pg(mdb, mdb->pg_buf, pg);
|
||||
//fprintf(stderr, "read page %d type %02x\n", pg, mdb->pg_buf[0]);
|
||||
mdb->cur_pg = pg;
|
||||
/* kan - reset the cur_pos on a new page read */
|
||||
mdb->cur_pos = 0; /* kan */
|
||||
return len;
|
||||
|
@@ -58,7 +58,7 @@ mdb_read_indices(MdbTableDef *table)
|
||||
{
|
||||
MdbHandle *mdb = table->entry->mdb;
|
||||
MdbIndex idx, *pidx;
|
||||
int len, i, j;
|
||||
int i, j;
|
||||
int idx_num, key_num, col_num;
|
||||
int cur_pos;
|
||||
int name_sz;
|
||||
@@ -127,6 +127,7 @@ int name_sz;
|
||||
cur_pos += 4;
|
||||
pidx->flags = mdb->pg_buf[cur_pos++];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void
|
||||
mdb_index_hash_text(guchar *text, guchar *hash)
|
||||
@@ -147,8 +148,8 @@ mdb_index_swap_int32(guint32 l)
|
||||
unsigned char *c, *c2;
|
||||
guint32 l2;
|
||||
|
||||
c = &l;
|
||||
c2 = &l2;
|
||||
c = (unsigned char *) &l;
|
||||
c2 = (unsigned char *) &l2;
|
||||
c2[0]=c[3];
|
||||
c2[1]=c[2];
|
||||
c2[2]=c[1];
|
||||
@@ -156,9 +157,10 @@ mdb_index_swap_int32(guint32 l)
|
||||
|
||||
return l2;
|
||||
}
|
||||
void mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg)
|
||||
void
|
||||
mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg)
|
||||
{
|
||||
guint32 cache_int;
|
||||
//guint32 cache_int;
|
||||
unsigned char *c;
|
||||
|
||||
switch (col->col_type) {
|
||||
@@ -169,7 +171,7 @@ void mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg)
|
||||
case MDB_LONGINT:
|
||||
idx_sarg->value.i = mdb_index_swap_int32(sarg->value.i);
|
||||
//cache_int = sarg->value.i * -1;
|
||||
c = &(idx_sarg->value.i);
|
||||
c = (unsigned char *) &(idx_sarg->value.i);
|
||||
c[0] |= 0x80;
|
||||
//printf("int %08x %02x %02x %02x %02x\n", sarg->value.i, c[0], c[1], c[2], c[3]);
|
||||
break;
|
||||
@@ -181,6 +183,33 @@ void mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
int
|
||||
mdb_index_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int len)
|
||||
{
|
||||
char tmpbuf[256];
|
||||
int lastchar;
|
||||
|
||||
switch (col->col_type) {
|
||||
case MDB_BYTE:
|
||||
return mdb_test_int(sarg, mdb_get_byte(mdb, offset));
|
||||
break;
|
||||
case MDB_INT:
|
||||
return mdb_test_int(sarg, mdb_get_int16(mdb, offset));
|
||||
break;
|
||||
case MDB_LONGINT:
|
||||
return mdb_test_int(sarg, mdb_get_int32(mdb, offset));
|
||||
break;
|
||||
case MDB_TEXT:
|
||||
strncpy(tmpbuf, &mdb->pg_buf[offset],255);
|
||||
lastchar = len > 255 ? 255 : len;
|
||||
tmpbuf[lastchar]='\0';
|
||||
return mdb_test_string(sarg, tmpbuf);
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int
|
||||
mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, int offset, int len)
|
||||
{
|
||||
@@ -189,6 +218,7 @@ mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, int offset, int len)
|
||||
MdbTableDef *table = idx->table;
|
||||
MdbSarg *idx_sarg;
|
||||
MdbSarg *sarg;
|
||||
MdbSargNode node;
|
||||
int c_offset = 0, c_len;
|
||||
|
||||
for (i=0;i<idx->num_keys;i++) {
|
||||
@@ -220,9 +250,12 @@ mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, int offset, int len)
|
||||
|
||||
for (j=0;j<col->num_sargs;j++) {
|
||||
sarg = g_ptr_array_index (col->idx_sarg_cache, j);
|
||||
if (!mdb_test_sarg(mdb, col, sarg, offset + c_offset, c_len)) {
|
||||
/* sarg didn't match, no sense going on */
|
||||
return 0;
|
||||
/* XXX - kludge */
|
||||
node.op = sarg->op;
|
||||
node.value = sarg->value;
|
||||
if (!mdb_test_sarg(col, &node, &mdb->pg_buf[offset + c_offset], c_len)) {
|
||||
/* sarg didn't match, no sense going on */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,7 +333,7 @@ mdb_find_next_leaf(MdbHandle *mdb, MdbIndexChain *chain)
|
||||
*/
|
||||
chain->cur_depth++;
|
||||
if (chain->cur_depth > MDB_MAX_INDEX_DEPTH) {
|
||||
fprintf(stderr,"Error! maximum index depth of %d exceeded. This is probably due to a programming bug, If you are confident that your indexes really are this deep, adjust MDB_MAX_INDEX_DEPTH in mdbtools.h and recompile.\n");
|
||||
fprintf(stderr,"Error! maximum index depth of %d exceeded. This is probably due to a programming bug, If you are confident that your indexes really are this deep, adjust MDB_MAX_INDEX_DEPTH in mdbtools.h and recompile.\n", MDB_MAX_INDEX_DEPTH);
|
||||
exit(1);
|
||||
}
|
||||
newipg = &(chain->pages[chain->cur_depth - 1]);
|
||||
@@ -403,7 +436,7 @@ int i;
|
||||
for (i=0;i<idx->num_keys;i++) {
|
||||
marker = mdb->pg_buf[cur_pos++];
|
||||
col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1);
|
||||
printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_col_fixed_size(col), col->col_size);
|
||||
//printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_col_fixed_size(col), col->col_size);
|
||||
}
|
||||
}
|
||||
void
|
||||
@@ -428,3 +461,145 @@ mdb_index_dump(MdbTableDef *table, MdbIndex *idx)
|
||||
}
|
||||
mdb_index_walk(table, idx);
|
||||
}
|
||||
int mdb_index_compute_cost(MdbTableDef *table, MdbIndex *idx)
|
||||
{
|
||||
int i;
|
||||
MdbColumn *col;
|
||||
MdbSarg *sarg;
|
||||
int not_all_equal = 0;
|
||||
|
||||
if (!idx->num_keys) return 0;
|
||||
if (idx->num_keys > 1) {
|
||||
for (i=0;i<idx->num_keys;i++) {
|
||||
col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1);
|
||||
sarg = g_ptr_array_index (col->sargs, 0);
|
||||
if (!sarg || sarg->op != MDB_EQUAL) not_all_equal++;
|
||||
}
|
||||
}
|
||||
|
||||
col=g_ptr_array_index(table->columns,idx->key_col_num[0]-1);
|
||||
/*
|
||||
* if this is the first key column and there are no sargs,
|
||||
* then this index is useless.
|
||||
*/
|
||||
if (!col->num_sargs) return 0;
|
||||
|
||||
sarg = g_ptr_array_index (col->sargs, 0);
|
||||
|
||||
/*
|
||||
* a like with a wild card first is useless as a sarg */
|
||||
if (sarg->op == MDB_LIKE && sarg->value.s[0]=='%')
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* this needs a lot of tweaking.
|
||||
*/
|
||||
if (idx->flags & MDB_IDX_UNIQUE) {
|
||||
if (idx->num_keys == 1) {
|
||||
//printf("op is %d\n", sarg->op);
|
||||
switch (sarg->op) {
|
||||
case MDB_EQUAL:
|
||||
return 1; break;
|
||||
case MDB_LIKE:
|
||||
return 4; break;
|
||||
case MDB_ISNULL:
|
||||
return 12; break;
|
||||
default:
|
||||
return 8; break;
|
||||
}
|
||||
} else {
|
||||
switch (sarg->op) {
|
||||
case MDB_EQUAL:
|
||||
if (not_all_equal) return 2;
|
||||
else return 1;
|
||||
break;
|
||||
case MDB_LIKE:
|
||||
return 6; break;
|
||||
case MDB_ISNULL:
|
||||
return 12; break;
|
||||
default:
|
||||
return 9; break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (idx->num_keys == 1) {
|
||||
switch (sarg->op) {
|
||||
case MDB_EQUAL:
|
||||
return 2; break;
|
||||
case MDB_LIKE:
|
||||
return 5; break;
|
||||
case MDB_ISNULL:
|
||||
return 12; break;
|
||||
default:
|
||||
return 10; break;
|
||||
}
|
||||
} else {
|
||||
switch (sarg->op) {
|
||||
case MDB_EQUAL:
|
||||
if (not_all_equal) return 3;
|
||||
else return 2;
|
||||
break;
|
||||
case MDB_LIKE:
|
||||
return 7; break;
|
||||
case MDB_ISNULL:
|
||||
return 12; break;
|
||||
default:
|
||||
return 11; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
MdbStrategy
|
||||
mdb_choose_index(MdbTableDef *table, int *choice)
|
||||
{
|
||||
int i;
|
||||
MdbIndex *idx;
|
||||
int cost = 0;
|
||||
int least = 99;
|
||||
|
||||
*choice = -1;
|
||||
for (i=0;i<table->num_idxs;i++) {
|
||||
idx = g_ptr_array_index (table->indices, i);
|
||||
cost = mdb_index_compute_cost(table, idx);
|
||||
//printf("cost for %s is %d\n", idx->name, cost);
|
||||
if (cost && cost < least) {
|
||||
least = cost;
|
||||
*choice = i;
|
||||
}
|
||||
}
|
||||
/* and the winner is: *choice */
|
||||
if (!least) return MDB_TABLE_SCAN;
|
||||
return MDB_INDEX_SCAN;
|
||||
}
|
||||
void
|
||||
mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table)
|
||||
{
|
||||
int i;
|
||||
int use_index=0;
|
||||
char *s;
|
||||
|
||||
if (s=getenv("MDBOPTS")) {
|
||||
if (!strcmp(s, "use_index")) use_index++;
|
||||
}
|
||||
if (use_index && mdb_choose_index(table, &i) == MDB_INDEX_SCAN) {
|
||||
table->strategy = MDB_INDEX_SCAN;
|
||||
table->scan_idx = g_ptr_array_index (table->indices, i);
|
||||
table->chain = g_malloc0(sizeof(MdbIndexChain));
|
||||
table->mdbidx = mdb_clone_handle(mdb);
|
||||
mdb_read_pg(table->mdbidx, table->scan_idx->first_pg);
|
||||
//printf("best index is %s\n",table->scan_idx->name);
|
||||
}
|
||||
}
|
||||
void
|
||||
mdb_index_scan_free(MdbTableDef *table)
|
||||
{
|
||||
if (table->chain) {
|
||||
g_free(table->chain);
|
||||
table->chain = NULL;
|
||||
}
|
||||
if (table->mdbidx) {
|
||||
mdb_close(table->mdbidx);
|
||||
table->mdbidx = NULL;
|
||||
}
|
||||
}
|
||||
|
@@ -18,8 +18,9 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int likecmp(char *s, char *r)
|
||||
int mdb_like_cmp(char *s, char *r)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
@@ -32,13 +33,13 @@ int i, ret;
|
||||
}
|
||||
case '_':
|
||||
/* skip one character */
|
||||
return likecmp(&s[1],&r[1]);
|
||||
return mdb_like_cmp(&s[1],&r[1]);
|
||||
case '%':
|
||||
/* skip any number of characters */
|
||||
/* the strlen(s)+1 is important so the next call can */
|
||||
/* if there are trailing characters */
|
||||
for(i=0;i<strlen(s)+1;i++) {
|
||||
if (likecmp(&s[i],&r[1])) {
|
||||
if (mdb_like_cmp(&s[i],&r[1])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +51,7 @@ int i, ret;
|
||||
if (strncmp(s,r,i)) {
|
||||
return 0;
|
||||
} else {
|
||||
ret = likecmp(&s[i],&r[i]);
|
||||
ret = mdb_like_cmp(&s[i],&r[i]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@@ -125,4 +125,6 @@ int top, i, j;
|
||||
s[j++]=array[i]+'0';
|
||||
}
|
||||
s[j]='\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@@ -19,15 +19,24 @@
|
||||
|
||||
#include "mdbtools.h"
|
||||
|
||||
int mdb_test_string(MdbSarg *sarg, char *s)
|
||||
void
|
||||
mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data)
|
||||
{
|
||||
if (func(node, data))
|
||||
return;
|
||||
if (node->left) mdb_sql_walk_tree(node->left, func, data);
|
||||
if (node->right) mdb_sql_walk_tree(node->right, func, data);
|
||||
}
|
||||
int
|
||||
mdb_test_string(MdbSargNode *node, char *s)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (sarg->op == MDB_LIKE) {
|
||||
return likecmp(s,sarg->value.s);
|
||||
if (node->op == MDB_LIKE) {
|
||||
return mdb_like_cmp(s,node->value.s);
|
||||
}
|
||||
rc = strncmp(sarg->value.s, s, 255);
|
||||
switch (sarg->op) {
|
||||
rc = strncmp(node->value.s, s, 255);
|
||||
switch (node->op) {
|
||||
case MDB_EQUAL:
|
||||
if (rc==0) return 1;
|
||||
break;
|
||||
@@ -44,61 +53,149 @@ int rc;
|
||||
if (rc>=0) return 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",sarg->op);
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",node->op);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int mdb_test_int(MdbSarg *sarg, gint32 i)
|
||||
int mdb_test_int(MdbSargNode *node, gint32 i)
|
||||
{
|
||||
switch (sarg->op) {
|
||||
switch (node->op) {
|
||||
case MDB_EQUAL:
|
||||
if (sarg->value.i == i) return 1;
|
||||
if (node->value.i == i) return 1;
|
||||
break;
|
||||
case MDB_GT:
|
||||
if (sarg->value.i < i) return 1;
|
||||
if (node->value.i < i) return 1;
|
||||
break;
|
||||
case MDB_LT:
|
||||
if (sarg->value.i > i) return 1;
|
||||
if (node->value.i > i) return 1;
|
||||
break;
|
||||
case MDB_GTEQ:
|
||||
if (sarg->value.i <= i) return 1;
|
||||
if (node->value.i <= i) return 1;
|
||||
break;
|
||||
case MDB_LTEQ:
|
||||
if (sarg->value.i >= i) return 1;
|
||||
if (node->value.i >= i) return 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",sarg->op);
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int len)
|
||||
#if 0
|
||||
#endif
|
||||
int
|
||||
mdb_find_indexable_sargs(MdbSargNode *node, gpointer data)
|
||||
{
|
||||
MdbSarg sarg;
|
||||
|
||||
if (node->op == MDB_OR || node->op == MDB_NOT) return 1;
|
||||
|
||||
/*
|
||||
* right now all we do is look for sargs that are anded together from
|
||||
* the root. Later we may put together OR ops into a range, and then
|
||||
* range scan the leaf pages. That is col1 = 2 or col1 = 4 becomes
|
||||
* col1 >= 2 and col1 <= 4 for the purpose of index scans, and then
|
||||
* extra rows are thrown out when the row is tested against the main
|
||||
* sarg tree. range scans are generally only a bit better than table
|
||||
* scanning anyway.
|
||||
*
|
||||
* also, later we should support the NOT operator, but it's generally
|
||||
* a pretty worthless test for indexes, ie NOT col1 = 3, we are
|
||||
* probably better off table scanning.
|
||||
*/
|
||||
if (mdb_is_relational_op(node->op)) {
|
||||
//printf("op = %d value = %s\n", node->op, node->value.s);
|
||||
sarg.op = node->op;
|
||||
sarg.value = node->value;
|
||||
mdb_add_sarg(node->col, &sarg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
mdb_test_sarg(MdbColumn *col, MdbSargNode *node, void *buf, int len)
|
||||
{
|
||||
char tmpbuf[256];
|
||||
int lastchar;
|
||||
|
||||
switch (col->col_type) {
|
||||
case MDB_BYTE:
|
||||
return mdb_test_int(sarg, mdb_get_byte(mdb, offset));
|
||||
return mdb_test_int(node, (int)((char *)buf)[0]);
|
||||
break;
|
||||
case MDB_INT:
|
||||
return mdb_test_int(sarg, mdb_get_int16(mdb, offset));
|
||||
return mdb_test_int(node, _mdb_get_int16(buf, 0));
|
||||
break;
|
||||
case MDB_LONGINT:
|
||||
return mdb_test_int(sarg, mdb_get_int32(mdb, offset));
|
||||
return mdb_test_int(node, _mdb_get_int32(buf, 0));
|
||||
break;
|
||||
case MDB_TEXT:
|
||||
strncpy(tmpbuf, &mdb->pg_buf[offset],255);
|
||||
strncpy(tmpbuf, buf,255);
|
||||
lastchar = len > 255 ? 255 : len;
|
||||
tmpbuf[lastchar]='\0';
|
||||
return mdb_test_string(sarg, tmpbuf);
|
||||
return mdb_test_string(node, tmpbuf);
|
||||
default:
|
||||
fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int
|
||||
mdb_find_field(int col_num, MdbField *fields, int num_fields)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<num_fields;i++) {
|
||||
if (fields[i].colnum == col_num) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
mdb_test_sarg_node(MdbSargNode *node, MdbField *fields, int num_fields)
|
||||
{
|
||||
int elem;
|
||||
MdbColumn *col;
|
||||
int rc;
|
||||
|
||||
if (mdb_is_relational_op(node->op)) {
|
||||
col = node->col;
|
||||
elem = mdb_find_field(col->col_num, fields, num_fields);
|
||||
if (!mdb_test_sarg(col,
|
||||
node,
|
||||
fields[elem].value,
|
||||
fields[elem].siz))
|
||||
return 0;
|
||||
} else { /* logical op */
|
||||
switch (node->op) {
|
||||
case MDB_NOT:
|
||||
rc = mdb_test_sarg_node(node->left, fields, num_fields);
|
||||
return !rc;
|
||||
break;
|
||||
case MDB_AND:
|
||||
if (!mdb_test_sarg_node(node->left, fields, num_fields))
|
||||
return 0;
|
||||
return mdb_test_sarg_node(node->right, fields, num_fields);
|
||||
break;
|
||||
case MDB_OR:
|
||||
if (mdb_test_sarg_node(node->left, fields, num_fields))
|
||||
return 1;
|
||||
return mdb_test_sarg_node(node->right, fields, num_fields);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int
|
||||
mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields)
|
||||
{
|
||||
MdbSargNode *node;
|
||||
|
||||
node = table->sarg_tree;
|
||||
|
||||
/* there may not be a sarg tree */
|
||||
if (!node) return 1;
|
||||
|
||||
return mdb_test_sarg_node(node, fields, num_fields);
|
||||
}
|
||||
#if 0
|
||||
int mdb_test_sargs(MdbHandle *mdb, MdbColumn *col, int offset, int len)
|
||||
{
|
||||
MdbSarg *sarg;
|
||||
@@ -114,6 +211,7 @@ int i;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg)
|
||||
{
|
||||
MdbSarg *sarg;
|
||||
|
@@ -233,14 +233,13 @@ int coln;
|
||||
MdbIndex *idx;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
int i,bitn;
|
||||
int pgnum;
|
||||
guint32 pgnum;
|
||||
|
||||
table = mdb_read_table(entry);
|
||||
fprintf(stdout,"definition page = %lu\n",entry->table_pg);
|
||||
fprintf(stdout,"number of datarows = %d\n",table->num_rows);
|
||||
fprintf(stdout,"number of columns = %d\n",table->num_cols);
|
||||
fprintf(stdout,"number of indices = %d\n",table->num_real_idxs);
|
||||
fprintf(stdout,"first data page = %lu\n",table->first_data_pg);
|
||||
|
||||
mdb_read_columns(table);
|
||||
mdb_read_indices(table);
|
||||
@@ -259,7 +258,7 @@ int pgnum;
|
||||
mdb_index_dump(table, idx);
|
||||
}
|
||||
if (table->usage_map) {
|
||||
printf("pages reserved by this object\n",pgnum);
|
||||
printf("pages reserved by this object\n");
|
||||
pgnum = _mdb_get_int32(table->usage_map,1);
|
||||
/* the first 5 bytes of the usage map mean something */
|
||||
coln = 0;
|
||||
@@ -267,7 +266,7 @@ int pgnum;
|
||||
for (bitn=0;bitn<8;bitn++) {
|
||||
if (table->usage_map[i] & 1 << bitn) {
|
||||
coln++;
|
||||
printf("%6ld ",pgnum);
|
||||
printf("%6lu ",(long unsigned) pgnum);
|
||||
if (coln==10) {
|
||||
printf("\n");
|
||||
coln = 0;
|
||||
|
@@ -227,7 +227,8 @@ int i;
|
||||
}
|
||||
|
||||
/* EOD */
|
||||
row_buffer[pos++] = pos;
|
||||
row_buffer[pos] = pos;
|
||||
pos++;
|
||||
|
||||
for (i=num_fields-1;i>=num_fields - var_cols;i--) {
|
||||
row_buffer[pos++] = fields[i].offset % 256;
|
||||
@@ -295,7 +296,7 @@ int old_row_size, new_row_size, delta, num_fields;
|
||||
row_start &= 0x0FFF; /* remove flags */
|
||||
|
||||
#if MDB_DEBUG_WRITE
|
||||
printf("page %lu row %d start %d end %d\n", table->cur_phys_pg, table->cur_row-1, row_start, row_end);
|
||||
printf("page %lu row %d start %d end %d\n", (unsigned long) table->cur_phys_pg, table->cur_row-1, row_start, row_end);
|
||||
buffer_dump(mdb->pg_buf, row_start, row_end);
|
||||
#endif
|
||||
|
||||
@@ -333,6 +334,7 @@ int old_row_size, new_row_size, delta, num_fields;
|
||||
}
|
||||
/* do it! */
|
||||
mdb_replace_row(table, table->cur_row-1, row_buffer, new_row_size);
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size)
|
||||
@@ -348,7 +350,7 @@ int i, pos;
|
||||
#if MDB_DEBUG_WRITE
|
||||
buffer_dump(mdb->pg_buf, 0, 39);
|
||||
buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1);
|
||||
printf("updating row %d on page %lu\n", row, table->cur_phys_pg);
|
||||
printf("updating row %d on page %lu\n", row, (unsigned long) table->cur_phys_pg);
|
||||
#endif
|
||||
new_pg = (unsigned char *) g_malloc0(fmt->pg_size);
|
||||
g_free(new_pg);
|
||||
@@ -400,5 +402,5 @@ int i, pos;
|
||||
fprintf(stderr, "write failed! exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user