PostGIS  2.5.0dev-r@@SVN_REVISION@@
int ShpLoaderOpenShape ( SHPLOADERSTATE state)

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

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().

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

Here is the call graph for this function:

Here is the caller graph for this function: