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

◆ ShpLoaderOpenShape()

int ShpLoaderOpenShape ( SHPLOADERSTATE state)

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

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