diff --git a/configure.in b/configure.in index 247a757..5cf84c2 100644 --- a/configure.in +++ b/configure.in @@ -25,16 +25,29 @@ OPTDIRS="" dnl --------------------------------------------------------------------- dnl Compile time options dnl --------------------------------------------------------------------- -AC_ARG_ENABLE(sql, - [ --enable-sql Enable SQL engine]) -if test "$enable_sql" = "yes" ; then - CFLAGS="$CFLAGS -DSQL" - sql=true - OPTDIRS="$OPTDIRS sql" +sql=true +AC_MSG_CHECKING( Are we using flex ) +if test "x$LEX" = "xflex"; then +LFLAGS="$LFLAGS -i" +AC_MSG_RESULT( yes ); +else +AC_MSG_RESULT( no - SQL engine disable); +sql=false fi + +if test "x$YACC" = "x"; then +sql=false +fi + +if test "x$sql" = "xtrue"; then + CFLAGS="$CFLAGS -DSQL" + OPTDIRS="$OPTDIRS sql" +fi + AM_CONDITIONAL(SQL, test x$sql = xtrue) AC_SUBST(SQL) +AC_SUBST(LFLAGS) dnl check for iODBC @@ -45,9 +58,9 @@ if test "$with_iodbc"; then ODBC_INC=$with_iodbc/include; odbc=true OPTDIRS="$OPTDIRS odbc" - if test "$enable_sql" != "yes" ; then + if test "x$sql" != "xtrue" ; then echo - echo ODBC requires the --enable-sql flag + echo ODBC requires flex and bison for the SQL engine exit 1 fi fi @@ -60,9 +73,9 @@ if test "$with_unixodbc"; then ODBC_INC=$with_unixodbc/include odbc=true OPTDIRS="$OPTDIRS odbc" - if test "$enable_sql" != "yes" ; then + if test "x$sql" != "xtrue" ; then echo - echo ODBC requires the --enable-sql flag + echo ODBC requires flex and bison for the SQL engine exit 1 fi fi @@ -81,9 +94,9 @@ if test "$no_glib" == yes; then exit 1 fi -PKG_CHECK_MODULES(GNOME,libglade-2.0 libgnomeui-2.0) +PKG_CHECK_MODULES(GNOME,libglade-2.0 libgnomeui-2.0, HAVE_GNOME=true, HAVE_GNOME=false) -if test "$GNOME_CFLAGS" != ""; then +if test "x$HAVE_GNOME" = "xtrue"; then AC_SUBST(GNOME_CFLAGS) AC_SUBST(GNOME_LIBS) OPTDIRS="$OPTDIRS gmdb2" diff --git a/include/mdbtools.h b/include/mdbtools.h index 09583c3..5aacc0c 100644 --- a/include/mdbtools.h +++ b/include/mdbtools.h @@ -40,6 +40,14 @@ #define MDB_MEMO_OVERHEAD 12 #define MDB_BIND_SIZE 16384 +enum { + MDB_PAGE_DB = 0, + MDB_PAGE_DATA, + MDB_PAGE_TABLE, + MDB_PAGE_INDEX, + MDB_PAGE_LEAF, + MDB_PAGE_MAP +}; enum { MDB_VER_JET3 = 0, MDB_VER_JET4 = 1 @@ -210,8 +218,25 @@ typedef struct { short key_col_num[MDB_MAX_IDX_COLS]; unsigned char key_col_order[MDB_MAX_IDX_COLS]; unsigned char flags; + MdbTableDef *table; } MdbIndex; +typedef struct { + guint32 pg; + int mask_pos; + unsigned char mask_byte; + int mask_bit; + int offset; + int len; +} MdbIndexPage; + +#define MDB_MAX_INDEX_DEPTH 10 + +typedef struct { + int cur_depth; + MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; +} MdbIndexChain; + typedef struct { char name[MDB_MAX_OBJ_NAME+1]; } MdbColumnProp; @@ -225,6 +250,7 @@ typedef struct { GHashTable *properties; int num_sargs; GPtrArray *sargs; + GPtrArray *idx_sarg_cache; unsigned char is_fixed; int query_order; int col_num; @@ -235,6 +261,16 @@ typedef struct { int col_scale; } MdbColumn; +typedef struct { + void *value; + int siz; + int start; + unsigned char is_null; + unsigned char is_fixed; + int colnum; + int offset; +} MdbField; + typedef union { int i; double d; @@ -265,6 +301,7 @@ extern long mdb_get_int32(MdbHandle *mdb, int offset); extern float mdb_get_single(MdbHandle *mdb, int offset); extern double mdb_get_double(MdbHandle *mdb, int offset); extern MdbHandle *mdb_open(char *filename); +extern MdbHandle *mdb_clone_handle(MdbHandle *mdb); extern void mdb_swap_pgbuf(MdbHandle *mdb); /* catalog.c */ diff --git a/src/gmdb2/debug.c b/src/gmdb2/debug.c index 96005d5..0d9e370 100644 --- a/src/gmdb2/debug.c +++ b/src/gmdb2/debug.c @@ -35,6 +35,8 @@ static guint16 get_uint16(unsigned char *c); static guint32 get_uint24(unsigned char *c); static guint32 get_uint32(unsigned char *c); static long gmdb_get_max_page(MdbHandle *mdb); +void gmdb_debug_display_cb(GtkWidget *w, GladeXML *xml); +void gmdb_debug_display(GladeXML *xml, guint32 page); /* value to string stuff */ typedef struct GMdbValStr { @@ -134,6 +136,95 @@ GtkWidget *textview; } } void +gmdb_debug_forward_cb(GtkWidget *w, GladeXML *xml) +{ + guint *nav_elem; + gchar *page; + GtkWidget *win; + GList *nav_list = NULL; + guint32 page_num; + guint num_items; + + win = glade_xml_get_widget (xml, "debug_window"); + nav_list = g_object_get_data(G_OBJECT(win),"nav_list"); + nav_elem = g_object_get_data(G_OBJECT(win),"nav_elem"); + num_items = g_list_length(nav_list); + if (!nav_elem || *nav_elem == num_items) + return; + (*nav_elem)++; + g_object_set_data(G_OBJECT(win), "nav_elem", nav_elem); + page = g_list_nth_data(nav_list,(*nav_elem) - 1); + + page_num = atol(page); + gmdb_debug_display(xml, page_num); +} +void +gmdb_debug_back_cb(GtkWidget *w, GladeXML *xml) +{ + guint *nav_elem; + gchar *page; + GtkWidget *win; + GList *nav_list = NULL; + guint32 page_num; + + win = glade_xml_get_widget (xml, "debug_window"); + nav_list = g_object_get_data(G_OBJECT(win),"nav_list"); + nav_elem = g_object_get_data(G_OBJECT(win),"nav_elem"); + if (!nav_elem || *nav_elem==1) + return; /* at top of list already */ + (*nav_elem)--; + g_object_set_data(G_OBJECT(win), "nav_elem", nav_elem); + page = g_list_nth_data(nav_list,(*nav_elem) - 1); + + page_num = atol(page); + gmdb_debug_display(xml, page_num); +} +void +gmdb_nav_add_page(GladeXML *xml, guint32 page_num) +{ + GList *nav_list = NULL; + GList *link = NULL; + GtkWidget *win; + guint *nav_elem; + guint num_items; + char buf[100]; + int i; + + win = glade_xml_get_widget (xml, "debug_window"); + + nav_elem = g_object_get_data(G_OBJECT(win),"nav_elem"); + if (!nav_elem) { + nav_elem = g_malloc0(sizeof(guint)); + } + + sprintf(buf, "%lu", page_num); + nav_list = g_object_get_data(G_OBJECT(win),"nav_list"); + + /* + * If we are positioned in the middle of the list and jumping from here + * clear the end of the list first. + */ + num_items = g_list_length(nav_list); + if (num_items > *nav_elem) { + for (i=num_items - 1; i >= *nav_elem; i--) { + printf("freeing element %d\n",i); + link = g_list_nth(nav_list,i); + nav_list = g_list_remove_link(nav_list, link); + g_free(link->data); + g_list_free_1(link); + } + } + + *nav_elem = g_list_length(nav_list); + + nav_list = g_list_append(nav_list, g_strdup(buf)); + + *nav_elem = g_list_length(nav_list); + + g_object_set_data(G_OBJECT(win), "nav_list", nav_list); + g_object_set_data(G_OBJECT(win), "nav_elem", nav_elem); +} +void gmdb_debug_jump_cb(GtkWidget *w, GladeXML *xml) { GtkTextView *textview; @@ -155,7 +246,6 @@ gmdb_debug_jump_cb(GtkWidget *w, GladeXML *xml) return; } text = g_strdup(gtk_text_buffer_get_text(txtbuffer, &start, &end, FALSE)); - fprintf(stderr, "selected text = %s\n",text); hex_digit = strtok(text, " "); strcpy(page, "0x"); do { @@ -169,7 +259,7 @@ gmdb_debug_jump_cb(GtkWidget *w, GladeXML *xml) strcat(page, digits[i]); } g_free(text); - fprintf(stderr, "going to page %s\n",page); + //fprintf(stderr, "going to page %s\n",page); entry = glade_xml_get_widget (xml, "debug_entry"); gtk_entry_set_text(GTK_ENTRY(entry),page); gmdb_debug_display_cb(w, xml); @@ -219,24 +309,14 @@ void gmdb_debug_display_cb(GtkWidget *w, GladeXML *xml) { int page; -off_t pos; -unsigned char *fbuf; -unsigned char *tbuf; int i,j; -int length; -char line[80]; -char field[10]; -GtkTextBuffer *buffer; -GtkTextIter iter; GtkWidget *entry; -GtkTextView *textview; gchar *s; if (!mdb) return; entry = glade_xml_get_widget (xml, "debug_entry"); - textview = glade_xml_get_widget (xml, "debug_textview"); s = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); @@ -255,8 +335,34 @@ gchar *s; gmdb_info_msg("Page entered is outside valid page range."); } + /* add to the navigation list */ + gmdb_nav_add_page(xml, page); + /* gmdb_debug_display handles the mechanics of getting the page up */ + gmdb_debug_display(xml, page); +} +void +gmdb_debug_display(GladeXML *xml, guint32 page) +{ + unsigned char *fbuf; + unsigned char *tbuf; + int length; + int i, j; + off_t pos; + gchar line[80]; + gchar field[10]; + GtkTextBuffer *buffer; + GtkTextIter iter; + GtkTextView *textview; + GtkWidget *entry; + char pagestr[20]; + + textview = (GtkTextView *) glade_xml_get_widget (xml, "debug_textview"); gmdb_debug_clear(xml); + sprintf(pagestr, "%lu", page); + entry = glade_xml_get_widget (xml, "debug_entry"); + gtk_entry_set_text(GTK_ENTRY(entry),pagestr); + pos = lseek(mdb->f->fd, 0, SEEK_CUR); lseek(mdb->f->fd, page * mdb->fmt->pg_size, SEEK_SET); @@ -290,9 +396,9 @@ gchar *s; gtk_text_buffer_insert(buffer,&iter,tbuf,strlen(tbuf)); GtkWidget *tree = glade_xml_get_widget(xml, "debug_treeview"); - GtkTreeView *store = gtk_tree_view_get_model(GTK_TREE_VIEW(tree)); + GtkTreeView *store = (GtkTreeView *) gtk_tree_view_get_model(GTK_TREE_VIEW(tree)); - gmdb_debug_dissect(store, fbuf, 0, length); + gmdb_debug_dissect(GTK_TREE_STORE(store), fbuf, 0, length); free(fbuf); free(tbuf); @@ -406,6 +512,7 @@ gmdb_debug_dissect_index2(GtkTreeStore *store, GtkTreeIter *parent, char *fbuf, snprintf(str, 100, "Root index page"); gmdb_debug_add_item(store, parent, str, offset+34, offset+37); flags = fbuf[offset+38]; + flagstr[0]=0; if (flags & MDB_IDX_UNIQUE) { strcat(flagstr, "Unique"); mod++; } @@ -673,7 +780,7 @@ GtkWidget *treeview, *textview, *store; textview = glade_xml_get_widget (xml, "debug_textview"); treeview = glade_xml_get_widget (xml, "debug_treeview"); - store = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); + store = (GtkWidget *) gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); /* clear the tree */ gtk_tree_store_clear(GTK_TREE_STORE(store)); @@ -755,7 +862,6 @@ gmdb_debug_close_cb(GtkWidget *w, GladeXML *xml) debug_list = g_list_remove(debug_list, xml); win = glade_xml_get_widget (xml, "debug_window"); if (win) gtk_widget_destroy(win); - return FALSE; } void gmdb_debug_close_all() @@ -811,6 +917,22 @@ GladeXML *debugwin_xml; g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (gmdb_debug_jump_cb), debugwin_xml); + mi = glade_xml_get_widget (debugwin_xml, "back_menu"); + g_signal_connect (G_OBJECT (mi), "activate", + G_CALLBACK (gmdb_debug_back_cb), debugwin_xml); + + button = glade_xml_get_widget (debugwin_xml, "back_button"); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (gmdb_debug_back_cb), debugwin_xml); + + mi = glade_xml_get_widget (debugwin_xml, "forward_menu"); + g_signal_connect (G_OBJECT (mi), "activate", + G_CALLBACK (gmdb_debug_forward_cb), debugwin_xml); + + button = glade_xml_get_widget (debugwin_xml, "forward_button"); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (gmdb_debug_forward_cb), debugwin_xml); + button = glade_xml_get_widget (debugwin_xml, "debug_button"); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (gmdb_debug_display_cb), debugwin_xml); @@ -830,6 +952,14 @@ GladeXML *debugwin_xml; gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); GtkCellRenderer *renderer; + button = glade_xml_get_widget (debugwin_xml, "debug_button"); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (gmdb_debug_display_cb), debugwin_xml); + + debugwin = glade_xml_get_widget (debugwin_xml, "debug_window"); + gtk_signal_connect (GTK_OBJECT (debugwin), "delete_event", + GTK_SIGNAL_FUNC (gmdb_debug_delete_cb), debugwin_xml); + GtkTreeViewColumn *column; renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Field", diff --git a/src/libmdb/index.c b/src/libmdb/index.c index 5901db7..ee9750f 100644 --- a/src/libmdb/index.c +++ b/src/libmdb/index.c @@ -23,18 +23,34 @@ char idx_to_text[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8-15 0x09-0x0f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16-23 0x10-0x17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24-31 0x19-0x1f */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32-39 0x20-0x27 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 40-47 0x29-0x2f */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48-55 0x30-0x37 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 56-63 0x39-0x3f */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 64-71 0x40-0x47 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 72-79 0x49-0x4f */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '0', '1', /* 80-87 0x50-0x57 */ -'2', '3', '4', '5', '6', '7', '8', '9', /* 88-95 0x59-0x5f */ -'A', 'B', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 96-103 0x60-0x67 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 104-111 0x69-0x6f */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 112-119 0x70-0x77 */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 120-127 0x79-0x7f */ +' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32-39 0x20-0x27 */ +0x00, 0x00, 0x00, 0x00, 0x00, ' ', ' ', 0x00, /* 40-47 0x29-0x2f */ +'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', /* 48-55 0x30-0x37 */ +'^', '_', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 56-63 0x39-0x3f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 64-71 0x40-0x47 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 72-79 0x49-0x4f H */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 80-87 0x50-0x57 P */ +'|', '}', '~', '5', '6', '7', '8', '9', /* 88-95 0x59-0x5f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 96-103 0x60-0x67 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 014-111 0x69-0x6f h */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 112-119 0x70-0x77 p */ +'|', '}', '~', 0x00, 0x00, 0x00, 0x00, 0x00, /* 120-127 0x78-0x7f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128-135 0x80-0x87 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ +0x00, 0x00, 0x00, 0x00, 0x00, '`', 0x00, 0x00, /* 0xc0-0xc7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ +0x00, '`', 0x00, '`', '`', '`', 0x00, 0x00, /* 0xe0-0xe7 */ +'f', 'f', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ +0x00, 0x00, 0x00, 'r', 0x00, 0x00, 'r', 0x00, /* 0xf0-0xf7 */ +0x81, 0x00, 0x00, 0x00, 'x', 0x00, 0x00, 0x00, /* 0xf8-0xff */ }; GPtrArray *mdb_read_indices(MdbTableDef *table) @@ -54,6 +70,7 @@ int name_sz; for (i=0;inum_idxs;i++) { memset(&idx, '\0', sizeof(MdbIndex)); + idx.table = table; idx.index_num = mdb_get_int16(mdb, cur_pos); cur_pos += 19; idx.index_type = mdb->pg_buf[cur_pos++]; @@ -110,6 +127,192 @@ int name_sz; pidx->flags = mdb->pg_buf[cur_pos++]; } } +void +mdb_index_hash_text(guchar *text, guchar *hash) +{ + int k; + + for (k=0;kcol_type) { + case MDB_TEXT: + mdb_index_hash_text(sarg->value.s, idx_sarg->value.s); + break; + + 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[0] |= 0x80; + printf("int %08x %02x %02x %02x %02x\n", sarg->value.i, c[0], c[1], c[2], c[3]); + break; + + case MDB_INT: + break; + + default: + break; + } +} +int +mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, int offset, int len) +{ + int i, j; + MdbColumn *col; + MdbTableDef *table = idx->table; + MdbSarg *idx_sarg; + MdbSarg *sarg; + int c_offset = 0, c_len; + + for (i=0;inum_keys;i++) { + c_offset++; /* the per column null indicator/flags */ + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + /* + * This will go away eventually + */ + if (col->col_type==MDB_TEXT) { + c_len = strlen(&mdb->pg_buf[offset + c_offset]); + } else { + c_len = col->col_size; + fprintf(stderr,"Only text types currently supported. How did we get here?\n"); + } + /* + * If we have no cached index values for this column, + * create them. + */ + if (col->num_sargs && !col->idx_sarg_cache) { + col->idx_sarg_cache = g_ptr_array_new(); + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->sargs, j); + idx_sarg = g_memdup(sarg,sizeof(MdbSarg)); + printf("calling mdb_index_cache_sarg\n"); + mdb_index_cache_sarg(col, sarg, idx_sarg); + g_ptr_array_add(col->idx_sarg_cache, idx_sarg); + } + } + + for (j=0;jnum_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; + } + } + } + return 1; +} +int +mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg) +{ + do { + //fprintf(stdout, "%d %d\n", ipg->mask_bit, ipg->mask_byte); + ipg->mask_bit++; + if (ipg->mask_bit==8) { + ipg->mask_bit=0; + ipg->mask_pos++; + } + ipg->mask_byte = mdb->pg_buf[ipg->mask_pos]; + ipg->len++; + } while (ipg->mask_pos <= 0xf8 && + !((1 << ipg->mask_bit) & ipg->mask_byte)); + + if (ipg->mask_pos>=0xf8) + return 0; + + return ipg->len; +} +void mdb_index_page_init(MdbIndexPage *ipg) +{ + ipg->offset = 0xf8; /* start byte of the index entries */ + ipg->mask_pos = 0x16; + ipg->mask_bit=0; + ipg->len = 0; +} +int +mdb_find_next_leaf(MdbHandle *mdb, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + /* + * If we are at the first page deep and it's not an index page then + * we are simply done. (there is no page to find + */ + if (chain->cur_depth==1) { + ipg = &(chain->pages[0]); + if (mdb->pg_buf[0]==MDB_PAGE_LEAF || + mdb->pg_buf[0]==MDB_PAGE_DATA) { + return ipg->pg; + } + } + + ipg = &(chain->pages[chain->cur_depth - 1]); + + /* no more pages */ + return 0; + +} +int +mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row) +{ + MdbIndexPage *ipg; + int passed = 0; + + if (!chain->cur_depth) { + ipg = &(chain->pages[0]); + mdb_index_page_init(ipg); + chain->cur_depth = 1; + ipg->pg = idx->first_pg; + if (!mdb_find_next_leaf(mdb, chain)) + return 0; + } else { + ipg = &(chain->pages[chain->cur_depth - 1]); + ipg->len = 0; + } + + mdb_read_pg(mdb, ipg->pg); + + do { + ipg->len = 0; + if (!mdb_index_find_next_on_page(mdb, ipg)) + return 0; + *row = mdb->pg_buf[ipg->offset + ipg->len - 1]; + *pg = mdb_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + + passed = mdb_index_test_sargs(mdb, idx, ipg->offset, ipg->len); + + ipg->offset += ipg->len; + } while (!passed); + + //fprintf(stdout,"len = %d pos %d\n", ipg->len, ipg->mask_pos); + //buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); + + return ipg->len; +} void mdb_index_walk(MdbTableDef *table, MdbIndex *idx) { MdbHandle *mdb = table->entry->mdb; diff --git a/src/libmdb/write.c b/src/libmdb/write.c index 4cf5e60..4dc7cdc 100644 --- a/src/libmdb/write.c +++ b/src/libmdb/write.c @@ -23,16 +23,6 @@ #define MDB_DEBUG_WRITE 1 -typedef struct { - void *value; - int siz; - int start; - unsigned char is_null; - unsigned char is_fixed; - int colnum; - int offset; -} MdbField; - void _mdb_put_int16(unsigned char *buf, guint32 offset, guint32 value) { @@ -141,7 +131,7 @@ int eod, len; /* end of data */ bit_num = i % 8; /* logic on nulls is reverse, 1 is not null, 0 is null */ fields[i].is_null = nullmask[byte_num] & 1 << bit_num ? 0 : 1; - printf("col %d is %s\n", i, fields[i].is_null ? "null" : "not null"); + //printf("col %d is %s\n", i, fields[i].is_null ? "null" : "not null"); } /* find the end of data pointer */ @@ -150,7 +140,7 @@ int eod, len; /* end of data */ } else { eod = mdb->pg_buf[row_end-1-var_cols-bitmask_sz]; } - printf("eod is %d\n", eod); + //printf("eod is %d\n", eod); if (IS_JET4(mdb)) { col_start = 2; @@ -178,7 +168,7 @@ int eod, len; /* end of data */ if (!mdb_is_fixed_col(col) && ++var_cols_found <= var_cols) { if (var_cols_found==var_cols) { len=eod - col_start; - printf("len = %d eod %d col_start %d\n",len, eod, col_start); + //printf("len = %d eod %d col_start %d\n",len, eod, col_start); } else { if (IS_JET4(mdb)) { /* position of the var table @@ -195,7 +185,7 @@ int eod, len; /* end of data */ bitmask_sz - var_cols_found - 1; len=mdb->pg_buf[var_entry_pos] - mdb->pg_buf[var_entry_pos+1]; - printf("%d %d %d %d\n", mdb->pg_buf[var_entry_pos-1],mdb->pg_buf[var_entry_pos],len, col_start); + //printf("%d %d %d %d\n", mdb->pg_buf[var_entry_pos-1],mdb->pg_buf[var_entry_pos],len, col_start); } } /* if found==var_cols */ if (len<0) len+=256; diff --git a/src/util/prindex.c b/src/util/prindex.c index 088f533..6ddcb78 100644 --- a/src/util/prindex.c +++ b/src/util/prindex.c @@ -19,7 +19,9 @@ */ #include "mdbtools.h" +extern char idx_to_text[]; +void walk_index(MdbHandle *mdb, MdbIndex *idx); main(int argc, char **argv) { int rows; @@ -39,7 +41,10 @@ int found = 0; } mdb_init(); - mdb = mdb_open(argv[1]); + if (!(mdb = mdb_open(argv[1]))) { + fprintf(stderr,"Unable to open database.\n"); + exit(1); + } mdb_read_catalog(mdb, MDB_TABLE); @@ -71,34 +76,108 @@ int found = 0; exit(0); } +char * +page_name(int page_type) +{ + switch(page_type) { + case 0x00: return "Database Properties"; break; + case 0x01: return "Data"; break; + case 0x02: return "Table Definition"; break; + case 0x03: return "Index"; break; + case 0x04: return "Index Leaf"; break; + case 0x05: return "Page Usage"; break; + } +} +void check_row(MdbHandle *mdb, MdbIndex *idx, guint32 pg, int row, unsigned char *idxrow, int len) +{ + MdbField fields[256]; + MdbFormatConstants *fmt; + int num_fields, i, j, k; + int row_start, row_end; + MdbColumn *col; + guchar buf[256], key[256], mykey[256]; + int elem, pos; + MdbTableDef *table = idx->table; + + fmt = mdb->fmt; + mdb_read_pg(mdb, pg); + row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (row*2)); + row_end = mdb_find_end_of_row(mdb, row); + + num_fields = mdb_crack_row(table, row_start, row_end, &fields); + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + if (col->col_type==MDB_TEXT) { + mdb_index_hash_text(buf, key); + } + for (j=0;jkey_col_num[i]) { + elem = j; + break; + } + } + //j = idx->key_col_num[i]; + strncpy(buf, fields[elem].value, fields[elem].siz); + buf[fields[elem].siz]=0; + fprintf(stdout, "elem %d %d column %d %s %s\n",elem, fields[elem].colnum, idx->key_col_num[i], col->name, buf); + if (col->col_type == MDB_TEXT) { + fprintf(stdout, "%s = %s \n", buf, key); + } + } +} void walk_index(MdbHandle *mdb, MdbIndex *idx) { int i, j, start, len; unsigned char byte; guint32 pg; - int row; + guint16 row; + MdbHandle *mdbidx; + MdbIndexChain chain; + MdbTableDef *table = idx->table; + MdbSarg sarg; +#if 1 + sarg.op = MDB_EQUAL; + //strcpy(sarg.value.s, "SP"); + sarg.value.i = 2; + mdb_add_sarg_by_name(table, "ShipperID", &sarg); +#endif + + memset(&chain, 0, sizeof(MdbIndexChain)); printf("name %s\n", idx->name); printf("root page %ld\n", idx->first_pg); - mdb_read_pg(mdb, idx->first_pg); + /* clone the handle to search the index, and use the original to read + * the data */ + mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(mdbidx, idx->first_pg); + printf("page type %02x %s\n", mdbidx->pg_buf[0], page_name(mdbidx->pg_buf[0])); + while (mdb_index_find_next(mdbidx, idx, &chain, &pg, &row)) { + printf("row = %d pg = %lu\n", row, pg); + check_row(mdb, idx, pg, row, &mdbidx->pg_buf[start], len - 4); + } +#if 0 + if (mdbidx->pg_buf[0]!=MDB_PAGE_LEAF) { + return; + } start = 0xf8; /* start byte of the index entries */ len = -1; for (i=0x16;i<0xf8;i++) { - byte = mdb->pg_buf[i]; + byte = mdbidx->pg_buf[i]; //printf("%02x ",byte); for (j=0;j<8;j++) { len++; if ((1 << j) & byte) { // printf("start = %04x len = %d\n", start, len); - buffer_dump(mdb->pg_buf, start, start+len-1); - row = mdb->pg_buf[start+len-1]; - pg = mdb_get_int24_msb(mdb, start+len-4); - printf("row = %d pg = %lu\n", row, pg); + buffer_dump(mdbidx->pg_buf, start, start+len-1); + row = mdbidx->pg_buf[start+len-1]; + pg = mdb_get_int24_msb(mdbidx, start+len-4); start += len; len = 0; // printf("\nbit %d set\n", j); } } } +#endif + mdb_close(mdbidx); }