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

◆ 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':
1065 break;
1066
1067 case 'm':
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 *)
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, 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: