PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ getTableInfo()

static int getTableInfo ( SHPDUMPERSTATE state)
static

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

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

References _, shp_dumper_state::conn, free(), shp_dumper_state::geo_col_name, geometry_type_from_string(), LINETYPE, LWDEBUGF, lwtype_is_collection(), malloc(), 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: