odbc inst fixes.

deleted column fix for jet4 fixed columns
This commit is contained in:
brianb 2004-03-04 21:25:09 +00:00
parent fb02e23b6b
commit c5f4a8bb04
14 changed files with 220 additions and 44 deletions

View File

@ -1,3 +1,17 @@
Thu Mar 4 15:30:21 EST 2004 Brian Bruns <brian@bruns.com>
* src/odbc/Makefile.am: add newer files to driver
* src/libmdb/options.c: add debug_row option
* src/libmdb/data.c: loop for num_cols (current columns definition) not num_fields (columns on row)
* src/libmdb/write.c: read deleted fixed columns correctly under jet4
* include/mdbtools.h:
* src/libmdb/file.c:
* src/libmdb/table.c: store fixed and variable offsets and postions from tdef in column structure.
* include/mdbodbc.h:
* src/odbc/connectparams.c: Add ODBCINSTGetProperties function for setup lib.
* configure.in: Add detection of SQLGetPrivateProfileString
* README: clarify LGPL covered files
* INSTALL: clarify yacc/bison
Sun Feb 15 07:37:19 EST 2004 Brian Bruns <brian@bruns.com> Sun Feb 15 07:37:19 EST 2004 Brian Bruns <brian@bruns.com>
* HACKING: better description of Jet4 column deletion/addition * HACKING: better description of Jet4 column deletion/addition
* src/gmdb2/gladefiles/gmdb-debug.glade: * src/gmdb2/gladefiles/gmdb-debug.glade:

17
HACKING
View File

@ -203,7 +203,7 @@ Notes:
Each memo column (or other long binary data) in a row Each memo column (or other long binary data) in a row
+-------------------------------------------------------------------------+ +-------------------------------------------------------------------------+
| Memo Field Definition (12 bytes) | Memo Field Definition (12 bytes) |
+------+---------+-------------+------------------------------------------+ +------+---------+-------------+------------------------------------------+
| data | length | name | description | | data | length | name | description |
+------+---------+-------------+------------------------------------------+ +------+---------+-------------+------------------------------------------+
@ -319,10 +319,13 @@ next_pg field.
| Iterate for the number of num_cols (18 bytes per column) | | Iterate for the number of num_cols (18 bytes per column) |
+-------------------------------------------------------------------------+ +-------------------------------------------------------------------------+
| ???? | 1 byte | col_type | Column Type (see table below) | | ???? | 1 byte | col_type | Column Type (see table below) |
| ???? | 2 bytes | col_num | Column Number, (not always) | | ???? | 2 bytes | col_pos | Column Position, (counts deleted cols) |
| ???? | 2 bytes | offset_V | Offset for variable length columns | | ???? | 2 bytes | offset_V | Offset for variable length columns |
| ???? | 4 bytes | ??? | | | ???? | 4 bytes | ??? | |
| ???? | 4 bytes | ??? | | | ???? | 2 bytes | ??? | |
| ???? | 1 byte | precision | precision if numeric column |
| ???? | 1 byte | scale | scale if numeric column |
| ???? | 2 bytes | ??? | |
| ???? | 1 byte | bitmask | low order bit indicates variable columns | | ???? | 1 byte | bitmask | low order bit indicates variable columns |
| ???? | 2 bytes | offset_F | Offset for fixed length columns | | ???? | 2 bytes | offset_F | Offset for fixed length columns |
| ???? | 2 bytes | col_len | Length of the column (0 if memo) | | ???? | 2 bytes | col_len | Length of the column (0 if memo) |
@ -396,8 +399,8 @@ next_pg field.
| ???? | 4 bytes | unknown | matches first unknown definition block | | ???? | 4 bytes | unknown | matches first unknown definition block |
| ???? | 2 bytes | col_num | Column Number | | ???? | 2 bytes | col_num | Column Number |
| ???? | 2 bytes | offset_V | Offset for variable length columns | | ???? | 2 bytes | offset_V | Offset for variable length columns |
| ???? | 2 bytes | col_num | Column Number (repeat) | | ???? | 2 bytes | col_num | Column Number (includes deleted columns) |
| ???? | 4 bytes | ??? | | | ???? | 4 bytes | ??? | prec/scale? verify |
| ???? | 1 byte | bitmask | low order bit indicates variable columns | | ???? | 1 byte | bitmask | low order bit indicates variable columns |
| ???? | 1 byte | ??? | seems to be 1 when variable len | | ???? | 1 byte | ??? | seems to be 1 when variable len |
| 0000 | 4 bytes | ??? | | | 0000 | 4 bytes | ??? | |
@ -470,7 +473,7 @@ Column Type may be one of the following (not complete):
Notes on deleted and added columns: (sort of Jet4 specific) Notes on deleted and added columns: (sort of Jet4 specific)
If a fixed length column is deleted the offset_F field will contain the offsets If a fixed length column is deleted the offset_F field will contain the offsets
of the original row definition. Thus is the number of columns on the row does of the original row definition. Thus if the number of columns on the row does
not match the number in the tdef, the offset_F field could be used to return not match the number in the tdef, the offset_F field could be used to return
the proper data. Columns are never really deleted in the row data. The deleted column will forever exist and be set to null for new rows. the proper data. Columns are never really deleted in the row data. The deleted column will forever exist and be set to null for new rows.
@ -488,7 +491,7 @@ Page Usage Maps
There are three uses for the page usage bitmaps. There is a global page usage There are three uses for the page usage bitmaps. There is a global page usage
stored on page 1 which tracks allocated pages throughout the database. stored on page 1 which tracks allocated pages throughout the database.
Tables store two page usage bitmaps. One is straight map of which pages are Tables store two page usage bitmaps. One is a straight map of which pages are
owned by the table. The second is a map of the pages owned by the table which owned by the table. The second is a map of the pages owned by the table which
have free space on them (used for inserting data). have free space on them (used for inserting data).

View File

@ -44,7 +44,7 @@ configure can be passed any of the following flags to turn on other
capabilities. capabilities.
--enable-sql will cause the SQL engine to be built, you must have flex --enable-sql will cause the SQL engine to be built, you must have flex
and bison installed for this option. and bison (or yacc) installed for this option.
--with-unixodbc specifies the location of the unixODBC driver manager and --with-unixodbc specifies the location of the unixODBC driver manager and
causes the ODBC driver to be built. causes the ODBC driver to be built.

8
README
View File

@ -22,8 +22,9 @@ The initial goal of these tools is to be able to extract data structures and
data from mdb files. This goal will of course expand over time as the file data from mdb files. This goal will of course expand over time as the file
format becomes more well understood. format becomes more well understood.
Files in libmdb are licensed under LGPL and the utilities under the GPL, see Files in libmdb, libmdbsql, and libmdbodbc are licensed under LGPL and the
COPYING.LIB and COPYING files respectively. utilities and gui program are under the GPL, see COPYING.LIB and COPYING files
respectively.
To install see the INSTALL file To install see the INSTALL file
@ -32,3 +33,6 @@ Check out http://mdbtools.sourceforge.net for CVS, mailing list and similar.
Brian Bruns Brian Bruns
brian@bruns.com brian@bruns.com
P.S. I, like many other free software authors enjoy receiving postcards from the
places users of my software live. So, if you enjoy the software and it has
helped you out, consider sending me one, eh? Just email me for my postal address.

View File

@ -84,6 +84,11 @@ AM_CONDITIONAL(HAVE_ODBC, test x$odbc = xtrue)
AC_SUBST(HAVE_ODBC) AC_SUBST(HAVE_ODBC)
AC_SUBST(ODBC_INC) AC_SUBST(ODBC_INC)
if test "x$odbc" = "xtrue"; then
AC_CHECK_LIB(odbcinst, SQLGetPrivateProfileString, [ODBCINSTLIB="-lodbcinst"
AC_DEFINE_UNQUOTED(HAVE_SQLGETPRIVATEPROFILESTRING, 1, [Define to 1 if you have the SQLGetPrivateProfileString function.])])
fi
dnl check for glib/gtk/gnome dnl check for glib/gtk/gnome
AM_PATH_GLIB_2_0(2.0.0) AM_PATH_GLIB_2_0(2.0.0)

View File

@ -22,12 +22,25 @@
#include <mdbtools.h> #include <mdbtools.h>
#include <mdbsql.h> #include <mdbsql.h>
#ifdef UNIXODBC
#include <sql.h>
#include <sqlext.h>
#include <odbcinst.h>
#elif defined(MDB_NO_DM)
#include <sql.h>
#include <sqlext.h>
#else /* IODBC */
#include "isql.h"
#include "isqlext.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
static char rcsid_sql_h [ ] = static char rcsid_sql_h [ ] =
"$Id: mdbodbc.h,v 1.2 2002/04/09 01:18:17 brianb Exp $"; "$Id: mdbodbc.h,v 1.3 2004/03/04 21:25:09 brianb Exp $";
static void *no_unused_sql_h_warn[]={rcsid_sql_h, no_unused_sql_h_warn}; static void *no_unused_sql_h_warn[]={rcsid_sql_h, no_unused_sql_h_warn};
struct _henv { struct _henv {

View File

@ -110,7 +110,8 @@ enum {
MDB_DEBUG_WRITE = 0x0002, MDB_DEBUG_WRITE = 0x0002,
MDB_DEBUG_USAGE = 0x0004, MDB_DEBUG_USAGE = 0x0004,
MDB_DEBUG_OLE = 0x0008, MDB_DEBUG_OLE = 0x0008,
MDB_USE_INDEX = 0x0010 MDB_DEBUG_ROW = 0x0010,
MDB_USE_INDEX = 0x0020
}; };
#define mdb_is_logical_op(x) (x == MDB_OR || \ #define mdb_is_logical_op(x) (x == MDB_OR || \
@ -196,6 +197,9 @@ typedef struct {
guint16 col_num_offset; guint16 col_num_offset;
guint16 tab_col_entry_size; guint16 tab_col_entry_size;
guint16 tab_free_map_offset; guint16 tab_free_map_offset;
guint16 tab_col_offset_var;
guint16 tab_col_offset_fixed;
guint16 tab_row_col_num_offset;
} MdbFormatConstants; } MdbFormatConstants;
typedef struct { typedef struct {
@ -248,6 +252,8 @@ typedef struct {
GPtrArray *idx_sarg_cache; GPtrArray *idx_sarg_cache;
unsigned char is_fixed; unsigned char is_fixed;
int query_order; int query_order;
/* col_num is the current column order,
* does not include deletes */
int col_num; int col_num;
int cur_value_start; int cur_value_start;
int cur_value_len; int cur_value_len;
@ -259,8 +265,12 @@ typedef struct {
int col_prec; int col_prec;
int col_scale; int col_scale;
MdbProperties *props; MdbProperties *props;
/* info needed for handling deleted/added columns */
int fixed_offset; int fixed_offset;
int var_col_num; int var_col_num;
/* row_col_num is the row column number order,
* including deleted columns */
int row_col_num;
} MdbColumn; } MdbColumn;
typedef struct _mdbsargtree { typedef struct _mdbsargtree {

View File

@ -241,7 +241,8 @@ int mdb_read_row(MdbTableDef *table, int row)
#if 1 #if 1
/* take advantage of mdb_crack_row() to clean up binding */ /* 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); col = g_ptr_array_index(table->columns,fields[i].colnum);
if (fields[i].is_fixed) { if (fields[i].is_fixed) {
rc = _mdb_attempt_bind(mdb, col, rc = _mdb_attempt_bind(mdb, col,

View File

@ -40,13 +40,16 @@ typedef struct {
guint16 col_num_offset; guint16 col_num_offset;
guint16 tab_col_entry_size; guint16 tab_col_entry_size;
guint16 tab_free_map_offset; guint16 tab_free_map_offset;
guint16 tab_col_offset_var;
guint16 tab_col_offset_fixed;
guint16 tab_row_col_num_offset;
} MdbFormatConstants; } MdbFormatConstants;
*/ */
MdbFormatConstants MdbJet4Constants = { 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 = { 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); static size_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg);

View File

@ -65,9 +65,13 @@ load_options()
if (!strcmp(opt, "debug_write")) opts |= MDB_DEBUG_WRITE; if (!strcmp(opt, "debug_write")) opts |= MDB_DEBUG_WRITE;
if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE; if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE;
if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE; if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE;
if (!strcmp(opt, "debug_row")) opts |= MDB_DEBUG_ROW;
if (!strcmp(opt, "debug_all")) { if (!strcmp(opt, "debug_all")) {
opts |= MDB_DEBUG_LIKE; opts |= MDB_DEBUG_LIKE;
opts |= MDB_DEBUG_WRITE; opts |= MDB_DEBUG_WRITE;
opts |= MDB_DEBUG_USAGE;
opts |= MDB_DEBUG_OLE;
opts |= MDB_DEBUG_ROW;
} }
opt = strtok(NULL,":"); opt = strtok(NULL,":");
} while (opt); } while (opt);

View File

@ -189,9 +189,24 @@ GPtrArray *mdb_read_columns(MdbTableDef *table)
read_pg_if(mdb, &cur_col, 0); read_pg_if(mdb, &cur_col, 0);
col.col_type = mdb->pg_buf[cur_col]; 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]; 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? */ /* FIXME: can this be right in Jet3 and Jet4? */
if (col.col_type == MDB_NUMERIC) { if (col.col_type == MDB_NUMERIC) {
read_pg_if(mdb, &cur_col, 11); 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 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] & col.is_fixed = mdb->pg_buf[cur_col + fmt->col_fixed_offset] &
0x01 ? 1 : 0; 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) { if (col.col_type != MDB_BOOL) {
read_pg_if(mdb, &cur_col, fmt->col_size_offset); // col_size_offset == 16 or 23 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]; low_byte = mdb->pg_buf[cur_col + fmt->col_size_offset];

View File

@ -87,20 +87,41 @@ MdbIndex *idx;
int int
mdb_crack_row4(MdbTableDef *table, int row_start, int row_end, MdbField *fields) mdb_crack_row4(MdbTableDef *table, int row_start, int row_end, MdbField *fields)
{ {
MdbCatalogEntry *entry = table->entry; MdbCatalogEntry *entry = table->entry;
MdbHandle *mdb = entry->mdb; MdbHandle *mdb = entry->mdb;
MdbColumn *col; MdbColumn *col;
int i, j; int i, j;
int var_cols = 0, fixed_cols = 0, num_cols, totcols = 0; int var_cols = 0, fixed_cols = 0, num_cols, totcols = 0;
int var_cols_found, fixed_cols_found, var_entry_pos; int var_cols_found, fixed_cols_found, var_entry_pos;
int col_start, next_col; int col_start, next_col;
unsigned char *nullmask; unsigned char *nullmask;
int bitmask_sz; int bitmask_sz;
int byte_num, bit_num; int byte_num, bit_num;
int eod, len; /* end of data */ 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); 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++) { for (i = 0; i < table->num_cols; i++) {
col = g_ptr_array_index (table->columns, i); col = g_ptr_array_index (table->columns, i);
if (mdb_is_fixed_col(col)) { 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 */ /* find the end of data pointer */
eod = mdb_pg_get_int16(mdb, row_end - 3 - var_cols*2 - bitmask_sz); 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; var_cols_found = 0;
totcols = 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[] */ /* loop through fixed columns and add values to fields[] */
/*
for (j=0;j<table->num_cols;j++) { for (j=0;j<table->num_cols;j++) {
col = g_ptr_array_index(table->columns,j); col = g_ptr_array_index(table->columns,j);
if (mdb_is_fixed_col(col) && ++fixed_cols_found <= fixed_cols) { 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 += col->col_size;
} }
} }
*/
col_start = mdb_pg_get_int16(mdb, row_end - 3 - bitmask_sz);
for (j=0;j<table->num_cols;j++) { for (j=0;j<table->num_cols;j++) {
col = g_ptr_array_index(table->columns,j); col = g_ptr_array_index(table->columns,j);
if (!mdb_is_fixed_col(col) && ++var_cols_found <= var_cols) { if (!mdb_is_fixed_col(col) && ++var_cols_found <= var_cols) {

View File

@ -3,7 +3,10 @@ SQLDIR = ../sql
SQLSOURCES = mdbsql.c parser.c lexer.c SQLSOURCES = mdbsql.c parser.c lexer.c
MDBDIR = ../libmdb MDBDIR = ../libmdb
MDBSOURCES = backend.c index.c money.c catalog.c kkd.c sargs.c \ 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 bin_PROGRAMS = unittest
lib_LTLIBRARIES = libmdbodbc.la lib_LTLIBRARIES = libmdbodbc.la
AM_CPPFLAGS = -I ../../include $(GLIB_CFLAGS) AM_CPPFLAGS = -I ../../include $(GLIB_CFLAGS)

View File

@ -1,5 +1,7 @@
/* MDB Tools - A library for reading MS Access database file /* 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -24,6 +26,12 @@
#include "connectparams.h" #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 #ifndef SYS_ODBC_INI
#define SYS_ODBC_INI "/etc/odbc.ini" #define SYS_ODBC_INI "/etc/odbc.ini"
#endif #endif
@ -444,4 +452,63 @@ static gboolean cleanup (gpointer key, gpointer value, gpointer user_data)
return TRUE; 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