[patch] exporting indexes

Nirgal Vourgère <[email protected]> Tue, 8 Feb 2011 23:49:11 +0000
Newsgroups gmane.comp.db.mdb-tools.devel
Message-ID <[email protected]>
Here is a more intrusive patch, mostly for indexes:

* I was fed up with adding code both in util/mdb-schema.c and gmdb2/schema.c. These were mostly duplicated code.
So I moved the common parts in libmdb/backend.c, that means a new function called "print_schema" that will call the relevant code.

* Indexed now are generated for postgres backend: normal ones, unique ones, and primary keys.

* Fixed a bug in where all the foreign keys were generated when you export only one table (added a parameter to mdb_get_relationships).

* Now using PATH_MAX and MDB_MAX_OBJ_NAME macro for sizes of constants in gmdb2/schema.c, rather than hardcoded values 256/100.


Question:
Do we want to keep all the "sanitize" stuff?? We now have proper escaping for all backends, I think.

------------------------------------------------------------------------------
The ultimate all-in-one performance toolkit: Intel(R) Parallel Studio XE:
Pinpoint memory and threading errors before they happen.
Find and fix more than 250 security defects in the development cycle.
Locate bottlenecks in serial and parallel code that limit performance.
http://p.sf.net/sfu/intel-dev2devfeb

_______________________________________________
mdbtools-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mdbtools-dev
schema-indexes.patch (text/x-patch, 18.4 KB)
Index: mdbtools-0.6pre1+git20110208/src/util/mdb-schema.c
===================================================================
--- mdbtools-0.6pre1+git20110208.orig/src/util/mdb-schema.c
+++ mdbtools-0.6pre1+git20110208/src/util/mdb-schema.c
@@ -24,18 +24,13 @@
 #include "dmalloc.h"
 #endif
 
-static void generate_table_schema(MdbCatalogEntry *entry, char *namespace, int sanitize);
-
 int
 main (int argc, char **argv)
 {
-	unsigned int   i;
 	MdbHandle *mdb;
-	MdbCatalogEntry *entry;
-	char		*the_relation;
 	char *tabname = NULL;
 	char *namespace = NULL;
-	int s = 0;
+	int sanitize = 0;
 	int opt;
 
 	if (argc < 2) {
@@ -56,7 +51,7 @@
 				namespace = (char *) g_strdup(optarg);
 			break;
 			case 'S':
-				s = 1;
+				sanitize = 1;
 			break;
 		}
 	}
@@ -81,142 +76,17 @@
 
 	/* read the catalog */
  	if (!mdb_read_catalog (mdb, MDB_TABLE)) {
-		fprintf(stderr,"File does not appear to be an Access database\n");
+		fprintf(stderr, "File does not appear to be an Access database\n");
 		exit(1);
 	}
 
-	/* Print out a little message to show that this came from mdb-tools.
-	   I like to know how something is generated. DW */
-	fprintf(stdout,"-------------------------------------------------------------\n");
-	fprintf(stdout,"-- MDB Tools - A library for reading MS Access database files\n");
-	fprintf(stdout,"-- Copyright (C) 2000-2004 Brian Bruns\n");
-	fprintf(stdout,"-- Files in libmdb are licensed under LGPL and the utilities under\n");
-	fprintf(stdout,"-- the GPL, see COPYING.LIB and COPYING files respectively.\n");
-	fprintf(stdout,"-- Check out http://mdbtools.sourceforge.net\n");
-	fprintf(stdout,"-------------------------------------------------------------\n\n");
-
-	for (i=0; i < mdb->num_catalog; i++) {
-		entry = g_ptr_array_index (mdb->catalog, i);
-		if (entry->object_type == MDB_TABLE) {
-			if ((tabname && !strcmp(entry->object_name, tabname)) 
-			 || (!tabname && mdb_is_user_table(entry))) {
-				generate_table_schema(entry, namespace, s);
-			}
-		}
-	}
+	print_schema(stdout, mdb, tabname, namespace, sanitize, 1, 1);
 
-	fprintf (stdout, "\n\n");
-	fprintf (stdout, "-- CREATE ANY Relationships ...\n");
-	fprintf (stdout, "\n");
-	while ((the_relation=mdb_get_relationships(mdb)) != NULL) {
-		fprintf(stdout,"%s\n",the_relation);
-		g_free(the_relation);
-	}            
- 
 	g_free(namespace);
 	g_free(tabname);
 	mdb_close (mdb);
 	mdb_exit();
 
-	exit(0);
+	return 0;
 }
-static void
-generate_table_schema(MdbCatalogEntry *entry, char *namespace, int sanitize)
-{
-	MdbTableDef *table;
-	MdbHandle *mdb = entry->mdb;
-	unsigned int i;
-	MdbColumn *col;
-	char* table_name;
-	char* quoted_table_name;
-	char* quoted_name;
-	char* sql_sequences;
-
-	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;
-	}
 
-	/* drop the table if it exists */
-	fprintf (stdout, "DROP TABLE %s;\n", quoted_table_name);
-
-	/* create the table */
-	fprintf (stdout, "CREATE TABLE %s\n", quoted_table_name);
-	fprintf (stdout, " (\n");
-
-	table = mdb_read_table (entry);
-
-	/* get the columns */
-	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);
-		fprintf (stdout, "\t%s\t\t\t%s", quoted_name,
-			mdb_get_coltype_string (mdb->default_backend, col->col_type));
-		free(quoted_name);
-		   
-		if (mdb_coltype_takes_length(mdb->default_backend, 
-			col->col_type)) {
-
-			/* more portable version from DW patch */	
-			if (col->col_size == 0) 
-	    			fprintf (stdout, " (255)");
-			else 
-	    			fprintf (stdout, " (%d)", col->col_size);
-		}
-		   
-		if (i < table->num_cols - 1)
-			fprintf (stdout, ", \n");
-		else
-			fprintf (stdout, "\n");
-	} /* for */
-
-	fprintf (stdout, ");\n");
-
-	fprintf (stdout, "-- CREATE SEQUENCES ...\n");
-	fprintf (stdout, "\n");
-
-	while ((sql_sequences = mdb_get_sequences(entry, namespace, sanitize)))
-		fprintf(stdout, sql_sequences);
-
-	/*
-	for (i = 0; i < table->num_cols; i++) {
-		col = g_ptr_array_index (table->columns, i);
-		if (col->is_long_auto) {
-			char sequence_name[256+1+256+4]; // FIXME
-			char *quoted_column_name;
-			quoted_column_name = mdb->default_backend->quote_name(col->name);
-			sprintf(sequence_name, "%s_%s_seq", entry->object_name, col->name);
-			quoted_name = mdb->default_backend->quote_name(sequence_name);
-			fprintf (stdout, "CREATE SEQUENCE %s;\n", quoted_name);
-			fprintf (stdout, "ALTER TABLE %s ALTER COLUMN %s SET DEFAULT pg_catalog.nextval('%s');\n",
-				quoted_table_name, quoted_column_name, quoted_name);
-			free(quoted_column_name);
-			free(quoted_name);
-		}
-
-	}
-	*/
-
-	fprintf (stdout, "-- CREATE ANY INDEXES ...\n");
-	fprintf (stdout, "\n");
-
-	free(quoted_table_name);
-
-	mdb_free_tabledef (table);
-}
Index: mdbtools-0.6pre1+git20110208/src/libmdb/backend.c
===================================================================
--- mdbtools-0.6pre1+git20110208.orig/src/libmdb/backend.c
+++ mdbtools-0.6pre1+git20110208/src/libmdb/backend.c
@@ -279,7 +279,9 @@
 
 /**
  * mdb_get_sequences
- * @mdb: Handle to open MDB database file
+ * @entry: Handle to open MDB database file
+ * @namespace: Prefix for output names
+ * @sanitize: Remove weird characters if true
  *
  * Generates sequences and set default values
  *
@@ -311,8 +313,8 @@
 		backend = 2;
 	} else {
 		return (char *) g_strconcat(
-			"-- sequences are not supported for ",
-			mdb->backend_name, NULL);
+			"-- sequences are not implemented for ",
+			mdb->backend_name, "\n", NULL);
 	}
 
 	/* get the columns */
@@ -361,8 +363,89 @@
 
 
 /**
+ * mdb_print_indexes
+ * @output: Where to print the sql
+ * @table: Table to process
+ */
+void
+mdb_print_indexes(FILE* output, MdbTableDef *table, char *namespace, int sanitize)
+{
+	unsigned int i, j;
+	char* quoted_table_name;
+	char* index_name;
+	char* quoted_name;
+	MdbHandle* mdb = table->entry->mdb;
+	MdbIndex *idx;
+	MdbColumn *col;
+
+	if (strcmp(mdb->backend_name, "postgres")) {
+		fprintf(output, "-- Indexes are not implemented for %s\n\n", mdb->backend_name);
+		return;
+	}
+
+	/* read indexes */
+	mdb_read_indices(table);
+
+	fprintf (output, "-- CREATE ANY INDEXES ...\n");
+
+	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_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);
+		strcpy(index_name, table->name);
+		strcat(index_name, idx->name);
+		if (idx->index_type==1)
+			strcat(index_name, "_pk");
+		else
+			strcat(index_name, "_idx");
+		if (sanitize)
+			quoted_name = sanitize_name(index_name);
+		else
+			quoted_name = mdb->default_backend->quote_name(index_name);
+		if (idx->index_type==1) {
+			fprintf (output, "ALTER TABLE %s ADD CONSTRAINT %s PRIMARY KEY (", quoted_table_name, quoted_name);
+		} else {
+			fprintf(output, "CREATE");
+			if (idx->flags & MDB_IDX_UNIQUE)
+				fprintf (output, " UNIQUE");
+			fprintf(output, " INDEX %s ON %s (", quoted_name, quoted_table_name);
+		}
+		free(quoted_name);
+		free(index_name);
+
+		for (j=0;j<idx->num_keys;j++) {
+			if (j)
+				fprintf(output, ", ");
+			col=g_ptr_array_index(table->columns,idx->key_col_num[j]-1);
+			if (sanitize)
+				quoted_name = sanitize_name(col->name);
+			else
+				quoted_name = mdb->default_backend->quote_name(col->name);
+			fprintf (output, "%s", quoted_name);
+			if (idx->index_type!=1 && idx->key_col_order[j])
+				/* no DESC for primary keys */
+				fprintf(output, " DESC");
+
+			free(quoted_name);
+
+		}
+		fprintf (output, ");\n");
+	}
+	fprintf (output, "\n");
+	fprintf (output, "\n");
+}
+
+/**
  * mdb_get_relationships
  * @mdb: Handle to open MDB database file
+ * @tablename: Name of the table to process. Process all tables if NULL.
  *
  * Generates relationships by reading the MSysRelationships table.
  *   'szColumn' contains the column name of the child table.
@@ -377,7 +460,7 @@
  *   Returns NULL on last iteration.
  *   The caller is responsible for freeing this string.
  */
-char *mdb_get_relationships(MdbHandle *mdb)
+char *mdb_get_relationships(MdbHandle *mdb, const char* tablename)
 {
 	unsigned int i;
 	gchar *text = NULL;  /* String to be returned */
@@ -386,7 +469,6 @@
 	int backend = 0;  /* Backends: 1=oracle, 2=postgres */
 	char *quoted_table_1, *quoted_column_1,
 	     *quoted_table_2, *quoted_column_2,
-	     *index_name, *quoted_index_name,
 	     *constraint_name, *quoted_constraint_name;
 	long grbit;
 
@@ -399,7 +481,7 @@
 			is_init = 1;
 			return (char *) g_strconcat(
 				"-- relationships are not supported for ",
-				mdb->backend_name, NULL);
+				mdb->backend_name, "\n", NULL);
 		} else { /* the second time through */
 			is_init = 0;
 			return NULL;
@@ -438,11 +520,15 @@
 		}
 	}
 
-	if (!mdb_fetch_row(table)) {
-		for (i=0;i<5;i++)
-			g_free(bound[i]);
-		is_init = 0;
-		return NULL;
+	while (1) {
+		if (!mdb_fetch_row(table)) {
+			for (i=0;i<5;i++)
+				g_free(bound[i]);
+			is_init = 0;
+			return NULL;
+		}
+		if (!tablename || !strcmp(bound[1], tablename))
+			break;
 	}
 
 	quoted_table_1 = mdb->default_backend->quote_name(bound[1]);
@@ -453,9 +539,6 @@
 	constraint_name = g_strconcat(bound[1], "_", bound[0], "_fk", NULL);
 	quoted_constraint_name = mdb->default_backend->quote_name(constraint_name);
 	free(constraint_name);
-	index_name = g_strconcat(bound[3], "_", bound[2], "_idx", NULL);
-	quoted_index_name = mdb->default_backend->quote_name(index_name);
-	free(index_name);
 
 	if (grbit & 0x00000002) {
 		text = g_strconcat(
@@ -484,8 +567,127 @@
 	free(quoted_table_2);
 	free(quoted_column_2);
 	free(quoted_constraint_name);
-	free(quoted_index_name);
 
 	return (char *)text;
 }
+
+static void
+generate_table_schema(FILE *output, MdbCatalogEntry *entry, int use_drop, char *namespace, int sanitize)
+{
+	MdbTableDef *table;
+	MdbHandle *mdb = entry->mdb;
+	MdbColumn *col;
+	unsigned int i;
+	char* table_name;
+	char* quoted_table_name;
+	char* quoted_name;
+	char* sql_sequences;
+
+	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;
+	}
+
+	/* drop the table if it exists */
+	fprintf (output, "DROP TABLE %s;\n", quoted_table_name);
+
+	/* create the table */
+	fprintf (output, "CREATE TABLE %s\n", quoted_table_name);
+	fprintf (output, " (\n");
+
+	table = mdb_read_table (entry);
+
+	/* get the columns */
+	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);
+		fprintf (output, "\t%s\t\t\t%s", quoted_name,
+			mdb_get_coltype_string (mdb->default_backend, col->col_type));
+		free(quoted_name);
+
+		if (mdb_coltype_takes_length(mdb->default_backend,
+			col->col_type)) {
+
+			/* more portable version from DW patch */
+			if (col->col_size == 0)
+	    			fputs(" (255)", output);
+			else
+	    			fprintf(output, " (%d)", col->col_size);
+		}
+
+		if (i < table->num_cols - 1)
+			fputs(", \n", output);
+		else
+			fputs("\n", output);
+	} /* for */
+
+	fputs(");\n", output);
+
+	fputs("-- CREATE SEQUENCES ...\n", output);
+	fputs("\n", output);
+
+	while ((sql_sequences = mdb_get_sequences(entry, namespace, sanitize)))
+		fprintf(output, sql_sequences);
+
+	// prints all the indexes of that table
+	mdb_print_indexes(output, table, namespace, sanitize);
+
+	free(quoted_table_name);
+
+	mdb_free_tabledef (table);
+}
+
+
+void
+print_schema(FILE *output, MdbHandle *mdb, char *tabname, char *namespace, int sanitize, int drops, int relation)
+{
+	unsigned int   i;
+	char		*the_relation;
+	MdbCatalogEntry *entry;
+
+	/* Print out a little message to show that this came from mdb-tools.
+	   I like to know how something is generated. DW */
+	fputs("-------------------------------------------------------------\n", output);
+	fputs("-- MDB Tools - A library for reading MS Access database files\n", output);
+	fputs("-- Copyright (C) 2000-2011 Brian Bruns and others.\n", output);
+	fputs("-- Files in libmdb are licensed under LGPL and the utilities under\n", output);
+	fputs("-- the GPL, see COPYING.LIB and COPYING files respectively.\n", output);
+	fputs("-- Check out http://mdbtools.sourceforge.net\n", output);
+	fputs("-------------------------------------------------------------\n\n", output);
+
+	for (i=0; i < mdb->num_catalog; i++) {
+		entry = g_ptr_array_index (mdb->catalog, i);
+		if (entry->object_type == MDB_TABLE) {
+			if ((tabname && !strcmp(entry->object_name, tabname))
+			 || (!tabname && mdb_is_user_table(entry))) {
+				generate_table_schema(output, entry, drops, namespace, sanitize);
+			}
+		}
+	}
+	fprintf (output, "\n");
+
+	if (relation) {
+		fputs ("-- CREATE Relationships ...\n", output);
+		while ((the_relation=mdb_get_relationships(mdb, tabname)) != NULL) {
+			fputs(the_relation, output);
+			g_free(the_relation);
+		}
+	}
+}
 #endif
Index: mdbtools-0.6pre1+git20110208/include/mdbtools.h
===================================================================
--- mdbtools-0.6pre1+git20110208.orig/include/mdbtools.h
+++ mdbtools-0.6pre1+git20110208/include/mdbtools.h
@@ -463,7 +463,8 @@
 extern void mdb_remove_backends();
 extern int  mdb_set_default_backend(MdbHandle *mdb, const char *backend_name);
 extern char *mdb_get_sequences(MdbCatalogEntry *entry, char *namespace, int sanitize);
-extern char *mdb_get_relationships(MdbHandle *mdb);
+extern char *mdb_get_relationships(MdbHandle *mdb, const char* tablename);
+extern void print_schema(FILE *output, MdbHandle *mdb, char *tabname, char *namespace, int sanitize, int drops, int relation);
 
 /* sargs.c */
 extern int mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields);
Index: mdbtools-0.6pre1+git20110208/src/gmdb2/schema.c
===================================================================
--- mdbtools-0.6pre1+git20110208.orig/src/gmdb2/schema.c
+++ mdbtools-0.6pre1+git20110208/src/gmdb2/schema.c
@@ -26,8 +26,8 @@
 
 GladeXML *schemawin_xml;
 static gchar backend[100];
-static gchar tabname[100];
-static gchar file_path[256];
+static gchar tabname[MDB_MAX_OBJ_NAME+1];
+static gchar file_path[PATH_MAX+1];
 static gchar relation;
 static gchar drops;
 
@@ -37,18 +37,6 @@
 gmdb_schema_export()
 {
 FILE *outfile;
-MdbTableDef *table;
-MdbCatalogEntry *entry;
-MdbColumn *col;
-int i,k;
-int need_headers = 0;
-int need_quote = 0;
-gchar delimiter[11];
-gchar quotechar;
-gchar lineterm[5];
-gchar *str;
-int rows=0;
-char            *the_relation;
 
 	GtkWidget *dlg;
 
@@ -63,62 +51,7 @@
 	}
 	mdb_set_default_backend(mdb,backend);
 
-	for (i=0; i < mdb->num_catalog; i++) {
-		entry = g_ptr_array_index (mdb->catalog, i);
-
-		if (entry->object_type != MDB_TABLE)
-			continue;
-		/* Do not show system tables if table name is not specified */
-		if (mdb_is_system_table(entry) && !strlen(tabname))
-			continue;
-		/* If object name does not match the table specified */
-		if (strlen(tabname) && strcmp(entry->object_name, tabname))
-			continue;
-
-	       /* drop the table if it exists */
-	       if (drops=='Y') 
-		       fprintf(outfile, "DROP TABLE %s;\n", entry->object_name);
-
-	       /* create the table */
-	       fprintf (outfile, "CREATE TABLE %s\n", entry->object_name);
-	       fprintf (outfile, " (\n");
-	       	       
-	       table = mdb_read_table (entry);
-
-	       /* get the columns */
-	       mdb_read_columns (table);
-
-	       /* loop over the columns, dumping the names and types */
-
-	       for (k = 0; k < table->num_cols; k++) {
-		   col = g_ptr_array_index (table->columns, k);
-		   
-		   fprintf (outfile, "\t%s\t\t\t%s", col->name, 
-			    mdb_get_coltype_string (mdb->default_backend, col->col_type));
-		   
-		   if (col->col_size != 0)
-		     fprintf (outfile, " (%d)", col->col_size);
-		   
-		   if (k < table->num_cols - 1)
-		     fprintf (outfile, ", \n");
-		   else
-		     fprintf (outfile, "\n");
-		 }
-
-	       fprintf (outfile, "\n);\n");
-	       fprintf (outfile, "-- CREATE ANY INDEXES ...\n");
-	       fprintf (outfile, "\n");
-	}
-	fprintf (outfile, "\n\n");
-
-	if (relation=='Y') {
-		fprintf (outfile, "-- CREATE ANY Relationships ...\n");
-		fprintf (outfile, "\n");
-		while ((the_relation=mdb_get_relationships(mdb)) != NULL) {
-			fprintf(outfile,"%s\n",the_relation);
-			g_free(the_relation);
-		}            
- 	}
+	print_schema(outfile, mdb, *tabname?tabname:NULL, NULL, 0, drops=='Y', relation=='Y');
 
 	fclose(outfile);
 	dlg = gtk_message_dialog_new (NULL,
@@ -135,10 +68,14 @@
 	schemawin = glade_xml_get_widget (schemawin_xml, "schema_dialog");
 
 	entry = glade_xml_get_widget (schemawin_xml, "filename_entry");
-	strncpy(file_path,gtk_entry_get_text(GTK_ENTRY(entry)),255);
+	strncpy(file_path,gtk_entry_get_text(GTK_ENTRY(entry)),PATH_MAX);
+	file_path[PATH_MAX]=0;
+
 	combo = glade_xml_get_widget (schemawin_xml, "table_combo");
-	strncpy(tabname,gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),99);
+	strncpy(tabname,gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),MDB_MAX_OBJ_NAME);
+	tabname[MDB_MAX_OBJ_NAME]=0;
 	if (!strcmp(tabname,ALL_TABLES)) tabname[0]='\0';
+
 	combo = glade_xml_get_widget (schemawin_xml, "backend_combo");
 	if (!strcmp(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),"Oracle")) strcpy(backend,"oracle");
 	else if (!strcmp(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),"Sybase")) strcpy(backend,"sybase");
@@ -146,6 +83,7 @@
 	else if (!strcmp(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),"PostgreSQL")) strcpy(backend,"postgres");
 	else if (!strcmp(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry)),"MySQL")) strcpy(backend,"mysql");
 	else strcpy(backend,"access");
+
 	checkbox = glade_xml_get_widget (schemawin_xml, "rel_checkbox");
 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox)))
 		relation = 'Y';