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

◆ ShpLoaderOpenShape()

int ShpLoaderOpenShape ( SHPLOADERSTATE state)

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

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