PostGIS  2.1.10dev-r@@SVN_REVISION@@
static int getTableInfo ( SHPDUMPERSTATE state)
static

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

References _, shp_dumper_state::conn, 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, and shp_dumper_state::table.

Referenced by ShpDumperOpenTable().

861 {
862 
863  /* Get some more information from the table:
864  - count = total number of geometries/geographies in the table
865 
866  and if we have found a suitable geometry column:
867 
868  - max = maximum number of dimensions within the geometry/geography column
869  - geometrytype = string representing the geometry/geography type, e.g. POINT
870 
871  Since max/geometrytype already require a sequential scan of the table, we may as
872  well get the row count too.
873  */
874 
875  PGresult *res;
876  char *query;
877  int tmpint;
878 
879 
880  if (state->geo_col_name)
881  {
882  /* Include geometry information */
883  if (state->schema)
884  {
885  query = malloc(150 + 4 * strlen(state->geo_col_name) + strlen(state->schema) + strlen(state->table));
886 
887  sprintf(query, "SELECT count(\"%s\"), max(ST_zmflag(\"%s\"::geometry)), geometrytype(\"%s\"::geometry) FROM \"%s\".\"%s\" GROUP BY geometrytype(\"%s\"::geometry)",
888  state->geo_col_name, state->geo_col_name, state->geo_col_name, state->schema, state->table, state->geo_col_name);
889  }
890  else
891  {
892  query = malloc(150 + 4 * strlen(state->geo_col_name) + strlen(state->table));
893 
894  sprintf(query, "SELECT count(\"%s\"), max(ST_zmflag(\"%s\"::geometry)), geometrytype(\"%s\"::geometry) FROM \"%s\" GROUP BY geometrytype(\"%s\"::geometry)",
895  state->geo_col_name, state->geo_col_name, state->geo_col_name, state->table, state->geo_col_name);
896  }
897  }
898  else
899  {
900  /* Otherwise... just a row count will do */
901  if (state->schema)
902  {
903  query = malloc(40 + strlen(state->schema) + strlen(state->table));
904 
905  sprintf(query, "SELECT count(1) FROM \"%s\".\"%s\"", state->schema, state->table);
906  }
907  else
908  {
909  query = malloc(40 + strlen(state->table));
910 
911  sprintf(query, "SELECT count(1) FROM \"%s\"", 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  geometry_type_from_string(PQgetvalue(res, i, 2), &type, &dummy, &dummy);
956 
957  if (!type) continue; /* skip null geometries */
958 
959  /* We can always set typefound to that of the first column found */
960  if (!typefound)
961  typefound = type;
962 
963  switch (type)
964  {
965  case MULTIPOINTTYPE:
966  if (typefound != MULTIPOINTTYPE && typefound != POINTTYPE)
967  typemismatch = 1;
968  else
969  typefound = MULTIPOINTTYPE;
970  break;
971 
972  case MULTILINETYPE:
973  if (typefound != MULTILINETYPE && typefound != LINETYPE)
974  typemismatch = 1;
975  else
976  typefound = MULTILINETYPE;
977  break;
978 
979  case MULTIPOLYGONTYPE:
980  if (typefound != MULTIPOLYGONTYPE && typefound != POLYGONTYPE)
981  typemismatch = 1;
982  else
983  typefound = MULTIPOLYGONTYPE;
984  break;
985 
986  case POINTTYPE:
987  if (typefound != POINTTYPE && typefound != MULTIPOINTTYPE)
988  typemismatch = 1;
989  else if (!lwtype_is_collection(type))
990  typefound = POINTTYPE;
991  break;
992 
993  case LINETYPE:
994  if (typefound != LINETYPE && typefound != MULTILINETYPE)
995  typemismatch = 1;
996  else if (!lwtype_is_collection(type))
997  typefound = LINETYPE;
998  break;
999 
1000  case POLYGONTYPE:
1001  if (typefound != POLYGONTYPE && typefound != MULTIPOLYGONTYPE)
1002  typemismatch = 1;
1003  else if (!lwtype_is_collection(type))
1004  typefound = POLYGONTYPE;
1005  break;
1006  }
1007 
1008  /* Update the rowcount for each type */
1009  state->rowcount += atoi(PQgetvalue(res, i, 0));
1010 
1011  /* Set up the dimension output type (note: regardless of how many rows
1012  the table metadata query returns, this value will be the same. But
1013  we'll choose to use the first value anyway) */
1014  tmpint = atoi(PQgetvalue(res, i, 1));
1015  switch (tmpint)
1016  {
1017  case 0:
1018  state->outtype = 's';
1019  break;
1020  case 1:
1021  state->outtype = 'm';
1022  break;
1023  default:
1024  state->outtype = 'z';
1025  break;
1026  }
1027 
1028  }
1029 
1030  /* Flag an error if the table contains incompatible geometry combinations */
1031  if (typemismatch)
1032  {
1033  snprintf(state->message, SHPDUMPERMSGLEN, _("ERROR: Incompatible mixed geometry types in table"));
1034  PQclear(res);
1035  return SHPDUMPERERR;
1036  }
1037 
1038  /* Set up the shapefile output type based upon the dimension information */
1039  switch (typefound)
1040  {
1041  case POINTTYPE:
1042  switch(state->outtype)
1043  {
1044  case 'z':
1045  state->outshptype = SHPT_POINTZ;
1046  break;
1047 
1048  case 'm':
1049  state->outshptype = SHPT_POINTM;
1050  break;
1051 
1052  default:
1053  state->outshptype = SHPT_POINT;
1054  }
1055  break;
1056 
1057  case MULTIPOINTTYPE:
1058  switch(state->outtype)
1059  {
1060  case 'z':
1061  state->outshptype = SHPT_MULTIPOINTZ;
1062  break;
1063 
1064  case 'm':
1065  state->outshptype = SHPT_MULTIPOINTM;
1066  break;
1067 
1068  default:
1069  state->outshptype = SHPT_MULTIPOINT;
1070  }
1071  break;
1072 
1073  case LINETYPE:
1074  case MULTILINETYPE:
1075  switch(state->outtype)
1076  {
1077  case 'z':
1078  state->outshptype = SHPT_ARCZ;
1079  break;
1080 
1081  case 'm':
1082  state->outshptype = SHPT_ARCM;
1083  break;
1084 
1085  default:
1086  state->outshptype = SHPT_ARC;
1087  }
1088  break;
1089 
1090  case POLYGONTYPE:
1091  case MULTIPOLYGONTYPE:
1092  switch(state->outtype)
1093  {
1094  case 'z':
1095  state->outshptype = SHPT_POLYGONZ;
1096  break;
1097 
1098  case 'm':
1099  state->outshptype = SHPT_POLYGONM;
1100  break;
1101 
1102  default:
1103  state->outshptype = SHPT_POLYGON;
1104  }
1105  break;
1106  }
1107  }
1108  else
1109  {
1110  /* Without a geo* column the total is simply the first (COUNT) column */
1111  state->rowcount = atoi(PQgetvalue(res, 0, 0));
1112  }
1113 
1114  /* Dispose of the result set */
1115  PQclear(res);
1116 
1117  return SHPDUMPEROK;
1118 }
#define LINETYPE
Definition: liblwgeom.h:61
#define SHPT_ARCM
Definition: shapefil.h:317
tuple res
Definition: window.py:80
#define SHPT_POLYGONM
Definition: shapefil.h:318
#define POLYGONTYPE
Definition: liblwgeom.h:62
#define _(String)
Definition: shpcommon.h:23
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m)
Calculate type integer and dimensional flags from string input.
Definition: g_util.c:149
#define SHPT_MULTIPOINT
Definition: shapefil.h:311
#define SHPT_POLYGON
Definition: shapefil.h:310
#define SHPT_MULTIPOINTZ
Definition: shapefil.h:315
#define SHPT_ARCZ
Definition: shapefil.h:313
#define SHPDUMPERERR
int lwtype_is_collection(uint8_t type)
Determine whether a type number is a collection or not.
Definition: lwgeom.c:955
#define SHPT_MULTIPOINTM
Definition: shapefil.h:319
#define SHPDUMPERMSGLEN
#define SHPT_POINTZ
Definition: shapefil.h:312
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define SHPT_POINTM
Definition: shapefil.h:316
#define SHPT_POLYGONZ
Definition: shapefil.h:314
#define SHPT_POINT
Definition: shapefil.h:308
#define SHPDUMPEROK
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
char message[SHPDUMPERMSGLEN]
#define MULTILINETYPE
Definition: liblwgeom.h:64
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:55
#define SHPT_ARC
Definition: shapefil.h:309

Here is the call graph for this function:

Here is the caller graph for this function: