PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ getTableInfo()

static int getTableInfo ( SHPDUMPERSTATE state)
static

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

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