PostGIS  2.1.10dev-r@@SVN_REVISION@@
static void pgui_action_import ( GtkWidget *  widget,
gpointer  data 
)
static

Definition at line 1415 of file shp2pgsql-gui.c.

References _, shp_loader_state::config, connection_test(), shp_loader_config::createindex, dialog_progress, shp_loader_config::dump_format, FALSE, shp_loader_config::geo_col, shp_loader_config::geography, import_file_list_store, IMPORT_POINTER_COLUMN, is_running, label_progress, lw_asprintf(), shp_loader_state::message, shp_loader_config::opt, pg_connection, shp_loader_state::pgdims, shp_loader_state::pgtype, pgui_copy_end(), pgui_copy_start(), pgui_copy_write(), pgui_exec(), pgui_logf(), pgui_raise_error_dialogue(), pgui_seterr(), progress, shp_loader_config::readshape, result, shp_loader_config::schema, shp_loader_config::shp_file, ShpDumperGetConnectionStringFromConn(), shp_loader_state::shpfiletype, ShpLoaderCreate(), ShpLoaderDestroy(), SHPLOADERERR, ShpLoaderGenerateSQLRowStatement(), ShpLoaderGetRecordCount(), ShpLoaderGetSQLCopyStatement(), ShpLoaderGetSQLFooter(), ShpLoaderGetSQLHeader(), SHPLOADEROK, ShpLoaderOpenShape(), SHPLOADERRECDELETED, SHPLOADERRECISNULL, SHPLOADERWARN, SHPTypeName(), shp_loader_config::simple_geometries, shp_loader_config::sr_id, shp_loader_config::table, TRUE, update_conn_ui_from_conn_config(), validate_remote_loader_columns(), and window_conn.

Referenced by pgui_create_main_window().

1416 {
1417  SHPLOADERCONFIG *loader_file_config;
1418  SHPLOADERSTATE *state;
1419  gint is_valid;
1420  gpointer gptr;
1421  GtkTreeIter iter;
1422  char *sql_form, *query, *connection_string, *progress_text = NULL, *progress_shapefile = NULL;
1423  PGresult *result;
1424 
1425  int ret, i = 0;
1426  char *header, *footer, *record;
1427 
1428  /* Get the first row of the import list */
1429  is_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(import_file_list_store), &iter);
1430  if (!is_valid)
1431  {
1432  pgui_seterr(_("ERROR: You haven't specified any files to import"));
1434 
1435  return;
1436  }
1437 
1438  /* Firstly make sure that we can connect to the database - if we can't then there isn't much
1439  point doing anything else... */
1440  if (!connection_test())
1441  {
1442  pgui_seterr(_("Unable to connect to the database - please check your connection settings"));
1444 
1445  /* Open the connections UI for the user */
1447 
1448  gtk_widget_show_all(GTK_WIDGET(window_conn));
1449  return;
1450  }
1451 
1452  /* Let's open a single connection to the remote DB for the duration of the validation pass;
1453  note that we already know the connection string works, otherwise we would have bailed
1454  out earlier in the function */
1455  connection_string = ShpDumperGetConnectionStringFromConn(conn);
1456  pg_connection = PQconnectdb(connection_string);
1457 
1458  /* Setup the table/column type discovery query */
1459  sql_form = "SELECT a.attnum, a.attname AS field, t.typname AS type, a.attlen AS length, a.atttypmod AS precision FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n WHERE c.relname = '%s' AND n.nspname = '%s' AND a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid AND c.relnamespace = n.oid ORDER BY a.attnum";
1460 
1461  /* Validation: we loop through each of the files in order to validate them as a separate pass */
1462  while (is_valid)
1463  {
1464  /* Grab the SHPLOADERCONFIG for this row */
1465  gtk_tree_model_get(GTK_TREE_MODEL(import_file_list_store), &iter, IMPORT_POINTER_COLUMN, &gptr, -1);
1466  loader_file_config = (SHPLOADERCONFIG *)gptr;
1467 
1468  /* For each entry, we execute a remote query in order to determine the column names
1469  and types for the remote table if they actually exist */
1470  query = malloc(strlen(sql_form) + strlen(loader_file_config->schema) + strlen(loader_file_config->table) + 1);
1471  sprintf(query, sql_form, loader_file_config->table, loader_file_config->schema);
1472  result = PQexec(pg_connection, query);
1473 
1474  /* Call the validation function with the SHPLOADERCONFIG and the result set */
1475  ret = validate_remote_loader_columns(loader_file_config, result);
1476  if (ret == SHPLOADERERR)
1477  {
1479 
1480  PQclear(result);
1481  free(query);
1482 
1483  return;
1484  }
1485 
1486  /* Free the SQL query */
1487  PQclear(result);
1488  free(query);
1489 
1490  /* Get next entry */
1491  is_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(import_file_list_store), &iter);
1492  }
1493 
1494  /* Close our database connection */
1495  PQfinish(pg_connection);
1496 
1497 
1498  /* Once we've done the validation pass, now let's load the shapefile */
1499  is_valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(import_file_list_store), &iter);
1500  while (is_valid)
1501  {
1502  /* Grab the SHPLOADERCONFIG for this row */
1503  gtk_tree_model_get(GTK_TREE_MODEL(import_file_list_store), &iter, IMPORT_POINTER_COLUMN, &gptr, -1);
1504  loader_file_config = (SHPLOADERCONFIG *)gptr;
1505 
1506  pgui_logf("\n==============================");
1507  pgui_logf("Importing with configuration: %s, %s, %s, %s, mode=%c, dump=%d, simple=%d, geography=%d, index=%d, shape=%d, srid=%d", loader_file_config->table, loader_file_config->schema, loader_file_config->geo_col, loader_file_config->shp_file, loader_file_config->opt, loader_file_config->dump_format, loader_file_config->simple_geometries, loader_file_config->geography, loader_file_config->createindex, loader_file_config->readshape, loader_file_config->sr_id);
1508 
1509  /*
1510  * Loop through the items in the shapefile
1511  */
1512  is_running = TRUE;
1513 
1514  /* One connection per file, otherwise error handling becomes tricky... */
1515  pg_connection = PQconnectdb(connection_string);
1516 
1517  /* Disable the button to prevent multiple imports running at the same time */
1518  gtk_widget_set_sensitive(widget, FALSE);
1519 
1520  /* Allow GTK events to get a look in */
1521  while (gtk_events_pending())
1522  gtk_main_iteration();
1523 
1524  /* Create the shapefile state object */
1525  state = ShpLoaderCreate(loader_file_config);
1526 
1527  /* Open the shapefile */
1528  ret = ShpLoaderOpenShape(state);
1529  if (ret != SHPLOADEROK)
1530  {
1531  pgui_logf("%s", state->message);
1532 
1533  if (ret == SHPLOADERERR)
1534  goto import_cleanup;
1535  }
1536 
1537  /* For progress display, only show the "core" filename */
1538  for (i = strlen(loader_file_config->shp_file); i >= 0
1539  && loader_file_config->shp_file[i - 1] != '\\' && loader_file_config->shp_file[i - 1] != '/'; i--);
1540 
1541  progress_shapefile = malloc(strlen(loader_file_config->shp_file));
1542  strcpy(progress_shapefile, &loader_file_config->shp_file[i]);
1543 
1544  /* Display the progress dialog */
1545  lw_asprintf(&progress_text, _("Importing shapefile %s (%d records)..."), progress_shapefile, ShpLoaderGetRecordCount(state));
1546  gtk_label_set_text(GTK_LABEL(label_progress), progress_text);
1547  gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.0);
1548  gtk_widget_show_all(dialog_progress);
1549 
1550  /* If reading the whole shapefile, display its type */
1551  if (state->config->readshape)
1552  {
1553  pgui_logf("Shapefile type: %s", SHPTypeName(state->shpfiletype));
1554  pgui_logf("PostGIS type: %s[%d]", state->pgtype, state->pgdims);
1555  }
1556 
1557  /* Get the header */
1558  ret = ShpLoaderGetSQLHeader(state, &header);
1559  if (ret != SHPLOADEROK)
1560  {
1561  pgui_logf("%s", state->message);
1562 
1563  if (ret == SHPLOADERERR)
1564  goto import_cleanup;
1565  }
1566 
1567  /* Send the header to the remote server: if we are in COPY mode then the last
1568  statement will be a COPY and so will change connection mode */
1569  ret = pgui_exec(header);
1570  free(header);
1571 
1572  if (!ret)
1573  goto import_cleanup;
1574 
1575  /* If we are in prepare mode, we need to skip the actual load. */
1576  if (state->config->opt != 'p')
1577  {
1578  int numrecords = ShpLoaderGetRecordCount(state);
1579  int records_per_tick = (numrecords / 200) - 1;
1580 
1581  if ( records_per_tick < 1 )
1582  records_per_tick = 1;
1583 
1584  /* If we are in COPY (dump format) mode, output the COPY statement and enter COPY mode */
1585  if (state->config->dump_format)
1586  {
1587  ret = ShpLoaderGetSQLCopyStatement(state, &header);
1588 
1589  if (ret != SHPLOADEROK)
1590  {
1591  pgui_logf("%s", state->message);
1592 
1593  if (ret == SHPLOADERERR)
1594  goto import_cleanup;
1595  }
1596 
1597  /* Send the result to the remote server: this should put us in COPY mode */
1598  ret = pgui_copy_start(header);
1599  free(header);
1600 
1601  if (!ret)
1602  goto import_cleanup;
1603  }
1604 
1605  /* Main loop: iterate through all of the records and send them to stdout */
1606  for (i = 0; i < numrecords && is_running; i++)
1607  {
1608  ret = ShpLoaderGenerateSQLRowStatement(state, i, &record);
1609 
1610  switch (ret)
1611  {
1612  case SHPLOADEROK:
1613  /* Simply send the statement */
1614  if (state->config->dump_format)
1615  ret = pgui_copy_write(record);
1616  else
1617  ret = pgui_exec(record);
1618 
1619  /* Display a record number if we failed */
1620  if (!ret)
1621  pgui_logf(_("Import failed on record number %d"), i);
1622 
1623  free(record);
1624  break;
1625 
1626  case SHPLOADERERR:
1627  /* Display the error message then stop */
1628  pgui_logf("%s\n", state->message);
1629  goto import_cleanup;
1630  break;
1631 
1632  case SHPLOADERWARN:
1633  /* Display the warning, but continue */
1634  pgui_logf("%s\n", state->message);
1635 
1636  if (state->config->dump_format)
1637  ret = pgui_copy_write(record);
1638  else
1639  ret = pgui_exec(record);
1640 
1641  /* Display a record number if we failed */
1642  if (!ret)
1643  pgui_logf(_("Import failed on record number %d"), i);
1644 
1645  free(record);
1646  break;
1647 
1648  case SHPLOADERRECDELETED:
1649  /* Record is marked as deleted - ignore */
1650  break;
1651 
1652  case SHPLOADERRECISNULL:
1653  /* Record is NULL and should be ignored according to NULL policy */
1654  break;
1655  }
1656 
1657  /* Update the progress bar */
1658  if ( i % records_per_tick == 0 )
1659  gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (float)i / numrecords);
1660 
1661  /* Allow GTK events to get a look in */
1662  while (gtk_events_pending())
1663  gtk_main_iteration();
1664  }
1665 
1666  /* If we are in COPY (dump format) mode, leave COPY mode */
1667  if (state->config->dump_format)
1668  {
1669  if (! pgui_copy_end(0) )
1670  goto import_cleanup;
1671 
1672  result = PQgetResult(pg_connection);
1673  if (PQresultStatus(result) != PGRES_COMMAND_OK)
1674  {
1675  pgui_logf(_("COPY failed with the following error: %s"), PQerrorMessage(pg_connection));
1676  ret = SHPLOADERERR;
1677  goto import_cleanup;
1678  }
1679  }
1680  } /* if (state->config->opt != 'p') */
1681 
1682  /* Only continue if we didn't abort part way through */
1683  if (is_running)
1684  {
1685  /* Get the footer */
1686  ret = ShpLoaderGetSQLFooter(state, &footer);
1687  if (ret != SHPLOADEROK)
1688  {
1689  pgui_logf("%s\n", state->message);
1690 
1691  if (ret == SHPLOADERERR)
1692  goto import_cleanup;
1693  }
1694 
1695  /* Just in case index creation takes a long time, update the progress text */
1696  if (state->config->createindex)
1697  {
1698  gtk_label_set_text(GTK_LABEL(label_progress), _("Creating spatial index..."));
1699 
1700  /* Allow GTK events to get a look in */
1701  while (gtk_events_pending())
1702  gtk_main_iteration();
1703  }
1704 
1705  /* Send the footer to the server */
1706  ret = pgui_exec(footer);
1707  free(footer);
1708 
1709  if (!ret)
1710  goto import_cleanup;
1711  }
1712 
1713 import_cleanup:
1714  /* Import has definitely stopped running */
1715  is_running = FALSE;
1716 
1717  /* Close the existing connection */
1718  PQfinish(pg_connection);
1719  pg_connection = NULL;
1720 
1721  /* If we didn't finish inserting all of the items (and we expected to), an error occurred */
1722  if ((state->config->opt != 'p' && i != ShpLoaderGetRecordCount(state)) || !ret)
1723  pgui_logf(_("Shapefile import failed."));
1724  else
1725  pgui_logf(_("Shapefile import completed."));
1726 
1727  /* Free the state object */
1728  ShpLoaderDestroy(state);
1729 
1730  /* Tidy up */
1731  if (progress_text)
1732  free(progress_text);
1733 
1734  if (progress_shapefile)
1735  free(progress_shapefile);
1736 
1737  /* Get next entry */
1738  is_valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(import_file_list_store), &iter);
1739  }
1740 
1741  /* Import has definitely finished */
1742  is_running = FALSE;
1743 
1744  /* Enable the button once again */
1745  gtk_widget_set_sensitive(widget, TRUE);
1746 
1747  /* Silly GTK bug means we have to hide and show the button for it to work again! */
1748  gtk_widget_hide(widget);
1749  gtk_widget_show(widget);
1750 
1751  /* Hide the progress dialog */
1752  gtk_widget_hide(dialog_progress);
1753 
1754  /* Allow GTK events to get a look in */
1755  while (gtk_events_pending())
1756  gtk_main_iteration();
1757 
1758  /* Tidy up */
1759  free(connection_string);
1760 
1761  return;
1762 }
static int connection_test(void)
SHPLOADERCONFIG * config
int ShpLoaderGetSQLFooter(SHPLOADERSTATE *state, char **strfooter)
static int pgui_copy_write(const char *line)
int ShpLoaderOpenShape(SHPLOADERSTATE *state)
static int validate_remote_loader_columns(SHPLOADERCONFIG *config, PGresult *result)
#define SHPLOADERRECISNULL
#define _(String)
Definition: shpcommon.h:23
static int pgui_exec(const char *sql)
static void pgui_logf(const char *fmt,...)
#define SHPLOADERWARN
#define SHPLOADERRECDELETED
int ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader)
static GtkWidget * progress
static SHPCONNECTIONCONFIG * conn
char ** result
Definition: liblwgeom.h:218
void ShpLoaderDestroy(SHPLOADERSTATE *state)
static void pgui_seterr(const char *fmt,...)
static int pgui_copy_start(const char *sql)
int ShpLoaderGetRecordCount(SHPLOADERSTATE *state)
SHPLOADERSTATE * ShpLoaderCreate(SHPLOADERCONFIG *config)
static volatile int is_running
char * ShpDumperGetConnectionStringFromConn(SHPCONNECTIONCONFIG *conn)
#define SHPLOADEROK
const char SHPAPI_CALL1 * SHPTypeName(int nSHPType);const char SHPAPI_CALL1(*) SHPPartTypeName(int nPartType
Definition: shpopen.c:2093
int lw_asprintf(result, va_alist)
GtkListStore * import_file_list_store
Definition: shp2pgsql-gui.c:58
char message[SHPLOADERMSGLEN]
#define FALSE
Definition: dbfopen.c:169
static void update_conn_ui_from_conn_config(void)
static GtkWidget * label_progress
int ShpLoaderGetSQLCopyStatement(SHPLOADERSTATE *state, char **strheader)
int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord)
static GtkWidget * window_conn
static void pgui_raise_error_dialogue(void)
static int pgui_copy_end(const int rollback)
static PGconn * pg_connection
#define SHPLOADERERR
static GtkWidget * dialog_progress
#define TRUE
Definition: dbfopen.c:170

Here is the call graph for this function:

Here is the caller graph for this function: