mdbtools/include/mdbtools.h

516 lines
15 KiB
C
Raw Normal View History

2001-04-12 07:53:50 +08:00
/* MDB Tools - A library for reading MS Access database files
* Copyright (C) 2000 Brian Bruns
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _mdbtools_h_
#define _mdbtools_h_
#include <stdio.h>
2002-12-11 07:35:24 +08:00
#include <stdlib.h>
2004-02-16 10:00:45 +08:00
#include <stdarg.h>
2001-04-12 07:53:50 +08:00
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <glib.h>
2002-12-11 07:35:24 +08:00
#define MDB_DEBUG 0
#define MDB_PGSIZE 4096
2001-04-12 07:53:50 +08:00
#define MDB_MAX_OBJ_NAME 30
#define MDB_MAX_COLS 256
#define MDB_MAX_IDX_COLS 10
2001-04-12 07:53:50 +08:00
#define MDB_CATALOG_PG 18
#define MDB_MEMO_OVERHEAD 12
#define MDB_BIND_SIZE 16384
2001-04-12 07:53:50 +08:00
enum {
MDB_PAGE_DB = 0,
MDB_PAGE_DATA,
MDB_PAGE_TABLE,
MDB_PAGE_INDEX,
MDB_PAGE_LEAF,
MDB_PAGE_MAP
};
2001-04-12 07:53:50 +08:00
enum {
MDB_VER_JET3 = 0,
MDB_VER_JET4 = 1
};
enum {
MDB_FORM = 0,
MDB_TABLE,
MDB_MACRO,
MDB_SYSTEM_TABLE,
MDB_REPORT,
MDB_QUERY,
MDB_LINKED_TABLE,
MDB_MODULE,
MDB_RELATIONSHIP,
MDB_UNKNOWN_09,
MDB_UNKNOWN_0A,
MDB_DATABASE_PROPERTY,
MDB_ANY = -1
2001-04-12 07:53:50 +08:00
};
enum {
MDB_BOOL = 0x01,
MDB_BYTE = 0x02,
MDB_INT = 0x03,
MDB_LONGINT = 0x04,
MDB_MONEY = 0x05,
MDB_FLOAT = 0x06,
MDB_DOUBLE = 0x07,
MDB_SDATETIME = 0x08,
MDB_TEXT = 0x0a,
MDB_OLE = 0x0b,
MDB_MEMO = 0x0c,
2002-12-11 07:35:24 +08:00
MDB_REPID = 0x0f,
MDB_NUMERIC = 0x10
2001-04-12 07:53:50 +08:00
};
/* SARG operators */
enum {
MDB_OR = 1,
MDB_AND,
MDB_NOT,
MDB_EQUAL,
2001-04-12 07:53:50 +08:00
MDB_GT,
MDB_LT,
MDB_GTEQ,
MDB_LTEQ,
MDB_LIKE,
2001-04-12 07:53:50 +08:00
MDB_ISNULL,
MDB_NOTNULL
};
typedef enum {
MDB_TABLE_SCAN,
MDB_LEAF_SCAN,
MDB_INDEX_SCAN
} MdbStrategy;
2004-02-16 10:00:45 +08:00
enum {
MDB_DEBUG_LIKE = 0x0001,
MDB_DEBUG_WRITE = 0x0002,
MDB_DEBUG_USAGE = 0x0004,
MDB_DEBUG_OLE = 0x0008,
MDB_DEBUG_ROW = 0x0010,
MDB_USE_INDEX = 0x0020
2004-02-16 10:00:45 +08:00
};
#define mdb_is_logical_op(x) (x == MDB_OR || \
x == MDB_AND || \
x == MDB_NOT )
#define mdb_is_relational_op(x) (x == MDB_EQUAL || \
x == MDB_GT || \
x == MDB_LT || \
x == MDB_GTEQ || \
x == MDB_LTEQ || \
x == MDB_LIKE || \
x == MDB_ISNULL || \
x == MDB_NOTNULL )
2001-04-12 07:53:50 +08:00
enum {
MDB_ASC,
MDB_DESC
};
2003-01-02 06:29:39 +08:00
enum {
MDB_IDX_UNIQUE = 0x01,
MDB_IDX_IGNORENULLS = 0x02,
MDB_IDX_REQUIRED = 0x08
};
#define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4)
#define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3)
2001-04-12 07:53:50 +08:00
/* hash to store registered backends */
extern GHashTable *mdb_backends;
2001-04-12 07:53:50 +08:00
/* forward declarations */
typedef struct mdbindex MdbIndex;
2001-04-12 07:53:50 +08:00
typedef struct {
2004-01-06 08:42:07 +08:00
char *name;
unsigned char needs_length; /* or precision */
unsigned char needs_scale;
unsigned char needs_quotes;
} MdbBackendType;
typedef struct {
MdbBackendType *types_table;
2001-04-12 07:53:50 +08:00
} MdbBackend;
typedef struct {
gboolean collect;
unsigned long pg_reads;
} MdbStatistics;
2001-04-12 07:53:50 +08:00
typedef struct {
int fd;
2003-01-02 06:29:39 +08:00
gboolean writable;
2001-04-12 07:53:50 +08:00
char *filename;
guint32 jet_version;
guint32 db_key;
char db_passwd[14];
MdbBackend *default_backend;
char *backend_name;
MdbStatistics *stats;
/* free map */
int map_sz;
unsigned char *free_map;
/* reference count */
int refs;
2003-01-02 06:29:39 +08:00
} MdbFile;
/* offset to row count on data pages...version dependant */
typedef struct {
int pg_size;
guint16 row_count_offset;
2002-02-03 10:49:08 +08:00
guint16 tab_num_rows_offset;
guint16 tab_num_cols_offset;
guint16 tab_num_idxs_offset;
guint16 tab_num_ridxs_offset;
2002-12-20 14:18:10 +08:00
guint16 tab_usage_map_offset;
2002-02-03 10:49:08 +08:00
guint16 tab_first_dpg_offset;
guint16 tab_cols_start_offset;
guint16 tab_ridx_entry_size;
guint16 col_fixed_offset;
guint16 col_size_offset;
2003-01-02 06:29:39 +08:00
guint16 col_num_offset;
2002-02-03 10:49:08 +08:00
guint16 tab_col_entry_size;
2003-02-10 07:19:21 +08:00
guint16 tab_free_map_offset;
guint16 tab_col_offset_var;
guint16 tab_col_offset_fixed;
guint16 tab_row_col_num_offset;
2003-01-02 06:29:39 +08:00
} MdbFormatConstants;
typedef struct {
MdbFile *f;
guint32 cur_pg;
2003-01-02 06:29:39 +08:00
guint16 row_num;
unsigned int cur_pos;
unsigned char pg_buf[MDB_PGSIZE];
unsigned char alt_pg_buf[MDB_PGSIZE];
int num_catalog;
GPtrArray *catalog;
MdbBackend *default_backend;
char *backend_name;
MdbFormatConstants *fmt;
MdbStatistics *stats;
2001-04-12 07:53:50 +08:00
} MdbHandle;
typedef struct {
MdbHandle *mdb;
char object_name[MDB_MAX_OBJ_NAME+1];
int object_type;
unsigned long table_pg; /* misnomer since object may not be a table */
unsigned long kkd_pg;
unsigned int kkd_rowid;
2002-02-03 10:49:08 +08:00
int num_props;
2001-04-12 07:53:50 +08:00
GArray *props;
2002-02-03 10:49:08 +08:00
GArray *columns;
2001-04-12 07:53:50 +08:00
} MdbCatalogEntry;
typedef struct {
gchar *name;
GHashTable *hash;
} MdbProperties;
typedef union {
int i;
double d;
char s[256];
} MdbAny;
typedef struct {
char name[MDB_MAX_OBJ_NAME+1];
int col_type;
int col_size;
void *bind_ptr;
int *len_ptr;
GHashTable *properties;
int num_sargs;
GPtrArray *sargs;
GPtrArray *idx_sarg_cache;
unsigned char is_fixed;
int query_order;
/* col_num is the current column order,
* does not include deletes */
int col_num;
int cur_value_start;
int cur_value_len;
/* MEMO/OLE readers */
guint32 cur_blob_pg;
int cur_blob_row;
int chunk_size;
/* numerics only */
int col_prec;
int col_scale;
MdbProperties *props;
/* info needed for handling deleted/added columns */
int fixed_offset;
int var_col_num;
/* row_col_num is the row column number order,
* including deleted columns */
int row_col_num;
} MdbColumn;
typedef struct _mdbsargtree {
int op;
MdbColumn *col;
MdbAny value;
void *parent;
struct _mdbsargtree *left;
struct _mdbsargtree *right;
} MdbSargNode;
typedef struct {
guint32 pg;
int start_pos;
int offset;
int len;
guint16 idx_starts[2000];
unsigned char cache_value[256];
} MdbIndexPage;
typedef int MdbSargTreeFunc(MdbSargNode *, gpointer);
#define MDB_MAX_INDEX_DEPTH 10
typedef struct {
int cur_depth;
guint32 last_leaf_found;
int clean_up_mode;
MdbIndexPage pages[MDB_MAX_INDEX_DEPTH];
} MdbIndexChain;
2001-04-12 07:53:50 +08:00
typedef struct {
MdbCatalogEntry *entry;
char name[MDB_MAX_OBJ_NAME+1];
int num_cols;
GPtrArray *columns;
int num_rows;
int index_start;
int num_real_idxs;
int num_idxs;
GPtrArray *indices;
guint32 first_data_pg;
guint32 cur_pg_num;
guint32 cur_phys_pg;
2001-04-12 07:53:50 +08:00
int cur_row;
int noskip_del; /* don't skip deleted rows */
2002-03-17 10:40:16 +08:00
/* object allocation map */
guint32 map_base_pg;
2002-03-17 10:40:16 +08:00
int map_sz;
unsigned char *usage_map;
/* pages with free space left */
guint32 freemap_base_pg;
int freemap_sz;
unsigned char *free_usage_map;
/* query planner */
MdbSargNode *sarg_tree;
MdbStrategy strategy;
MdbIndex *scan_idx;
MdbHandle *mdbidx;
MdbIndexChain *chain;
MdbProperties *props;
2001-04-12 07:53:50 +08:00
} MdbTableDef;
struct mdbindex {
2001-04-12 07:53:50 +08:00
int index_num;
char name[MDB_MAX_OBJ_NAME+1];
unsigned char index_type;
guint32 first_pg;
2001-07-11 06:35:37 +08:00
int num_rows; /* number rows in index */
int num_keys;
short key_col_num[MDB_MAX_IDX_COLS];
unsigned char key_col_order[MDB_MAX_IDX_COLS];
2003-01-02 06:29:39 +08:00
unsigned char flags;
MdbTableDef *table;
};
2001-04-12 07:53:50 +08:00
typedef struct {
char name[MDB_MAX_OBJ_NAME+1];
} MdbColumnProp;
typedef struct {
void *value;
int siz;
int start;
unsigned char is_null;
unsigned char is_fixed;
int colnum;
int offset;
} MdbField;
2001-04-12 07:53:50 +08:00
typedef struct {
int op;
MdbAny value;
} MdbSarg;
/* mem.c */
extern void mdb_init();
extern void mdb_exit();
extern MdbHandle *mdb_alloc_handle();
extern void mdb_free_handle(MdbHandle *mdb);
extern void mdb_free_catalog(MdbHandle *mdb);
extern MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry);
extern void mdb_alloc_catalog(MdbHandle *mdb);
extern MdbFile *mdb_alloc_file();
extern void mdb_free_file(MdbFile *f);
extern void mdb_append_index(GPtrArray *indices, MdbIndex *in_idx);
extern MdbStatistics *mdb_alloc_stats(MdbHandle *mdb);
2001-04-12 07:53:50 +08:00
/* file.c */
extern size_t mdb_read_pg(MdbHandle *mdb, unsigned long pg);
extern size_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg);
extern unsigned char mdb_get_byte(unsigned char *buf, int offset);
extern int mdb_get_int16(unsigned char *buf, int offset);
extern gint32 mdb_get_int24(unsigned char *buf, int offset);
extern long mdb_get_int32(unsigned char *buf, int offset);
extern float mdb_get_single(unsigned char *buf, int offset);
extern double mdb_get_double(unsigned char *buf, int offset);
extern unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset);
extern int mdb_pg_get_int16(MdbHandle *mdb, int offset);
extern gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset);
extern long mdb_pg_get_int32(MdbHandle *mdb, int offset);
extern float mdb_pg_get_single(MdbHandle *mdb, int offset);
extern double mdb_pg_get_double(MdbHandle *mdb, int offset);
extern gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset);
2001-04-12 07:53:50 +08:00
extern MdbHandle *mdb_open(char *filename);
extern MdbHandle *_mdb_open(char *filename, gboolean writable);
extern void mdb_close(MdbHandle *mdb);
extern MdbHandle *mdb_clone_handle(MdbHandle *mdb);
2002-12-11 07:35:24 +08:00
extern void mdb_swap_pgbuf(MdbHandle *mdb);
extern long _mdb_get_int32(unsigned char *buf, int offset);
extern void mdb_free_tabledef(MdbTableDef *table);
2001-04-12 07:53:50 +08:00
/* catalog.c */
GPtrArray *mdb_read_catalog(MdbHandle *mdb, int obj_type);
2001-04-12 07:53:50 +08:00
extern void mdb_catalog_dump(MdbHandle *mdb, int obj_type);
extern int mdb_catalog_rows(MdbHandle *mdb);
extern MdbCatalogEntry *mdb_get_catalog_entry(MdbHandle *mdb, int rowid, MdbCatalogEntry *entry);
extern char *mdb_get_objtype_string(int obj_type);
extern void mdb_dump_catalog(MdbHandle *mdb, int obj_type);
2001-04-12 07:53:50 +08:00
/* table.c */
extern MdbTableDef *mdb_read_table(MdbCatalogEntry *entry);
extern GPtrArray *mdb_read_columns(MdbTableDef *table);
extern void mdb_table_dump(MdbCatalogEntry *entry);
extern guint16 read_pg_if_16(MdbHandle *mdb, int *cur_pos);
extern guint32 read_pg_if_32(MdbHandle *mdb, int *cur_pos);
extern int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset);
extern guint16 read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len);
2001-04-12 07:53:50 +08:00
/* data.c */
extern int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr);
2001-04-12 07:53:50 +08:00
extern void mdb_data_dump(MdbTableDef *table);
extern void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr);
extern int mdb_rewind_table(MdbTableDef *table);
extern int mdb_fetch_row(MdbTableDef *table);
extern int mdb_is_fixed_col(MdbColumn *col);
extern char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size);
extern int mdb_find_end_of_row(MdbHandle *mdb, int row);
extern int mdb_col_fixed_size(MdbColumn *col);
extern int mdb_col_disp_size(MdbColumn *col);
extern void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr);
extern int mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr);
extern int mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size);
2004-01-06 08:42:07 +08:00
extern void mdb_set_date_fmt(const char *);
2004-03-07 07:59:54 +08:00
extern int mdb_read_row(MdbTableDef *table, int row);
2001-04-12 07:53:50 +08:00
/* dump.c */
extern void buffer_dump(const unsigned char* buf, int start, int end);
/* backend.c */
extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type);
2004-01-06 08:42:07 +08:00
extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type);
2001-04-12 07:53:50 +08:00
extern void mdb_init_backends();
extern void mdb_register_backend(MdbBackend *backend, char *backend_name);
2004-04-12 22:33:56 +08:00
extern void mdb_remove_backends();
2001-04-12 07:53:50 +08:00
extern int mdb_set_default_backend(MdbHandle *mdb, char *backend_name);
extern char *mdb_get_relationships(MdbHandle *mdb);
2002-12-11 07:35:24 +08:00
/* sargs.c */
extern int mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields);
extern int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field);
extern void mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data);
extern int mdb_find_indexable_sargs(MdbSargNode *node, gpointer data);
extern int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg);
extern int mdb_test_string(MdbSargNode *node, char *s);
extern int mdb_test_int(MdbSargNode *node, gint32 i);
extern int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg);
/* index.c */
extern GPtrArray *mdb_read_indices(MdbTableDef *table);
extern void mdb_index_dump(MdbTableDef *table, MdbIndex *idx);
extern void mdb_index_scan_free(MdbTableDef *table);
extern int mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg);
extern int mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row);
extern void mdb_index_hash_text(guchar *text, guchar *hash);
extern void mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table);
extern int mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row);
/* stats.c */
extern void mdb_stats_on(MdbHandle *mdb);
extern void mdb_stats_off(MdbHandle *mdb);
extern void mdb_dump_stats(MdbHandle *mdb);
/* like.c */
extern int mdb_like_cmp(char *s, char *r);
/* write.c */
extern int mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields);
2004-02-06 10:34:20 +08:00
extern guint16 mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size);
extern int mdb_update_index(MdbTableDef *table, MdbIndex *idx, int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum);
extern int mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, int num_fields, MdbField *fields);
extern int mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size);
extern int mdb_pg_get_freespace(MdbHandle *mdb);
extern int mdb_update_row(MdbTableDef *table);
extern unsigned char *mdb_new_data_pg(MdbCatalogEntry *entry);
/* map.c */
extern guint32 mdb_map_find_next_freepage(MdbTableDef *table, int row_size);
/* props.c */
extern GPtrArray *mdb_read_props_list(gchar *kkd, int len);
extern void mdb_free_props(MdbProperties *props);
extern MdbProperties *mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len);
/* worktable.c */
extern MdbTableDef *mdb_create_temp_table(MdbHandle *mdb, char *name);
extern void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col);
2004-03-07 07:59:54 +08:00
extern void mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed);
extern void mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int column);
2004-02-16 10:00:45 +08:00
/* options.c */
extern int mdb_get_option(unsigned long optnum);
void mdb_debug(int klass, char *fmt, ...);
/* iconv.c */
extern int mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, int len, char *dest);
extern int mdb_ascii2unicode(MdbHandle *mdb, unsigned char *buf, int offset, int len, char *dest);
2001-04-12 07:53:50 +08:00
#endif /* _mdbtools_h_ */