/* * the main index function. * caller provides an index chain which is the current traversal of index * pages from the root page to the leaf. Initially passed as blank, * mdb_index_find_next will store it's state information here. Each invocation * then picks up where the last one left off, allowing us to scroll through * the index one by one. * * Sargs are applied here but also need to be applied on the whole row b/c * text columns may return false positives due to hashing and non-index * columns with sarg values can't be tested here. */ int mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row) { MdbIndexPage *ipg; int passed = 0; int idx_sz; int idx_start = 0; MdbColumn *col; ipg = mdb_index_read_bottom_pg(mdb, idx, chain); /* * loop while the sargs don't match */ do { ipg->len = 0; /* * if no more rows on this leaf, try to find a new leaf */ if (!mdb_index_find_next_on_page(mdb, ipg)) { if (!chain->clean_up_mode) { if (!(ipg = mdb_index_unwind(mdb, idx, chain))) chain->clean_up_mode = 1; } if (chain->clean_up_mode) { //fprintf(stdout,"in cleanup mode\n"); if (!chain->last_leaf_found) return 0; mdb_read_pg(mdb, chain->last_leaf_found); chain->last_leaf_found = mdb_pg_get_int24(mdb, 0x0c); //printf("next leaf %lu\n", chain->last_leaf_found); mdb_read_pg(mdb, chain->last_leaf_found); /* reuse the chain for cleanup mode */ chain->cur_depth = 1; ipg = &chain->pages[0]; mdb_index_page_init(ipg); ipg->pg = chain->last_leaf_found; //printf("next on page %d\n", if (!mdb_index_find_next_on_page(mdb, ipg)) return 0; } } *row = mdb->pg_buf[ipg->offset + ipg->len - 1]; #if 0 printf("page: "); buffer_dump(mdb->pg_buf, ipg->offset+ipg->len-4, ipg->offset+ipg->len-2); #endif *pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); #if 0 printf("row = %d pg = %lu ipg->pg = %lu offset = %lu len = %d\n", *row, *pg, ipg->pg, ipg->offset, ipg->len); #endif col=g_ptr_array_index(idx->table->columns,idx->key_col_num[0]-1); idx_sz = mdb_col_fixed_size(col); /* handle compressed indexes, single key indexes only? */ if (idx->num_keys==1 && idx_sz>0 && ipg->len - 4 < idx_sz) { #if 0 printf("short index found\n"); buffer_dump(ipg->cache_value, 0, idx_sz); #endif memcpy(&ipg->cache_value[idx_sz - (ipg->len - 4)], &mdb->pg_buf[ipg->offset], ipg->len); #if 0 buffer_dump(ipg->cache_value, 0, idx_sz); #endif } else { idx_start = ipg->offset + (ipg->len - 4 - idx_sz); memcpy(ipg->cache_value, &mdb->pg_buf[idx_start], idx_sz); } //idx_start = ipg->offset + (ipg->len - 4 - idx_sz); passed = mdb_index_test_sargs(mdb, idx, ipg->cache_value, idx_sz); // printf("passed=%d\n", passed); buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); ipg->offset += ipg->len; } while (!passed); #if 0 fprintf(stdout,"len = %d pos %d\n", ipg->len, ipg->len); buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); #endif return ipg->len; }
int convert_field(MdbColumn *col, char *s, MdbField *field) { char *c; MdbAny any; field->colnum = col->col_num; field->is_fixed = col->is_fixed; switch (col->col_type) { case MDB_TEXT: field->value = g_strdup(s); field->siz = strlen(s); break; case MDB_BYTE: any.i = strtol(s, &c, 16); if (*c) return 1; field->siz = mdb_col_fixed_size(col); field->value = g_malloc(field->siz); ((unsigned char *)field->value)[0] = any.i; break; case MDB_INT: any.i = strtol(s, &c, 16); if (*c) return 1; field->siz = mdb_col_fixed_size(col); field->value = g_malloc(field->siz); mdb_put_int16(field->value, 0, any.i); break; case MDB_LONGINT: any.i = strtol(s, &c, 16); if (*c) return 1; field->siz = mdb_col_fixed_size(col); field->value = g_malloc(field->siz); mdb_put_int32(field->value, 0, any.i); break; case MDB_BOOL: if (*s == '1') { field->is_null = 1; } else if (*s == '0') { field->is_null = 0; } else { fprintf(stderr, "%c is not a valid value for type BOOLEAN\n", *s); return 1; } /* case MDB_FLOAT: any.d = strtod(s, &c); if (*c) return 1; field.value = g_malloc(mdb_col_fixed_size(col)); mdb_put_single(field.value, 0, any.i); break; case MDB_DOUBLE: any.d = strtod(s, &c); if (*c) return 1; field.value = g_malloc(mdb_col_fixed_size(col)); mdb_put_double(field.value, 0, any.i); break; */ /* case MDB_MONEY: case MDB_SDATETIME: case MDB_OLE: case MDB_MEMO: case MDB_REPID: case MDB_NUMERIC: */ default: fprintf(stderr,"Conversion of type %02x not supported yet.\n", col->col_type); return 1; break; } return 0; }