1 /* MDB Tools - A library for reading MS Access database files 2 * Copyright (C) 2000 Brian Bruns 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #ifdef JAVA 21 #include "javadefines.h" 22 #define MdbBackendType_STRUCT_ELEMENT(a,b,c,d) new MdbBackendType(a,b,c,d) 23 #else 24 #define MdbBackendType_STRUCT_ELEMENT(a,b,c,d) {a,b,c,d} 25 /* 26 ** functions to deal with different backend database engines 27 */ 28 # 29 #include "mdbtools.h" 30 31 #ifdef DMALLOC 32 #include "dmalloc.h" 33 #endif 34 35 #endif /* JAVA */ 36 37 static int is_init; 38 GHashTable *mdb_backends; 39 40 /* Access data types */ 41 static MdbBackendType mdb_access_types[] = { 42 MdbBackendType_STRUCT_ELEMENT("Unknown 0x00", 0,0,0), 43 MdbBackendType_STRUCT_ELEMENT("Boolean", 0,0,0), 44 MdbBackendType_STRUCT_ELEMENT("Byte", 0,0,0), 45 MdbBackendType_STRUCT_ELEMENT("Integer", 0,0,0), 46 MdbBackendType_STRUCT_ELEMENT("Long Integer", 0,0,0), 47 MdbBackendType_STRUCT_ELEMENT("Currency", 0,0,0), 48 MdbBackendType_STRUCT_ELEMENT("Single", 0,0,0), 49 MdbBackendType_STRUCT_ELEMENT("Double", 0,0,0), 50 MdbBackendType_STRUCT_ELEMENT("DateTime (Short)", 0,0,1), 51 MdbBackendType_STRUCT_ELEMENT("Unknown 0x09", 0,0,0), 52 MdbBackendType_STRUCT_ELEMENT("Text", 1,0,1), 53 MdbBackendType_STRUCT_ELEMENT("OLE", 1,0,1), 54 MdbBackendType_STRUCT_ELEMENT("Memo/Hyperlink",1,0,1), 55 MdbBackendType_STRUCT_ELEMENT("Unknown 0x0d",0,0,0), 56 MdbBackendType_STRUCT_ELEMENT("Unknown 0x0e",0,0,0), 57 MdbBackendType_STRUCT_ELEMENT("Replication ID",0,0,0), 58 MdbBackendType_STRUCT_ELEMENT("Numeric",1,1,0) 59 }; 60 61 /* Oracle data types */ 62 static MdbBackendType mdb_oracle_types[] = { 63 MdbBackendType_STRUCT_ELEMENT("Oracle_Unknown 0x00",0,0,0), 64 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 65 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 66 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 67 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 68 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 69 MdbBackendType_STRUCT_ELEMENT("FLOAT",0,0,0), 70 MdbBackendType_STRUCT_ELEMENT("FLOAT",0,0,0), 71 MdbBackendType_STRUCT_ELEMENT("DATE",0,0,0), 72 MdbBackendType_STRUCT_ELEMENT("Oracle_Unknown 0x09",0,0,0), 73 MdbBackendType_STRUCT_ELEMENT("VARCHAR2",1,0,1), 74 MdbBackendType_STRUCT_ELEMENT("BLOB",1,0,1), 75 MdbBackendType_STRUCT_ELEMENT("CLOB",1,0,1), 76 MdbBackendType_STRUCT_ELEMENT("Oracle_Unknown 0x0d",0,0,0), 77 MdbBackendType_STRUCT_ELEMENT("Oracle_Unknown 0x0e",0,0,0), 78 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 79 MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), 80 }; 81 82 /* Sybase/MSSQL data types */ 83 static MdbBackendType mdb_sybase_types[] = { 84 MdbBackendType_STRUCT_ELEMENT("Sybase_Unknown 0x00",0,0,0), 85 MdbBackendType_STRUCT_ELEMENT("bit",0,0,0), 86 MdbBackendType_STRUCT_ELEMENT("char",1,0,1), 87 MdbBackendType_STRUCT_ELEMENT("smallint",0,0,0), 88 MdbBackendType_STRUCT_ELEMENT("int",0,0,0), 89 MdbBackendType_STRUCT_ELEMENT("money",0,0,0), 90 MdbBackendType_STRUCT_ELEMENT("real",0,0,0), 91 MdbBackendType_STRUCT_ELEMENT("float",0,0,0), 92 MdbBackendType_STRUCT_ELEMENT("smalldatetime",0,0,0), 93 MdbBackendType_STRUCT_ELEMENT("Sybase_Unknown 0x09",0,0,0), 94 MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), 95 MdbBackendType_STRUCT_ELEMENT("varbinary",1,0,1), 96 MdbBackendType_STRUCT_ELEMENT("text",1,0,1), 97 MdbBackendType_STRUCT_ELEMENT("Sybase_Unknown 0x0d",0,0,0), 98 MdbBackendType_STRUCT_ELEMENT("Sybase_Unknown 0x0e",0,0,0), 99 MdbBackendType_STRUCT_ELEMENT("Sybase_Replication ID",0,0,0), 100 MdbBackendType_STRUCT_ELEMENT("numeric",1,1,0), 101 }; 102 103 /* Postgres data types */ 104 static MdbBackendType mdb_postgres_types[] = { 105 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x00",0,0,0), 106 MdbBackendType_STRUCT_ELEMENT("Bool",0,0,0), 107 MdbBackendType_STRUCT_ELEMENT("Int2",0,0,0), 108 MdbBackendType_STRUCT_ELEMENT("Int4",0,0,0), 109 MdbBackendType_STRUCT_ELEMENT("Int8",0,0,0), 110 MdbBackendType_STRUCT_ELEMENT("Money",0,0,0), 111 MdbBackendType_STRUCT_ELEMENT("Float4",0,0,0), 112 MdbBackendType_STRUCT_ELEMENT("Float8",0,0,0), 113 MdbBackendType_STRUCT_ELEMENT("Timestamp",0,0,0), 114 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x09",0,0,0), 115 MdbBackendType_STRUCT_ELEMENT("Char",1,0,1), 116 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0b",0,0,0), 117 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0c",0,0,0), 118 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0d",0,0,0), 119 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0e",0,0,0), 120 MdbBackendType_STRUCT_ELEMENT("Serial",0,0,0), 121 MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x10",0,0,0), 122 }; 123 /* MySQL data types */ 124 static MdbBackendType mdb_mysql_types[] = { 125 MdbBackendType_STRUCT_ELEMENT("Text",1,0,1), 126 MdbBackendType_STRUCT_ELEMENT("char",0,0,0), 127 MdbBackendType_STRUCT_ELEMENT("int",0,0,0), 128 MdbBackendType_STRUCT_ELEMENT("int",0,0,0), 129 MdbBackendType_STRUCT_ELEMENT("int",0,0,0), 130 MdbBackendType_STRUCT_ELEMENT("float",0,0,0), 131 MdbBackendType_STRUCT_ELEMENT("float",0,0,0), 132 MdbBackendType_STRUCT_ELEMENT("float",0,0,0), 133 MdbBackendType_STRUCT_ELEMENT("date",0,0,1), 134 MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), 135 MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), 136 MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), 137 MdbBackendType_STRUCT_ELEMENT("text",1,0,1), 138 MdbBackendType_STRUCT_ELEMENT("blob",0,0,0), 139 MdbBackendType_STRUCT_ELEMENT("text",1,0,1), 140 MdbBackendType_STRUCT_ELEMENT("numeric",1,1,0), 141 MdbBackendType_STRUCT_ELEMENT("numeric",1,1,0), 142 }; 143 #ifndef JAVA 144 static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data); 145 146 char *mdb_get_coltype_string(MdbBackend *backend, int col_type) 147 { 148 static char buf[16]; 149 150 if (col_type > 0x10 ) { 151 // return NULL; 152 snprintf(buf,sizeof(buf), "type %04x", col_type); 153 return buf; 154 } else { 155 return backend->types_table[col_type].name; 156 } 157 } 158 159 int mdb_coltype_takes_length(MdbBackend *backend, int col_type) 160 { 161 return backend->types_table[col_type].needs_length; 162 } 163 164 /** 165 * mdb_init_backends 166 * 167 * Initializes the mdb_backends hash and loads the builtin backends. 168 * Use mdb_remove_backends() to destroy this hash when done. 169 */ 170 void mdb_init_backends() 171 { 172 mdb_backends = g_hash_table_new(g_str_hash, g_str_equal); 173 174 mdb_register_backend(mdb_access_types, "access"); 175 mdb_register_backend(mdb_sybase_types, "sybase"); 176 mdb_register_backend(mdb_oracle_types, "oracle"); 177 mdb_register_backend(mdb_postgres_types, "postgres"); 178 mdb_register_backend(mdb_mysql_types, "mysql"); 179 } 180 void mdb_register_backend(MdbBackendType *backend_type, char *backend_name) 181 { 182 MdbBackend *backend = (MdbBackend *) g_malloc0(sizeof(MdbBackend)); 183 backend->types_table = backend_type; 184 g_hash_table_insert(mdb_backends, backend_name, backend); 185 } 186 187 /** 188 * mdb_remove_backends 189 * 190 * Removes all entries from and destroys the mdb_backends hash. 191 */ 192 void mdb_remove_backends() 193 { 194 g_hash_table_foreach_remove(mdb_backends, mdb_drop_backend, NULL); 195 g_hash_table_destroy(mdb_backends); 196 } 197 static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data) 198 { 199 MdbBackend *backend = (MdbBackend *)value; 200 g_free (backend); 201 return TRUE; 202 } 203 204 /** 205 * mdb_set_default_backend 206 * @mdb: Handle to open MDB database file 207 * @backend_name: Name of the backend to set as default 208 * 209 * Sets the default backend of the handle @mdb to @backend_name. 210 * 211 * Returns: 1 if successful, 0 if unsuccessful. 212 */ 213 int mdb_set_default_backend(MdbHandle *mdb, char *backend_name) 214 { 215 MdbBackend *backend; 216 217 backend = (MdbBackend *) g_hash_table_lookup(mdb_backends, backend_name); 218 if (backend) { 219 mdb->default_backend = backend; 220 mdb->backend_name = (char *) g_strdup(backend_name); 221 is_init = 0; 222 return 1; 223 } else { 224 return 0; 225 } 226 } 227 228 /** 229 * mdb_get_relationships 230 * @mdb: Handle to open MDB database file 231 * 232 * Generates relationships by reading the MSysRelationships table. 233 * 'szColumn' contains the column name of the child table. 234 * 'szObject' contains the table name of the child table. 235 * 'szReferencedColumn' contains the column name of the parent table. 236 * 'szReferencedObject' contains the table name of the parent table. 237 * 238 * Returns: a string stating that relationships are not supported for the 239 * selected backend, or a string containing SQL commands for setting up 240 * the relationship, tailored for the selected backend. The caller is 241 * responsible for freeing this string. 242 */ 243 char *mdb_get_relationships(MdbHandle *mdb) 244 { 245 unsigned int i; 246 gchar *text = NULL; /* String to be returned */ 247 static char *bound[4]; /* Bound values */ 248 static MdbTableDef *table; /* Relationships table */ 249 int backend = 0; /* Backends: 1=oracle */ 250 251 if (strncmp(mdb->backend_name,"oracle",6) == 0) { 252 backend = 1; 253 } else { 254 if (is_init == 0) { /* the first time through */ 255 is_init = 1; 256 return (char *) g_strconcat( 257 "-- relationships are not supported for ", 258 mdb->backend_name, NULL); 259 } else { /* the second time through */ 260 is_init = 0; 261 return NULL; 262 } 263 } 264 265 if (is_init == 0) { 266 table = mdb_read_table_by_name(mdb, "MSysRelationships", MDB_TABLE); 267 if ((!table) || (table->num_rows == 0)) { 268 return NULL; 269 } 270 271 mdb_read_columns(table); 272 for (i=0;i<4;i++) { 273 bound[i] = (char *) g_malloc0(MDB_BIND_SIZE); 274 } 275 mdb_bind_column_by_name(table, "szColumn", bound[0], NULL); 276 mdb_bind_column_by_name(table, "szObject", bound[1], NULL); 277 mdb_bind_column_by_name(table, "szReferencedColumn", bound[2], NULL); 278 mdb_bind_column_by_name(table, "szReferencedObject", bound[3], NULL); 279 mdb_rewind_table(table); 280 281 is_init = 1; 282 } 283 else if (table->cur_row >= table->num_rows) { /* past the last row */ 284 for (i=0;i<4;i++) 285 g_free(bound[i]); 286 is_init = 0; 287 return NULL; 288 } 289 290 if (!mdb_fetch_row(table)) { 291 for (i=0;i<4;i++) 292 g_free(bound[i]); 293 is_init = 0; 294 return NULL; 295 } 296 297 switch (backend) { 298 case 1: /* oracle */ 299 text = g_strconcat("alter table ", bound[1], 300 " add constraint ", bound[3], "_", bound[1], 301 " foreign key (", bound[0], ")" 302 " references ", bound[3], "(", bound[2], ")", NULL); 303 break; 304 } 305 306 return (char *)text; 307 } 308 #endif 309