diff --git a/doc/mdb-schema.txt b/doc/mdb-schema.txt index 1e2d867..f7e60fd 100644 --- a/doc/mdb-schema.txt +++ b/doc/mdb-schema.txt @@ -1,7 +1,7 @@ NAME mdb-schema - Generate schema creation DDL SYNOPSIS - mdb-schema [-T ] [] + mdb-schema [options] [] DESCRIPTION mdb-schema is a utility program distributed with MDB Tools. @@ -9,8 +9,35 @@ DESCRIPTION It produces DDL (data definition language) output for the given database. This can be passed to another database to create a replica of the original access table format. OPTIONS - -T Single table option. Create schema for this table only. - backend Specifies target DDL dialect. Supported values are access, sybase, oracle, and postgres. If not specified the generated DDL will be in access format. + -T
, --table
Single table option. Create schema for this table only. Default is to export all tables. + --drop-table Issue DROP TABLE statement. + --no-drop-table Don't issue DROP TABLE statement. This is the default. + --not-null Issue NOT NULL constraints. This is the default. + --no-not-null Don't issue NOT NULL constraints. + --not-empty Issue CHECK <> '' constraints. + --no-not-empty Don't issue CHECK <> '' constraints. This is the default. + --indexes Export INDEXes. This is the default. + --no-indexes Don't export INDEXes. + --relations Export foreign keys constraints. This is the default. + --no-relations Don't export foreign keys constraints. + -S, --sanitize Replace non alphanumric characters by underscore. + --no-sanitize Don't replace non alphanumric characters by underscore. This is the default. + + backend Specifies target DDL dialect. Supported values are access, sybase, oracle, postgres, and mysql. If not specified the generated DDL will be in access format. + +ENVIRONMENT + MDB_JET3_CHARSET Defines the charset of the input JET3 (access 97) file. Default is CP1252. See iconv(1). + MDBICONV Defines the output charset to use for the SQL file. Default is UTF-8. mdbtools must have been compiled with iconv. + MDBOPTS semi-column separated list of options: + * use_index + * no_memo + * debug_like + * debug_write + * debug_usage + * debug_ole + * debug_row + * debug_props + * debug_all is a shortcut for all debug_* options NOTES @@ -18,7 +45,7 @@ HISTORY mdb-schema first appeared in MDB Tools 0\.1 AUTHORS - The mdb-schema utility was written by Brian Bruns + The mdb-schema utility was written by Brian Bruns and others. BUGS Relationships and other features may not be supported by all databases. diff --git a/include/mdbtools.h b/include/mdbtools.h index 0d3ed1f..781c95d 100644 --- a/include/mdbtools.h +++ b/include/mdbtools.h @@ -83,7 +83,7 @@ enum { MDB_MONEY = 0x05, MDB_FLOAT = 0x06, MDB_DOUBLE = 0x07, - MDB_SDATETIME = 0x08, + MDB_DATETIME = 0x08, MDB_BINARY = 0x09, MDB_TEXT = 0x0a, MDB_OLE = 0x0b, @@ -155,12 +155,15 @@ enum { /* export schema options */ enum { - MDB_SHEXP_DROPTABLE = 0x01, - MDB_SHEXP_INDEXES = 0x02, - MDB_SHEXP_RELATIONS = 0x04, - MDB_SHEXP_SANITIZE = 0x08 + MDB_SHEXP_DROPTABLE = 1<<0, /* issue drop table during export */ + MDB_SHEXP_CST_NOTNULL = 1<<1, /* generate NOT NULL constraints */ + MDB_SHEXP_CST_NOTEMPTY = 1<<2, /* <>'' constraints */ + MDB_SHEXP_COMMENTS = 1<<3, /* export comments on columns & tables */ + MDB_SHEXP_INDEXES = 1<<4, /* export indices */ + MDB_SHEXP_RELATIONS = 1<<5, /* export relation (foreign keys) */ + MDB_SHEXP_SANITIZE = 1<<6 /* clean up names */ }; -#define MDB_SHEXP_DEFAULT (MDB_SHEXP_DROPTABLE | MDB_SHEXP_INDEXES | MDB_SHEXP_RELATIONS) +#define MDB_SHEXP_DEFAULT (MDB_SHEXP_CST_NOTNULL | MDB_SHEXP_COMMENTS | MDB_SHEXP_INDEXES | MDB_SHEXP_RELATIONS) #define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4) #define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3) @@ -177,8 +180,16 @@ typedef struct { } MdbBackendType; typedef struct { - MdbBackendType *types_table; - char* (*quote_name)(const char*); + guint32 capabilities; /* see MDB_SHEXP_* */ + MdbBackendType *types_table; + MdbBackendType *type_shortdate; + MdbBackendType *type_autonum; + const char *charset_statement; + const char *drop_statement; + const char *constaint_not_empty_statement; + const char *column_comment_statement; + const char *table_comment_statement; + gchar* (*quote_schema_name)(const gchar*, const gchar*); } MdbBackend; typedef struct { @@ -266,7 +277,9 @@ typedef union { char s[256]; } MdbAny; +struct S_MdbTableDef; /* forward definition */ typedef struct { + struct S_MdbTableDef *table; char name[MDB_MAX_OBJ_NAME+1]; int col_type; int col_size; @@ -329,7 +342,7 @@ typedef struct { MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; } MdbIndexChain; -typedef struct { +typedef struct S_MdbTableDef { MdbCatalogEntry *entry; char name[MDB_MAX_OBJ_NAME+1]; unsigned int num_cols; @@ -468,10 +481,13 @@ extern void buffer_dump(const void *buf, int start, size_t len); /* backend.c */ extern char* sanitize_name(const char* name); -extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type); -extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); +extern char* mdb_get_coltype_string(MdbBackend *backend, int col_type); /* obsolete */ +extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); /* obsolete */ +extern const MdbBackendType* mdb_get_colbacktype(const MdbColumn *col); +extern const char* mdb_get_colbacktype_string(const MdbColumn *col); +extern int mdb_colbacktype_takes_length(const MdbColumn *col); extern void mdb_init_backends(); -extern void mdb_register_backend(MdbBackendType *backend, char* (*quote_name)(const char*), char *backend_name); +extern void mdb_register_backend(char *backend_name, guint32 capabilities, MdbBackendType *backend_type, MdbBackendType *type_shortdate, MdbBackendType *type_autonum, const char *charset_statement, const char *drop_statement, const char *constaint_not_empty_statement, const char *column_comment_statement, const char *table_comment_statement, gchar* (*quote_schema_name)(const gchar*, const gchar*)); extern void mdb_remove_backends(); extern int mdb_set_default_backend(MdbHandle *mdb, const char *backend_name); extern void mdb_print_schema(MdbHandle *mdb, FILE *outfile, char *tabname, char *namespace, guint32 export_options); @@ -546,6 +562,7 @@ extern int mdb_unicode2ascii(MdbHandle *mdb, char *src, size_t slen, char *dest, extern int mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t slen, char *dest, size_t dlen); extern void mdb_iconv_init(MdbHandle *mdb); extern void mdb_iconv_close(MdbHandle *mdb); +extern const char* mdb_target_charset(MdbHandle *mdb); #ifdef __cplusplus } diff --git a/src/gmdb2/gladefiles/gmdb-schema.glade b/src/gmdb2/gladefiles/gmdb-schema.glade index 72b40cb..85f7b24 100644 --- a/src/gmdb2/gladefiles/gmdb-schema.glade +++ b/src/gmdb2/gladefiles/gmdb-schema.glade @@ -1,443 +1,433 @@ - - - + - - - - True - Export Schema - GTK_WINDOW_TOPLEVEL - GTK_WIN_POS_NONE - False - True - False - True - - - - True - False - 0 - - - - True - GTK_BUTTONBOX_END - - - - True - True - True - gtk-help - True - GTK_RELIEF_NORMAL - -11 - - - - - - - True - True - True - gtk-cancel - True - GTK_RELIEF_NORMAL - -6 - - - - - - - True - True - True - GTK_RELIEF_NORMAL - -5 - - - - - True - 0.5 - 0.5 - 0 - 0 - - - - True - False - 2 - - - - True - gtk-convert - 4 - 0.5 - 0.5 - 0 - 0 - - - 0 - False - False - - - - - - True - _Export - True - False - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - - - 0 - False - False - - - - - - - - - - - 0 - False - True - GTK_PACK_END - - - - - - 33 - True - 5 - 2 - False - 8 - 30 - - - - True - <b>Table:</b> - False - True - GTK_JUSTIFY_RIGHT - False - False - 0 - 0.5 - 0 - 0 - - - 0 - 1 - 1 - 2 - fill - - - - - - - True - <b>Schema Dialect:</b> - False - True - GTK_JUSTIFY_RIGHT - False - False - 0 - 0.5 - 0 - 0 - - - 0 - 1 - 2 - 3 - fill - - - - - - - True - False - True - False - True - False - - - - True - True - True - True - 0 - Access - True - * - False - - - - - - True - GTK_SELECTION_BROWSE - - - - - 1 - 2 - 1 - 2 - - - - - - - True - True - False - False - True - False - - - - True - True - False - True - 0 - Access - True - * - False - - - - - - True - GTK_SELECTION_BROWSE - - - - True - True - Access - - - - - - True - True - Oracle - - - - - - True - True - Sybase - - - - - - True - True - MS SQL Server - - - - - - True - True - PostgreSQL - - - - - - True - True - MySQL - - - - - - - 1 - 2 - 2 - 3 - - - - - - - True - True - Include Relationships - True - GTK_RELIEF_NORMAL - True - False - True - - - 1 - 2 - 3 - 4 - fill - - - - - - - True - <b>Options:</b> - False - True - GTK_JUSTIFY_RIGHT - False - False - 0 - 0.5 - 0 - 0 - - - 0 - 1 - 3 - 4 - fill - - - - - - - True - True - Include Drop Table commands - True - GTK_RELIEF_NORMAL - True - False - True - - - 1 - 2 - 4 - 5 - fill - - - - - - - True - <b>File Name:</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - - - 0 - 1 - 0 - 1 - fill - - - - - - - True - 10 - False - False - - - - True - True - True - True - 0 - - True - * - False - - - - - 1 - 2 - 0 - 1 - - - - - - 0 - True - False - - - - - - + + + + + + True + Export Schema + normal + + + True + + + True + 33 + 9 + 2 + 30 + 8 + + + True + 0 + <b>Table:</b> + True + right + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + <b>Schema Dialect:</b> + True + right + + + 2 + 3 + GTK_FILL + + + + + + True + False + + + True + True + Access + + + 0 + + + + + True + browse + + + + + 1 + 2 + 1 + 2 + + + + + + True + False + False + True + + + True + True + False + Access + + + 0 + + + + + True + browse + + + True + True + Access + + + + + True + True + Oracle + + + + + True + True + Sybase + + + + + True + True + MS SQL Server + + + + + True + True + PostgreSQL + + + + + True + True + MySQL + + + + + + + 1 + 2 + 2 + 3 + + + + + + True + 0 + <b>Options:</b> + True + right + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + <b>File Name:</b> + True + + + GTK_FILL + + + + + + True + 10 + + + True + True + + + + + 1 + 2 + + + + + + Include Drop Table commands + True + True + False + True + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + + Include Not Null constraints + True + True + False + True + True + True + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + + Include Relationships + True + True + False + True + True + True + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + + Include indexes + True + True + False + True + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + + Include Not Empty constraints + True + True + False + True + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + + Include description on tables and columns + True + True + False + True + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + + + + + + + + + + + + + + + + + False + 2 + + + + + True + end + + + gtk-help + -11 + True + True + True + False + True + + + + False + False + 0 + + + + + gtk-cancel + -6 + True + True + True + False + True + + + + False + False + 1 + + + + + -5 + True + True + True + False + + + + True + 0 + 0 + + + True + 2 + + + True + gtk-convert + + + False + False + 0 + + + + + True + _Export + True + + + False + False + 1 + + + + + + + + + False + False + 2 + + + + + False + end + 0 + + + + + diff --git a/src/gmdb2/schema.c b/src/gmdb2/schema.c index 1b805ce..19d9746 100644 --- a/src/gmdb2/schema.c +++ b/src/gmdb2/schema.c @@ -28,12 +28,23 @@ GladeXML *schemawin_xml; static gchar backend[100]; static gchar tabname[MDB_MAX_OBJ_NAME+1]; static gchar file_path[PATH_MAX+1]; -static gchar relation; -static gchar drops; static guint32 export_options; #define ALL_TABLES "(All Tables)" +static struct { + const char *option_name; + guint32 option_value; +} capabilities_xlt[] = { + { "drop_checkbox", MDB_SHEXP_DROPTABLE }, + { "cstnotnull_checkbox", MDB_SHEXP_CST_NOTNULL }, + { "cstnotempty_checkbox", MDB_SHEXP_CST_NOTEMPTY}, + { "comments_checkbox", MDB_SHEXP_COMMENTS}, + { "index_checkbox", MDB_SHEXP_INDEXES}, + { "rel_checkbox", MDB_SHEXP_RELATIONS} +}; +#define n_capabilities (sizeof(capabilities_xlt)/sizeof(capabilities_xlt[0])) + static void gmdb_schema_export() { @@ -65,6 +76,7 @@ void gmdb_schema_export_cb(GtkWidget *w, gpointer data) { GtkWidget *schemawin, *combo, *checkbox, *entry; +int i; schemawin = glade_xml_get_widget (schemawin_xml, "schema_dialog"); @@ -85,19 +97,66 @@ GtkWidget *schemawin, *combo, *checkbox, *entry; else if (!strcmp(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),"MySQL")) strcpy(backend,"mysql"); else strcpy(backend,"access"); - export_options = MDB_SHEXP_DEFAULT & ~ (MDB_SHEXP_RELATIONS|MDB_SHEXP_DROPTABLE); - checkbox = glade_xml_get_widget (schemawin_xml, "rel_checkbox"); - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox))) - export_options |= MDB_SHEXP_RELATIONS; - checkbox = glade_xml_get_widget (schemawin_xml, "drop_checkbox"); - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox))) - export_options |= MDB_SHEXP_DROPTABLE; - // TODO add support for other options + /* make sure unknown default options are enabled */ + export_options = MDB_SHEXP_DEFAULT; + for (i=0; ientry)); + if (!strcmp(backend_name,"Oracle")) strcpy(backend,"oracle"); + else if (!strcmp(backend_name,"Sybase")) strcpy(backend,"sybase"); + else if (!strcmp(backend_name,"MS SQL Server")) strcpy(backend,"sybase"); + else if (!strcmp(backend_name,"PostgreSQL")) strcpy(backend,"postgres"); + else if (!strcmp(backend_name,"MySQL")) strcpy(backend,"mysql"); + else strcpy(backend,"access"); + + backend_obj = (MdbBackend *) g_hash_table_lookup(mdb_backends, backend); + //printf("backend_obj: %p\n", backend_obj); + + capabilities = backend_obj->capabilities; + //printf("backend capabilities: 0x%04x\n", capabilities); + for (i=0; icol_num+1); strcpy(row[2],col->name); - strcpy(row[3], mdb_get_coltype_string(mdb->default_backend, col->col_type)); + strcpy(row[3], mdb_get_colbacktype_string(col)); sprintf(row[4],"%d",col->col_size); if (col->is_fixed) { strcpy(row[5],"No"); diff --git a/src/libmdb/backend.c b/src/libmdb/backend.c index 99092f0..7dce76b 100644 --- a/src/libmdb/backend.c +++ b/src/libmdb/backend.c @@ -37,7 +37,7 @@ static int is_init; GHashTable *mdb_backends; - /* Access data types */ +/* Access data types */ static MdbBackendType mdb_access_types[] = { MdbBackendType_STRUCT_ELEMENT("Unknown 0x00", 0,0,0), MdbBackendType_STRUCT_ELEMENT("Boolean", 0,0,0), @@ -47,7 +47,7 @@ static MdbBackendType mdb_access_types[] = { MdbBackendType_STRUCT_ELEMENT("Currency", 0,0,0), MdbBackendType_STRUCT_ELEMENT("Single", 0,0,0), MdbBackendType_STRUCT_ELEMENT("Double", 0,0,0), - MdbBackendType_STRUCT_ELEMENT("DateTime (Short)", 0,0,1), + MdbBackendType_STRUCT_ELEMENT("DateTime", 0,0,1), MdbBackendType_STRUCT_ELEMENT("Binary", 0,0,0), MdbBackendType_STRUCT_ELEMENT("Text", 1,0,1), MdbBackendType_STRUCT_ELEMENT("OLE", 1,0,1), @@ -68,8 +68,8 @@ static MdbBackendType mdb_oracle_types[] = { MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), MdbBackendType_STRUCT_ELEMENT("FLOAT",0,0,0), MdbBackendType_STRUCT_ELEMENT("FLOAT",0,0,0), - MdbBackendType_STRUCT_ELEMENT("DATE",0,0,0), - MdbBackendType_STRUCT_ELEMENT("Oracle_Unknown 0x09",0,0,0), + MdbBackendType_STRUCT_ELEMENT("TIMESTAMP",0,0,0), + MdbBackendType_STRUCT_ELEMENT("BINARY",0,0,0), MdbBackendType_STRUCT_ELEMENT("VARCHAR2",1,0,1), MdbBackendType_STRUCT_ELEMENT("BLOB",1,0,1), MdbBackendType_STRUCT_ELEMENT("CLOB",1,0,1), @@ -78,6 +78,8 @@ static MdbBackendType mdb_oracle_types[] = { MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), MdbBackendType_STRUCT_ELEMENT("NUMBER",1,0,0), }; +static MdbBackendType mdb_oracle_shortdate_type = + MdbBackendType_STRUCT_ELEMENT("DATE",0,0,0); /* Sybase/MSSQL data types */ static MdbBackendType mdb_sybase_types[] = { @@ -99,6 +101,8 @@ static MdbBackendType mdb_sybase_types[] = { MdbBackendType_STRUCT_ELEMENT("Sybase_Replication ID",0,0,0), MdbBackendType_STRUCT_ELEMENT("numeric",1,1,0), }; +static MdbBackendType mdb_sybase_shortdate_type = + MdbBackendType_STRUCT_ELEMENT("DATE",0,0,0); /* Postgres data types */ static MdbBackendType mdb_postgres_types[] = { @@ -113,13 +117,18 @@ static MdbBackendType mdb_postgres_types[] = { MdbBackendType_STRUCT_ELEMENT("TIMESTAMP WITHOUT TIME ZONE",0,0,0), MdbBackendType_STRUCT_ELEMENT("BYTEA",0,0,0), MdbBackendType_STRUCT_ELEMENT("VARCHAR",1,0,1), - MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0b",0,0,0), + MdbBackendType_STRUCT_ELEMENT("BYTEA",0,0,0), MdbBackendType_STRUCT_ELEMENT("TEXT",0,0,0), MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0d",0,0,0), MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x0e",0,0,0), MdbBackendType_STRUCT_ELEMENT("UUID",0,0,0), MdbBackendType_STRUCT_ELEMENT("Postgres_Unknown 0x10",0,0,0), }; +static MdbBackendType mdb_postgres_shortdate_type = + MdbBackendType_STRUCT_ELEMENT("DATE",0,0,0); +static MdbBackendType mdb_postgres_serial_type = + MdbBackendType_STRUCT_ELEMENT("SERIAL",0,0,0); + /* MySQL data types */ static MdbBackendType mdb_mysql_types[] = { MdbBackendType_STRUCT_ELEMENT("Text",1,0,1), @@ -130,7 +139,7 @@ static MdbBackendType mdb_mysql_types[] = { MdbBackendType_STRUCT_ELEMENT("float",0,0,0), MdbBackendType_STRUCT_ELEMENT("float",0,0,0), MdbBackendType_STRUCT_ELEMENT("float",0,0,0), - MdbBackendType_STRUCT_ELEMENT("date",0,0,1), + MdbBackendType_STRUCT_ELEMENT("datetime",0,0,1), MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), MdbBackendType_STRUCT_ELEMENT("varchar",1,0,1), @@ -140,6 +149,8 @@ static MdbBackendType mdb_mysql_types[] = { MdbBackendType_STRUCT_ELEMENT("numeric",1,1,0), MdbBackendType_STRUCT_ELEMENT("numeric",1,1,0), }; +static MdbBackendType mdb_mysql_shortdate_type = + MdbBackendType_STRUCT_ELEMENT("date",0,0,0); #ifndef JAVA static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data); @@ -166,52 +177,155 @@ char* sanitize_name(const char* str) return result; } -static char* quote_name_with_brackets(const char* name) -{ - char *result = malloc(strlen(name)+3); - sprintf(result, "[%s]", name); - return result; -} +static gchar* +quote_generic(const gchar *value, gchar quote_char, gchar escape_char) { + gchar *result, *pr; + unsigned char c; -static char* quote_name_with_dquotes(const char* name) -{ - char *result = malloc(2*strlen(name)+3); - char *p = result; - *p++ = '"'; - while (*name) { - *p++ = *name; - if (*name == '"') - *p++ = *name; /* double it */ - name ++; + pr = result = g_malloc(1+4*strlen(value)+2); // worst case scenario + + *pr++ = quote_char; + while ((c=*(unsigned char*)value++)) { + if (c<32) { + sprintf(pr, "\\%03o", c); + pr+=4; + continue; + } + else if (c == quote_char) { + *pr++ = escape_char; + } + *pr++ = c; } - *p++ = '"'; - *p++ = 0; + *pr++ = quote_char; + *pr++ = '\0'; return result; } - -static char* quote_name_with_rquotes(const char* name) -{ - return (char*)g_strconcat("`", name, "`", NULL); +static gchar* +quote_schema_name_bracket_merge(const gchar* schema, const gchar *name) { + if (schema) + return g_strconcat("[", schema, "_", name, "]", NULL); + else + return g_strconcat("[", name, "]", NULL); } -char *mdb_get_coltype_string(MdbBackend *backend, int col_type) +/* + * For backends that really does support schema + * returns "name" or "schema"."name" + */ +static gchar* +quote_schema_name_dquote(const gchar* schema, const gchar *name) { + if (schema) { + gchar *frag1 = quote_generic(schema, '"', '"'); + gchar *frag2 = quote_generic(name, '"', '"'); + gchar *result = g_strconcat(frag1, ".", frag2, NULL); + g_free(frag1); + g_free(frag2); + return result; + } + return quote_generic(name, '"', '"'); +} + +/* + * For backends that really do NOT support schema + * returns "name" or "schema_name" + */ +static gchar* +quote_schema_name_dquote_merge(const gchar* schema, const gchar *name) +{ + if (schema) { + gchar *combined = g_strconcat(schema, "_", name, NULL); + gchar *result = quote_generic(combined, '"', '"'); + g_free(combined); + return result; + } + return quote_generic(name, '"', '"'); +} + +static gchar* +quote_schema_name_rquotes_merge(const gchar* schema, const gchar *name) +{ + if (schema) { + gchar *combined = g_strconcat(schema, "_", name, NULL); + gchar *result = quote_generic(combined, '`', '`'); + g_free(combined); + return result; + } + return quote_generic(name, '`', '`'); +} + +static gchar* +quote_with_squotes(gchar* value) +{ + return quote_generic(value, '\'', '\''); +} + +/* deprecated */ char * +mdb_get_coltype_string(MdbBackend *backend, int col_type) +{ + static int warn_deprecated = 0; static char buf[16]; + if (!warn_deprecated) { + warn_deprecated = 1; + fprintf(stderr, "mdb_get_coltype_string is deprecated. Use mdb_get_colbacktype_string.\n"); + } if (col_type > 0x10 ) { // return NULL; snprintf(buf,sizeof(buf), "type %04x", col_type); return buf; - } else { + } else return backend->types_table[col_type].name; - } } -int mdb_coltype_takes_length(MdbBackend *backend, int col_type) +/* deprecated */ int +mdb_coltype_takes_length(MdbBackend *backend, int col_type) { + static int warn_deprecated = 0; + if (!warn_deprecated) { + warn_deprecated = 1; + fprintf(stderr, "mdb_coltype_takes_length is deprecated. Use mdb_colbacktype_takes_length.\n"); + } return backend->types_table[col_type].needs_length; } + +const MdbBackendType* +mdb_get_colbacktype(const MdbColumn *col) { + MdbBackend *backend = col->table->entry->mdb->default_backend; + int col_type = col->col_type; + if (col_type > 0x10 ) + return NULL; + if (col_type == MDB_LONGINT && col->is_long_auto && backend->type_autonum) + return backend->type_autonum; + if (col_type == MDB_DATETIME && backend->type_shortdate) { + const char *format = mdb_col_get_prop(col, "Format"); + if (format && !strcmp(format, "Short Date")) + return backend->type_shortdate; + } + return &backend->types_table[col_type]; +} + +const char * +mdb_get_colbacktype_string(const MdbColumn *col) +{ + const MdbBackendType *type = mdb_get_colbacktype(col); + if (!type) { + // return NULL; + static char buf[16]; + snprintf(buf,sizeof(buf), "type %04x", col->col_type); + return buf; + } + return type->name; +} +int +mdb_colbacktype_takes_length(const MdbColumn *col) +{ + const MdbBackendType *type = mdb_get_colbacktype(col); + if (!type) return 0; + return type->needs_length; +} + /** * mdb_init_backends * @@ -222,17 +336,65 @@ void mdb_init_backends() { mdb_backends = g_hash_table_new(g_str_hash, g_str_equal); - mdb_register_backend(mdb_access_types, quote_name_with_brackets, "access"); - mdb_register_backend(mdb_sybase_types, quote_name_with_dquotes, "sybase"); - mdb_register_backend(mdb_oracle_types, quote_name_with_dquotes, "oracle"); - mdb_register_backend(mdb_postgres_types, quote_name_with_dquotes, "postgres"); - mdb_register_backend(mdb_mysql_types, quote_name_with_rquotes, "mysql"); + mdb_register_backend("access", + MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_SANITIZE, + mdb_access_types, NULL, NULL, + "-- That file uses encoding %s\n", + "DROP TABLE %s;\n", + NULL, + NULL, + NULL, + quote_schema_name_bracket_merge); + mdb_register_backend("sybase", + MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_CST_NOTEMPTY|MDB_SHEXP_COMMENTS|MDB_SHEXP_SANITIZE, + mdb_sybase_types, &mdb_sybase_shortdate_type, NULL, + "-- That file uses encoding %s\n", + "DROP TABLE %s;\n", + "ALTER TABLE %s ADD CHECK (%s <>'');\n", + "COMMENT ON COLUMN %s.%s IS %s;\n", + "COMMENT ON TABLE %s IS %s;\n", + quote_schema_name_dquote); + mdb_register_backend("oracle", + MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_COMMENTS|MDB_SHEXP_INDEXES|MDB_SHEXP_RELATIONS|MDB_SHEXP_SANITIZE, + mdb_oracle_types, &mdb_oracle_shortdate_type, NULL, + "-- That file uses encoding %s\n", + "DROP TABLE %s;\n", + NULL, + "COMMENT ON COLUMN %s.%s IS %s;\n", + "COMMENT ON TABLE %s IS %s;\n", + quote_schema_name_dquote); + mdb_register_backend("postgres", + MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_CST_NOTEMPTY|MDB_SHEXP_COMMENTS|MDB_SHEXP_INDEXES|MDB_SHEXP_RELATIONS|MDB_SHEXP_SANITIZE, + mdb_postgres_types, &mdb_postgres_shortdate_type, &mdb_postgres_serial_type, + "SET client_encoding = '%s';\n", + "DROP TABLE IF EXISTS %s;\n", + "ALTER TABLE %s ADD CHECK (%s <>'');\n", + "COMMENT ON COLUMN %s.%s IS %s;\n", + "COMMENT ON TABLE %s IS %s;\n", + quote_schema_name_dquote); + mdb_register_backend("mysql", + MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_CST_NOTEMPTY|MDB_SHEXP_COMMENTS|MDB_SHEXP_SANITIZE, + mdb_mysql_types, &mdb_mysql_shortdate_type, NULL, + "-- That file uses encoding %s\n", + "DROP TABLE IF EXISTS %s;\n", + "ALTER TABLE %s ADD CHECK (%s <>'');\n", + "COMMENT ON COLUMN %s.%s IS %s;\n", + "COMMENT ON TABLE %s IS %s;\n", + quote_schema_name_rquotes_merge); } -void mdb_register_backend(MdbBackendType *backend_type, char* (*quote_name)(const char*), char *backend_name) +void mdb_register_backend(char *backend_name, guint32 capabilities, MdbBackendType *backend_type, MdbBackendType *type_shortdate, MdbBackendType *type_autonum, const char *charset_statement, const char *drop_statement, const char *constaint_not_empty_statement, const char *column_comment_statement, const char *table_comment_statement, gchar* (*quote_schema_name)(const gchar*, const gchar*)) { MdbBackend *backend = (MdbBackend *) g_malloc0(sizeof(MdbBackend)); + backend->capabilities = capabilities; backend->types_table = backend_type; - backend->quote_name = quote_name; + backend->type_shortdate = type_shortdate; + backend->type_autonum = type_autonum; + backend->charset_statement = charset_statement; + backend->drop_statement = drop_statement; + backend->constaint_not_empty_statement = constaint_not_empty_statement; + backend->column_comment_statement = column_comment_statement; + backend->table_comment_statement = table_comment_statement; + backend->quote_schema_name = quote_schema_name; g_hash_table_insert(mdb_backends, backend_name, backend); } @@ -277,92 +439,6 @@ int mdb_set_default_backend(MdbHandle *mdb, const char *backend_name) } } -/** - * mdb_get_sequences - * @entry: Handle to open MDB database file - * @namespace: Prefix for output names - * @sanitize: Remove weird characters if true - * - * Generates sequences and set default values - * - * Returns: a string stating that relationships are not supported for the - * selected backend, or a string containing SQL commands for setting up - * the sequences, tailored for the selected backend. - * Returns NULL on last iteration. - * The caller is responsible for freeing this string. - */ -static char * -mdb_get_sequences(MdbCatalogEntry *entry, char *namespace, int sanitize) -{ - MdbTableDef *table; - MdbHandle *mdb = entry->mdb; - int i; - int backend = 0; /* Backends: 1=oracle, 2=postgres */ - const char *quoted_table_name; - char *result = NULL; - char tmp[4*512+512]; /* maximum size is 4 quoted names + some constants */ - - - if (is_init == 1) { /* the second time through */ - is_init = 0; - return NULL; - } - is_init = 1; - /* the first time through */ - - if (!strcmp(mdb->backend_name, "postgres")) { - backend = 2; - } else { - return (char *) g_strconcat( - "-- sequences are not implemented for ", - mdb->backend_name, "\n", NULL); - } - - /* get the columns */ - table = mdb_read_table (entry); - - /* get the columns */ - mdb_read_columns (table); - - if (sanitize) - quoted_table_name = sanitize_name(table->name); - else - quoted_table_name = mdb->default_backend->quote_name(table->name); - - for (i = 0; i < table->num_cols; i++) { - MdbColumn *col; - col = g_ptr_array_index (table->columns, i); - if (col->is_long_auto) { - const char *quoted_column_name; - char sequence_name[256+1+256+4+1]; - const char *quoted_sequence_name; - quoted_column_name = mdb->default_backend->quote_name(col->name); - sprintf(sequence_name, "%s_%s_seq", entry->object_name, col->name); - quoted_sequence_name = mdb->default_backend->quote_name(sequence_name); - sprintf (tmp, "CREATE SEQUENCE %s OWNED BY %s.%s;\n", quoted_sequence_name, quoted_table_name, quoted_column_name); - if (result) { - result = realloc(result, strlen(result) + strlen(tmp) + 1); /* sentry */ - strcat(result, tmp); - } else - result = strdup(tmp); - /* after that point, result can't be NULL any more */ - - sprintf (tmp, "ALTER TABLE %s ALTER COLUMN %s SET DEFAULT pg_catalog.nextval('%s');\n\n", - quoted_table_name, quoted_column_name, quoted_sequence_name); - result = realloc(result, strlen(result) + strlen(tmp) + 1); /* sentry */ - strcat(result, tmp); - - free((void*)quoted_column_name); - free((void*)quoted_sequence_name); - } - } - - if (!result) - is_init = 0; - return result; -} - - /** * mdb_print_indexes * @output: Where to print the sql @@ -387,29 +463,31 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *namespace, int saniti /* read indexes */ mdb_read_indices(table); - fprintf (outfile, "-- CREATE ANY INDEXES ...\n"); + fprintf (outfile, "-- CREATE INDEXES ...\n"); if (sanitize) quoted_table_name = sanitize_name(table->name); else - quoted_table_name = mdb->default_backend->quote_name(table->name); + quoted_table_name = mdb->default_backend->quote_schema_name(namespace, table->name); for (i=0;inum_idxs;i++) { idx = g_ptr_array_index (table->indices, i); if (idx->index_type==2) continue; - index_name = malloc(strlen(table->name)+strlen(idx->name)+4+1); + index_name = malloc(strlen(table->name)+strlen(idx->name)+5+1); strcpy(index_name, table->name); - strcat(index_name, idx->name); if (idx->index_type==1) - strcat(index_name, "_pk"); - else + strcat(index_name, "_pkey"); + else { + strcat(index_name, "_"); + strcat(index_name, idx->name); strcat(index_name, "_idx"); + } if (sanitize) quoted_name = sanitize_name(index_name); else - quoted_name = mdb->default_backend->quote_name(index_name); + quoted_name = mdb->default_backend->quote_schema_name(namespace, index_name); if (idx->index_type==1) { fprintf (outfile, "ALTER TABLE %s ADD CONSTRAINT %s PRIMARY KEY (", quoted_table_name, quoted_name); } else { @@ -428,7 +506,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *namespace, int saniti if (sanitize) quoted_name = sanitize_name(col->name); else - quoted_name = mdb->default_backend->quote_name(col->name); + quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); fprintf (outfile, "%s", quoted_name); if (idx->index_type!=1 && idx->key_col_order[j]) /* no DESC for primary keys */ @@ -439,8 +517,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *namespace, int saniti } fprintf (outfile, ");\n"); } - fprintf (outfile, "\n"); - fprintf (outfile, "\n"); + fputc ('\n', outfile); } /** @@ -462,7 +539,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *namespace, int saniti * The caller is responsible for freeing this string. */ static char * -mdb_get_relationships(MdbHandle *mdb, const char* tablename) +mdb_get_relationships(MdbHandle *mdb, const gchar *namespace, const char* tablename) { unsigned int i; gchar *text = NULL; /* String to be returned */ @@ -533,13 +610,13 @@ mdb_get_relationships(MdbHandle *mdb, const char* tablename) break; } - quoted_table_1 = mdb->default_backend->quote_name(bound[1]); - quoted_column_1 = mdb->default_backend->quote_name(bound[0]); - quoted_table_2 = mdb->default_backend->quote_name(bound[3]); - quoted_column_2 = mdb->default_backend->quote_name(bound[2]); + quoted_table_1 = mdb->default_backend->quote_schema_name(namespace, bound[1]); + quoted_column_1 = mdb->default_backend->quote_schema_name(namespace, bound[0]); + quoted_table_2 = mdb->default_backend->quote_schema_name(namespace, bound[3]); + quoted_column_2 = mdb->default_backend->quote_schema_name(namespace, bound[2]); grbit = atoi(bound[4]); constraint_name = g_strconcat(bound[1], "_", bound[0], "_fk", NULL); - quoted_constraint_name = mdb->default_backend->quote_name(constraint_name); + quoted_constraint_name = mdb->default_backend->quote_schema_name(namespace, constraint_name); free(constraint_name); if (grbit & 0x00000002) { @@ -580,28 +657,20 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *namespace, gu MdbHandle *mdb = entry->mdb; MdbColumn *col; unsigned int i; - char* table_name; char* quoted_table_name; char* quoted_name; - char* sql_sequences; int sanitize = export_options & MDB_SHEXP_SANITIZE; + MdbProperties *props; + char *prop_value; if (sanitize) quoted_table_name = sanitize_name(entry->object_name); else - quoted_table_name = mdb->default_backend->quote_name(entry->object_name); - - if (namespace) { - table_name = malloc(strlen(namespace)+strlen(quoted_table_name)+1); - strcpy(table_name, namespace); - strcat(table_name, quoted_table_name); - free(quoted_table_name); - quoted_table_name = table_name; - } + quoted_table_name = mdb->default_backend->quote_schema_name(namespace, entry->object_name); /* drop the table if it exists */ if (export_options & MDB_SHEXP_DROPTABLE) - fprintf (outfile, "DROP TABLE %s;\n", quoted_table_name); + fprintf (outfile, mdb->default_backend->drop_statement, quoted_table_name); /* create the table */ fprintf (outfile, "CREATE TABLE %s\n", quoted_table_name); @@ -613,20 +682,18 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *namespace, gu mdb_read_columns (table); /* loop over the columns, dumping the names and types */ - for (i = 0; i < table->num_cols; i++) { col = g_ptr_array_index (table->columns, i); if (sanitize) quoted_name = sanitize_name(col->name); else - quoted_name = mdb->default_backend->quote_name(col->name); + quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); fprintf (outfile, "\t%s\t\t\t%s", quoted_name, - mdb_get_coltype_string (mdb->default_backend, col->col_type)); + mdb_get_colbacktype_string (col)); free(quoted_name); - if (mdb_coltype_takes_length(mdb->default_backend, - col->col_type)) { + if (mdb_colbacktype_takes_length(col)) { /* more portable version from DW patch */ if (col->col_size == 0) @@ -635,6 +702,16 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *namespace, gu fprintf(outfile, " (%d)", col->col_size); } + if (export_options & MDB_SHEXP_CST_NOTNULL) { + if (col->col_type == MDB_BOOL) { + /* access booleans are never null */ + fputs(" NOT NULL", outfile); + } else { + const gchar *not_null = mdb_col_get_prop(col, "Required"); + if (not_null && not_null[0]=='y') + fputs(" NOT NULL", outfile); + } + } if (i < table->num_cols - 1) fputs(", \n", outfile); else @@ -643,13 +720,56 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *namespace, gu fputs(");\n", outfile); - fputs("-- CREATE SEQUENCES ...\n", outfile); - fputs("\n", outfile); - while ((sql_sequences = mdb_get_sequences(entry, namespace, sanitize))) { - fputs(sql_sequences, outfile); - free(sql_sequences); + /* Add the constraints on columns */ + for (i = 0; i < table->num_cols; i++) { + const gchar *prop_value; + + col = g_ptr_array_index (table->columns, i); + props = col->props; + if (!props) + continue; + + if (sanitize) + quoted_name = sanitize_name(col->name); + else + quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); + + if (export_options & MDB_SHEXP_CST_NOTEMPTY) { + prop_value = mdb_col_get_prop(col, "AllowZeroLength"); + if (prop_value && prop_value[0]=='n') + fprintf(outfile, + mdb->default_backend->constaint_not_empty_statement, + quoted_table_name, quoted_name); + } + + if (export_options & MDB_SHEXP_COMMENTS) { + prop_value = mdb_col_get_prop(col, "Description"); + if (prop_value) { + char *comment = quote_with_squotes(prop_value); + fprintf(outfile, + mdb->default_backend->column_comment_statement, + quoted_table_name, quoted_name, comment); + free(comment); + } + } + + free(quoted_name); } + /* Add the constraints on table */ + if (export_options & MDB_SHEXP_COMMENTS) { + prop_value = mdb_table_get_prop(table, "Description"); + if (prop_value) { + char *comment = quote_with_squotes(prop_value); + fprintf(outfile, + mdb->default_backend->table_comment_statement, + quoted_table_name, comment); + free(comment); + } + } + fputc('\n', outfile); + + if (export_options & MDB_SHEXP_INDEXES) // prints all the indexes of that table mdb_print_indexes(outfile, table, namespace, sanitize); @@ -667,6 +787,9 @@ mdb_print_schema(MdbHandle *mdb, FILE *outfile, char *tabname, char *namespace, char *the_relation; MdbCatalogEntry *entry; + /* clear unsupported options */ + export_options &= mdb->default_backend->capabilities; + /* Print out a little message to show that this came from mdb-tools. I like to know how something is generated. DW */ fputs("-------------------------------------------------------------\n" @@ -678,6 +801,12 @@ mdb_print_schema(MdbHandle *mdb, FILE *outfile, char *tabname, char *namespace, "-------------------------------------------------------------\n\n", outfile); + const char *charset = mdb_target_charset(mdb); + if (charset) { + fprintf(outfile, mdb->default_backend->charset_statement, charset); + fputc('\n', outfile); + } + for (i=0; i < mdb->num_catalog; i++) { entry = g_ptr_array_index (mdb->catalog, i); if (entry->object_type == MDB_TABLE) { @@ -691,7 +820,7 @@ mdb_print_schema(MdbHandle *mdb, FILE *outfile, char *tabname, char *namespace, if (export_options & MDB_SHEXP_RELATIONS) { fputs ("-- CREATE Relationships ...\n", outfile); - while ((the_relation=mdb_get_relationships(mdb, tabname)) != NULL) { + while ((the_relation=mdb_get_relationships(mdb, namespace, tabname)) != NULL) { fputs(the_relation, outfile); g_free(the_relation); } diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 60fd57a..11585a7 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -923,7 +923,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int size, text, MDB_BIND_SIZE); } break; - case MDB_SDATETIME: + case MDB_DATETIME: text = mdb_date_to_string(mdb, start); break; case MDB_MEMO: @@ -964,7 +964,7 @@ int mdb_col_disp_size(MdbColumn *col) case MDB_TEXT: return col->col_size; break; - case MDB_SDATETIME: + case MDB_DATETIME: return 20; break; case MDB_MEMO: @@ -1000,7 +1000,7 @@ int mdb_col_fixed_size(MdbColumn *col) case MDB_TEXT: return -1; break; - case MDB_SDATETIME: + case MDB_DATETIME: return 4; break; case MDB_BINARY: diff --git a/src/libmdb/iconv.c b/src/libmdb/iconv.c index 04ed31a..d58be97 100644 --- a/src/libmdb/iconv.c +++ b/src/libmdb/iconv.c @@ -181,6 +181,21 @@ mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t slen, char *dest, size_t dle return dlen; } +const char* +mdb_target_charset(MdbHandle *mdb) +{ +#ifdef HAVE_ICONV + const char *iconv_code = getenv("MDBICONV"); + if (!iconv_code) + iconv_code = "UTF-8"; + return iconv_code; +#else + if (IS_JET4(mdb)) + return "ISO-8859-1"; + return NULL; // same as input: unknown +#endif +} + void mdb_iconv_init(MdbHandle *mdb) { const char *iconv_code; @@ -191,11 +206,11 @@ void mdb_iconv_init(MdbHandle *mdb) } #ifdef HAVE_ICONV - if (IS_JET4(mdb)) { - mdb->iconv_out = iconv_open("UCS-2LE", iconv_code); - mdb->iconv_in = iconv_open(iconv_code, "UCS-2LE"); - } else { - /* According to Microsoft Knowledge Base pages 289525 and */ + if (IS_JET4(mdb)) { + mdb->iconv_out = iconv_open("UCS-2LE", iconv_code); + mdb->iconv_in = iconv_open(iconv_code, "UCS-2LE"); + } else { + /* According to Microsoft Knowledge Base pages 289525 and */ /* 202427, code page info is not contained in the database */ const char *jet3_iconv_code; @@ -204,15 +219,17 @@ void mdb_iconv_init(MdbHandle *mdb) jet3_iconv_code="CP1252"; } - mdb->iconv_out = iconv_open(jet3_iconv_code, iconv_code); - mdb->iconv_in = iconv_open(iconv_code, jet3_iconv_code); - } + mdb->iconv_out = iconv_open(jet3_iconv_code, iconv_code); + mdb->iconv_in = iconv_open(iconv_code, jet3_iconv_code); + } #endif } void mdb_iconv_close(MdbHandle *mdb) { #ifdef HAVE_ICONV - if (mdb->iconv_out != (iconv_t)-1) iconv_close(mdb->iconv_out); - if (mdb->iconv_in != (iconv_t)-1) iconv_close(mdb->iconv_in); + if (mdb->iconv_out != (iconv_t)-1) iconv_close(mdb->iconv_out); + if (mdb->iconv_in != (iconv_t)-1) iconv_close(mdb->iconv_in); #endif } + + diff --git a/src/libmdb/table.c b/src/libmdb/table.c index 715e1bb..2cb5d5e 100644 --- a/src/libmdb/table.c +++ b/src/libmdb/table.c @@ -237,6 +237,8 @@ GPtrArray *mdb_read_columns(MdbTableDef *table) read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size); pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn)); + pcol->table = table; + pcol->col_type = col[0]; // col_num_offset == 1 or 5 @@ -328,7 +330,6 @@ MdbTableDef *table; MdbColumn *col; int coln; MdbIndex *idx; -MdbHandle *mdb = entry->mdb; unsigned int i, bitn; guint32 pgnum; @@ -348,7 +349,7 @@ guint32 pgnum; fprintf(stdout,"column %d Name: %-20s Type: %s(%d)\n", i, col->name, - mdb_get_coltype_string(mdb->default_backend, col->col_type), + mdb_get_colbacktype_string(col), col->col_size); if (col->props) mdb_dump_props(col->props, stdout, 0); diff --git a/src/libmdb/worktable.c b/src/libmdb/worktable.c index 6f893dc..2353b08 100644 --- a/src/libmdb/worktable.c +++ b/src/libmdb/worktable.c @@ -74,6 +74,7 @@ mdb_create_temp_table(MdbHandle *mdb, char *name) void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col) { + col->table = table, col->col_num = table->num_cols; if (!col->is_fixed) col->var_col_num = table->num_var_cols++; diff --git a/src/sql/mdbsql.c b/src/sql/mdbsql.c index 243ac0b..b455960 100644 --- a/src/sql/mdbsql.c +++ b/src/sql/mdbsql.c @@ -622,7 +622,7 @@ void mdb_sql_describe_table(MdbSQL *sql) tmpsiz = mdb_ascii2unicode(mdb, col->name, 0, col_name, 100); mdb_fill_temp_field(&fields[0],col_name, tmpsiz, 0,0,0,0); - strcpy(tmpstr, mdb_get_coltype_string(mdb->default_backend, col->col_type)); + strcpy(tmpstr, mdb_get_colbacktype_string(col)); tmpsiz = mdb_ascii2unicode(mdb, tmpstr, 0, col_type, 100); mdb_fill_temp_field(&fields[1],col_type, tmpsiz, 0,0,0,1); diff --git a/src/util/mdb-export.c b/src/util/mdb-export.c index dc92e28..f4c8d1f 100644 --- a/src/util/mdb-export.c +++ b/src/util/mdb-export.c @@ -26,7 +26,7 @@ #undef MDB_BIND_SIZE #define MDB_BIND_SIZE 200000 -#define is_text_type(x) (x==MDB_TEXT || x==MDB_OLE || x==MDB_MEMO || x==MDB_SDATETIME || x==MDB_BINARY) +#define is_text_type(x) (x==MDB_TEXT || x==MDB_OLE || x==MDB_MEMO || x==MDB_DATETIME || x==MDB_BINARY) static char *escapes(char *s); @@ -214,7 +214,7 @@ main(int argc, char **argv) if (sanitize) quoted_name = sanitize_name(argv[optind + 1]); else - quoted_name = mdb->default_backend->quote_name(argv[optind + 1]); + quoted_name = mdb->default_backend->quote_schema_name(NULL, argv[optind + 1]); fprintf(stdout, "INSERT INTO %s%s (", namespace, quoted_name); free(quoted_name); for (j=0;jnum_cols;j++) { @@ -223,7 +223,7 @@ main(int argc, char **argv) if (sanitize) quoted_name = sanitize_name(col->name); else - quoted_name = mdb->default_backend->quote_name(col->name); + quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); fprintf(stdout,"%s", quoted_name); free(quoted_name); } diff --git a/src/util/mdb-schema.c b/src/util/mdb-schema.c index 4246aa2..9b62ffa 100644 --- a/src/util/mdb-schema.c +++ b/src/util/mdb-schema.c @@ -18,6 +18,7 @@ /* this utility dumps the schema for an existing database */ #include +#include #include "mdbtools.h" #ifdef DMALLOC @@ -42,16 +43,104 @@ main (int argc, char **argv) exit (1); } - while ((opt=getopt(argc, argv, "T:N:S"))!=-1) { + int digit_optind = 0; + while (1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"table", 1, NULL, 'T'}, + {"namespace", 1, NULL, 'N'}, + {"drop-table", 0, NULL, 0}, + {"no-drop-table", 0, NULL, 0}, + {"not-null", 0, NULL, 0}, + {"no-not-null", 0, NULL, 0}, + {"not-empty", 0, NULL, 0}, + {"no-not-empty", 0, NULL, 0}, + {"description", 0, NULL, 0}, + {"no-description", 0, NULL, 0}, + {"indexes", 0, NULL, 0}, + {"no-indexes", 0, NULL, 0}, + {"relations", 0, NULL, 0}, + {"no-relations", 0, NULL, 0}, + {"sanitize", 0, NULL, 'S'}, + {"no-sanitize", 0, NULL, 0}, + {NULL, 0, NULL, 0}, + }; + opt = getopt_long(argc, argv, "T:N:S", long_options, &option_index); + if (opt == -1) + break; + switch (opt) { - case 'T': - tabname = (char *) g_strdup(optarg); + case 0: + if (!strcmp(long_options[option_index].name, "drop-table")) { + export_options |= MDB_SHEXP_DROPTABLE; + break; + } + if (!strcmp(long_options[option_index].name, "no-drop-table")) { + export_options &= ~MDB_SHEXP_DROPTABLE; + break; + } + if (!strcmp(long_options[option_index].name, "not-null")) { + export_options |= MDB_SHEXP_CST_NOTNULL; + break; + } + if (!strcmp(long_options[option_index].name, "no-not-null")) { + export_options &= ~MDB_SHEXP_CST_NOTNULL; + break; + } + if (!strcmp(long_options[option_index].name, "not-empty")) { + export_options |= MDB_SHEXP_CST_NOTEMPTY; + break; + } + if (!strcmp(long_options[option_index].name, "no-not-empty")) { + export_options &= ~MDB_SHEXP_CST_NOTEMPTY; + break; + } + if (!strcmp(long_options[option_index].name, "description")) { + export_options |= MDB_SHEXP_COMMENTS; + break; + } + if (!strcmp(long_options[option_index].name, "no-description")) { + export_options &= ~MDB_SHEXP_COMMENTS; + break; + } + if (!strcmp(long_options[option_index].name, "indexes")) { + export_options |= MDB_SHEXP_INDEXES; + break; + } + if (!strcmp(long_options[option_index].name, "no-indexes")) { + export_options &= ~MDB_SHEXP_INDEXES; + break; + } + if (!strcmp(long_options[option_index].name, "relations")) { + export_options |= MDB_SHEXP_RELATIONS; + break; + } + if (!strcmp(long_options[option_index].name, "no-relations")) { + export_options &= ~MDB_SHEXP_RELATIONS; + break; + } + if (!strcmp(long_options[option_index].name, "no-sanitize")) { + export_options &= ~MDB_SHEXP_SANITIZE; + break; + } + fprintf(stderr, "unimplemented option %s", long_options[option_index].name); + if (optarg) + fprintf(stderr, " with arg %s", optarg); + fputc('\n', stderr); + exit(1); break; - case 'N': - namespace = (char *) g_strdup(optarg); + + case 'T': + tabname = (char *) g_strdup(optarg); break; - case 'S': - export_options |= MDB_SHEXP_SANITIZE; + + case 'N': + namespace = (char *) g_strdup(optarg); + break; + + case 'S': + export_options |= MDB_SHEXP_SANITIZE; break; } }