From be2a287f5c5d9cb78c103f9d98a74ea6cd055311 Mon Sep 17 00:00:00 2001 From: Brian Bruns Date: Mon, 7 Feb 2011 21:57:13 -0500 Subject: [PATCH] =?UTF-8?q?fix=20index=20counting,=20from=20Nirgal=20Vourg?= =?UTF-8?q?=C3=A8re?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HACKING | 12 +++---- src/libmdb/index.c | 81 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/HACKING b/HACKING index ba6ce51..00ee53c 100644 --- a/HACKING +++ b/HACKING @@ -316,7 +316,7 @@ next_pg field. | ???? | 1 byte | col_name_len| len of the name of the column | | ???? | n bytes | col_name | Name of the column | +-------------------------------------------------------------------------+ -| Iterate for the number of num_real_idx (30+9 = 39 bytes) | +| Iterate for indexes with index_type 0 or 1 (30+9 = 39 bytes) | +-------------------------------------------------------------------------+ | Iterate 10 times for 10 possible columns (10*3 = 30 bytes) | +-------------------------------------------------------------------------+ @@ -327,7 +327,7 @@ next_pg field. | ???? | 4 bytes | first_dp | Data pointer of the index page | | ???? | 1 byte | flags | See flags table for indexes | +-------------------------------------------------------------------------+ -| Iterate for the number of num_real_idx (20 bytes) | +| Iterate for the number of num_idx (20 bytes) | +-------------------------------------------------------------------------+ | ???? | 4 bytes | index_num | Number of the index | | | | |(warn: not always in the sequential order)| @@ -338,7 +338,7 @@ next_pg field. | 0x04 | 2 bytes | ??? | | | ???? | 1 byte | primary_key | 0x01 if this index is primary | +-------------------------------------------------------------------------+ -| Iterate for the number of num_real_idx | +| Iterate for the number of num_idx | +-------------------------------------------------------------------------+ | ???? | 1 byte | idx_name_len| len of the name of the index | | ???? | n bytes | idx_name | Name of the index | @@ -394,7 +394,7 @@ next_pg field. | ???? | 2 bytes | col_name_len| len of the name of the column | | ???? | n bytes | col_name | Name of the column (UCS-2 format) | +-------------------------------------------------------------------------+ -| Iterate for the number of num_real_idx (30+22 = 52 bytes) | +| Iterate for indexes with index_type 0 or 1 (30+22 = 52 bytes) | +-------------------------------------------------------------------------+ | ???? | 4 bytes | ??? | | +-------------------------------------------------------------------------+ @@ -408,7 +408,7 @@ next_pg field. | ???? | 1 byte | flags | See flags table for indexes | | ???? | 9 bytes | unknown | | +-------------------------------------------------------------------------+ -| Iterate for the number of num_real_idx (28 bytes) | +| Iterate for the number of num_idx (28 bytes) | +-------------------------------------------------------------------------+ | ???? | 4 bytes | unknown | matches first unknown definition block | | ???? | 4 bytes | index_num | Number of the index | @@ -421,7 +421,7 @@ next_pg field. | ???? | 1 byte | primary_key | 0x01 if this index is primary | | ???? | 4 bytes | unknown | | +-------------------------------------------------------------------------+ -| Iterate for the number of num_real_idx | +| Iterate for the number of num_idx | +-------------------------------------------------------------------------+ | ???? | 2 bytes | idx_name_len| len of the name of the index | | ???? | n bytes | idx_name | Name of the index (UCS-2) | diff --git a/src/libmdb/index.c b/src/libmdb/index.c index bd9b19a..ea16be2 100644 --- a/src/libmdb/index.c +++ b/src/libmdb/index.c @@ -69,15 +69,15 @@ mdb_read_indices(MdbTableDef *table) MdbHandle *mdb = entry->mdb; MdbFormatConstants *fmt = mdb->fmt; MdbIndex *pidx; - unsigned int i, j; - int idx_num, key_num, col_num; + unsigned int i, j, k; + int key_num, col_num, cleaned_col_num; int cur_pos, name_sz, idx2_sz, type_offset; int index_start_pg = mdb->cur_pg; gchar *tmpbuf; - table->indices = g_ptr_array_new(); + table->indices = g_ptr_array_new(); - if (IS_JET4(mdb)) { + if (IS_JET4(mdb)) { cur_pos = table->index_start + 52 * table->num_real_idxs; idx2_sz = 28; type_offset = 23; @@ -87,15 +87,33 @@ mdb_read_indices(MdbTableDef *table) type_offset = 19; } + //fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs); + /* num_real_idxs should be the number of indexes of type 2. + * It's not always the case. Happens on Northwind Orders table. + */ + table->num_real_idxs = 0; tmpbuf = (gchar *) g_malloc(idx2_sz); for (i=0;inum_idxs;i++) { read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz); pidx = (MdbIndex *) g_malloc0(sizeof(MdbIndex)); pidx->table = table; pidx->index_num = mdb_get_int16(tmpbuf, 4); - pidx->index_type = tmpbuf[type_offset]; + pidx->index_type = tmpbuf[type_offset]; g_ptr_array_add(table->indices, pidx); + /* + { + gint32 dumy0 = mdb_get_int32(tmpbuf, 0); + gint8 dumy1 = tmpbuf[8]; + gint32 dumy2 = mdb_get_int32(tmpbuf, 9); + gint32 dumy3 = mdb_get_int32(tmpbuf, 13); + gint16 dumy4 = mdb_get_int16(tmpbuf, 17); + fprintf(stderr, "idx #%d: num2:%d type:%d\n", i, pidx->index_num, pidx->index_type); + fprintf(stderr, "idx #%d: %d %d %d %d %d\n", i, dumy0, dumy1, dumy2, dumy3, dumy4); + }*/ + if (pidx->index_type!=2) + table->num_real_idxs++; } + //fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, table->num_real_idxs); g_free(tmpbuf); for (i=0;inum_idxs;i++) { @@ -109,31 +127,35 @@ mdb_read_indices(MdbTableDef *table) read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz); mdb_unicode2ascii(mdb, tmpbuf, name_sz, pidx->name, MDB_MAX_OBJ_NAME); g_free(tmpbuf); - //fprintf(stderr, "index name %s\n", pidx->name); + //fprintf(stderr, "index %d type %d name %s\n", pidx->index_num, pidx->index_type, pidx->name); } mdb_read_alt_pg(mdb, entry->table_pg); mdb_read_pg(mdb, index_start_pg); cur_pos = table->index_start; - idx_num=0; for (i=0;inum_real_idxs;i++) { if (IS_JET4(mdb)) cur_pos += 4; - do { - pidx = g_ptr_array_index (table->indices, idx_num++); - } while (pidx && pidx->index_type==2); - - /* if there are more real indexes than index entries left after - removing type 2's decrement real indexes and continue. Happens - on Northwind Orders table. - */ - if (!pidx) { - table->num_real_idxs--; - continue; + /* look for index number i */ + for (j=0; jnum_idxs; ++j) { + pidx = g_ptr_array_index (table->indices, j); + if (pidx->index_type!=2 && pidx->index_num==i) + break; } + if (j==table->num_idxs) + fprintf(stderr, "ERROR: can't find index #%d.\n", i); + //fprintf(stderr, "index %d #%d (%s) index_type:%d\n", i, pidx->index_num, pidx->name, pidx->index_type); pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, fmt->tab_cols_start_offset + - (i*fmt->tab_ridx_entry_size)); + (pidx->index_num*fmt->tab_ridx_entry_size)); + /* + fprintf(stderr, "ridx block1 i:%d data1:0x%08x data2:0x%08x\n", + i, + mdb_get_int32(mdb->pg_buf, + fmt->tab_cols_start_offset + pidx->index_num * fmt->tab_ridx_entry_size), + mdb_get_int32(mdb->pg_buf, + fmt->tab_cols_start_offset + pidx->index_num * fmt->tab_ridx_entry_size +4)); + fprintf(stderr, "pidx->num_rows:%d\n", pidx->num_rows);*/ key_num=0; for (j=0;jnum_cols; k++) { + MdbColumn *col = g_ptr_array_index(table->columns,k); + if (col->col_num == col_num) { + cleaned_col_num = k; + break; + } + } + if (cleaned_col_num==-1) { + fprintf(stderr, "CRITICAL: can't find column with internal id %d in index %s\n", + col_num, pidx->name); + cur_pos++; + continue; + } /* set column number to a 1 based column number and store */ - pidx->key_col_num[key_num] = col_num + 1; + pidx->key_col_num[key_num] = cleaned_col_num + 1; pidx->key_col_order[key_num] = (read_pg_if_8(mdb, &cur_pos)) ? MDB_ASC : MDB_DESC; + //fprintf(stderr, "component %d using column #%d (internally %d)\n", j, cleaned_col_num, col_num); key_num++; } pidx->num_keys = key_num; cur_pos += 4; + //fprintf(stderr, "pidx->unknown_pre_first_pg:0x%08x\n", read_pg_if_32(mdb, &cur_pos)); pidx->first_pg = read_pg_if_32(mdb, &cur_pos); pidx->flags = read_pg_if_8(mdb, &cur_pos); + //fprintf(stderr, "pidx->first_pg:%d pidx->flags:0x%02x\n", pidx->first_pg, pidx->flags); if (IS_JET4(mdb)) cur_pos += 9; } return NULL;