PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ 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 = -1;
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  {
878  ret = colmap_read(state->config->column_map_filename,
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  /* Generate a string of comma separated column names of the form "(col1, col2 ... colN)" for the SQL
1104  insertion string */
1105  strcpy(state->col_names, "(" );
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  strcat(state->col_names, ")");
1274 
1275 
1276  /* Return status */
1277  return ret;
1278 }
int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
Definition: dbfopen.c:1195
DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
Definition: dbfopen.c:365
int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
Definition: dbfopen.c:1208
DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField, char *pszFieldName, int *pnWidth, int *pnDecimals)
Definition: dbfopen.c:1221
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
#define MULTILINETYPE
Definition: liblwgeom.h:89
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
void lwfree(void *mem)
Definition: lwutil.c:244
void * malloc(YYSIZE_T)
void free(void *)
type
Definition: ovdump.py:41
#define SHPT_ARCZ
Definition: shapefil.h:312
SHPObject SHPAPI_CALL1 * SHPReadObject(SHPHandle hSHP, int iShape);int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape, SHPObject *psObject
#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
#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
const char * colmap_pg_by_dbf(colmap *map, const char *dbfname)
Definition: shpcommon.c:199
char * codepage2encoding(const char *cpg)
Definition: shpcommon.c:288
#define _(String)
Definition: shpcommon.h:24
int nVertices
Definition: shapefil.h:348
char message[SHPLOADERMSGLEN]
DBFFieldType * types
SHPHandle hSHPHandle
DBFHandle hDBFHandle
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(), ovdump::type, shp_loader_state::types, utf8(), UTF8_BAD_RESULT, UTF8_GOOD_RESULT, UTF8_NO_RESULT, and shp_loader_state::widths.

Referenced by pgui_action_import(), and validate_remote_loader_columns().

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