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

◆ ShpLoaderOpenShape()

int ShpLoaderOpenShape ( SHPLOADERSTATE state)

Definition at line 842 of file shp2pgsql-core.c.

843{
844 SHPObject *obj = NULL;
845 int ret = SHPLOADEROK;
846 char name[MAXFIELDNAMELEN];
848 char *utf8str;
849
850 /* If we are reading the entire shapefile, open it */
851 if (state->config->readshape == 1)
852 {
853 state->hSHPHandle = SHPOpen(state->config->shp_file, "rb");
854
855 if (state->hSHPHandle == NULL)
856 {
857 snprintf(state->message, SHPLOADERMSGLEN, _("%s: shape (.shp) or index files (.shx) can not be opened, will just import attribute data."), state->config->shp_file);
858 state->config->readshape = 0;
859
860 ret = SHPLOADERWARN;
861 }
862 }
863
864 /* Open the DBF (attributes) file */
865 state->hDBFHandle = DBFOpen(state->config->shp_file, "rb");
866 if ((state->hSHPHandle == NULL && state->config->readshape == 1) || state->hDBFHandle == NULL)
867 {
868 snprintf(state->message, SHPLOADERMSGLEN, _("%s: dbf file (.dbf) can not be opened."), state->config->shp_file);
869
870 return SHPLOADERERR;
871 }
872
873
874 /* Open the column map if one was specified */
875 if (state->config->column_map_filename)
876 {
878 &state->column_map, state->message, SHPLOADERMSGLEN);
879 if (!ret) return SHPLOADERERR;
880 }
881
882 /* User hasn't altered the default encoding preference... */
883 if ( strcmp(state->config->encoding, ENCODING_DEFAULT) == 0 )
884 {
885 /* But the file has a code page entry... */
886 if ( state->hDBFHandle->pszCodePage )
887 {
888 /* And we figured out what iconv encoding it maps to, so use it! */
889 char *newencoding = NULL;
890 if ( (newencoding = codepage2encoding(state->hDBFHandle->pszCodePage)) )
891 {
892 lwfree(state->config->encoding);
893 state->config->encoding = newencoding;
894 }
895 }
896 }
897
898 /* If reading the whole shapefile (not just attributes)... */
899 if (state->config->readshape == 1)
900 {
901 SHPGetInfo(state->hSHPHandle, &state->num_entities, &state->shpfiletype, NULL, NULL);
902
903 /* If null_policy is set to abort, check for NULLs */
904 if (state->config->null_policy == POLICY_NULL_ABORT)
905 {
906 /* If we abort on null items, scan the entire file for NULLs */
907 for (int j = 0; j < state->num_entities; j++)
908 {
909 obj = SHPReadObject(state->hSHPHandle, j);
910
911 if (!obj)
912 {
913 snprintf(state->message, SHPLOADERMSGLEN, _("Error reading shape object %d"), j);
914 return SHPLOADERERR;
915 }
916
917 if (obj->nVertices == 0)
918 {
919 snprintf(state->message, SHPLOADERMSGLEN, _("Empty geometries found, aborted.)"));
920 return SHPLOADERERR;
921 }
922
923 SHPDestroyObject(obj);
924 }
925 }
926
927 /* Check the shapefile type */
928 int geomtype = 0;
929 switch (state->shpfiletype)
930 {
931 case SHPT_POINT:
932 /* Point */
933 state->pgtype = "POINT";
934 geomtype = POINTTYPE;
935 state->pgdims = 2;
936 break;
937
938 case SHPT_ARC:
939 /* PolyLine */
940 state->pgtype = "MULTILINESTRING";
941 geomtype = MULTILINETYPE ;
942 state->pgdims = 2;
943 break;
944
945 case SHPT_POLYGON:
946 /* Polygon */
947 state->pgtype = "MULTIPOLYGON";
948 geomtype = MULTIPOLYGONTYPE;
949 state->pgdims = 2;
950 break;
951
952 case SHPT_MULTIPOINT:
953 /* MultiPoint */
954 state->pgtype = "MULTIPOINT";
955 geomtype = MULTIPOINTTYPE;
956 state->pgdims = 2;
957 break;
958
959 case SHPT_POINTM:
960 /* PointM */
961 geomtype = POINTTYPE;
962 state->has_m = 1;
963 state->pgtype = "POINTM";
964 state->pgdims = 3;
965 break;
966
967 case SHPT_ARCM:
968 /* PolyLineM */
969 geomtype = MULTILINETYPE;
970 state->has_m = 1;
971 state->pgtype = "MULTILINESTRINGM";
972 state->pgdims = 3;
973 break;
974
975 case SHPT_POLYGONM:
976 /* PolygonM */
977 geomtype = MULTIPOLYGONTYPE;
978 state->has_m = 1;
979 state->pgtype = "MULTIPOLYGONM";
980 state->pgdims = 3;
981 break;
982
983 case SHPT_MULTIPOINTM:
984 /* MultiPointM */
985 geomtype = MULTIPOINTTYPE;
986 state->has_m = 1;
987 state->pgtype = "MULTIPOINTM";
988 state->pgdims = 3;
989 break;
990
991 case SHPT_POINTZ:
992 /* PointZ */
993 geomtype = POINTTYPE;
994 state->has_m = 1;
995 state->has_z = 1;
996 state->pgtype = "POINT";
997 state->pgdims = 4;
998 break;
999
1000 case SHPT_ARCZ:
1001 /* PolyLineZ */
1002 state->pgtype = "MULTILINESTRING";
1003 geomtype = MULTILINETYPE;
1004 state->has_z = 1;
1005 state->has_m = 1;
1006 state->pgdims = 4;
1007 break;
1008
1009 case SHPT_POLYGONZ:
1010 /* MultiPolygonZ */
1011 state->pgtype = "MULTIPOLYGON";
1012 geomtype = MULTIPOLYGONTYPE;
1013 state->has_z = 1;
1014 state->has_m = 1;
1015 state->pgdims = 4;
1016 break;
1017
1018 case SHPT_MULTIPOINTZ:
1019 /* MultiPointZ */
1020 state->pgtype = "MULTIPOINT";
1021 geomtype = MULTIPOINTTYPE;
1022 state->has_z = 1;
1023 state->has_m = 1;
1024 state->pgdims = 4;
1025 break;
1026
1027 default:
1028 state->pgtype = "GEOMETRY";
1029 geomtype = COLLECTIONTYPE;
1030 state->has_z = 1;
1031 state->has_m = 1;
1032 state->pgdims = 4;
1033
1034 snprintf(state->message, SHPLOADERMSGLEN, _("Unknown geometry type: %d\n"), state->shpfiletype);
1035 return SHPLOADERERR;
1036
1037 break;
1038 }
1039
1040 /* Force Z/M-handling if configured to do so */
1041 switch(state->config->force_output)
1042 {
1043 case FORCE_OUTPUT_2D:
1044 state->has_z = 0;
1045 state->has_m = 0;
1046 state->pgdims = 2;
1047 break;
1048
1049 case FORCE_OUTPUT_3DZ:
1050 state->has_z = 1;
1051 state->has_m = 0;
1052 state->pgdims = 3;
1053 break;
1054
1055 case FORCE_OUTPUT_3DM:
1056 state->has_z = 0;
1057 state->has_m = 1;
1058 state->pgdims = 3;
1059 break;
1060
1061 case FORCE_OUTPUT_4D:
1062 state->has_z = 1;
1063 state->has_m = 1;
1064 state->pgdims = 4;
1065 break;
1066 default:
1067 /* Simply use the auto-detected values above */
1068 break;
1069 }
1070
1071 /* If in simple geometry mode, alter names for CREATE TABLE by skipping MULTI */
1072 if (state->config->simple_geometries)
1073 {
1074 if ((geomtype == MULTIPOLYGONTYPE) || (geomtype == MULTILINETYPE) || (geomtype == MULTIPOINTTYPE))
1075 {
1076 /* Chop off the "MULTI" from the string. */
1077 state->pgtype += 5;
1078 }
1079 }
1080
1081 }
1082 else
1083 {
1084 /* Otherwise just count the number of records in the DBF */
1085 state->num_entities = DBFGetRecordCount(state->hDBFHandle);
1086 }
1087
1088
1089 /* Get the field information from the DBF */
1090 state->num_fields = DBFGetFieldCount(state->hDBFHandle);
1091
1092 state->num_records = DBFGetRecordCount(state->hDBFHandle);
1093
1094 /* Allocate storage for field information */
1095 state->field_names = malloc(state->num_fields * sizeof(char*));
1096 state->types = (DBFFieldType *)malloc(state->num_fields * sizeof(int));
1097 state->widths = malloc(state->num_fields * sizeof(int));
1098 state->precisions = malloc(state->num_fields * sizeof(int));
1099 state->pgfieldtypes = malloc(state->num_fields * sizeof(char *));
1100 state->col_names = malloc((state->num_fields + 2) * sizeof(char) * MAXFIELDNAMELEN);
1101
1102 strcpy(state->col_names, "" );
1103 /* Generate a string of comma separated column names of the form "col1, col2 ... colN" for the SQL
1104 insertion string */
1105
1106 for (int j = 0; j < state->num_fields; j++)
1107 {
1108 int field_precision = 0, field_width = 0;
1109 type = DBFGetFieldInfo(state->hDBFHandle, j, name, &field_width, &field_precision);
1110
1111 state->types[j] = type;
1112 state->widths[j] = field_width;
1113 state->precisions[j] = field_precision;
1114/* fprintf(stderr, "XXX %s width:%d prec:%d\n", name, field_width, field_precision); */
1115
1116 if (state->config->encoding)
1117 {
1118 char *encoding_msg = _("Try \"LATIN1\" (Western European), or one of the values described at http://www.gnu.org/software/libiconv/.");
1119
1120 int rv = utf8(state->config->encoding, name, &utf8str);
1121
1122 if (rv != UTF8_GOOD_RESULT)
1123 {
1124 if ( rv == UTF8_BAD_RESULT )
1125 snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert field name \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), utf8str, strerror(errno), state->config->encoding, encoding_msg);
1126 else if ( rv == UTF8_NO_RESULT )
1127 snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert field name to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), strerror(errno), state->config->encoding, encoding_msg);
1128 else
1129 snprintf(state->message, SHPLOADERMSGLEN, _("Unexpected return value from utf8()"));
1130
1131 if ( rv == UTF8_BAD_RESULT )
1132 free(utf8str);
1133
1134 return SHPLOADERERR;
1135 }
1136
1137 strncpy(name, utf8str, MAXFIELDNAMELEN);
1138 name[MAXFIELDNAMELEN-1] = '\0';
1139 free(utf8str);
1140 }
1141
1142 /* If a column map file has been passed in, use this to create the postgresql field name from
1143 the dbf column name */
1144 {
1145 const char *mapped = colmap_pg_by_dbf(&state->column_map, name);
1146 if (mapped)
1147 {
1148 strncpy(name, mapped, MAXFIELDNAMELEN);
1149 name[MAXFIELDNAMELEN-1] = '\0';
1150 }
1151 }
1152
1153 /*
1154 * Make field names lowercase unless asked to
1155 * keep identifiers case.
1156 */
1157 if (!state->config->quoteidentifiers)
1158 strtolower(name);
1159
1160 /*
1161 * Escape names starting with the
1162 * escape char (_), those named 'gid'
1163 * or after pgsql reserved attribute names
1164 */
1165 if (name[0] == '_' ||
1166 ! strcmp(name, "gid") ||
1167 ! strcmp(name, "tableoid") ||
1168 ! strcmp(name, "cmin") ||
1169 ! strcmp(name, "cmax") ||
1170 ! strcmp(name, "xmin") ||
1171 ! strcmp(name, "xmax") ||
1172 ! strcmp(name, "primary") ||
1173 ! strcmp(name, "oid") ||
1174 ! strcmp(name, "ctid"))
1175 {
1176 char tmp[MAXFIELDNAMELEN] = "__";
1177 memcpy(tmp+2, name, MAXFIELDNAMELEN-2);
1178 tmp[MAXFIELDNAMELEN-1] = '\0';
1179 strncpy(name, tmp, MAXFIELDNAMELEN);
1180 }
1181
1182 /* Avoid duplicating field names */
1183 for (int z = 0; z < j; z++)
1184 {
1185 if (strcmp(state->field_names[z], name) == 0)
1186 {
1187 strncat(name, "__", MAXFIELDNAMELEN - 1);
1188 snprintf(name + strlen(name),
1189 MAXFIELDNAMELEN - 1 - strlen(name),
1190 "%i",
1191 j);
1192 break;
1193 }
1194 }
1195
1196 state->field_names[j] = strdup(name);
1197
1198 /* Now generate the PostgreSQL type name string and width based upon the shapefile type */
1199 switch (state->types[j])
1200 {
1201 case FTString:
1202 state->pgfieldtypes[j] = strdup("varchar");
1203 break;
1204
1205 case FTDate:
1206 state->pgfieldtypes[j] = strdup("date");
1207 break;
1208
1209 case FTInteger:
1210 /* Determine exact type based upon field width */
1211 if (state->config->forceint4 || (state->widths[j] >=5 && state->widths[j] < 10))
1212 {
1213 state->pgfieldtypes[j] = strdup("int4");
1214 }
1215 else if (state->widths[j] >=10 && state->widths[j] < 19)
1216 {
1217 state->pgfieldtypes[j] = strdup("int8");
1218 }
1219 else if (state->widths[j] < 5)
1220 {
1221 state->pgfieldtypes[j] = strdup("int2");
1222 }
1223 else
1224 {
1225 state->pgfieldtypes[j] = strdup("numeric");
1226 }
1227 break;
1228
1229 case FTDouble:
1230 /* Determine exact type based upon field width */
1231 fprintf(stderr, "Field %s is an FTDouble with width %d and precision %d\n",
1232 state->field_names[j], state->widths[j], state->precisions[j]);
1233 if (state->widths[j] > 18)
1234 {
1235 state->pgfieldtypes[j] = strdup("numeric");
1236 }
1237 else
1238 {
1239 state->pgfieldtypes[j] = strdup("float8");
1240 }
1241 break;
1242
1243 case FTLogical:
1244 state->pgfieldtypes[j] = strdup("boolean");
1245 break;
1246
1247 default:
1248 snprintf(state->message, SHPLOADERMSGLEN, _("Invalid type %x in DBF file"), state->types[j]);
1249 return SHPLOADERERR;
1250 }
1251
1252 strcat(state->col_names, "\"");
1253 strcat(state->col_names, name);
1254
1255 if (state->config->readshape == 1 || j < (state->num_fields - 1))
1256 {
1257 /* Don't include last comma if its the last field and no geometry field will follow */
1258 strcat(state->col_names, "\",");
1259 }
1260 else
1261 {
1262 strcat(state->col_names, "\"");
1263 }
1264 }
1265
1266 /* Append the geometry column if required */
1267 if (state->config->readshape == 1)
1268 strcat(state->col_names, state->geo_col);
1269
1270 /* Return status */
1271 return ret;
1272}
int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
Definition dbfopen.c:1237
DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
Definition dbfopen.c:351
int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
Definition dbfopen.c:1250
DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals)
Definition dbfopen.c:1265
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define MULTILINETYPE
Definition liblwgeom.h:106
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
void lwfree(void *mem)
Definition lwutil.c:248
void * malloc(YYSIZE_T)
void free(void *)
#define SHPT_ARCZ
Definition shapefil.h:354
DBFFieldType
Definition shapefil.h:638
@ FTDouble
Definition shapefil.h:641
@ FTString
Definition shapefil.h:639
@ FTInvalid
Definition shapefil.h:644
@ FTLogical
Definition shapefil.h:642
@ FTDate
Definition shapefil.h:643
@ FTInteger
Definition shapefil.h:640
#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
void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject)
Definition shpopen.c:2641
SHPHandle SHPAPI_CALL SHPOpen(const char *pszShapeFile, const char *pszAccess)
Definition shpopen.c:291
#define SHPT_MULTIPOINT
Definition shapefil.h:352
void SHPAPI_CALL SHPGetInfo(SHPHandle hSHP, int *pnEntities, int *pnShapeType, double *padfMinBound, double *padfMaxBound)
Definition shpopen.c:947
SHPObject SHPAPI_CALL1 * SHPReadObject(SHPHandle hSHP, int iShape);int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape, SHPObject *psObject
Definition shpopen.c:1831
#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
static int utf8(const char *fromcode, char *inputbuf, char **outputbuf)
#define UTF8_GOOD_RESULT
#define UTF8_BAD_RESULT
void strtolower(char *s)
#define UTF8_NO_RESULT
#define FORCE_OUTPUT_4D
#define POLICY_NULL_ABORT
#define FORCE_OUTPUT_2D
#define SHPLOADERWARN
#define FORCE_OUTPUT_3DM
#define ENCODING_DEFAULT
#define SHPLOADERMSGLEN
#define SHPLOADERERR
#define MAXFIELDNAMELEN
#define SHPLOADEROK
#define FORCE_OUTPUT_3DZ
int colmap_read(const char *filename, colmap *map, char *errbuf, size_t errbuflen)
Read the content of filename into a symbol map.
Definition shpcommon.c:217
char * codepage2encoding(const char *cpg)
Definition shpcommon.c:302
const char * colmap_pg_by_dbf(colmap *map, const char *dbfname)
Definition shpcommon.c:203
#define _(String)
Definition shpcommon.h:24
char * pszCodePage
Definition shapefil.h:625
char message[SHPLOADERMSGLEN]
DBFFieldType * types
SHPLOADERCONFIG * config

References _, codepage2encoding(), shp_loader_state::col_names, COLLECTIONTYPE, colmap_pg_by_dbf(), colmap_read(), shp_loader_state::column_map, shp_loader_config::column_map_filename, shp_loader_state::config, DBFGetFieldCount(), DBFGetFieldInfo(), DBFGetRecordCount(), DBFOpen(), shp_loader_config::encoding, ENCODING_DEFAULT, shp_loader_state::field_names, shp_loader_config::force_output, FORCE_OUTPUT_2D, FORCE_OUTPUT_3DM, FORCE_OUTPUT_3DZ, FORCE_OUTPUT_4D, shp_loader_config::forceint4, free(), FTDate, FTDouble, FTInteger, FTInvalid, FTLogical, FTString, shp_loader_state::geo_col, shp_loader_state::has_m, shp_loader_state::has_z, shp_loader_state::hDBFHandle, shp_loader_state::hSHPHandle, lwfree(), malloc(), MAXFIELDNAMELEN, shp_loader_state::message, MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, shp_loader_config::null_policy, shp_loader_state::num_entities, shp_loader_state::num_fields, shp_loader_state::num_records, tagSHPObject::nVertices, shp_loader_state::pgdims, shp_loader_state::pgfieldtypes, shp_loader_state::pgtype, POINTTYPE, POLICY_NULL_ABORT, shp_loader_state::precisions, DBFInfo::pszCodePage, shp_loader_config::quoteidentifiers, shp_loader_config::readshape, shp_loader_config::shp_file, SHPDestroyObject(), shp_loader_state::shpfiletype, SHPGetInfo(), SHPLOADERERR, SHPLOADERMSGLEN, SHPLOADEROK, SHPLOADERWARN, SHPOpen(), SHPReadObject(), 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_loader_config::simple_geometries, strtolower(), shp_loader_state::types, utf8(), UTF8_BAD_RESULT, UTF8_GOOD_RESULT, UTF8_NO_RESULT, and shp_loader_state::widths.

Referenced by main(), pgui_action_import(), and validate_remote_loader_columns().

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