PostGIS  3.7.0dev-r@@SVN_REVISION@@

◆ getTableInfo()

static int getTableInfo ( SHPDUMPERSTATE state)
static

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

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