PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ pgui_action_import()

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

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

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