patch 'schema2' from Nirgal Vourgère

This commit is contained in:
Brian Bruns
2011-02-16 18:58:22 -05:00
parent 6696edf1f8
commit 39277312d4
13 changed files with 995 additions and 658 deletions

View File

@@ -1,7 +1,7 @@
NAME
mdb-schema - Generate schema creation DDL
SYNOPSIS
mdb-schema [-T <table>] <database> [<backend>]
mdb-schema [options] <database> [<backend>]
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>, --table <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.

View File

@@ -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 {
guint32 capabilities; /* see MDB_SHEXP_* */
MdbBackendType *types_table;
char* (*quote_name)(const char*);
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
}

View File

@@ -1,216 +1,72 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<?xml version="1.0"?>
<glade-interface>
<requires lib="gnome"/>
<widget class="GtkDialog" id="schema_dialog">
<!-- interface-requires gtk+ 2.6 -->
<requires lib="gnome"/>
<!-- interface-requires gnome 2412.41848 -->
<!-- interface-naming-policy toplevel-contextual -->
<widget class="GtkDialog" id="schema_dialog">
<property name="visible">True</property>
<property name="title" translatable="yes">Export Schema</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="has_separator">True</property>
<property name="type_hint">normal</property>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="cancelbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="response_id">-11</property>
<signal name="clicked" handler="gmdb_schema_help_cb" last_modification_time="Tue, 14 Jan 2003 14:45:37 GMT"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="okbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="response_id">-6</property>
<signal name="clicked" handler="gtk_widget_destroy" object="schema_dialog" last_modification_time="Mon, 12 Jan 2004 18:40:24 GMT"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="response_id">-5</property>
<signal name="clicked" handler="gmdb_schema_export_cb" last_modification_time="Tue, 14 Jan 2003 14:46:39 GMT"/>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="stock">gtk-convert</property>
<property name="icon_size">4</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">_Export</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table1">
<property name="border_width">33</property>
<property name="visible">True</property>
<property name="n_rows">5</property>
<property name="border_width">33</property>
<property name="n_rows">9</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">8</property>
<property name="column_spacing">30</property>
<property name="row_spacing">8</property>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Table:&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="label" translatable="yes">&lt;b&gt;Table:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="justify">right</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Schema Dialect:&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="label" translatable="yes">&lt;b&gt;Schema Dialect:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="justify">right</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCombo" id="table_combo">
<property name="visible">True</property>
<property name="value_in_list">False</property>
<property name="allow_empty">True</property>
<property name="case_sensitive">False</property>
<property name="enable_arrow_keys">True</property>
<property name="enable_arrows_always">False</property>
<child internal-child="entry">
<widget class="GtkEntry" id="combo-entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes">Access</property>
<property name="has_frame">True</property>
<property name="invisible_char" translatable="yes">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child internal-child="list">
<widget class="GtkList" id="combo-list1">
<property name="visible">True</property>
<property name="selection_mode">GTK_SELECTION_BROWSE</property>
<property name="selection_mode">browse</property>
</widget>
</child>
</widget>
@@ -222,35 +78,27 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCombo" id="backend_combo">
<property name="visible">True</property>
<property name="value_in_list">True</property>
<property name="allow_empty">False</property>
<property name="case_sensitive">False</property>
<property name="enable_arrow_keys">True</property>
<property name="enable_arrows_always">False</property>
<property name="allow_empty">False</property>
<property name="value_in_list">True</property>
<child internal-child="entry">
<widget class="GtkEntry" id="entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes">Access</property>
<property name="has_frame">True</property>
<property name="invisible_char" translatable="yes">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child internal-child="list">
<widget class="GtkList" id="combo-list2">
<property name="visible">True</property>
<property name="selection_mode">GTK_SELECTION_BROWSE</property>
<property name="selection_mode">browse</property>
<child>
<widget class="GtkListItem" id="listitem141">
<property name="visible">True</property>
@@ -258,7 +106,6 @@
<property name="label" translatable="yes">Access</property>
</widget>
</child>
<child>
<widget class="GtkListItem" id="listitem142">
<property name="visible">True</property>
@@ -266,7 +113,6 @@
<property name="label" translatable="yes">Oracle</property>
</widget>
</child>
<child>
<widget class="GtkListItem" id="listitem143">
<property name="visible">True</property>
@@ -274,7 +120,6 @@
<property name="label" translatable="yes">Sybase</property>
</widget>
</child>
<child>
<widget class="GtkListItem" id="listitem144">
<property name="visible">True</property>
@@ -282,7 +127,6 @@
<property name="label" translatable="yes">MS SQL Server</property>
</widget>
</child>
<child>
<widget class="GtkListItem" id="listitem145">
<property name="visible">True</property>
@@ -290,7 +134,6 @@
<property name="label" translatable="yes">PostgreSQL</property>
</widget>
</child>
<child>
<widget class="GtkListItem" id="listitem146">
<property name="visible">True</property>
@@ -309,16 +152,58 @@
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="rel_checkbox">
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;Options:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="justify">right</property>
</widget>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">&lt;b&gt;File Name:&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GnomeFileEntry" id="fileentry1">
<property name="visible">True</property>
<property name="max_saved">10</property>
<child internal-child="entry">
<widget class="GtkEntry" id="filename_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Include Relationships</property>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="drop_checkbox">
<property name="label" translatable="yes">Include Drop Table commands</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="active">True</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
@@ -326,44 +211,18 @@
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Options:&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_RIGHT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="drop_checkbox">
<widget class="GtkCheckButton" id="cstnotnull_checkbox">
<property name="label" translatable="yes">Include Not Null constraints</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Include Drop Table commands</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="active">True</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
@@ -371,73 +230,204 @@
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options">fill</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;File Name:&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GnomeFileEntry" id="fileentry1">
<property name="visible">True</property>
<property name="max_saved">10</property>
<property name="directory_entry">False</property>
<property name="modal">False</property>
<child internal-child="entry">
<widget class="GtkEntry" id="filename_entry">
<widget class="GtkCheckButton" id="rel_checkbox">
<property name="label" translatable="yes">Include Relationships</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char" translatable="yes">*</property>
<property name="activates_default">False</property>
</widget>
</child>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="top_attach">8</property>
<property name="bottom_attach">9</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="index_checkbox">
<property name="label" translatable="yes">Include indexes</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="cstnotempty_checkbox">
<property name="label" translatable="yes">Include Not Empty constraints</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="comments_checkbox">
<property name="label" translatable="yes">Include description on tables and columns</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="cancelbutton1">
<property name="label">gtk-help</property>
<property name="response_id">-11</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="gmdb_schema_help_cb"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="okbutton1">
<property name="label">gtk-cancel</property>
<property name="response_id">-6</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="gtk_widget_destroy" object="schema_dialog"/>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="response_id">-5</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">False</property>
<signal name="clicked" handler="gmdb_schema_export_cb"/>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<widget class="GtkImage" id="image2">
<property name="visible">True</property>
<property name="stock">gtk-convert</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="label" translatable="yes">_Export</property>
<property name="use_underline">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</widget>
</child>
</widget>
</widget>
</glade-interface>

View File

@@ -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");
/* make sure unknown default options are enabled */
export_options = MDB_SHEXP_DEFAULT;
for (i=0; i<n_capabilities; ++i)
export_options &= ~capabilities_xlt[i].option_value;
/* fill the bit field from the checkboxes */
for (i=0; i<n_capabilities; ++i) {
checkbox = glade_xml_get_widget (schemawin_xml, capabilities_xlt[i].option_name);
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
export_options |= capabilities_xlt[i].option_value;
}
//printf("%s %s %02X\n",tabname,backend,export_options);
gtk_widget_destroy(schemawin);
gmdb_schema_export();
}
static void
check_default_options() {
int i;
GtkToggleButton *checkbox;
for (i=0; i<n_capabilities; ++i) {
checkbox = GTK_TOGGLE_BUTTON(glade_xml_get_widget (schemawin_xml, capabilities_xlt[i].option_name));
gtk_toggle_button_set_active(checkbox, (MDB_SHEXP_DEFAULT & capabilities_xlt[i].option_value) != 0);
}
}
static void
refresh_available_options() {
GtkWidget *combo, *checkbox;
guint32 capabilities;
extern GHashTable *mdb_backends; /* FIXME */
MdbBackend *backend_obj;
int i;
combo = glade_xml_get_widget (schemawin_xml, "backend_combo");
if (!combo) return; /* window is beeing destroyed */
const gchar *backend_name = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
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; i<n_capabilities; ++i) {
checkbox = glade_xml_get_widget (schemawin_xml, capabilities_xlt[i].option_name);
gtk_widget_set_sensitive(checkbox, (capabilities & capabilities_xlt[i].option_value) != 0);
}
}
void
gmdb_schema_capabilities_cb(GtkList *list) {
refresh_available_options();
}
void
gmdb_schema_help_cb(GtkWidget *w, gpointer data)
{
@@ -122,6 +181,10 @@ gmdb_schema_new_cb(GtkWidget *w, gpointer data)
schemawin_xml = glade_xml_new(GMDB_GLADEDIR "gmdb-schema.glade", NULL, NULL);
/* connect the signals in the interface */
glade_xml_signal_autoconnect(schemawin_xml);
/* set up capabilities call back. TODO: autoconnect should do that */
combo = glade_xml_get_widget(schemawin_xml, "combo-list2");
g_signal_connect( G_OBJECT (combo), "selection_changed",
G_CALLBACK(gmdb_schema_capabilities_cb), schemawin_xml);
/* set signals with user data, anyone know how to do this in glade? */
combo = glade_xml_get_widget (schemawin_xml, "table_combo");
@@ -136,4 +199,7 @@ gmdb_schema_new_cb(GtkWidget *w, gpointer data)
} /* for */
gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist);
g_list_free(glist);
check_default_options();
refresh_available_options();
}

View File

@@ -106,7 +106,7 @@ GtkStyle *style;
strcpy(row[0],"");
sprintf(row[1],"%d", col->col_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");

View File

@@ -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;
}
*p++ = '"';
*p++ = 0;
else if (c == quote_char) {
*pr++ = escape_char;
}
*pr++ = c;
}
*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;i<table->num_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);
}

View File

@@ -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:

View File

@@ -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;
@@ -216,3 +231,5 @@ void mdb_iconv_close(MdbHandle *mdb)
if (mdb->iconv_in != (iconv_t)-1) iconv_close(mdb->iconv_in);
#endif
}

View File

@@ -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);

View File

@@ -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++;

View File

@@ -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);

View File

@@ -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;j<table->num_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);
}

View File

@@ -18,6 +18,7 @@
/* this utility dumps the schema for an existing database */
#include <ctype.h>
#include <getopt.h>
#include "mdbtools.h"
#ifdef DMALLOC
@@ -42,14 +43,102 @@ 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 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 'T':
tabname = (char *) g_strdup(optarg);
break;
case 'N':
namespace = (char *) g_strdup(optarg);
break;
case 'S':
export_options |= MDB_SHEXP_SANITIZE;
break;