]> granicus.if.org Git - postgis/commitdiff
More improvements to the shapefile loader:
authorMark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Tue, 22 Dec 2009 12:28:35 +0000 (12:28 +0000)
committerMark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
Tue, 22 Dec 2009 12:28:35 +0000 (12:28 +0000)
 - Fix COPY support for shapefiles containing more than 1 record
 - Fix cancellation on mid-import
 - Remove progress logging on import, and replace with flashly progress bar

git-svn-id: http://svn.osgeo.org/postgis/trunk@5044 b70326c6-7e19-0410-871a-916f4a2858ee

loader/shp2pgsql-core.c
loader/shp2pgsql-gui.c

index 036cfb39d4801be169d809e2e81f70472446a0e2..a96d842ed50491f2d45572d07066547cf402035d 100644 (file)
@@ -1720,8 +1720,8 @@ ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strreco
                                /* Output SRID if relevant */
                                if (state->config->sr_id != 0)
                                        vasbappend(sb, ", %d)", state->config->sr_id);
-       
-                               vasbappend(sb, ");");
+                               else
+                                       vasbappend(sb, ")");
                        }
                }
                else
@@ -1733,19 +1733,17 @@ ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strreco
                        vasbappend(sb, "%s", geometry);
        
                        if (!state->config->dump_format)
-                               vasbappend(sb, "');");
+                               vasbappend(sb, "'");
                }
 
                /* Tidy up everything */
                SHPDestroyObject(obj);
                free(geometry);
        }
-       else
-       {
-               /* Close the line correctly for dump/insert format */
-               if (!state->config->dump_format)
-                       vasbappend(sb, ");");
-       }
+
+       /* Close the line correctly for dump/insert format */
+       if (!state->config->dump_format)
+               vasbappend(sb, ");");
 
 
        /* Copy the string buffer into a new string, destroying the string buffer */
index 1996e7c39364a2b83aed219800ef4d7fb1022c59..d5327aa352d2aee9f9bd130c00c9240419204831 100644 (file)
@@ -38,6 +38,7 @@ static GtkWidget *entry_config_geocolumn;
 static GtkWidget *label_pg_connection_test;
 static GtkWidget *textview_log;
 static GtkWidget *file_chooser_button_shape;
+static GtkWidget *progress;
 static GtkTextBuffer *textbuffer_log;
 
 /* Options window */
@@ -58,6 +59,8 @@ static SHPLOADERCONFIG *config;
 static SHPLOADERSTATE *state;
 static SHPCONNECTIONCONFIG *conn;
 
+static volatile int import_running = 0;
+
 
 /*
 ** Write a message to the Import Log text area.
@@ -351,7 +354,6 @@ pgui_copy_start(const char *sql)
 static int
 pgui_copy_write(const char *line)
 {
-
        /* We need a connection to do anything. */
        if ( ! pg_connection ) return 0;
        if ( ! line ) return 0;
@@ -365,6 +367,9 @@ pgui_copy_write(const char *line)
                return 0;
        }
 
+       /* Send linefeed to signify end of line */
+       PQputCopyData(pg_connection, "\n", 1);
+
        return 1;
 }
 
@@ -441,7 +446,10 @@ pgui_read_connection(void)
 static void
 pgui_action_cancel(GtkWidget *widget, gpointer data)
 {
-       pgui_quit(widget, data); /* quit if we're not running */
+       if (!import_running)
+               pgui_quit(widget, data); /* quit if we're not running */
+       else
+               import_running = FALSE;
 }
 
 static void
@@ -562,9 +570,9 @@ pgui_action_import(GtkWidget *widget, gpointer data)
 {
        char *connection_string = NULL;
        char *dest_string = NULL;
-       int ret, i;
+       int ret, i = 0;
        char *header, *footer, *record; 
-       int log_frequency = 500;
+       PGresult *result;
 
 
        if ( ! (connection_string = pgui_read_connection() ) )
@@ -657,8 +665,8 @@ pgui_action_import(GtkWidget *widget, gpointer data)
        /* If we are in COPY (dump format) mode, output the COPY statement and enter COPY mode */
        if (state->config->dump_format)
        {
-               log_frequency = 5000; /* log less often so we run faster */
                ret = ShpLoaderGetSQLCopyStatement(state, &header);
+
                if (ret != SHPLOADEROK)
                {
                        pgui_logf("%s", state->message);
@@ -676,7 +684,10 @@ pgui_action_import(GtkWidget *widget, gpointer data)
        }
 
        /* Main loop: iterate through all of the records and send them to stdout */
-       for (i = 0; i < ShpLoaderGetRecordCount(state); i++)
+       pgui_logf("Importing shapefile (%d records)...", ShpLoaderGetRecordCount(state));
+
+       import_running = TRUE;
+       for (i = 0; i < ShpLoaderGetRecordCount(state) && import_running; i++)
        {
                ret = ShpLoaderGenerateSQLRowStatement(state, i, &record);
 
@@ -689,10 +700,6 @@ pgui_action_import(GtkWidget *widget, gpointer data)
                                else
                                        ret = pgui_exec(record);
 
-                               /* Display a record number as we load */
-                               if ((i % log_frequency) == 0)
-                                       pgui_logf("Loaded record number #%d", i);
-
                                /* Display a record number if we failed */
                                if (!ret)
                                        pgui_logf("Failed record number #%d", i);
@@ -703,7 +710,7 @@ pgui_action_import(GtkWidget *widget, gpointer data)
                        case SHPLOADERERR:
                                /* Display the error message then stop */
                                pgui_logf("%s\n", state->message);
-                               return;
+                               goto import_cleanup;
                                break;
 
                        case SHPLOADERWARN:
@@ -731,6 +738,9 @@ pgui_action_import(GtkWidget *widget, gpointer data)
                                break;
                }
 
+               /* Update the progress bar */
+               gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (float)i / ShpLoaderGetRecordCount(state));
+
                /* Allow GTK events to get a look in */
                while (gtk_events_pending())
                        gtk_main_iteration();
@@ -741,30 +751,51 @@ pgui_action_import(GtkWidget *widget, gpointer data)
        {
                if (! pgui_copy_end(0) )
                        goto import_cleanup;
+
+               result = PQgetResult(pg_connection);
+               if (PQresultStatus(result) != PGRES_COMMAND_OK)
+               {
+                       pgui_logf("COPY failed with the following error: %s", PQerrorMessage(pg_connection));
+                       ret = SHPLOADERERR;
+                       goto import_cleanup;
+               }
        }
 
-       /* Get the footer */
-       ret = ShpLoaderGetSQLFooter(state, &footer);
-       if (ret != SHPLOADEROK)
+       /* Only continue if we didn't abort part way through */
+       if (import_running)
        {
-               pgui_logf("%s\n", state->message);
-
-               if (ret == SHPLOADERERR)
+               /* Get the footer */
+               ret = ShpLoaderGetSQLFooter(state, &footer);
+               if (ret != SHPLOADEROK)
+               {
+                       pgui_logf("%s\n", state->message);
+       
+                       if (ret == SHPLOADERERR)
+                               goto import_cleanup;
+               }
+       
+               /* Send the footer to the server */
+               ret = pgui_exec(footer);
+               free(footer);
+       
+               if (!ret)
                        goto import_cleanup;
        }
 
-       /* Send the footer to the server */
-       ret = pgui_exec(footer);
-       free(footer);
 
-       if (!ret)
-               return;
+import_cleanup:
+       /* If we didn't finish inserting all of the items, an error occurred */
+       if (i != ShpLoaderGetRecordCount(state) || !ret)
+               pgui_logf("Shapefile import failed");
+       else
+               pgui_logf("Shapefile import completed");
 
        /* Free the state object */
        ShpLoaderDestroy(state);
 
+       /* Import has definitely finished */
+       import_running = FALSE;
 
-import_cleanup:
        /* Enable the button once again */
        gtk_widget_set_sensitive(widget, TRUE);
 
@@ -772,6 +803,9 @@ import_cleanup:
        gtk_widget_hide(widget);
        gtk_widget_show(widget);
 
+       /* Reset the progress bar */
+       gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.0);
+
        /* Allow GTK events to get a look in */
        while (gtk_events_pending())
                gtk_main_iteration();
@@ -1028,6 +1062,10 @@ pgui_create_main_window(const SHPCONNECTIONCONFIG *conn)
        /* Add table into containing frame */
        gtk_container_add (GTK_CONTAINER (frame_config), table_config);
 
+       /* Progress bar for the import */
+       progress = gtk_progress_bar_new();
+       gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(progress), GTK_PROGRESS_LEFT_TO_RIGHT);
+       gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.0);
 
        /*
        ** Row of action buttons
@@ -1074,6 +1112,7 @@ pgui_create_main_window(const SHPCONNECTIONCONFIG *conn)
        gtk_box_pack_start(GTK_BOX(vbox_main), frame_pg, FALSE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_main), frame_config, FALSE, TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_main), hbox_buttons, FALSE, FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox_main), progress, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox_main), frame_log, TRUE, TRUE, 0);
        /* and insert the vbox into the main window  */
        gtk_container_add (GTK_CONTAINER (window_main), vbox_main);