PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ ShpLoaderGenerateShapeRow()

int ShpLoaderGenerateShapeRow ( SHPDUMPERSTATE state)

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

1951 {
1952  char *hexewkb = NULL;
1953  unsigned char *hexewkb_binary = NULL;
1954  size_t hexewkb_len;
1955  char *val;
1956  SHPObject *obj = NULL;
1957  LWGEOM *lwgeom;
1958 
1959  int i, geocolnum = 0;
1960 
1961  /* If we try to go pass the end of the table, fail immediately */
1962  if (state->currow > state->rowcount)
1963  {
1964  snprintf(state->message, SHPDUMPERMSGLEN, _("Tried to read past end of table!"));
1965  PQclear(state->fetchres);
1966  return SHPDUMPERERR;
1967  }
1968 
1969  /* If we have reached the end of the current batch, fetch a new one */
1970  if (state->curresrow == state->currescount && state->currow < state->rowcount)
1971  {
1972  /* Clear the previous batch results */
1973  if (state->fetchres)
1974  PQclear(state->fetchres);
1975 
1976  state->fetchres = PQexec(state->conn, state->fetch_query);
1977  if (PQresultStatus(state->fetchres) != PGRES_TUPLES_OK)
1978  {
1979  snprintf(state->message, SHPDUMPERMSGLEN, _("Error executing fetch query: %s"), PQresultErrorMessage(state->fetchres));
1980  PQclear(state->fetchres);
1981  return SHPDUMPERERR;
1982  }
1983 
1984  state->curresrow = 0;
1985  state->currescount = PQntuples(state->fetchres);
1986  }
1987 
1988  /* Grab the id of the geo column if we have one */
1989  if (state->geo_col_name)
1990  geocolnum = PQfnumber(state->fetchres, "_geoX");
1991 
1992  /* Process the next record within the batch. First write out all of
1993  the non-geo fields */
1994  for (i = 0; i < state->fieldcount; i++)
1995  {
1996  /*
1997  * Transform NULL numbers to '0'
1998  * This is because the shapelib
1999  * won't easly take care of setting
2000  * nulls unless paying the acquisition
2001  * of a bug in long integer values
2002  */
2003  if (PQgetisnull(state->fetchres, state->curresrow, i))
2004  {
2005  val = nullDBFValue(state->dbffieldtypes[i]);
2006  }
2007  else
2008  {
2009  val = PQgetvalue(state->fetchres, state->curresrow, i);
2010  val = goodDBFValue(val, state->dbffieldtypes[i]);
2011  }
2012 
2013  /* Write it to the DBF file */
2014  if (!DBFWriteAttributeDirectly(state->dbf, state->currow, i, val))
2015  {
2016  snprintf(state->message, SHPDUMPERMSGLEN, _("Error: record %d could not be created"), state->currow);
2017  PQclear(state->fetchres);
2018  return SHPDUMPERERR;
2019  }
2020  }
2021 
2022  /* Now process the geo field, if present */
2023  if (state->geo_col_name)
2024  {
2025  /* Handle NULL shapes */
2026  if (PQgetisnull(state->fetchres, state->curresrow, geocolnum))
2027  {
2028  obj = SHPCreateSimpleObject(SHPT_NULL, 0, NULL, NULL, NULL);
2029  if (SHPWriteObject(state->shp, -1, obj) == -1)
2030  {
2031  snprintf(state->message, SHPDUMPERMSGLEN, _("Error writing NULL shape for record %d"), state->currow);
2032  PQclear(state->fetchres);
2033  SHPDestroyObject(obj);
2034  return SHPDUMPERERR;
2035  }
2036  SHPDestroyObject(obj);
2037  }
2038  else
2039  {
2040  /* Get the value from the result set */
2041  val = PQgetvalue(state->fetchres, state->curresrow, geocolnum);
2042 
2043  if (!state->config->binary)
2044  {
2045  if (state->pgis_major_version > 0)
2046  {
2047  LWDEBUG(4, "PostGIS >= 1.0, non-binary cursor");
2048 
2049  /* Input is bytea encoded text field, so it must be unescaped and
2050  then converted to hexewkb string */
2051  hexewkb_binary = PQunescapeBytea((unsigned char *)val, &hexewkb_len);
2052  hexewkb = convert_bytes_to_hex(hexewkb_binary, hexewkb_len);
2053  }
2054  else
2055  {
2056  LWDEBUG(4, "PostGIS < 1.0, non-binary cursor");
2057 
2058  /* Input is already hexewkb string, so we can just
2059  copy directly to hexewkb */
2060  hexewkb_len = PQgetlength(state->fetchres, state->curresrow, geocolnum);
2061  hexewkb = malloc(hexewkb_len + 1);
2062  strncpy(hexewkb, val, hexewkb_len + 1);
2063  }
2064  }
2065  else /* binary */
2066  {
2067  LWDEBUG(4, "PostGIS (any version) using binary cursor");
2068 
2069  /* Input is binary field - must convert to hexewkb string */
2070  hexewkb_len = PQgetlength(state->fetchres, state->curresrow, geocolnum);
2071  hexewkb = convert_bytes_to_hex((unsigned char *)val, hexewkb_len);
2072  }
2073 
2074  LWDEBUGF(4, "HexEWKB - length: %d value: %s", strlen(hexewkb), hexewkb);
2075 
2076  /* Deserialize the LWGEOM */
2077  lwgeom = lwgeom_from_hexwkb(hexewkb, LW_PARSER_CHECK_NONE);
2078  if (!lwgeom)
2079  {
2080  snprintf(state->message, SHPDUMPERMSGLEN, _("Error parsing HEXEWKB for record %d"), state->currow);
2081  PQclear(state->fetchres);
2082  free(hexewkb);
2083  return SHPDUMPERERR;
2084  }
2085 
2086  /* Call the relevant method depending upon the geometry type */
2087  LWDEBUGF(4, "geomtype: %s\n", lwtype_name(lwgeom->type));
2088 
2089  switch (lwgeom->type)
2090  {
2091  case POINTTYPE:
2092  if (lwgeom_is_empty(lwgeom))
2093  {
2094  obj = create_point_empty(state, lwgeom_as_lwpoint(lwgeom));
2095  }
2096  else
2097  {
2098  obj = create_point(state, lwgeom_as_lwpoint(lwgeom));
2099  }
2100  break;
2101 
2102  case MULTIPOINTTYPE:
2103  obj = create_multipoint(state, lwgeom_as_lwmpoint(lwgeom));
2104  break;
2105 
2106  case POLYGONTYPE:
2107  obj = create_polygon(state, lwgeom_as_lwpoly(lwgeom));
2108  break;
2109 
2110  case MULTIPOLYGONTYPE:
2111  obj = create_multipolygon(state, lwgeom_as_lwmpoly(lwgeom));
2112  break;
2113 
2114  case LINETYPE:
2115  obj = create_linestring(state, lwgeom_as_lwline(lwgeom));
2116  break;
2117 
2118  case MULTILINETYPE:
2119  obj = create_multilinestring(state, lwgeom_as_lwmline(lwgeom));
2120  break;
2121 
2122  default:
2123  snprintf(state->message, SHPDUMPERMSGLEN, _("Unknown WKB type (%d) for record %d"), lwgeom->type, state->currow);
2124  PQclear(state->fetchres);
2125  SHPDestroyObject(obj);
2126  return SHPDUMPERERR;
2127  }
2128 
2129  /* Free both the original and geometries */
2130  lwgeom_free(lwgeom);
2131 
2132  /* Write the shape out to the file */
2133  if (SHPWriteObject(state->shp, -1, obj) == -1)
2134  {
2135  snprintf(state->message, SHPDUMPERMSGLEN, _("Error writing shape %d"), state->currow);
2136  PQclear(state->fetchres);
2137  SHPDestroyObject(obj);
2138  return SHPDUMPERERR;
2139  }
2140 
2141  SHPDestroyObject(obj);
2142 
2143  /* Free the hexewkb (and temporary bytea unescaped string if used) */
2144  if (hexewkb) free(hexewkb);
2145  if (hexewkb_binary) PQfreemem(hexewkb_binary);
2146  }
2147  }
2148 
2149  /* Increment ready for next time */
2150  state->curresrow++;
2151  state->currow++;
2152 
2153  return SHPDUMPEROK;
2154 }
int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField, void *pValue)
Definition: dbfopen.c:1437
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:179
LWGEOM * lwgeom_from_hexwkb(const char *hexwkb, const char check)
Definition: lwin_wkb.c:858
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:242
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2096
#define MULTILINETYPE
Definition: liblwgeom.h:121
#define LINETYPE
Definition: liblwgeom.h:118
#define MULTIPOINTTYPE
Definition: liblwgeom.h:120
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:260
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:117
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:251
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:122
#define POLYGONTYPE
Definition: liblwgeom.h:119
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:215
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void * malloc(YYSIZE_T)
void free(void *)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition: lwinline.h:203
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwinline.h:131
static SHPObject * create_polygon(SHPDUMPERSTATE *state, LWPOLY *lwpolygon)
static SHPObject * create_multipolygon(SHPDUMPERSTATE *state, LWMPOLY *lwmultipolygon)
char * convert_bytes_to_hex(uint8_t *ewkb, size_t size)
Binary to hexewkb conversion function.
static SHPObject * create_linestring(SHPDUMPERSTATE *state, LWLINE *lwlinestring)
static char * goodDBFValue(char *in, char fieldType)
Make appropriate formatting of a DBF value based on type.
static SHPObject * create_point(SHPDUMPERSTATE *state, LWPOINT *lwpoint)
static SHPObject * create_point_empty(SHPDUMPERSTATE *state, LWPOINT *lwpoint)
static char * nullDBFValue(char fieldType)
static SHPObject * create_multipoint(SHPDUMPERSTATE *state, LWMPOINT *lwmultipoint)
static SHPObject * create_multilinestring(SHPDUMPERSTATE *state, LWMLINE *lwmultilinestring)
#define SHPDUMPERMSGLEN
#define SHPDUMPEROK
#define SHPDUMPERERR
#define SHPT_NULL
Definition: shapefil.h:348
void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject)
Definition: shpopen.c:2641
#define _(String)
Definition: shpcommon.h:24
SHPObject SHPAPI_CALL1 * SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX, const double *padfY, const double *padfZ){ return(SHPCreateObject(nSHPType, -1, 0, SHPLIB_NULLPTR, SHPLIB_NULLPTR, nVertices, padfX, padfY, padfZ, SHPLIB_NULLPTR)
int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject *psObject)
Definition: shpopen.c:1334
uint8_t type
Definition: liblwgeom.h:477
SHPDUMPERCONFIG * config
PGresult * fetchres
char message[SHPDUMPERMSGLEN]

References _, shp_dumper_config::binary, shp_dumper_state::config, shp_dumper_state::conn, convert_bytes_to_hex(), create_linestring(), create_multilinestring(), create_multipoint(), create_multipolygon(), create_point(), create_point_empty(), create_polygon(), shp_dumper_state::currescount, shp_dumper_state::curresrow, shp_dumper_state::currow, shp_dumper_state::dbf, shp_dumper_state::dbffieldtypes, DBFWriteAttributeDirectly(), shp_dumper_state::fetch_query, shp_dumper_state::fetchres, shp_dumper_state::fieldcount, free(), shp_dumper_state::geo_col_name, goodDBFValue(), LINETYPE, LW_PARSER_CHECK_NONE, LWDEBUG, LWDEBUGF, lwgeom_as_lwline(), lwgeom_as_lwmline(), lwgeom_as_lwmpoint(), lwgeom_as_lwmpoly(), lwgeom_as_lwpoint(), lwgeom_as_lwpoly(), lwgeom_free(), lwgeom_from_hexwkb(), lwgeom_is_empty(), lwtype_name(), malloc(), shp_dumper_state::message, MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, nullDBFValue(), shp_dumper_state::pgis_major_version, POINTTYPE, POLYGONTYPE, shp_dumper_state::rowcount, shp_dumper_state::shp, SHPCreateSimpleObject(), SHPDestroyObject(), SHPDUMPERERR, SHPDUMPERMSGLEN, SHPDUMPEROK, SHPT_NULL, SHPWriteObject(), and LWGEOM::type.

Referenced by main(), and pgui_action_export().

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