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

◆ ShpLoaderGenerateShapeRow()

int ShpLoaderGenerateShapeRow ( SHPDUMPERSTATE state)

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

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