PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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
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
1740import_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)
SHPLOADERSTATE * ShpLoaderCreate(SHPLOADERCONFIG *config)
int ShpLoaderGetSQLCopyStatement(SHPLOADERSTATE *state, char **strheader)
int ShpLoaderOpenShape(SHPLOADERSTATE *state)
int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord)
int ShpLoaderGetSQLFooter(SHPLOADERSTATE *state, char **strfooter)
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
#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: