PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ pgui_action_import()

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

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

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

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