PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ getTableInfo()

static int getTableInfo ( SHPDUMPERSTATE state)
static

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

860 {
861 
862  /* Get some more information from the table:
863  - count = total number of geometries/geographies in the table
864 
865  and if we have found a suitable geometry column:
866 
867  - max = maximum number of dimensions within the geometry/geography column
868  - geometrytype = string representing the geometry/geography type, e.g. POINT
869 
870  Since max/geometrytype already require a sequential scan of the table, we may as
871  well get the row count too.
872  */
873 
874  PGresult *res;
875  char *query;
876  int tmpint;
877 
878 
879  if (state->geo_col_name)
880  {
881  /* Include geometry information */
882  if (state->schema)
883  {
884  query = core_asprintf(
885  "SELECT count(1), max(ST_zmflag(\"%s\"::geometry)), geometrytype(\"%s\"::geometry) FROM \"%s\".\"%s\" GROUP BY 3",
886  state->geo_col_name, state->geo_col_name, state->schema, state->table);
887  }
888  else
889  {
890  query = core_asprintf(
891  "SELECT count(1), max(ST_zmflag(\"%s\"::geometry)), geometrytype(\"%s\"::geometry) FROM \"%s\" GROUP BY 3",
892  state->geo_col_name, state->geo_col_name, state->table);
893  }
894  }
895  else
896  {
897  /* Otherwise... just a row count will do */
898  if (state->schema)
899  {
900  query = core_asprintf(
901  "SELECT count(1) FROM \"%s\".\"%s\"",
902  state->schema, state->table);
903  }
904  else
905  {
906  query = core_asprintf(
907  "SELECT count(1) FROM \"%s\"",
908  state->table);
909  }
910  }
911 
912  LWDEBUGF(3, "Table metadata query: %s\n", query);
913 
914  res = PQexec(state->conn, query);
915  free(query);
916 
917  if (PQresultStatus(res) != PGRES_TUPLES_OK)
918  {
919  snprintf(state->message, SHPDUMPERMSGLEN, _("ERROR: Could not execute table metadata query: %s"), PQresultErrorMessage(res));
920  PQclear(res);
921  return SHPDUMPERERR;
922  }
923 
924  /* Make sure we error if the table is empty */
925  if (PQntuples(res) == 0)
926  {
927  snprintf(state->message, SHPDUMPERMSGLEN, _("ERROR: Could not determine table metadata (empty table)"));
928  PQclear(res);
929  return SHPDUMPERERR;
930  }
931 
932  /* If we have a geo* column, get the dimension, type and count information */
933  if (state->geo_col_name)
934  {
935  /* If a table has a geometry column containing mixed types then
936  the metadata query will return multiple rows. We need to cycle
937  through all rows to determine if the type combinations are valid.
938 
939  Note that if we find a combination of a MULTI and non-MULTI geometry
940  of the same type, we always choose MULTI to ensure that everything
941  gets output correctly. The create_* conversion functions are clever
942  enough to up-convert the non-MULTI geometry to a MULTI in this case. */
943 
944  int dummy, i;
945  uint8_t type = 0;
946  int typefound = 0, typemismatch = 0;
947 
948  state->rowcount = 0;
949 
950  for (i = 0; i < PQntuples(res); i++)
951  {
952  /* skip null geometries */
953  if (PQgetisnull(res, i, 2))
954  {
955  state->rowcount += atoi(PQgetvalue(res, i, 0));
956  continue;
957  }
958 
959  geometry_type_from_string(PQgetvalue(res, i, 2), &type, &dummy, &dummy);
960 
961  /* We can always set typefound to that of the first column found */
962  if (!typefound)
963  typefound = type;
964 
965  switch (type)
966  {
967  case MULTIPOINTTYPE:
968  if (typefound != MULTIPOINTTYPE && typefound != POINTTYPE)
969  typemismatch = 1;
970  else
971  typefound = MULTIPOINTTYPE;
972  break;
973 
974  case MULTILINETYPE:
975  if (typefound != MULTILINETYPE && typefound != LINETYPE)
976  typemismatch = 1;
977  else
978  typefound = MULTILINETYPE;
979  break;
980 
981  case MULTIPOLYGONTYPE:
982  if (typefound != MULTIPOLYGONTYPE && typefound != POLYGONTYPE)
983  typemismatch = 1;
984  else
985  typefound = MULTIPOLYGONTYPE;
986  break;
987 
988  case POINTTYPE:
989  if (typefound != POINTTYPE && typefound != MULTIPOINTTYPE)
990  typemismatch = 1;
991  else if (!lwtype_is_collection(type))
992  typefound = POINTTYPE;
993  break;
994 
995  case LINETYPE:
996  if (typefound != LINETYPE && typefound != MULTILINETYPE)
997  typemismatch = 1;
998  else if (!lwtype_is_collection(type))
999  typefound = LINETYPE;
1000  break;
1001 
1002  case POLYGONTYPE:
1003  if (typefound != POLYGONTYPE && typefound != MULTIPOLYGONTYPE)
1004  typemismatch = 1;
1005  else if (!lwtype_is_collection(type))
1006  typefound = POLYGONTYPE;
1007  break;
1008  }
1009 
1010  /* Update the rowcount for each type */
1011  state->rowcount += atoi(PQgetvalue(res, i, 0));
1012 
1013  /* Set up the dimension output type (note: regardless of how many rows
1014  the table metadata query returns, this value will be the same. But
1015  we'll choose to use the first value anyway) */
1016  tmpint = atoi(PQgetvalue(res, i, 1));
1017  switch (tmpint)
1018  {
1019  case 0:
1020  state->outtype = 's';
1021  break;
1022  case 1:
1023  state->outtype = 'm';
1024  break;
1025  default:
1026  state->outtype = 'z';
1027  break;
1028  }
1029 
1030  }
1031 
1032  /* Flag an error if the table contains incompatible geometry combinations */
1033  if (typemismatch)
1034  {
1035  snprintf(state->message, SHPDUMPERMSGLEN, _("ERROR: Incompatible mixed geometry types in table"));
1036  PQclear(res);
1037  return SHPDUMPERERR;
1038  }
1039 
1040  /* Set up the shapefile output type based upon the dimension information */
1041  switch (typefound)
1042  {
1043  case POINTTYPE:
1044  switch(state->outtype)
1045  {
1046  case 'z':
1047  state->outshptype = SHPT_POINTZ;
1048  break;
1049 
1050  case 'm':
1051  state->outshptype = SHPT_POINTM;
1052  break;
1053 
1054  default:
1055  state->outshptype = SHPT_POINT;
1056  }
1057  break;
1058 
1059  case MULTIPOINTTYPE:
1060  switch(state->outtype)
1061  {
1062  case 'z':
1063  state->outshptype = SHPT_MULTIPOINTZ;
1064  break;
1065 
1066  case 'm':
1067  state->outshptype = SHPT_MULTIPOINTM;
1068  break;
1069 
1070  default:
1071  state->outshptype = SHPT_MULTIPOINT;
1072  }
1073  break;
1074 
1075  case LINETYPE:
1076  case MULTILINETYPE:
1077  switch(state->outtype)
1078  {
1079  case 'z':
1080  state->outshptype = SHPT_ARCZ;
1081  break;
1082 
1083  case 'm':
1084  state->outshptype = SHPT_ARCM;
1085  break;
1086 
1087  default:
1088  state->outshptype = SHPT_ARC;
1089  }
1090  break;
1091 
1092  case POLYGONTYPE:
1093  case MULTIPOLYGONTYPE:
1094  switch(state->outtype)
1095  {
1096  case 'z':
1097  state->outshptype = SHPT_POLYGONZ;
1098  break;
1099 
1100  case 'm':
1101  state->outshptype = SHPT_POLYGONM;
1102  break;
1103 
1104  default:
1105  state->outshptype = SHPT_POLYGON;
1106  }
1107  break;
1108  }
1109  }
1110  else
1111  {
1112  /* Without a geo* column the total is simply the first (COUNT) column */
1113  state->rowcount = atoi(PQgetvalue(res, 0, 0));
1114  }
1115 
1116  /* Dispose of the result set */
1117  PQclear(res);
1118 
1119  return SHPDUMPEROK;
1120 }
#define MULTILINETYPE
Definition: liblwgeom.h:121
#define LINETYPE
Definition: liblwgeom.h:118
#define MULTIPOINTTYPE
Definition: liblwgeom.h:120
int lwtype_is_collection(uint8_t type)
Determine whether a type number is a collection or not.
Definition: lwgeom.c:1105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:117
int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
Utility function to get type number from string.
Definition: lwutil.c:489
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:122
#define POLYGONTYPE
Definition: liblwgeom.h:119
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void free(void *)
type
Definition: ovdump.py:42
tuple res
Definition: window.py:79
static char * core_asprintf(const char *format,...)
#define SHPDUMPERMSGLEN
#define SHPDUMPEROK
#define SHPDUMPERERR
#define SHPT_ARCZ
Definition: shapefil.h:354
#define SHPT_ARCM
Definition: shapefil.h:358
#define SHPT_POLYGONM
Definition: shapefil.h:359
#define SHPT_ARC
Definition: shapefil.h:350
#define SHPT_POLYGON
Definition: shapefil.h:351
#define SHPT_MULTIPOINT
Definition: shapefil.h:352
#define SHPT_POINTZ
Definition: shapefil.h:353
#define SHPT_MULTIPOINTZ
Definition: shapefil.h:356
#define SHPT_MULTIPOINTM
Definition: shapefil.h:360
#define SHPT_POINTM
Definition: shapefil.h:357
#define SHPT_POINT
Definition: shapefil.h:349
#define SHPT_POLYGONZ
Definition: shapefil.h:355
#define _(String)
Definition: shpcommon.h:24
char message[SHPDUMPERMSGLEN]

References _, shp_dumper_state::conn, core_asprintf(), free(), shp_dumper_state::geo_col_name, geometry_type_from_string(), LINETYPE, LWDEBUGF, lwtype_is_collection(), shp_dumper_state::message, MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, shp_dumper_state::outshptype, shp_dumper_state::outtype, POINTTYPE, POLYGONTYPE, window::res, shp_dumper_state::rowcount, shp_dumper_state::schema, SHPDUMPERERR, SHPDUMPERMSGLEN, SHPDUMPEROK, SHPT_ARC, SHPT_ARCM, SHPT_ARCZ, SHPT_MULTIPOINT, SHPT_MULTIPOINTM, SHPT_MULTIPOINTZ, SHPT_POINT, SHPT_POINTM, SHPT_POINTZ, SHPT_POLYGON, SHPT_POLYGONM, SHPT_POLYGONZ, shp_dumper_state::table, and ovdump::type.

Referenced by ShpDumperOpenTable().

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