PostGIS  2.1.10dev-r@@SVN_REVISION@@
int ShpDumperOpenTable ( SHPDUMPERSTATE state)

Definition at line 1420 of file pgsql2shp-core.c.

References _, shp_dumper_state::big_endian, shp_dumper_config::binary, shp_dumper_state::column_map_dbffieldnames, shp_dumper_config::column_map_filename, shp_dumper_state::column_map_pgfieldnames, shp_dumper_state::column_map_size, shp_dumper_state::config, shp_dumper_state::conn, shp_dumper_state::currescount, shp_dumper_state::curresrow, shp_dumper_state::currow, shp_dumper_state::dbf, DBFAddField(), DBFCreate(), shp_dumper_state::dbffieldnames, shp_dumper_state::dbffieldtypes, shp_dumper_state::fetch_query, shp_dumper_state::fetchres, shp_dumper_config::fetchsize, shp_dumper_state::fieldcount, shp_dumper_config::geo_col_name, shp_dumper_state::geo_col_name, shp_dumper_state::geog_oid, shp_dumper_state::geom_oid, getMaxFieldSize(), getTableInfo(), shp_dumper_config::includegid, shp_dumper_config::keep_fieldname_case, LWDEBUGF, shp_dumper_state::main_scan_query, MAX_DBF_FIELD_SIZE, shp_dumper_state::message, shp_dumper_state::outshptype, shp_dumper_state::outtype, shp_dumper_state::pgfieldlens, shp_dumper_state::pgfieldnames, shp_dumper_state::pgfieldtypmods, shp_dumper_state::pgis_major_version, read_column_map(), window::res, shp_dumper_state::rowcount, shp_dumper_config::schema, shp_dumper_state::schema, shp_dumper_state::shp, shp_dumper_config::shp_file, shp_dumper_state::shp_file, SHPCreate(), SHPDUMPERERR, SHPDUMPERMSGLEN, SHPDUMPEROK, SHPDUMPERWARN, shp_dumper_config::table, shp_dumper_state::table, shp_dumper_config::unescapedattrs, and shp_dumper_config::usrquery.

Referenced by main(), and pgui_action_export().

1421 {
1422  PGresult *res;
1423 
1424  char buf[256];
1425  char *query;
1426  int gidfound = 0, i, j, ret, status;
1427 
1428 
1429  /* Open the column map if one was specified */
1430  if (state->config->column_map_filename)
1431  {
1432  ret = read_column_map(state);
1433  if (ret != SHPDUMPEROK)
1434  return SHPDUMPERERR;
1435  }
1436 
1437  /* If a user-defined query has been specified, create and point the state to our new table */
1438  if (state->config->usrquery)
1439  {
1440  state->table = malloc(20 + 20); // string + max long precision
1441  sprintf(state->table, "__pgsql2shp%lu_tmp_table", (long)getpid());
1442 
1443  query = malloc(32 + strlen(state->table) + strlen(state->config->usrquery));
1444 
1445  sprintf(query, "CREATE TEMP TABLE \"%s\" AS %s", state->table, state->config->usrquery);
1446  res = PQexec(state->conn, query);
1447  free(query);
1448 
1449  /* Execute the code to create the table */
1450  if (PQresultStatus(res) != PGRES_COMMAND_OK)
1451  {
1452  snprintf(state->message, SHPDUMPERMSGLEN, _("Error executing user query: %s"), PQresultErrorMessage(res));
1453  PQclear(res);
1454  return SHPDUMPERERR;
1455  }
1456  }
1457  else
1458  {
1459  /* Simply point the state to copies of the supplied schema and table */
1460  state->table = strdup(state->config->table);
1461  if (state->config->schema)
1462  state->schema = strdup(state->config->schema);
1463  }
1464 
1465 
1466  /* Get the list of columns and their types for the selected table */
1467  if (state->schema)
1468  {
1469  query = malloc(250 + strlen(state->schema) + strlen(state->table));
1470 
1471  sprintf(query, "SELECT a.attname, a.atttypid, "
1472  "a.atttypmod, a.attlen FROM "
1473  "pg_attribute a, pg_class c, pg_namespace n WHERE "
1474  "n.nspname = '%s' AND a.attrelid = c.oid AND "
1475  "n.oid = c.relnamespace AND "
1476  "a.atttypid != 0 AND "
1477  "a.attnum > 0 AND c.relname = '%s'", state->schema, state->table);
1478  }
1479  else
1480  {
1481  query = malloc(250 + strlen(state->table));
1482 
1483  sprintf(query, "SELECT a.attname, a.atttypid, "
1484  "a.atttypmod, a.attlen FROM "
1485  "pg_attribute a, pg_class c WHERE "
1486  "a.attrelid = c.oid and a.attnum > 0 AND "
1487  "a.atttypid != 0 AND "
1488  "c.relname = '%s' AND "
1489  "pg_catalog.pg_table_is_visible(c.oid)", state->table);
1490  }
1491 
1492  LWDEBUGF(3, "query is: %s\n", query);
1493 
1494  res = PQexec(state->conn, query);
1495  free(query);
1496 
1497  if (PQresultStatus(res) != PGRES_TUPLES_OK)
1498  {
1499  snprintf(state->message, SHPDUMPERMSGLEN, _("Error querying for attributes: %s"), PQresultErrorMessage(res));
1500  PQclear(res);
1501  return SHPDUMPERERR;
1502  }
1503 
1504  if (!PQntuples(res))
1505  {
1506  snprintf(state->message, SHPDUMPERMSGLEN, _("Table %s does not exist"), state->table);
1507  PQclear(res);
1508  return SHPDUMPERERR;
1509  }
1510 
1511  /* If a shapefile name was specified, use it. Otherwise simply use the table name. */
1512  if (state->config->shp_file != NULL)
1513  state->shp_file = state->config->shp_file;
1514  else
1515  state->shp_file = state->table;
1516 
1517  /* Create the dbf file */
1518  state->dbf = DBFCreate(state->shp_file);
1519  if (!state->dbf)
1520  {
1521  snprintf(state->message, SHPDUMPERMSGLEN, _("Could not create dbf file %s"), state->shp_file);
1522  return SHPDUMPERERR;
1523  }
1524 
1525  /*
1526  * Scan the result setting fields to be returned in mainscan
1527  * query, filling the type_ary, and creating .dbf and .shp files.
1528  */
1529  state->dbffieldnames = malloc(sizeof(char *) * PQntuples(res));
1530  state->dbffieldtypes = malloc(sizeof(int) * PQntuples(res));
1531  state->pgfieldnames = malloc(sizeof(char *) * PQntuples(res));
1532  state->pgfieldlens = malloc(sizeof(int) * PQntuples(res));
1533  state->pgfieldtypmods = malloc(sizeof(int) * PQntuples(res));
1534  state->fieldcount = 0;
1535  int tmpint = 1;
1536 
1537  for (i = 0; i < PQntuples(res); i++)
1538  {
1539  char *ptr;
1540 
1541  int pgfieldtype, pgtypmod, pgfieldlen;
1542  char *pgfieldname;
1543 
1544  int dbffieldtype, dbffieldsize, dbffielddecs;
1545  char *dbffieldname;
1546 
1547  pgfieldname = PQgetvalue(res, i, 0);
1548  pgfieldtype = atoi(PQgetvalue(res, i, 1));
1549  pgtypmod = atoi(PQgetvalue(res, i, 2));
1550  pgfieldlen = atoi(PQgetvalue(res, i, 3));
1551  dbffieldtype = -1;
1552  dbffieldsize = 0;
1553  dbffielddecs = 0;
1554 
1555  /*
1556  * This is a geometry/geography column
1557  */
1558  if (pgfieldtype == state->geom_oid || pgfieldtype == state->geog_oid)
1559  {
1560  /* If no geometry/geography column has been found yet... */
1561  if (!state->geo_col_name)
1562  {
1563  /* If either no geo* column name was provided (in which case this is
1564  the first match) or we match the provided column name, we have
1565  found our geo* column */
1566  if (!state->config->geo_col_name || !strcmp(state->config->geo_col_name, pgfieldname))
1567  {
1568  dbffieldtype = 9;
1569 
1570  state->geo_col_name = strdup(pgfieldname);
1571  }
1572  }
1573  }
1574 
1575  /*
1576  * Everything else (non geometries) will be
1577  * a DBF attribute.
1578  */
1579 
1580  /* Skip gid (if not asked to do otherwise */
1581  if (!strcmp(pgfieldname, "gid") )
1582  {
1583  gidfound = 1;
1584 
1585  if (!state->config->includegid)
1586  continue;
1587  }
1588 
1589  /* Unescape any reserved column names */
1590  ptr = pgfieldname;
1591  if (!state->config->unescapedattrs)
1592  {
1593  if (*ptr == '_')
1594  ptr += 2;
1595  }
1596 
1597  /*
1598  * This needs special handling since both xmin and _xmin
1599  * becomes __xmin when escaped
1600  */
1601 
1602  /* Limit dbf field name to 10-digits */
1603  dbffieldname = malloc(11);
1604  strncpy(dbffieldname, ptr, 10);
1605  dbffieldname[10] = '\0';
1606 
1607  /* If a column map file has been passed in, use this to create the dbf field name from
1608  the PostgreSQL column name */
1609  if (state->column_map_size > 0)
1610  {
1611  for (j = 0; j < state->column_map_size; j++)
1612  {
1613  if (!strcasecmp(state->column_map_pgfieldnames[j], dbffieldname))
1614  {
1615  strncpy(dbffieldname, state->column_map_dbffieldnames[j], 10);
1616  dbffieldname[10] = '\0';
1617  }
1618  }
1619  }
1620 
1621  /*
1622  * make sure the fields all have unique names,
1623  */
1624  tmpint = 1;
1625  for (j = 0; j < state->fieldcount; j++)
1626  {
1627  if (!strncasecmp(dbffieldname, state->dbffieldnames[j], 10))
1628  {
1629  sprintf(dbffieldname, "%.7s_%.2d", ptr, tmpint++);
1630  continue;
1631  }
1632  }
1633 
1634  /* make UPPERCASE if keep_fieldname_case = 0 */
1635  if (!state->config->keep_fieldname_case)
1636  for (j = 0; j < strlen(dbffieldname); j++)
1637  dbffieldname[j] = toupper(dbffieldname[j]);
1638 
1639  /* Issue warning if column has been renamed */
1640  if (strcasecmp(dbffieldname, pgfieldname))
1641  {
1642  /* Note: we concatenate all warnings from the main loop as this is useful information */
1643  snprintf(buf, 256, _("Warning, field %s renamed to %s\n"), pgfieldname, dbffieldname);
1644  strncat(state->message, buf, SHPDUMPERMSGLEN - strlen(state->message));
1645 
1646  ret = SHPDUMPERWARN;
1647  }
1648 
1649 
1650  /*
1651  * Find appropriate type of dbf attributes
1652  */
1653 
1654  /* int2 type */
1655  if (pgfieldtype == 21)
1656  {
1657  /*
1658  * Longest text representation for
1659  * an int2 type (16bit) is 6 bytes
1660  * (-32768)
1661  */
1662  dbffieldtype = FTInteger;
1663  dbffieldsize = 6;
1664  dbffielddecs = 0;
1665  }
1666 
1667  /* int4 type */
1668  else if (pgfieldtype == 23)
1669  {
1670  /*
1671  * Longest text representation for
1672  * an int4 type (32bit) is 11 bytes
1673  * (-2147483648)
1674  */
1675  dbffieldtype = FTInteger;
1676  dbffieldsize = 11;
1677  dbffielddecs = 0;
1678  }
1679 
1680  /* int8 type */
1681  else if (pgfieldtype == 20)
1682  {
1683  /*
1684  * Longest text representation for
1685  * an int8 type (64bit) is 20 bytes
1686  * (-9223372036854775808)
1687  */
1688  dbffieldtype = FTInteger;
1689  dbffieldsize = 19;
1690  dbffielddecs = 0;
1691  }
1692 
1693  /*
1694  * double or numeric types:
1695  * 700: float4
1696  * 701: float8
1697  * 1700: numeric
1698  *
1699  *
1700  * TODO: stricter handling of sizes
1701  */
1702  else if (pgfieldtype == 700 || pgfieldtype == 701 || pgfieldtype == 1700)
1703  {
1704  dbffieldtype = FTDouble;
1705  dbffieldsize = 32;
1706  dbffielddecs = 10;
1707  }
1708 
1709  /*
1710  * Boolean field, we use FTLogical
1711  */
1712  else if (pgfieldtype == 16)
1713  {
1714  dbffieldtype = FTLogical;
1715  dbffieldsize = 2;
1716  dbffielddecs = 0;
1717  }
1718 
1719  /*
1720  * Date field
1721  */
1722  else if (pgfieldtype == 1082)
1723  {
1724  dbffieldtype = FTDate;
1725  dbffieldsize = 8;
1726  dbffielddecs = 0;
1727  }
1728 
1729  /*
1730  * time, timetz, timestamp, or timestamptz field.
1731  */
1732  else if (pgfieldtype == 1083 || pgfieldtype == 1266 || pgfieldtype == 1114 || pgfieldtype == 1184)
1733  {
1734  int secondsize;
1735 
1736  switch (pgtypmod)
1737  {
1738  case -1:
1739  secondsize = 6 + 1;
1740  break;
1741  case 0:
1742  secondsize = 0;
1743  break;
1744  default:
1745  secondsize = pgtypmod + 1;
1746  break;
1747  }
1748 
1749  /* We assume the worst case scenario for all of these:
1750  * date = '5874897-12-31' = 13
1751  * date = '294276-11-20' = 12 (with --enable-interger-datetimes)
1752  * time = '00:00:00' = 8
1753  * zone = '+01:39:52' = 9 (see Europe/Helsinki around 1915)
1754  */
1755 
1756  /* time */
1757  if (pgfieldtype == 1083)
1758  {
1759  dbffieldsize = 8 + secondsize;
1760  }
1761  /* timetz */
1762  else if (pgfieldtype == 1266)
1763  {
1764  dbffieldsize = 8 + secondsize + 9;
1765  }
1766  /* timestamp */
1767  else if (pgfieldtype == 1114)
1768  {
1769  dbffieldsize = 13 + 1 + 8 + secondsize;
1770  }
1771  /* timestamptz */
1772  else if (pgfieldtype == 1184)
1773  {
1774  dbffieldsize = 13 + 1 + 8 + secondsize + 9;
1775  }
1776 
1777  dbffieldtype = FTString;
1778  dbffielddecs = 0;
1779  }
1780 
1781  /*
1782  * uuid type 36 bytes (12345678-9012-3456-7890-123456789012)
1783  */
1784  else if (pgfieldtype == 2950)
1785  {
1786  dbffieldtype = FTString;
1787  dbffieldsize = 36;
1788  dbffielddecs = 0;
1789  }
1790 
1791  /*
1792  * For variable-sized fields we know about, we use
1793  * the maximum allowed size.
1794  * 1042 is bpchar, 1043 is varchar
1795  */
1796  else if ((pgfieldtype == 1042 || pgfieldtype == 1043) && pgtypmod != -1)
1797  {
1798  /*
1799  * mod is maximum allowed size, including
1800  * header which contains *real* size.
1801  */
1802  dbffieldtype = FTString;
1803  dbffieldsize = pgtypmod - 4; /* 4 is header size */
1804  dbffielddecs = 0;
1805  }
1806 
1807  /* For all other valid non-geometry/geography fields... */
1808  else if (dbffieldtype == -1)
1809  {
1810  /*
1811  * For types we don't know anything about, all
1812  * we can do is query the table for the maximum field
1813  * size.
1814  */
1815  dbffieldsize = getMaxFieldSize(state->conn, state->schema, state->table, pgfieldname);
1816  if (dbffieldsize == -1)
1817  {
1818  free(dbffieldname);
1819  return 0;
1820  }
1821 
1822  if (!dbffieldsize)
1823  dbffieldsize = 32;
1824 
1825  /* might 0 be a good size ? */
1826 
1827  dbffieldtype = FTString;
1828  dbffielddecs = 0;
1829 
1830  /* Check to make sure the final field size isn't too large */
1831  if (dbffieldsize > MAX_DBF_FIELD_SIZE)
1832  {
1833  /* Note: we concatenate all warnings from the main loop as this is useful information */
1834  snprintf(buf, 256, _("Warning: values of field '%s' exceeding maximum dbf field width (%d) "
1835  "will be truncated.\n"), dbffieldname, MAX_DBF_FIELD_SIZE);
1836  strncat(state->message, buf, SHPDUMPERMSGLEN - strlen(state->message));
1837  dbffieldsize = MAX_DBF_FIELD_SIZE;
1838 
1839  ret = SHPDUMPERWARN;
1840  }
1841  }
1842 
1843  LWDEBUGF(3, "DBF FIELD_NAME: %s, SIZE: %d\n", dbffieldname, dbffieldsize);
1844 
1845  if (dbffieldtype != 9)
1846  {
1847  /* Add the field to the DBF file */
1848  if (DBFAddField(state->dbf, dbffieldname, dbffieldtype, dbffieldsize, dbffielddecs) == -1)
1849  {
1850  snprintf(state->message, SHPDUMPERMSGLEN, _("Error: field %s of type %d could not be created."), dbffieldname, dbffieldtype);
1851 
1852  return SHPDUMPERERR;
1853  }
1854 
1855  /* Add the field information to our field arrays */
1856  state->dbffieldnames[state->fieldcount] = dbffieldname;
1857  state->dbffieldtypes[state->fieldcount] = dbffieldtype;
1858  state->pgfieldnames[state->fieldcount] = pgfieldname;
1859  state->pgfieldlens[state->fieldcount] = pgfieldlen;
1860  state->pgfieldtypmods[state->fieldcount] = pgtypmod;
1861 
1862  state->fieldcount++;
1863  }
1864  }
1865 
1866  /* Now we have generated the field lists, grab some info about the table */
1867  status = getTableInfo(state);
1868  if (status == SHPDUMPERERR)
1869  return SHPDUMPERERR;
1870 
1871  LWDEBUGF(3, "rows: %d\n", state->rowcount);
1872  LWDEBUGF(3, "shptype: %c\n", state->outtype);
1873  LWDEBUGF(3, "shpouttype: %d\n", state->outshptype);
1874 
1875  /* If we didn't find a geometry/geography column... */
1876  if (!state->geo_col_name)
1877  {
1878  if (state->config->geo_col_name)
1879  {
1880  /* A geo* column was specified, but not found */
1881  snprintf(state->message, SHPDUMPERMSGLEN, _("%s: no such attribute in table %s"), state->config->geo_col_name, state->table);
1882 
1883  return SHPDUMPERERR;
1884  }
1885  else
1886  {
1887  /* No geo* column specified so we can only create the DBF section -
1888  but let's issue a warning... */
1889  snprintf(buf, 256, _("No geometry column found.\nThe DBF file will be created but not the shx or shp files.\n"));
1890  strncat(state->message, buf, SHPDUMPERMSGLEN - strlen(state->message));
1891 
1892  state->shp = NULL;
1893 
1894  ret = SHPDUMPERWARN;
1895  }
1896  }
1897  else
1898  {
1899  /* Since we have found a geo* column, open the shapefile */
1900  state->shp = SHPCreate(state->shp_file, state->outshptype);
1901  if (!state->shp)
1902  {
1903  snprintf(state->message, SHPDUMPERMSGLEN, _("Could not open shapefile %s!"), state->shp_file);
1904 
1905  return SHPDUMPERERR;
1906  }
1907  }
1908 
1909 
1910  /* Now we have the complete list of fieldnames, let's generate the SQL query. First let's make sure
1911  we reserve enough space for tables with lots of columns */
1912  j = 0;
1913  for (i = 0; i < state->fieldcount; i++)
1914  j += strlen(state->pgfieldnames[i] + 2); /* Add 2 for leading and trailing quotes */
1915 
1916  state->main_scan_query = malloc(1024 + j);
1917 
1918  sprintf(state->main_scan_query, "DECLARE cur ");
1919  if (state->config->binary)
1920  strcat(state->main_scan_query, "BINARY ");
1921 
1922  strcat(state->main_scan_query, "CURSOR FOR SELECT ");
1923 
1924  for (i = 0; i < state->fieldcount; i++)
1925  {
1926  /* Comma-separated column names */
1927  if (i > 0)
1928  strcat(state->main_scan_query, ",");
1929 
1930  if (state->config->binary)
1931  sprintf(buf, "\"%s\"::text", state->pgfieldnames[i]);
1932  else
1933  sprintf(buf, "\"%s\"", state->pgfieldnames[i]);
1934 
1935  strcat(state->main_scan_query, buf);
1936  }
1937 
1938  /* If we found a valid geometry/geography column then use it */
1939  if (state->geo_col_name)
1940  {
1941  /* If this is the (only) column, no need for the initial comma */
1942  if (state->fieldcount > 0)
1943  strcat(state->main_scan_query, ",");
1944 
1945  if (state->big_endian)
1946  {
1947  if (state->pgis_major_version > 0)
1948  {
1949  sprintf(buf, "ST_asEWKB(ST_SetSRID(\"%s\"::geometry, 0), 'XDR') AS _geoX", state->geo_col_name);
1950  }
1951  else
1952  {
1953  sprintf(buf, "asbinary(\"%s\"::geometry, 'XDR') AS _geoX",
1954  state->geo_col_name);
1955  }
1956  }
1957  else /* little_endian */
1958  {
1959  if (state->pgis_major_version > 0)
1960  {
1961  sprintf(buf, "ST_AsEWKB(ST_SetSRID(\"%s\"::geometry, 0), 'NDR') AS _geoX", state->geo_col_name);
1962  }
1963  else
1964  {
1965  sprintf(buf, "asbinary(\"%s\"::geometry, 'NDR') AS _geoX",
1966  state->geo_col_name);
1967  }
1968  }
1969 
1970  strcat(state->main_scan_query, buf);
1971  }
1972 
1973  if (state->schema)
1974  {
1975  sprintf(buf, " FROM \"%s\".\"%s\"", state->schema, state->table);
1976  }
1977  else
1978  {
1979  sprintf(buf, " FROM \"%s\"", state->table);
1980  }
1981 
1982  strcat(state->main_scan_query, buf);
1983 
1984  /* Order by 'gid' (if found) */
1985  if (gidfound)
1986  {
1987  sprintf(buf, " ORDER BY \"gid\"");
1988  strcat(state->main_scan_query, buf);
1989  }
1990 
1991  /* Now we've finished with the result set, we can dispose of it */
1992  PQclear(res);
1993 
1994  LWDEBUGF(3, "FINAL QUERY: %s\n", state->main_scan_query);
1995 
1996  /*
1997  * Begin the transaction
1998  * (a cursor can only be defined inside a transaction block)
1999  */
2000  res = PQexec(state->conn, "BEGIN");
2001  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2002  {
2003  snprintf(state->message, SHPDUMPERMSGLEN, _("Error starting transaction: %s"), PQresultErrorMessage(res));
2004  PQclear(res);
2005  return SHPDUMPERERR;
2006  }
2007 
2008  PQclear(res);
2009 
2010  /* Execute the main scan query */
2011  res = PQexec(state->conn, state->main_scan_query);
2012  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2013  {
2014  snprintf(state->message, SHPDUMPERMSGLEN, _("Error executing main scan query: %s"), PQresultErrorMessage(res));
2015  PQclear(res);
2016  return SHPDUMPERERR;
2017  }
2018 
2019  PQclear(res);
2020 
2021  /* Setup initial scan state */
2022  state->currow = 0;
2023  state->curresrow = 0;
2024  state->currescount = 0;
2025  state->fetchres = NULL;
2026 
2027  /* Generate the fetch query */
2028  state->fetch_query = malloc(256);
2029  sprintf(state->fetch_query, "FETCH %d FROM cur", state->config->fetchsize);
2030 
2031  return SHPDUMPEROK;
2032 }
char * column_map_filename
DBFHandle SHPAPI_CALL DBFCreate(const char *pszFilename)
Definition: dbfopen.c:629
tuple res
Definition: window.py:80
#define _(String)
Definition: shpcommon.h:23
SHPDUMPERCONFIG * config
SHPHandle SHPAPI_CALL SHPCreate(const char *pszShapeFile, int nShapeType)
Definition: shpopen.c:829
static int getTableInfo(SHPDUMPERSTATE *state)
char ** column_map_pgfieldnames
#define MAX_DBF_FIELD_SIZE
static int getMaxFieldSize(PGconn *conn, char *schema, char *table, char *fname)
#define SHPDUMPERERR
char ** column_map_dbffieldnames
static int read_column_map(SHPDUMPERSTATE *state)
Read the content of filename into a symbol map stored at state->column_map_filename.
int SHPAPI_CALL DBFAddField(DBFHandle psDBF, const char *pszFieldName, DBFFieldType eType, int nWidth, int nDecimals)
Definition: dbfopen.c:770
#define SHPDUMPERMSGLEN
#define SHPDUMPEROK
#define SHPDUMPERWARN
char message[SHPDUMPERMSGLEN]
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
PGresult * fetchres

Here is the call graph for this function:

Here is the caller graph for this function: