Esempio n. 1
0
int 
mdb_find_end_of_row(MdbHandle *mdb, int row)
{
	int rco = mdb->fmt->row_count_offset;
	int row_end;

#if 1
	if (row > 1000) return -1;

	row_end = (row == 0) ? mdb->fmt->pg_size :
		mdb_get_int16(mdb->pg_buf, rco + row*2) & OFFSET_MASK;
#else
	/* Search the previous "row start" values for the first non-'lookupflag'
	 * one. If we don't find one, then the end of the page is the correct
	 * value.
	 */
	int i, row_start;

	if (row > 1000) return -1;

	/* if lookupflag is not set, it's good (deleteflag is ok) */
        for (i = row; i > 0; i--) {
                row_start = mdb_get_int16(mdb->pg_buf, (rco + i*2));
                if (!(row_start & 0x8000)) {
                        break;
                }
        }

	row_end = (i == 0) ? mdb->fmt->pg_size : row_start & OFFSET_MASK;
#endif
	return row_end - 1;
}
Esempio n. 2
0
static MdbProperties *
mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len)
{
	guint32 record_len, name_len;
	int pos = 0;
	int elem, dtype, dsize;
	gchar *name, *value;
	MdbProperties *props;
	int i=0;

#if MDB_DEBUG
	mdb_buffer_dump(kkd, 0, len);
#endif
	pos = 0;

	record_len = mdb_get_int16(kkd, pos);
	pos += 4;
	name_len = mdb_get_int16(kkd, pos);
	pos += 2;
	props = mdb_alloc_props();
	if (name_len) {
		props->name = g_malloc(3*name_len + 1);
		mdb_unicode2ascii(mdb, kkd+pos, name_len, props->name, 3*name_len);
		mdb_debug(MDB_DEBUG_PROPS,"prop block named: %s", props->name);
	}
	pos += name_len;

	props->hash = g_hash_table_new(g_str_hash, g_str_equal);

	while (pos < len) {
		record_len = mdb_get_int16(kkd, pos);
		dtype = kkd[pos + 3];
		elem = mdb_get_int16(kkd, pos + 4);
		dsize = mdb_get_int16(kkd, pos + 6);
		value = g_malloc(dsize + 1);
		strncpy(value, &kkd[pos + 8], dsize);
		value[dsize] = '\0';
		name = g_ptr_array_index(names,elem);
		if (mdb_get_option(MDB_DEBUG_PROPS)) {
			fprintf(stderr, "%02d ",i++);
			mdb_debug(MDB_DEBUG_PROPS,"elem %d (%s) dsize %d dtype %d", elem, name, dsize, dtype);
			mdb_buffer_dump(value, 0, dsize);
		}
		if (dtype == MDB_MEMO) dtype = MDB_TEXT;
		if (dtype == MDB_BOOL) {
			g_hash_table_insert(props->hash, g_strdup(name),
				g_strdup(kkd[pos + 8] ? "yes" : "no"));
		} else {
			g_hash_table_insert(props->hash, g_strdup(name),
			  mdb_col_to_string(mdb, kkd, pos + 8, dtype, dsize));
		}
		g_free(value);
		pos += record_len;
	}
	return props;
	
}
Esempio n. 3
0
int mdb_find_row(MdbHandle *mdb, int row, int *start, size_t *len)
{
	int rco = mdb->fmt->row_count_offset;
	int next_start;

	if (row > 1000) return -1;

	*start = mdb_get_int16(mdb->pg_buf, rco + 2 + row*2);
	next_start = (row == 0) ? mdb->fmt->pg_size :
		mdb_get_int16(mdb->pg_buf, rco + row*2) & OFFSET_MASK;
	*len = next_start - (*start & OFFSET_MASK);
	return 0;
}
Esempio n. 4
0
MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
{
	MdbTableDef *table;
	MdbHandle *mdb = entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	int row_start, pg_row;
	void *buf, *pg_buf = mdb->pg_buf;
	guint i;

	mdb_read_pg(mdb, entry->table_pg);
	if (mdb_get_byte(pg_buf, 0) != 0x02)  /* not a valid table def page */
		return NULL;
	table = mdb_alloc_tabledef(entry);

	mdb_get_int16(pg_buf, 8); /* len */

	table->num_rows = mdb_get_int32(pg_buf, fmt->tab_num_rows_offset);
	table->num_var_cols = mdb_get_int16(pg_buf, fmt->tab_num_cols_offset-2);
	table->num_cols = mdb_get_int16(pg_buf, fmt->tab_num_cols_offset);
	table->num_idxs = mdb_get_int32(pg_buf, fmt->tab_num_idxs_offset);
	table->num_real_idxs = mdb_get_int32(pg_buf, fmt->tab_num_ridxs_offset);

	/* grab a copy of the usage map */
	pg_row = mdb_get_int32(pg_buf, fmt->tab_usage_map_offset);
	mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz));
	table->usage_map = g_memdup(buf + row_start, table->map_sz);
	if (mdb_get_option(MDB_DEBUG_USAGE)) 
		mdb_buffer_dump(buf, row_start, table->map_sz);
	mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d len %d",
		pg_row >> 8, pg_row & 0xff, row_start, table->map_sz);

	/* grab a copy of the free space page map */
	pg_row = mdb_get_int32(pg_buf, fmt->tab_free_map_offset);
	mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->freemap_sz));
	table->free_usage_map = g_memdup(buf + row_start, table->freemap_sz);
	mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n",
		pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz);

	table->first_data_pg = mdb_get_int16(pg_buf, fmt->tab_first_dpg_offset);

	if (entry->props)
		for (i=0; i<entry->props->len; ++i) {
			MdbProperties *props = g_array_index(entry->props, MdbProperties*, i);
			if (!props->name)
				table->props = props;
		}

	return table;
}
Esempio n. 5
0
int 
mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field)
{
	char tmpbuf[256];

	if (node->op == MDB_ISNULL)
		return field->is_null?1:0;
	else if (node->op == MDB_NOTNULL)
		return field->is_null?0:1;
	switch (col->col_type) {
		case MDB_BOOL:
			return mdb_test_int(node, !field->is_null);
			break;
		case MDB_BYTE:
			return mdb_test_int(node, (gint32)((char *)field->value)[0]);
			break;
		case MDB_INT:
			return mdb_test_int(node, (gint32)mdb_get_int16(field->value, 0));
			break;
		case MDB_LONGINT:
			return mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0));
			break;
		case MDB_TEXT:
			mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, 256);
			return mdb_test_string(node, tmpbuf);
		case MDB_DATETIME:
			return mdb_test_date(node, mdb_get_double(field->value, 0));
		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;
}
Esempio n. 6
0
static GPtrArray *
mdb_read_props_list(MdbHandle *mdb, gchar *kkd, int len)
{
	guint32 record_len;
	int pos = 0;
	gchar *name;
	GPtrArray *names = NULL;
	int i=0;

	names = g_ptr_array_new();
#if MDB_DEBUG
	mdb_buffer_dump(kkd, 0, len);
#endif
	pos = 0;
	while (pos < len) {
		record_len = mdb_get_int16(kkd, pos);
		pos += 2;
		if (mdb_get_option(MDB_DEBUG_PROPS)) {
			fprintf(stderr, "%02d ",i++);
			mdb_buffer_dump(kkd, pos - 2, record_len + 2);
		}
		name = g_malloc(3*record_len + 1); /* worst case scenario is 3 bytes out per byte in */
		mdb_unicode2ascii(mdb, &kkd[pos], record_len, name, 3*record_len);

		pos += record_len;
		g_ptr_array_add(names, name);
#if MDB_DEBUG
		printf("new len = %d\n", names->len);
#endif
	}
	return names;
}
Esempio n. 7
0
guint16 
read_pg_if_16(MdbHandle *mdb, int *cur_pos)
{
	char c[2];

	read_pg_if_n(mdb, c, cur_pos, 2);
	return mdb_get_int16(c, 0);
}
Esempio n. 8
0
/*
 * That function takes a raw KKD/MR2 binary buffer,
 * typically read from LvProp in table MSysbjects
 * and returns a GPtrArray of MdbProps*
 */
GArray*
mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) {
	guint32 record_len;
	guint16 record_type;
	size_t pos;
	GPtrArray *names = NULL;
	MdbProperties *props;
	GArray *result;

#if MDB_DEBUG
	mdb_buffer_dump(buffer, 0, len);
#endif
	mdb_debug(MDB_DEBUG_PROPS,"starting prop parsing of type %s", buffer);

	if (strcmp("KKD", buffer) && strcmp("MR2", buffer)) {
		fprintf(stderr, "Unrecognized format.\n");
		mdb_buffer_dump(buffer, 0, len);
		return NULL;
	}

	result = g_array_new(0, 0, sizeof(MdbProperties*));

	pos = 4;
	while (pos < len) {
		record_len = mdb_get_int32(buffer, pos);
		record_type = mdb_get_int16(buffer, pos + 4);
		mdb_debug(MDB_DEBUG_PROPS,"prop chunk type:0x%04x len:%d", record_type, record_len);
		//mdb_buffer_dump(buffer, pos+4, record_len);
		switch (record_type) {
			case 0x80:
				if (names) free_names(names);
				names = mdb_read_props_list(mdb, buffer+pos+6, record_len - 6);
				break;
			case 0x00:
			case 0x01:
				if (!names) {
					fprintf(stderr,"sequence error!\n");
					break;
				}
				props = mdb_read_props(mdb, names, buffer+pos+6, record_len - 6);
				g_array_append_val(result, props);
				//mdb_dump_props(props, stderr, 1);
				break;
			default:
				fprintf(stderr,"Unknown record type %d\n", record_type);
				break;
		}
		pos += record_len;
	}
	if (names) free_names(names);
	return result;
}
Esempio n. 9
0
int mdb_pg_get_int16(MdbHandle *mdb, int offset)
{
	if (offset < 0 || offset+2 > mdb->fmt->pg_size) return -1;
	mdb->cur_pos+=2;
	return mdb_get_int16(mdb->pg_buf, offset);
}
Esempio n. 10
0
GPtrArray *mdb_read_columns(MdbTableDef *table)
{
	MdbHandle *mdb = table->entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	MdbColumn *pcol;
	unsigned char *col;
	unsigned int i, j;
	int cur_pos;
	size_t name_sz;
	
	table->columns = g_ptr_array_new();

	col = (unsigned char *) g_malloc(fmt->tab_col_entry_size);

	cur_pos = fmt->tab_cols_start_offset + 
		(table->num_real_idxs * fmt->tab_ridx_entry_size);

	/* new code based on patch submitted by Tim Nelson 2000.09.27 */

	/* 
	** column attributes 
	*/
	for (i=0;i<table->num_cols;i++) {
#ifdef MDB_DEBUG
	/* printf("column %d\n", i);
	mdb_buffer_dump(mdb->pg_buf, cur_pos, fmt->tab_col_entry_size); */
#endif
		read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size);
		pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn));

		pcol->table = table;

		pcol->col_type = col[0];

		// col_num_offset == 1 or 5
		pcol->col_num = col[fmt->col_num_offset];

		//fprintf(stdout,"----- column %d -----\n",pcol->col_num);
		// col_var == 3 or 7
		pcol->var_col_num = mdb_get_int16(col, fmt->tab_col_offset_var);
		//fprintf(stdout,"var column pos %d\n",pcol->var_col_num);

		// col_var == 5 or 9
		pcol->row_col_num = mdb_get_int16(col, fmt->tab_row_col_num_offset);
		//fprintf(stdout,"row column num %d\n",pcol->row_col_num);

		/* FIXME: can this be right in Jet3 and Jet4? */
		if (pcol->col_type == MDB_NUMERIC) {
			pcol->col_prec = col[11];
			pcol->col_scale = col[12];
		}

		// col_flags_offset == 13 or 15
		pcol->is_fixed = col[fmt->col_flags_offset] & 0x01 ? 1 : 0;
		pcol->is_long_auto = col[fmt->col_flags_offset] & 0x04 ? 1 : 0;
		pcol->is_uuid_auto = col[fmt->col_flags_offset] & 0x40 ? 1 : 0;

		// tab_col_offset_fixed == 14 or 21
		pcol->fixed_offset = mdb_get_int16(col, fmt->tab_col_offset_fixed);
		//fprintf(stdout,"fixed column offset %d\n",pcol->fixed_offset);
		//fprintf(stdout,"col type %s\n",pcol->is_fixed ? "fixed" : "variable");

		if (pcol->col_type != MDB_BOOL) {
			// col_size_offset == 16 or 23
			pcol->col_size = mdb_get_int16(col, fmt->col_size_offset);
		} else {
			pcol->col_size=0;
		}
		
		g_ptr_array_add(table->columns, pcol);
	}

	g_free (col);

	/* 
	** column names - ordered the same as the column attributes table
	*/
	for (i=0;i<table->num_cols;i++) {
		char *tmp_buf;
		pcol = g_ptr_array_index(table->columns, i);

		if (IS_JET3(mdb))
			name_sz = read_pg_if_8(mdb, &cur_pos);
		else
			name_sz = read_pg_if_16(mdb, &cur_pos);
		tmp_buf = (char *) g_malloc(name_sz);
		read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz);
		mdb_unicode2ascii(mdb, tmp_buf, name_sz, pcol->name, MDB_MAX_OBJ_NAME);
		g_free(tmp_buf);


	}

	/* Sort the columns by col_num */
	g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer);

	GArray *allprops = table->entry->props;
	if (allprops)
		for (i=0;i<table->num_cols;i++) {
			pcol = g_ptr_array_index(table->columns, i);
			for (j=0; j<allprops->len; ++j) {
				MdbProperties *props = g_array_index(allprops, MdbProperties*, j);
				if (props->name && pcol->name && !strcmp(props->name, pcol->name)) {
					pcol->props = props;
					break;
				}

			}
		}
	table->index_start = cur_pos;
	return table->columns;
}
Esempio n. 11
0
GPtrArray *mdb_read_columns(MdbTableDef *table)
{
	MdbHandle *mdb = table->entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	MdbColumn *pcol;
	unsigned char *col;
	unsigned int i;
	int cur_pos;
	size_t name_sz;
	
	table->columns = g_ptr_array_new();

	col = (unsigned char *) g_malloc(fmt->tab_col_entry_size);

	cur_pos = fmt->tab_cols_start_offset + 
		(table->num_real_idxs * fmt->tab_ridx_entry_size);

	/* new code based on patch submitted by Tim Nelson 2000.09.27 */

	/* 
	** column attributes 
	*/
	for (i=0;i<table->num_cols;i++) {
#ifdef MDB_DEBUG
	/* printf("column %d\n", i);
	buffer_dump(mdb->pg_buf, cur_pos, fmt->tab_col_entry_size); */
#endif
		read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size);
		pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn));

		pcol->col_type = col[0];

		
		pcol->col_num = col[fmt->col_num_offset];

		
		
		pcol->var_col_num = mdb_get_int16(col, fmt->tab_col_offset_var);
		

		
		pcol->row_col_num = mdb_get_int16(col, fmt->tab_row_col_num_offset);
		

		/* FIXME: can this be right in Jet3 and Jet4? */
		if (pcol->col_type == MDB_NUMERIC) {
			pcol->col_prec = col[11];
			pcol->col_scale = col[12];
		}

		
		pcol->is_fixed = col[fmt->col_fixed_offset] & 0x01 ? 1 : 0;

		
		pcol->fixed_offset = mdb_get_int16(col, fmt->tab_col_offset_fixed);
		
		

		if (pcol->col_type != MDB_BOOL) {
			
			pcol->col_size = mdb_get_int16(col, fmt->col_size_offset);
		} else {
			pcol->col_size=0;
		}
		
		g_ptr_array_add(table->columns, pcol);
	}

	g_free (col);

	/* 
	** column names - ordered the same as the column attributes table
	*/
	for (i=0;i<table->num_cols;i++) {
		char *tmp_buf;
		pcol = g_ptr_array_index(table->columns, i);

		if (IS_JET4(mdb)) {
			name_sz = read_pg_if_16(mdb, &cur_pos);
		} else if (IS_JET3(mdb)) {
			name_sz = read_pg_if_8(mdb, &cur_pos);
		} else {
			fprintf(stderr,"Unknown MDB version\n");
			continue;
		}
		tmp_buf = (char *) g_malloc(name_sz);
		read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz);
		mdb_unicode2ascii(mdb, tmp_buf, name_sz, pcol->name, MDB_MAX_OBJ_NAME);
		g_free(tmp_buf);

	}

	/* Sort the columns by col_num */
	g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer);

	table->index_start = cur_pos;
	return table->columns;
}
Esempio n. 12
0
int 
mdb_fetch_row(MdbTableDef *table)
{
	MdbHandle *mdb = table->entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	unsigned int rows;
	int rc;
	guint32 pg;

	if (table->num_rows==0)
		return 0;

	/* initialize */
	if (!table->cur_pg_num) {
		table->cur_pg_num=1;
		table->cur_row=0;
		if ((!table->is_temp_table)&&(table->strategy!=MDB_INDEX_SCAN))
			if (!mdb_read_next_dpg(table)) return 0;
	}

	do {
		if (table->is_temp_table) {
			GPtrArray *pages = table->temp_table_pages;
			rows = mdb_get_int16(
				g_ptr_array_index(pages, table->cur_pg_num-1),
				fmt->row_count_offset);
			if (table->cur_row >= rows) {
				table->cur_row = 0;
				table->cur_pg_num++;
				if (table->cur_pg_num > pages->len)
					return 0;
			}
			memcpy(mdb->pg_buf,
				g_ptr_array_index(pages, table->cur_pg_num-1),
				fmt->pg_size);
		} else if (table->strategy==MDB_INDEX_SCAN) {
		
			if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) {
				mdb_index_scan_free(table);
				return 0;
			}
			mdb_read_pg(mdb, pg);
		} else {
			rows = mdb_get_int16(mdb->pg_buf,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); */
		rc = mdb_read_row(table, table->cur_row);
		table->cur_row++;
	} while (!rc);

	return 1;
}
Esempio n. 13
0
GPtrArray *
mdb_read_indices(MdbTableDef *table)
{
	MdbCatalogEntry *entry = table->entry;
	MdbHandle *mdb = entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	MdbIndex *pidx;
	unsigned int i, j;
	int idx_num, key_num, col_num;
	int cur_pos, name_sz, idx2_sz, type_offset;
	int index_start_pg = mdb->cur_pg;
	guchar *tmpbuf;

        table->indices = g_ptr_array_new();

        if (IS_JET4(mdb)) {
		cur_pos = table->index_start + 52 * table->num_real_idxs;
		idx2_sz = 28;
		type_offset = 23;
	} else {
		cur_pos = table->index_start + 39 * table->num_real_idxs;
		idx2_sz = 20;
		type_offset = 19;
	}

	tmpbuf = (guchar *) g_malloc(idx2_sz);
	for (i=0;i<table->num_idxs;i++) {
		read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz);
		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]; 
		g_ptr_array_add(table->indices, pidx);
	}
	g_free(tmpbuf);

	for (i=0;i<table->num_idxs;i++) {
		pidx = g_ptr_array_index (table->indices, i);
		if (IS_JET4(mdb)) {
			name_sz=read_pg_if_16(mdb, &cur_pos);
			cur_pos += 2;
			tmpbuf = g_malloc(name_sz);
			read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz);
			cur_pos += name_sz;
			mdb_unicode2ascii(mdb, tmpbuf, 0, name_sz, pidx->name); 
			g_free(tmpbuf);
		} else {
			read_pg_if(mdb, &cur_pos, 0);
			name_sz=mdb->pg_buf[cur_pos++];
			read_pg_if_n(mdb, (unsigned char *) pidx->name, &cur_pos, name_sz);
			cur_pos += name_sz;
			pidx->name[name_sz]='\0';		
		}
		//fprintf(stderr, "index name %s\n", 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;i<table->num_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;
		}

		pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, 
				fmt->tab_cols_start_offset +
				(i*fmt->tab_ridx_entry_size));

		key_num=0;
		for (j=0;j<MDB_MAX_IDX_COLS;j++) {
			col_num=read_pg_if_16(mdb,&cur_pos);
			cur_pos += 2;
			read_pg_if(mdb, &cur_pos, 0);
			cur_pos++;
			if (col_num == 0xFFFF)
				continue;
			/* set column number to a 1 based column number and store */
			pidx->key_col_num[key_num] = col_num + 1;
			pidx->key_col_order[key_num] =
				(mdb->pg_buf[cur_pos-1]) ? MDB_ASC : MDB_DESC;
			key_num++;
		}
		pidx->num_keys = key_num;

		cur_pos += 4;
		pidx->first_pg = read_pg_if_32(mdb, &cur_pos);
		cur_pos += 4;
		read_pg_if(mdb, &cur_pos, 0);
		pidx->flags = mdb->pg_buf[cur_pos++];
		if (IS_JET4(mdb)) cur_pos += 9;
	}
	return NULL;
}