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