From: Mark Cave-Ayland Date: Tue, 22 Dec 2009 12:28:35 +0000 (+0000) Subject: More improvements to the shapefile loader: X-Git-Tag: 1.5.0b1~58 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c0b845864c076e3e0de800b3846ced01b1a5708;p=postgis More improvements to the shapefile loader: - 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 --- diff --git a/loader/shp2pgsql-core.c b/loader/shp2pgsql-core.c index 036cfb39d..a96d842ed 100644 --- a/loader/shp2pgsql-core.c +++ b/loader/shp2pgsql-core.c @@ -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 */ diff --git a/loader/shp2pgsql-gui.c b/loader/shp2pgsql-gui.c index 1996e7c39..d5327aa35 100644 --- a/loader/shp2pgsql-gui.c +++ b/loader/shp2pgsql-gui.c @@ -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);