mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-06-28 15:39:02 +08:00
odbc inst fixes.
deleted column fix for jet4 fixed columns
This commit is contained in:
parent
fb02e23b6b
commit
c5f4a8bb04
14
ChangeLog
14
ChangeLog
@ -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
17
HACKING
@ -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).
|
||||||
|
|
||||||
|
2
INSTALL
2
INSTALL
@ -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
8
README
@ -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.
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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];
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user