PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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':
1071 break;
1072
1073 case 'm':
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:1196
#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 *)
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, 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().

Here is the call graph for this function:
Here is the caller graph for this function: