mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-09-19 10:37:54 +08:00
odbc inst fixes.
deleted column fix for jet4 fixed columns
This commit is contained in:
@@ -176,7 +176,7 @@ int ret;
|
||||
mdb_col_to_string(mdb, mdb->pg_buf, start, col->col_type, len));
|
||||
}
|
||||
} else {
|
||||
strcpy(col->bind_ptr, "");
|
||||
strcpy(col->bind_ptr, "");
|
||||
}
|
||||
ret = strlen(col->bind_ptr);
|
||||
if (col->len_ptr) {
|
||||
@@ -241,7 +241,8 @@ int mdb_read_row(MdbTableDef *table, int row)
|
||||
|
||||
#if 1
|
||||
/* take advantage of mdb_crack_row() to clean up binding */
|
||||
for (i = 0; i < num_fields; i++) {
|
||||
/* use num_cols instead of num_fields -- bsb 03/04/02 */
|
||||
for (i = 0; i < table->num_cols; i++) {
|
||||
col = g_ptr_array_index(table->columns,fields[i].colnum);
|
||||
if (fields[i].is_fixed) {
|
||||
rc = _mdb_attempt_bind(mdb, col,
|
||||
|
@@ -40,13 +40,16 @@ typedef struct {
|
||||
guint16 col_num_offset;
|
||||
guint16 tab_col_entry_size;
|
||||
guint16 tab_free_map_offset;
|
||||
guint16 tab_col_offset_var;
|
||||
guint16 tab_col_offset_fixed;
|
||||
guint16 tab_row_col_num_offset;
|
||||
} MdbFormatConstants;
|
||||
*/
|
||||
MdbFormatConstants MdbJet4Constants = {
|
||||
4096, 0x0c, 16, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25, 59
|
||||
4096, 0x0c, 16, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25, 59, 7, 21, 9
|
||||
};
|
||||
MdbFormatConstants MdbJet3Constants = {
|
||||
2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39
|
||||
2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39, 3, 14, 5 /* not sure on 5, need to check */
|
||||
};
|
||||
|
||||
static size_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg);
|
||||
|
@@ -65,9 +65,13 @@ load_options()
|
||||
if (!strcmp(opt, "debug_write")) opts |= MDB_DEBUG_WRITE;
|
||||
if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE;
|
||||
if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE;
|
||||
if (!strcmp(opt, "debug_row")) opts |= MDB_DEBUG_ROW;
|
||||
if (!strcmp(opt, "debug_all")) {
|
||||
opts |= MDB_DEBUG_LIKE;
|
||||
opts |= MDB_DEBUG_WRITE;
|
||||
opts |= MDB_DEBUG_USAGE;
|
||||
opts |= MDB_DEBUG_OLE;
|
||||
opts |= MDB_DEBUG_ROW;
|
||||
}
|
||||
opt = strtok(NULL,":");
|
||||
} while (opt);
|
||||
|
@@ -189,9 +189,24 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
|
||||
read_pg_if(mdb, &cur_col, 0);
|
||||
col.col_type = mdb->pg_buf[cur_col];
|
||||
|
||||
read_pg_if(mdb, &cur_col, fmt->col_num_offset); // col_num_offset == 1 or 5
|
||||
read_pg_if(mdb, &cur_col, cur_col + fmt->col_num_offset); // col_num_offset == 1 or 5
|
||||
col.col_num = mdb->pg_buf[cur_col + fmt->col_num_offset];
|
||||
|
||||
//fprintf(stdout,"----- column %d -----\n",col.col_num);
|
||||
read_pg_if(mdb, &cur_col, fmt->tab_col_offset_var); // col_var == 3 or 7
|
||||
low_byte = mdb->pg_buf[cur_col + fmt->tab_col_offset_var];
|
||||
read_pg_if(mdb, &cur_col, fmt->tab_col_offset_var + 1);
|
||||
high_byte = mdb->pg_buf[cur_col + fmt->tab_col_offset_var + 1];
|
||||
col.var_col_num = high_byte * 256 + low_byte;
|
||||
//fprintf(stdout,"var column pos %d\n",col.var_col_num);
|
||||
|
||||
read_pg_if(mdb, &cur_col, fmt->tab_row_col_num_offset); // col_var == 5 or 9
|
||||
low_byte = mdb->pg_buf[cur_col + fmt->tab_row_col_num_offset];
|
||||
read_pg_if(mdb, &cur_col, fmt->tab_row_col_num_offset + 1);
|
||||
high_byte = mdb->pg_buf[cur_col + fmt->tab_row_col_num_offset + 1];
|
||||
col.row_col_num = high_byte * 256 + low_byte;
|
||||
//fprintf(stdout,"row column num %d\n",col.row_col_num);
|
||||
|
||||
/* FIXME: can this be right in Jet3 and Jet4? */
|
||||
if (col.col_type == MDB_NUMERIC) {
|
||||
read_pg_if(mdb, &cur_col, 11);
|
||||
@@ -203,6 +218,15 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
|
||||
read_pg_if(mdb, &cur_col, fmt->col_fixed_offset); // col_fixed_offset == 13 or 15
|
||||
col.is_fixed = mdb->pg_buf[cur_col + fmt->col_fixed_offset] &
|
||||
0x01 ? 1 : 0;
|
||||
|
||||
read_pg_if(mdb, &cur_col, fmt->tab_col_offset_fixed); // col_fixed_offset == 13 or 15
|
||||
low_byte = mdb->pg_buf[cur_col + fmt->tab_col_offset_fixed];
|
||||
read_pg_if(mdb, &cur_col, fmt->tab_col_offset_fixed + 1);
|
||||
high_byte = mdb->pg_buf[cur_col + fmt->tab_col_offset_fixed + 1];
|
||||
col.fixed_offset = high_byte * 256 + low_byte;
|
||||
//fprintf(stdout,"fixed column offset %d\n",col.fixed_offset);
|
||||
//fprintf(stdout,"col type %s\n",col.is_fixed ? "fixed" : "variable");
|
||||
|
||||
if (col.col_type != MDB_BOOL) {
|
||||
read_pg_if(mdb, &cur_col, fmt->col_size_offset); // col_size_offset == 16 or 23
|
||||
low_byte = mdb->pg_buf[cur_col + fmt->col_size_offset];
|
||||
|
@@ -87,20 +87,41 @@ MdbIndex *idx;
|
||||
int
|
||||
mdb_crack_row4(MdbTableDef *table, int row_start, int row_end, MdbField *fields)
|
||||
{
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
MdbColumn *col;
|
||||
int i, j;
|
||||
int var_cols = 0, fixed_cols = 0, num_cols, totcols = 0;
|
||||
int var_cols_found, fixed_cols_found, var_entry_pos;
|
||||
int col_start, next_col;
|
||||
unsigned char *nullmask;
|
||||
int bitmask_sz;
|
||||
int byte_num, bit_num;
|
||||
int eod, len; /* end of data */
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
MdbColumn *col;
|
||||
int i, j;
|
||||
int var_cols = 0, fixed_cols = 0, num_cols, totcols = 0;
|
||||
int var_cols_found, fixed_cols_found, var_entry_pos;
|
||||
int col_start, next_col;
|
||||
unsigned char *nullmask;
|
||||
int bitmask_sz;
|
||||
int byte_num, bit_num;
|
||||
int eod, len; /* end of data */
|
||||
int real_offset = 0;
|
||||
int row_pos;
|
||||
|
||||
if (mdb_get_option(MDB_DEBUG_ROW)) {
|
||||
buffer_dump(mdb->pg_buf, row_start, row_end+1);
|
||||
}
|
||||
|
||||
num_cols = mdb_pg_get_int16(mdb, row_start);
|
||||
|
||||
/* compute nulls first to help with fixed colnum's */
|
||||
bitmask_sz = (num_cols - 1) / 8 + 1;
|
||||
nullmask = &mdb->pg_buf[row_end - bitmask_sz + 1];
|
||||
|
||||
for (i=0;i<table->num_cols;i++) {
|
||||
col = g_ptr_array_index (table->columns, i);
|
||||
row_pos = col->row_col_num;
|
||||
byte_num = row_pos / 8;
|
||||
bit_num = row_pos % 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");
|
||||
}
|
||||
|
||||
/* fields are ordered fixed then variable */
|
||||
for (i = 0; i < table->num_cols; i++) {
|
||||
col = g_ptr_array_index (table->columns, i);
|
||||
if (mdb_is_fixed_col(col)) {
|
||||
@@ -119,17 +140,6 @@ int eod, len; /* end of data */
|
||||
}
|
||||
}
|
||||
|
||||
bitmask_sz = (num_cols - 1) / 8 + 1;
|
||||
nullmask = &mdb->pg_buf[row_end - bitmask_sz + 1];
|
||||
|
||||
for (i=0;i<num_cols;i++) {
|
||||
byte_num = i / 8;
|
||||
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");
|
||||
}
|
||||
|
||||
/* find the end of data pointer */
|
||||
eod = mdb_pg_get_int16(mdb, row_end - 3 - var_cols*2 - bitmask_sz);
|
||||
|
||||
@@ -140,7 +150,18 @@ int eod, len; /* end of data */
|
||||
var_cols_found = 0;
|
||||
|
||||
totcols = 0;
|
||||
for (j=0;j<table->num_cols;j++) {
|
||||
col = g_ptr_array_index(table->columns,j);
|
||||
if (mdb_is_fixed_col(col) && fixed_cols_found <= fixed_cols) {
|
||||
real_offset += col->col_size;
|
||||
fields[totcols].start = row_start + col->fixed_offset + 2;
|
||||
fields[totcols++].value = &mdb->pg_buf[row_start + col->fixed_offset + 2];
|
||||
fixed_cols_found++;
|
||||
}
|
||||
}
|
||||
|
||||
/* loop through fixed columns and add values to fields[] */
|
||||
/*
|
||||
for (j=0;j<table->num_cols;j++) {
|
||||
col = g_ptr_array_index(table->columns,j);
|
||||
if (mdb_is_fixed_col(col) && ++fixed_cols_found <= fixed_cols) {
|
||||
@@ -150,6 +171,10 @@ int eod, len; /* end of data */
|
||||
col_start += col->col_size;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
col_start = mdb_pg_get_int16(mdb, row_end - 3 - bitmask_sz);
|
||||
|
||||
for (j=0;j<table->num_cols;j++) {
|
||||
col = g_ptr_array_index(table->columns,j);
|
||||
if (!mdb_is_fixed_col(col) && ++var_cols_found <= var_cols) {
|
||||
|
@@ -3,7 +3,10 @@ SQLDIR = ../sql
|
||||
SQLSOURCES = mdbsql.c parser.c lexer.c
|
||||
MDBDIR = ../libmdb
|
||||
MDBSOURCES = backend.c index.c money.c catalog.c kkd.c sargs.c \
|
||||
data.c like.c table.c dump.c file.c mem.c
|
||||
data.c like.c table.c dump.c file.c mem.c \
|
||||
map.c props.c worktable.c options.c \
|
||||
write.c stats.c
|
||||
|
||||
bin_PROGRAMS = unittest
|
||||
lib_LTLIBRARIES = libmdbodbc.la
|
||||
AM_CPPFLAGS = -I ../../include $(GLIB_CFLAGS)
|
||||
|
@@ -1,5 +1,7 @@
|
||||
/* MDB Tools - A library for reading MS Access database file
|
||||
* Copyright (C) 2000 Brian Bruns
|
||||
* Copyright (C) 2000-2004 Brian Bruns
|
||||
*
|
||||
* portions based on FreeTDS, Copyright (C) 1998-1999 Brian Bruns
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@@ -24,6 +26,12 @@
|
||||
|
||||
#include "connectparams.h"
|
||||
|
||||
#if !HAVE_SQLGETPRIVATEPROFILESTRING
|
||||
|
||||
/*
|
||||
* * Last resort place to check for INI file. This is usually set at compile time
|
||||
* * by build scripts.
|
||||
* */
|
||||
#ifndef SYS_ODBC_INI
|
||||
#define SYS_ODBC_INI "/etc/odbc.ini"
|
||||
#endif
|
||||
@@ -444,4 +452,63 @@ static gboolean cleanup (gpointer key, gpointer value, gpointer user_data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_SQLGETPRIVATEPROFILESTRING */
|
||||
|
||||
#ifdef UNIXODBC
|
||||
|
||||
/*
|
||||
* Begin BIG Hack.
|
||||
*
|
||||
* We need these from odbcinstext.h but it wants to
|
||||
* include <log.h> and <ini.h>, which are not in the
|
||||
* standard include path. XXX smurph
|
||||
* confirmed by unixODBC stuff, odbcinstext.h shouldn't be installed. freddy77
|
||||
*/
|
||||
#define INI_MAX_LINE 1000
|
||||
#define INI_MAX_OBJECT_NAME INI_MAX_LINE
|
||||
#define INI_MAX_PROPERTY_NAME INI_MAX_LINE
|
||||
#define INI_MAX_PROPERTY_VALUE INI_MAX_LINE
|
||||
|
||||
#define ODBCINST_PROMPTTYPE_LABEL 0 /* readonly */
|
||||
#define ODBCINST_PROMPTTYPE_TEXTEDIT 1
|
||||
#define ODBCINST_PROMPTTYPE_LISTBOX 2
|
||||
#define ODBCINST_PROMPTTYPE_COMBOBOX 3
|
||||
#define ODBCINST_PROMPTTYPE_FILENAME 4
|
||||
#define ODBCINST_PROMPTTYPE_HIDDEN 5
|
||||
|
||||
typedef struct tODBCINSTPROPERTY
|
||||
{
|
||||
struct tODBCINSTPROPERTY *pNext; /* pointer to next property, NULL if last property */
|
||||
|
||||
char szName[INI_MAX_PROPERTY_NAME + 1]; /* property name */
|
||||
char szValue[INI_MAX_PROPERTY_VALUE + 1]; /* property value */
|
||||
int nPromptType; /* PROMPTTYPE_TEXTEDIT, PROMPTTYPE_LISTBOX, PROMPTTYPE_COMBOBOX, PROMPTTYPE_FILENAME */
|
||||
char **aPromptData; /* array of pointers terminated with a NULL value in array. */
|
||||
char *pszHelp; /* help on this property (driver setups should keep it short) */
|
||||
void *pWidget; /* CALLER CAN STORE A POINTER TO ? HERE */
|
||||
int bRefresh; /* app should refresh widget ie Driver Setup has changed aPromptData or szValue */
|
||||
void *hDLL; /* for odbcinst internal use... only first property has valid one */
|
||||
}
|
||||
ODBCINSTPROPERTY, *HODBCINSTPROPERTY;
|
||||
|
||||
/*
|
||||
* End BIG Hack.
|
||||
*/
|
||||
|
||||
int
|
||||
ODBCINSTGetProperties(HODBCINSTPROPERTY hLastProperty)
|
||||
{
|
||||
hLastProperty->pNext = (HODBCINSTPROPERTY) malloc(sizeof(ODBCINSTPROPERTY));
|
||||
hLastProperty = hLastProperty->pNext;
|
||||
memset(hLastProperty, 0, sizeof(ODBCINSTPROPERTY));
|
||||
hLastProperty->nPromptType = ODBCINST_PROMPTTYPE_FILENAME;
|
||||
strncpy(hLastProperty->szName, "Database", INI_MAX_PROPERTY_NAME);
|
||||
strncpy(hLastProperty->szValue, "", INI_MAX_PROPERTY_VALUE);
|
||||
hLastProperty->pszHelp = (char *) strdup("Filename and Path of MDB file to connect to.\n"
|
||||
"Use the full path to the database file.");
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user