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

Definition at line 828 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().

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

Here is the call graph for this function:

Here is the caller graph for this function: