/* Return an allocated string representation of a specified record item */ int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord) { SHPObject *obj = NULL; stringbuffer_t *sb; stringbuffer_t *sbwarn; char val[MAXVALUELEN]; char *escval; char *geometry=NULL, *ret; char *utf8str; int res, i; int rv; /* Clear the stringbuffers */ sbwarn = stringbuffer_create(); stringbuffer_clear(sbwarn); sb = stringbuffer_create(); stringbuffer_clear(sb); /* If we are reading the DBF only and the record has been marked deleted, return deleted record status */ if (state->config->readshape == 0 && DBFIsRecordDeleted(state->hDBFHandle, item)) { *strrecord = NULL; return SHPLOADERRECDELETED; } /* If we are reading the shapefile, open the specified record */ if (state->config->readshape == 1) { obj = SHPReadObject(state->hSHPHandle, item); if (!obj) { snprintf(state->message, SHPLOADERMSGLEN, _("Error reading shape object %d"), item); return SHPLOADERERR; } /* If we are set to skip NULLs, return a NULL record status */ if (state->config->null_policy == POLICY_NULL_SKIP && obj->nVertices == 0 ) { SHPDestroyObject(obj); *strrecord = NULL; return SHPLOADERRECISNULL; } } /* If not in dump format, generate the INSERT string */ if (!state->config->dump_format) { if (state->config->schema) { stringbuffer_aprintf(sb, "INSERT INTO \"%s\".\"%s\" %s VALUES (", state->config->schema, state->config->table, state->col_names); } else { stringbuffer_aprintf(sb, "INSERT INTO \"%s\" %s VALUES (", state->config->table, state->col_names); } } /* Read all of the attributes from the DBF file for this item */ for (i = 0; i < DBFGetFieldCount(state->hDBFHandle); i++) { /* Special case for NULL attributes */ if (DBFIsAttributeNULL(state->hDBFHandle, item, i)) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\\N"); else stringbuffer_aprintf(sb, "NULL"); } else { /* Attribute NOT NULL */ switch (state->types[i]) { case FTInteger: case FTDouble: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } /* If the value is an empty string, change to 0 */ if (val[0] == '\0') { val[0] = '0'; val[1] = '\0'; } /* If the value ends with just ".", remove the dot */ if (val[strlen(val) - 1] == '.') val[strlen(val) - 1] = '\0'; break; case FTString: case FTLogical: case FTDate: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } break; default: snprintf(state->message, SHPLOADERMSGLEN, _("Error: field %d has invalid or unknown field type (%d)"), i, state->types[i]); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } if (state->config->encoding) { char *encoding_msg = _("Try \"LATIN1\" (Western European), or one of the values described at http://www.postgresql.org/docs/current/static/multibyte.html."); rv = utf8(state->config->encoding, val, &utf8str); if (rv != UTF8_GOOD_RESULT) { if ( rv == UTF8_BAD_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), utf8str, strerror(errno), state->config->encoding, encoding_msg); else if ( rv == UTF8_NO_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), strerror(errno), state->config->encoding, encoding_msg); else snprintf(state->message, SHPLOADERMSGLEN, _("Unexpected return value from utf8()")); if ( rv == UTF8_BAD_RESULT ) free(utf8str); return SHPLOADERERR; } strncpy(val, utf8str, MAXVALUELEN); free(utf8str); } /* Escape attribute correctly according to dump format */ if (state->config->dump_format) { escval = escape_copy_string(val); stringbuffer_aprintf(sb, "%s", escval); } else { escval = escape_insert_string(val); stringbuffer_aprintf(sb, "'%s'", escval); } /* Free the escaped version if required */ if (val != escval) free(escval); } /* Only put in delimeter if not last field or a shape will follow */ if (state->config->readshape == 1 || i < DBFGetFieldCount(state->hDBFHandle) - 1) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\t"); else stringbuffer_aprintf(sb, ","); } /* End of DBF attribute loop */ } /* Add the shape attribute if we are reading it */ if (state->config->readshape == 1) { /* Handle the case of a NULL shape */ if (obj->nVertices == 0) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\\N"); else stringbuffer_aprintf(sb, "NULL"); } else { /* Handle all other shape attributes */ switch (obj->nSHPType) { case SHPT_POLYGON: case SHPT_POLYGONM: case SHPT_POLYGONZ: res = GeneratePolygonGeometry(state, obj, &geometry); break; case SHPT_POINT: case SHPT_POINTM: case SHPT_POINTZ: res = GeneratePointGeometry(state, obj, &geometry, 0); break; case SHPT_MULTIPOINT: case SHPT_MULTIPOINTM: case SHPT_MULTIPOINTZ: /* Force it to multi unless using -S */ res = GeneratePointGeometry(state, obj, &geometry, state->config->simple_geometries ? 0 : 1); break; case SHPT_ARC: case SHPT_ARCM: case SHPT_ARCZ: res = GenerateLineStringGeometry(state, obj, &geometry); break; default: snprintf(state->message, SHPLOADERMSGLEN, _("Shape type is not supported, type id = %d"), obj->nSHPType); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* The default returns out of the function, so res will always have been set. */ if (res != SHPLOADEROK) { /* Error message has already been set */ SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* Now generate the geometry string according to the current configuration */ if (!state->config->dump_format) { if (state->to_srid != state->from_srid) { stringbuffer_aprintf(sb, "ST_Transform("); } stringbuffer_aprintf(sb, "'"); } stringbuffer_aprintf(sb, "%s", geometry); if (!state->config->dump_format) { stringbuffer_aprintf(sb, "'"); /* Close the ST_Transform if reprojecting. */ if (state->to_srid != state->from_srid) { /* We need to add an explicit cast to geography/geometry to ensure that PostgreSQL doesn't get confused with the ST_Transform() raster function. */ if (state->config->geography) stringbuffer_aprintf(sb, "::geometry, %d)::geography", state->to_srid); else stringbuffer_aprintf(sb, "::geometry, %d)", state->to_srid); } } free(geometry); } /* Tidy up everything */ SHPDestroyObject(obj); } /* Close the line correctly for dump/insert format */ if (!state->config->dump_format) stringbuffer_aprintf(sb, ");"); /* Copy the string buffer into a new string, destroying the string buffer */ ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1); strcpy(ret, (char *)stringbuffer_getstring(sb)); stringbuffer_destroy(sb); *strrecord = ret; /* If any warnings occurred, set the returned message string and warning status */ if (strlen((char *)stringbuffer_getstring(sbwarn)) > 0) { snprintf(state->message, SHPLOADERMSGLEN, "%s", stringbuffer_getstring(sbwarn)); stringbuffer_destroy(sbwarn); return SHPLOADERWARN; } else { /* Everything went okay */ stringbuffer_destroy(sbwarn); return SHPLOADEROK; } }
/* Return an allocated string representation of a specified record item */ int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord) { SHPObject *obj = NULL; stringbuffer_t *sb; stringbuffer_t *sbwarn; char val[MAXVALUELEN]; char *escval; char *geometry=NULL, *ret; char *utf8str; int res, i; int rv; /* Clear the stringbuffers */ sbwarn = stringbuffer_create(); stringbuffer_clear(sbwarn); sb = stringbuffer_create(); stringbuffer_clear(sb); /* If we are reading the DBF only and the record has been marked deleted, return deleted record status */ if (state->config->readshape == 0 && DBFReadDeleted(state->hDBFHandle, item)) { *strrecord = NULL; return SHPLOADERRECDELETED; } /* If we are reading the shapefile, open the specified record */ if (state->config->readshape == 1) { obj = SHPReadObject(state->hSHPHandle, item); if (!obj) { snprintf(state->message, SHPLOADERMSGLEN, "Error reading shape object %d", item); return SHPLOADERERR; } /* If we are set to skip NULLs, return a NULL record status */ if (state->config->null_policy == POLICY_NULL_SKIP && obj->nVertices == 0 ) { SHPDestroyObject(obj); *strrecord = NULL; return SHPLOADERRECISNULL; } } /* If not in dump format, generate the INSERT string */ if (!state->config->dump_format) { if (state->config->schema) { vasbappend(sb, "INSERT INTO \"%s\".\"%s\" %s VALUES (", state->config->schema, state->config->table, state->col_names); } else { vasbappend(sb, "INSERT INTO \"%s\" %s VALUES (", state->config->table, state->col_names); } } /* Read all of the attributes from the DBF file for this item */ for (i = 0; i < DBFGetFieldCount(state->hDBFHandle); i++) { /* Special case for NULL attributes */ if (DBFIsAttributeNULL(state->hDBFHandle, item, i)) { if (state->config->dump_format) vasbappend(sb, "\\N"); else vasbappend(sb, "NULL"); } else { /* Attribute NOT NULL */ switch (state->types[i]) { case FTInteger: case FTDouble: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { vasbappend(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } /* If the value is an empty string, change to 0 */ if (val[0] == '\0') { val[0] = '0'; val[1] = '\0'; } /* If the value ends with just ".", remove the dot */ if (val[strlen(val) - 1] == '.') val[strlen(val) - 1] = '\0'; break; case FTString: case FTLogical: case FTDate: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { vasbappend(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } break; default: snprintf(state->message, SHPLOADERMSGLEN, "Error: field %d has invalid or unknown field type (%d)", i, state->types[i]); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } if (state->config->encoding) { static char *encoding_msg = "Try \"LATIN1\" (Western European), or one of the values described at http://www.postgresql.org/docs/current/static/multibyte.html."; /* If we are converting from another encoding to UTF8, convert the field value to UTF8 */ int rv = utf8(state->config->encoding, val, &utf8str); if ( !UTF8_DROP_BAD_CHARACTERS && rv != UTF8_GOOD_RESULT ) { if( rv == UTF8_BAD_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, "Unable to convert data value \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s", utf8str, strerror(errno), state->config->encoding, encoding_msg); else if( rv == UTF8_NO_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, "Unable to convert data value to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s", strerror(errno), state->config->encoding, encoding_msg); else snprintf(state->message, SHPLOADERMSGLEN, "Unexpected return value from utf8()"); if( rv == UTF8_BAD_RESULT ) free(utf8str); return SHPLOADERERR; } /* Optionally (compile-time) suppress bad UTF8 values */ if ( UTF8_DROP_BAD_CHARACTERS && rv != UTF8_GOOD_RESULT ) { val[0] = '.'; val[1] = '\0'; } /* The utf8str buffer is only alloc'ed if the UTF8 conversion works */ if ( rv == UTF8_GOOD_RESULT ) { strncpy(val, utf8str, MAXVALUELEN); free(utf8str); } } /* Escape attribute correctly according to dump format */ if (state->config->dump_format) { escval = escape_copy_string(val); vasbappend(sb, "%s", escval); } else { escval = escape_insert_string(val); vasbappend(sb, "'%s'", escval); } /* Free the escaped version if required */ if (val != escval) free(escval); } /* Only put in delimeter if not last field or a shape will follow */ if (state->config->readshape == 1 || i < DBFGetFieldCount(state->hDBFHandle) - 1) { if (state->config->dump_format) vasbappend(sb, "\t"); else vasbappend(sb, ","); } /* End of DBF attribute loop */ } /* Add the shape attribute if we are reading it */ if (state->config->readshape == 1) { /* Handle the case of a NULL shape */ if (obj->nVertices == 0) { if (state->config->dump_format) vasbappend(sb, "\\N"); else vasbappend(sb, "NULL"); } else { /* Handle all other shape attributes */ switch (obj->nSHPType) { case SHPT_POLYGON: case SHPT_POLYGONM: case SHPT_POLYGONZ: res = GeneratePolygonGeometry(state, obj, &geometry); if (res != SHPLOADEROK) { /* Error message has already been set */ SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } break; case SHPT_POINT: case SHPT_POINTM: case SHPT_POINTZ: case SHPT_MULTIPOINT: case SHPT_MULTIPOINTM: case SHPT_MULTIPOINTZ: res = GeneratePointGeometry(state, obj, &geometry); if (res != SHPLOADEROK) { /* Error message has already been set */ SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } break; case SHPT_ARC: case SHPT_ARCM: case SHPT_ARCZ: res = GenerateLineStringGeometry(state, obj, &geometry); if (res != SHPLOADEROK) { /* Error message has already been set */ SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } break; default: snprintf(state->message, SHPLOADERMSGLEN, "Shape type is NOT SUPPORTED, type id = %d", obj->nSHPType); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* Now generate the geometry string according to the current configuration */ if (state->config->hwgeom) { /* Old-style hwgeom (WKT) */ if (!state->config->dump_format) vasbappend(sb, "GeomFromText('"); else { /* Output SRID if relevant */ if (state->config->sr_id != 0) vasbappend(sb, "SRID=%d;", state->config->sr_id); } vasbappend(sb, "%s", geometry); if (!state->config->dump_format) { vasbappend(sb, "'"); /* Output SRID if relevant */ if (state->config->sr_id != 0) vasbappend(sb, ", %d)", state->config->sr_id); else vasbappend(sb, ")"); } } else { /* New style lwgeom (HEXEWKB) */ if (!state->config->dump_format) vasbappend(sb, "'"); vasbappend(sb, "%s", geometry); if (!state->config->dump_format) vasbappend(sb, "'"); } free(geometry); } /* Tidy up everything */ SHPDestroyObject(obj); } /* Close the line correctly for dump/insert format */ if (!state->config->dump_format) vasbappend(sb, ");"); /* Copy the string buffer into a new string, destroying the string buffer */ ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1); strcpy(ret, (char *)stringbuffer_getstring(sb)); stringbuffer_destroy(sb); *strrecord = ret; /* If any warnings occurred, set the returned message string and warning status */ if (strlen((char *)stringbuffer_getstring(sbwarn)) > 0) { snprintf(state->message, SHPLOADERMSGLEN, "%s", stringbuffer_getstring(sbwarn)); stringbuffer_destroy(sbwarn); return SHPLOADERWARN; } else { /* Everything went okay */ stringbuffer_destroy(sbwarn); return SHPLOADEROK; } }