diff --git a/include/mdbfakeglib.h b/include/mdbfakeglib.h index c09c314..e38e3ec 100644 --- a/include/mdbfakeglib.h +++ b/include/mdbfakeglib.h @@ -39,6 +39,7 @@ typedef const void * gconstpointer; typedef uint8_t guint8; typedef guint32 GQuark; typedef guint32 gunichar; +typedef signed int gssize; typedef guint (*GHashFunc)(gconstpointer); typedef int (*GCompareFunc)(gconstpointer, gconstpointer); @@ -143,6 +144,7 @@ void g_printerr(const gchar *format, ...); gint g_unichar_to_utf8(gunichar c, gchar *dst); gchar *g_locale_to_utf8(const gchar *opsysstring, size_t len, size_t *bytes_read, size_t *bytes_written, GError **error); +gchar *g_utf8_strdown(const gchar *str, gssize len); /* GString */ GString *g_string_new(const gchar *init); diff --git a/include/mdbtools.h b/include/mdbtools.h index 9af66c1..fbb9469 100644 --- a/include/mdbtools.h +++ b/include/mdbtools.h @@ -235,6 +235,7 @@ typedef struct { const char *table_comment_statement; const char *per_table_comment_statement; gchar* (*quote_schema_name)(const gchar*, const gchar*); + gchar* (*normalise_case)(const gchar*); } MdbBackend; typedef struct { @@ -569,7 +570,8 @@ void mdb_register_backend(MdbHandle *mdb, char *backend_name, guint32 capabiliti const char *drop_statement, const char *constaint_not_empty_statement, const char *column_comment_statement, const char *per_column_comment_statement, const char *table_comment_statement, const char *per_table_comment_statement, - gchar* (*quote_schema_name)(const gchar*, const gchar*)); + gchar* (*quote_schema_name)(const gchar*, const gchar*), + gchar* (*normalise_case)(const gchar*)); int mdb_set_default_backend(MdbHandle *mdb, const char *backend_name); int mdb_print_schema(MdbHandle *mdb, FILE *outfile, char *tabname, char *dbnamespace, guint32 export_options); void mdb_print_col(FILE *outfile, gchar *col_val, int quote_text, int col_type, int bin_len, char *quote_char, char *escape_char, int flags); diff --git a/src/libmdb/backend.c b/src/libmdb/backend.c index 2b01cc3..1ee2316 100644 --- a/src/libmdb/backend.c +++ b/src/libmdb/backend.c @@ -155,6 +155,37 @@ enum { static void mdb_drop_backend(gpointer key, gpointer value, gpointer data); + +gchar *passthrough_unchanged(const gchar *str) { + return (gchar *)str; +} + +gchar *to_lower_case(const gchar *str) { + return g_utf8_strdown(str, -1); +} + +/** + * Convenience function to replace an input string with its database specific normalised version. + * + * This function throws away the input string after normalisation, freeing its memory, and replaces it with a new + * normalised version allocated on the stack. + * + * @param mdb Database specific MDB handle containing pointers to utility methods + * @param str string to normalise + * @return a pointer to the normalised version of the input string + */ +gchar *normalise_and_replace(MdbHandle *mdb, gchar **str) { + gchar *normalised_str = mdb->default_backend->normalise_case(*str); + if (normalised_str != *str) { + /* Free and replace the old string only and only if a new string was created at a different memory location + * so that we can account for the case where strings a just passed through unchanged. + */ + free(*str); + *str = normalised_str; + } + return *str; +} + static gchar* quote_generic(const gchar *value, gchar quote_char, gchar escape_char) { gchar *result, *pr; @@ -310,7 +341,8 @@ void mdb_init_backends(MdbHandle *mdb) NULL, NULL, NULL, - quote_schema_name_bracket_merge); + quote_schema_name_bracket_merge, + passthrough_unchanged); mdb_register_backend(mdb, "sybase", MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_CST_NOTEMPTY|MDB_SHEXP_COMMENTS|MDB_SHEXP_DEFVALUES, mdb_sybase_types, &mdb_sybase_shortdate_type, NULL, @@ -325,7 +357,8 @@ void mdb_init_backends(MdbHandle *mdb) NULL, "COMMENT ON TABLE %s IS %s;\n", NULL, - quote_schema_name_dquote); + quote_schema_name_dquote, + passthrough_unchanged); mdb_register_backend(mdb, "oracle", MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_COMMENTS|MDB_SHEXP_INDEXES|MDB_SHEXP_RELATIONS|MDB_SHEXP_DEFVALUES, mdb_oracle_types, &mdb_oracle_shortdate_type, NULL, @@ -340,7 +373,8 @@ void mdb_init_backends(MdbHandle *mdb) NULL, "COMMENT ON TABLE %s IS %s;\n", NULL, - quote_schema_name_dquote); + quote_schema_name_dquote, + passthrough_unchanged); mdb_register_backend(mdb, "postgres", MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_CST_NOTEMPTY|MDB_SHEXP_COMMENTS|MDB_SHEXP_INDEXES|MDB_SHEXP_RELATIONS|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT, mdb_postgres_types, &mdb_postgres_shortdate_type, &mdb_postgres_serial_type, @@ -355,7 +389,8 @@ void mdb_init_backends(MdbHandle *mdb) NULL, "COMMENT ON TABLE %s IS %s;\n", NULL, - quote_schema_name_dquote); + quote_schema_name_dquote, + to_lower_case); mdb_register_backend(mdb, "mysql", MDB_SHEXP_DROPTABLE|MDB_SHEXP_CST_NOTNULL|MDB_SHEXP_CST_NOTEMPTY|MDB_SHEXP_INDEXES|MDB_SHEXP_RELATIONS|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT, mdb_mysql_types, &mdb_mysql_shortdate_type, &mdb_mysql_serial_type, @@ -370,7 +405,8 @@ void mdb_init_backends(MdbHandle *mdb) "COMMENT %s", NULL, "COMMENT %s", - quote_schema_name_rquotes_merge); + quote_schema_name_rquotes_merge, + passthrough_unchanged); mdb_register_backend(mdb, "sqlite", MDB_SHEXP_DROPTABLE|MDB_SHEXP_DEFVALUES|MDB_SHEXP_BULK_INSERT, mdb_sqlite_types, NULL, NULL, @@ -385,7 +421,8 @@ void mdb_init_backends(MdbHandle *mdb) NULL, NULL, NULL, - quote_schema_name_rquotes_merge); + quote_schema_name_rquotes_merge, + passthrough_unchanged); } void mdb_register_backend(MdbHandle *mdb, char *backend_name, guint32 capabilities, @@ -400,7 +437,8 @@ void mdb_register_backend(MdbHandle *mdb, char *backend_name, guint32 capabiliti const char *per_column_comment_statement, const char *table_comment_statement, const char *per_table_comment_statement, - gchar* (*quote_schema_name)(const gchar*, const gchar*)) + gchar* (*quote_schema_name)(const gchar*, const gchar*), + gchar* (*normalise_case)(const gchar*)) { MdbBackend *backend = g_malloc0(sizeof(MdbBackend)); backend->capabilities = capabilities; @@ -420,6 +458,7 @@ void mdb_register_backend(MdbHandle *mdb, char *backend_name, guint32 capabiliti backend->table_comment_statement = table_comment_statement; backend->per_table_comment_statement = per_table_comment_statement; backend->quote_schema_name = quote_schema_name; + backend->normalise_case = normalise_case; g_hash_table_insert(mdb->backends, backend_name, backend); } @@ -548,6 +587,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace) fprintf (outfile, "-- CREATE INDEXES ...\n"); quoted_table_name = mdb->default_backend->quote_schema_name(dbnamespace, table->name); + quoted_table_name = mdb->default_backend->normalise_case(quoted_table_name); for (i=0;inum_idxs;i++) { idx = g_ptr_array_index (table->indices, i); @@ -569,6 +609,8 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace) quoted_name = mdb->default_backend->quote_schema_name(dbnamespace, index_name); } + quoted_name = normalise_and_replace(mdb, "ed_name); + if (idx->index_type==1) { switch (backend) { case MDB_BACKEND_ORACLE: @@ -604,6 +646,7 @@ mdb_print_indexes(FILE* outfile, MdbTableDef *table, char *dbnamespace) fprintf(outfile, ", "); col=g_ptr_array_index(table->columns,idx->key_col_num[j]-1); quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); + quoted_name = normalise_and_replace(mdb, "ed_name); fprintf (outfile, "%s", quoted_name); if (idx->index_type!=1 && idx->key_col_order[j]) /* no DESC for primary keys */ @@ -711,8 +754,11 @@ mdb_get_relationships(MdbHandle *mdb, const gchar *dbnamespace, const char* tabl * be namespaced. */ quoted_constraint_name = mdb->default_backend->quote_schema_name(NULL, constraint_name); + quoted_constraint_name = normalise_and_replace(mdb, "ed_constraint_name); quoted_column_1 = mdb->default_backend->quote_schema_name(NULL, bound[0]); + quoted_column_1 = normalise_and_replace(mdb, "ed_column_1); quoted_column_2 = mdb->default_backend->quote_schema_name(NULL, bound[2]); + quoted_column_2 = normalise_and_replace(mdb, "ed_column_2); break; default: @@ -795,6 +841,7 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace, const char *prop_value; quoted_table_name = mdb->default_backend->quote_schema_name(dbnamespace, entry->object_name); + quoted_table_name = normalise_and_replace(mdb, "ed_table_name); /* drop the table if it exists */ if (export_options & MDB_SHEXP_DROPTABLE) @@ -814,6 +861,7 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace, col = g_ptr_array_index (table->columns, i); quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); + quoted_name = normalise_and_replace(mdb, "ed_name); fprintf (outfile, "\t%s\t\t\t%s", quoted_name, mdb_get_colbacktype_string (col)); g_free(quoted_name); @@ -916,6 +964,7 @@ generate_table_schema(FILE *outfile, MdbCatalogEntry *entry, char *dbnamespace, continue; quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); + quoted_name = normalise_and_replace(mdb, "ed_name); if (export_options & MDB_SHEXP_CST_NOTEMPTY) { prop_value = mdb_col_get_prop(col, "AllowZeroLength"); diff --git a/src/libmdb/fakeglib.c b/src/libmdb/fakeglib.c index a2199d4..5198e9f 100644 --- a/src/libmdb/fakeglib.c +++ b/src/libmdb/fakeglib.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef HAVE_ICONV #include #endif @@ -259,6 +260,30 @@ gchar *g_locale_to_utf8(const gchar *opsysstring, size_t len, return utf8; } +gchar *g_utf8_strdown(const gchar *str, gssize len) { + gssize i = 0; + if (len == -1) + len = strlen(str); + gchar *lower = malloc(len+1); + while (idefault_backend->quote_schema_name(namespace, table_name); + quoted_name = mdb->default_backend->normalise_case(quoted_name); fprintf(outfile, "INSERT INTO %s (", quoted_name); free(quoted_name); for (i = 0; i < table->num_cols; i++) { if (i > 0) fputs(", ", outfile); col = g_ptr_array_index(table->columns, i); quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); + quoted_name = mdb->default_backend->normalise_case(quoted_name); fputs(quoted_name, outfile); free(quoted_name); } @@ -284,12 +286,14 @@ main(int argc, char **argv) if (insert_dialect) { char *quoted_name; quoted_name = mdb->default_backend->quote_schema_name(namespace, table_name); + quoted_name = mdb->default_backend->normalise_case(quoted_name); fprintf(outfile, "INSERT INTO %s (", quoted_name); free(quoted_name); for (i = 0; i < table->num_cols; i++) { if (i > 0) fputs(", ", outfile); col = g_ptr_array_index(table->columns, i); quoted_name = mdb->default_backend->quote_schema_name(NULL, col->name); + quoted_name = mdb->default_backend->normalise_case(quoted_name); fputs(quoted_name, outfile); free(quoted_name); }