PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ pgui_action_import()

static void pgui_action_import ( GtkWidget *  widget,
gpointer  data 
)
static

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

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

References _, shp_loader_state::config, conn, connection_test(), shp_loader_config::createindex, dialog_progress, shp_loader_config::dump_format, FALSE, free(), shp_loader_config::geo_col, shp_loader_config::geography, GUIMSG_LINE_MAXLEN, import_file_list_store, IMPORT_POINTER_COLUMN, is_running, label_progress, malloc(), 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, 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().

Here is the call graph for this function:
Here is the caller graph for this function: