[GRASS-SVN] r55692 - in grass/trunk: include/defs lib/vector/Vlib
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Apr 10 13:35:47 PDT 2013
Author: martinl
Date: 2013-04-10 13:35:47 -0700 (Wed, 10 Apr 2013)
New Revision: 55692
Modified:
grass/trunk/include/defs/vector.h
grass/trunk/lib/vector/Vlib/open_ogr.c
grass/trunk/lib/vector/Vlib/open_pg.c
grass/trunk/lib/vector/Vlib/write_ogr.c
grass/trunk/lib/vector/Vlib/write_pg.c
Log:
vlib: remove V2_open_new_ogr|pg() from public API
Modified: grass/trunk/include/defs/vector.h
===================================================================
--- grass/trunk/include/defs/vector.h 2013-04-10 18:38:57 UTC (rev 55691)
+++ grass/trunk/include/defs/vector.h 2013-04-10 20:35:47 UTC (rev 55692)
@@ -491,8 +491,6 @@
int V1_open_new_nat(struct Map_info *, const char *, int);
int V1_open_new_ogr(struct Map_info *, const char *, int);
int V1_open_new_pg(struct Map_info *, const char *, int);
-int V2_open_new_ogr(struct Map_info *, int);
-int V2_open_new_pg(struct Map_info *, int);
int V1_rewind_nat(struct Map_info *);
int V1_rewind_ogr(struct Map_info *);
int V1_rewind_pg(struct Map_info *);
Modified: grass/trunk/lib/vector/Vlib/open_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_ogr.c 2013-04-10 18:38:57 UTC (rev 55691)
+++ grass/trunk/lib/vector/Vlib/open_ogr.c 2013-04-10 20:35:47 UTC (rev 55692)
@@ -22,21 +22,18 @@
#include <grass/vector.h>
#include <grass/dbmi.h>
-#include <grass/gprojects.h>
#include <grass/glocale.h>
#ifdef HAVE_OGR
#include <ogr_api.h>
-#include <cpl_string.h>
static int sqltype_to_ogrtype(int);
-static dbDriver *create_table(OGRLayerH, const struct field_info *);
#endif
/*!
- \brief Open existing OGR layer (level 1 - without feature index file)
+ \brief Open existing OGR layer on non-topological level
- Map->name, Map->mapset, Map->fInfo.ogr.dsn and
+ Note: Map->name, Map->mapset, Map->fInfo.ogr.dsn and
Map->fInfo.ogr.layer_name must be set before.
\param[in,out] Map pointer to Map_info structure
@@ -129,8 +126,11 @@
}
/*!
- \brief Open existing OGR layer (level 2 - feature index)
+ \brief Open existing OGR layer on topological level
+ This functions reads feature index (fidx) file required for
+ pseudo-topology.
+
\param[in,out] Map pointer to Map_info structure
\return 0 success
@@ -149,7 +149,7 @@
G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset));
}
- Map->fInfo.ogr.next_line = 1;
+ Map->fInfo.ogr.next_line = 1; /* reset feature cache */
return 0;
#else
@@ -161,7 +161,7 @@
/*!
\brief Prepare OGR datasource for creating new OGR layer (level 1)
- New OGR layer can be created by V2_open_new_ogr().
+ New OGR layer is created by Vect__open_new_ogr().
\param[out] Map pointer to Map_info structure
\param name name of OGR layer to create
@@ -235,116 +235,7 @@
}
/*!
- \brief Create new OGR layer in given OGR datasource (level 2)
-
- V1_open_new_ogr() is required to be called before this function.
-
- List of currently supported types:
- - GV_POINT (wkbPoint)
- - GV_LINE (wkbLineString)
- - GV_BOUNDARY (wkb_Polygon)
- \param[in,out] Map pointer to Map_info structure
- \param type feature type (GV_POINT, GV_LINE, ...)
-
- \return 0 success
- \return -1 error
-*/
-int V2_open_new_ogr(struct Map_info *Map, int type)
-{
-#ifdef HAVE_OGR
- int ndblinks;
- OGRLayerH Ogr_layer;
- OGRSpatialReferenceH Ogr_spatial_ref;
-
- struct field_info *Fi;
- struct Key_Value *projinfo, *projunits;
- struct Format_info_ogr *ogr_info;
-
- OGRwkbGeometryType Ogr_geom_type;
- char **Ogr_layer_options;
-
- ogr_info = &(Map->fInfo.ogr);
-
- if (!ogr_info->driver_name ||
- !ogr_info->layer_name ||
- !ogr_info->ds)
- return -1;
-
- /* get spatial reference */
- projinfo = G_get_projinfo();
- projunits = G_get_projunits();
- Ogr_spatial_ref = GPJ_grass_to_osr(projinfo, projunits);
- G_free_key_value(projinfo);
- G_free_key_value(projunits);
-
- /* determine geometry type */
- switch(type) {
- case GV_POINT:
- Ogr_geom_type = wkbPoint;
- break;
- case GV_LINE:
- Ogr_geom_type = wkbLineString;
- break;
- case GV_BOUNDARY:
- Ogr_geom_type = wkbPolygon;
- break;
- default:
- G_warning(_("Unsupported geometry type (%d)"), type);
- return -1;
- }
-
- /* check creation options */
- Ogr_layer_options = ogr_info->layer_options;
- if (Vect_is_3d(Map)) {
- if (strcmp(ogr_info->driver_name, "PostgreSQL") == 0) {
- Ogr_layer_options = CSLSetNameValue(Ogr_layer_options, "DIM", "3");
- }
- }
- else {
- if (strcmp(ogr_info->driver_name, "PostgreSQL") == 0) {
- Ogr_layer_options = CSLSetNameValue(Ogr_layer_options, "DIM", "2");
- }
- }
-
- /* create new OGR layer */
- Ogr_layer = OGR_DS_CreateLayer(ogr_info->ds, ogr_info->layer_name,
- Ogr_spatial_ref, Ogr_geom_type, Ogr_layer_options);
- CSLDestroy(Ogr_layer_options);
- if (!Ogr_layer) {
- G_warning(_("Unable to create OGR layer <%s> in '%s'"),
- ogr_info->layer_name, ogr_info->dsn);
- return -1;
- }
- ogr_info->layer = Ogr_layer;
-
- ndblinks = Vect_get_num_dblinks(Map);
- if (ndblinks > 0) {
- /* write also attributes */
- Fi = Vect_get_dblink(Map, 0);
- if (Fi) {
- if (ndblinks > 1)
- G_warning(_("More layers defined, using driver <%s> and "
- "database <%s>"), Fi->driver, Fi->database);
- ogr_info->dbdriver = create_table(ogr_info->layer, Fi);
- G_free(Fi);
- }
- else
- G_warning(_("Database connection not defined. "
- "Unable to write attributes."));
- }
-
- if (OGR_L_TestCapability(ogr_info->layer, OLCTransactions))
- OGR_L_StartTransaction(ogr_info->layer);
-
- return 0;
-#else
- G_fatal_error(_("GRASS is not compiled with OGR support"));
- return -1;
-#endif
-}
-
-/*!
- \brief Open feature index file for vector map
+ \brief Open feature index file
\param[in,out] Map pointer to Map_info struct
\param[out] offset pointer to Format_info_offset (OGR or PG)
@@ -428,86 +319,6 @@
}
#ifdef HAVE_OGR
-dbDriver *create_table(OGRLayerH hLayer, const struct field_info *Fi)
-{
- int col, ncols;
- int sqltype, ogrtype, length;
-
- const char *colname;
-
- dbDriver *driver;
- dbHandle handle;
- dbCursor cursor;
- dbTable *table;
- dbColumn *column;
- dbString sql;
-
- OGRFieldDefnH hFieldDefn;
- OGRFeatureDefnH hFeatureDefn;
-
- db_init_string(&sql);
- db_init_handle(&handle);
-
- driver = db_start_driver(Fi->driver);
- if (!driver) {
- G_warning(_("Unable to start driver <%s>"), Fi->driver);
- return NULL;
- }
- db_set_handle(&handle, Fi->database, NULL);
- if (db_open_database(driver, &handle) != DB_OK) {
- G_warning(_("Unable to open database <%s> by driver <%s>"),
- Fi->database, Fi->driver);
- db_close_database_shutdown_driver(driver);
- return NULL;
- }
-
- /* to get no data */
- db_set_string(&sql, "select * from ");
- db_append_string(&sql, Fi->table);
- db_append_string(&sql, " where 0 = 1");
-
- if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
- DB_OK) {
- G_warning(_("Unable to open select cursor: '%s'"),
- db_get_string(&sql));
- db_close_database_shutdown_driver(driver);
- return NULL;
- }
-
- table = db_get_cursor_table(&cursor);
- ncols = db_get_table_number_of_columns(table);
-
- hFeatureDefn = OGR_L_GetLayerDefn(hLayer);
-
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- colname = db_get_column_name(column);
- sqltype = db_get_column_sqltype(column);
- ogrtype = sqltype_to_ogrtype(sqltype);
- length = db_get_column_length(column);
-
- if (strcmp(OGR_L_GetFIDColumn(hLayer), colname) == 0 ||
- OGR_FD_GetFieldIndex(hFeatureDefn, colname) > -1) {
- /* field already exists */
- continue;
- }
-
- hFieldDefn = OGR_Fld_Create(colname, ogrtype);
- /* GDAL 1.9.0 (r22968) uses VARCHAR instead of CHAR */
- if (ogrtype == OFTString && length > 0)
- OGR_Fld_SetWidth(hFieldDefn, length);
- if (OGR_L_CreateField(hLayer, hFieldDefn, TRUE) != OGRERR_NONE) {
- G_warning(_("Creating field <%s> failed"), colname);
- db_close_database_shutdown_driver(driver);
- return NULL;
- }
-
- OGR_Fld_Destroy(hFieldDefn);
- }
-
- return driver;
-}
-
int sqltype_to_ogrtype(int sqltype)
{
int ctype, ogrtype;
Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c 2013-04-10 18:38:57 UTC (rev 55691)
+++ grass/trunk/lib/vector/Vlib/open_pg.c 2013-04-10 20:35:47 UTC (rev 55692)
@@ -23,8 +23,6 @@
#ifdef HAVE_POSTGRES
#include "pg_local_proto.h"
-#define TOPOGEOM_COLUMN "topo"
-
struct edge_data {
int id;
int start_node;
@@ -37,9 +35,6 @@
static char *get_key_column(struct Format_info_pg *);
static SF_FeatureType ftype_from_string(const char *);
static int drop_table(struct Format_info_pg *);
-static int check_schema(const struct Format_info_pg *);
-static int create_table(struct Format_info_pg *, const struct field_info *);
-static int create_topo_schema(struct Format_info_pg *, int);
static void connect_db(struct Format_info_pg *);
static int check_topo(struct Format_info_pg *, struct Plus_head *);
static int parse_bbox(const char *, struct bound_box *);
@@ -50,7 +45,6 @@
struct Format_info_cache *);
static int load_plus_head(struct Format_info_pg *, struct Plus_head *);
static void notice_processor(void *, const char *);
-static char *get_sftype(SF_FeatureType);
#endif
/*!
@@ -307,110 +301,6 @@
}
/*!
- \brief Create new PostGIS layer in given database (level 2)
-
- V1_open_new_pg() is required to be called before this function.
-
- List of currently supported types:
- - GV_POINT (SF_POINT)
- - GV_LINE (SF_LINESTRING)
- - GV_BOUNDARY (SF_POLYGON)
- \param[in,out] Map pointer to Map_info structure
- \param type feature type (GV_POINT, GV_LINE, ...)
-
- \return 0 success
- \return -1 error
- */
-int V2_open_new_pg(struct Map_info *Map, int type)
-{
-#ifdef HAVE_POSTGRES
- int ndblinks;
-
- struct Format_info_pg *pg_info;
- struct field_info *Fi;
-
- Fi = NULL;
-
- pg_info = &(Map->fInfo.pg);
- if (!pg_info->conninfo) {
- G_warning(_("Connection string not defined"));
- return -1;
- }
-
- if (!pg_info->table_name) {
- G_warning(_("PostGIS feature table not defined"));
- return -1;
- }
-
- G_debug(1, "V2_open_new_pg(): conninfo='%s' table='%s' -> type = %d",
- pg_info->conninfo, pg_info->table_name, type);
-
- /* determine geometry type */
- switch (type) {
- case GV_POINT:
- pg_info->feature_type = SF_POINT;
- break;
- case GV_LINE:
- pg_info->feature_type = SF_LINESTRING;
- break;
- case GV_BOUNDARY:
- pg_info->feature_type = SF_POLYGON;
- break;
- default:
- G_warning(_("Unsupported geometry type (%d)"), type);
- return -1;
- }
-
- /* coordinate dimension */
- pg_info->coor_dim = Vect_is_3d(Map) ? 3 : 2;
-
- /* create new PostGIS table */
- ndblinks = Vect_get_num_dblinks(Map);
- if (ndblinks > 0) {
- Fi = Vect_get_dblink(Map, 0);
- if (Fi) {
- if (ndblinks > 1)
- G_warning(_("More layers defined, using driver <%s> and "
- "database <%s>"), Fi->driver, Fi->database);
- }
- else {
- G_warning(_("Database connection not defined. "
- "Unable to write attributes."));
- }
- }
-
- /* create new feature table */
- if (create_table(pg_info, Fi) == -1) {
- G_warning(_("Unable to create new PostGIS feature table"));
- return -1;
- }
-
- /* create new topology schema (if PostGIS topology support is enabled) */
- if (pg_info->toposchema_name) {
- /* force topological level */
- Map->level = LEVEL_2;
- Map->plus.built = GV_BUILD_BASE;
-
- /* track updated features, used in V2__add_line_to_topo_nat() */
- Vect_set_updated(Map, TRUE);
-
- if (create_topo_schema(pg_info, Vect_is_3d(Map)) == -1) {
- G_warning(_("Unable to create new PostGIS topology schema"));
- return -1;
- }
- }
-
- if (Fi)
- G_free(Fi);
-
- return 0;
-#else
- G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
- return -1;
-#endif
-}
-
-/*!
\brief Read full-topology for PostGIS links
Note: Only 2D topological primitives are currently supported
@@ -586,373 +476,6 @@
}
/*!
- \brief Creates new schema for feature table if not exists
-
- \param pg_info pointer to Format_info_pg
-
- \return -1 on error
- \return 0 on success
-*/
-int check_schema(const struct Format_info_pg *pg_info)
-{
- int i, found, nschema;
- char stmt[DB_SQL_MAX];
-
- PGresult *result;
-
- /* add geometry column */
- sprintf(stmt, "SELECT nspname FROM pg_namespace");
- G_debug(2, "SQL: %s", stmt);
- result = PQexec(pg_info->conn, stmt);
-
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
- PQclear(result);
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
-
- found = FALSE;
- nschema = PQntuples(result);
- for (i = 0; i < nschema && !found; i++) {
- if (strcmp(pg_info->schema_name, PQgetvalue(result, i, 0)) == 0)
- found = TRUE;
- }
-
- PQclear(result);
-
- if (!found) {
- sprintf(stmt, "CREATE SCHEMA %s", pg_info->schema_name);
- if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
- G_warning(_("Schema <%s> doesn't exist, created"),
- pg_info->schema_name);
- }
-
- return 0;
-}
-
-/*!
- \brief Create new feature table
-
- \param pg_info pointer to Format_info_pg
- \param Fi pointer to field_info
-
- \return -1 on error
- \return 0 on success
-*/
-int create_table(struct Format_info_pg *pg_info, const struct field_info *Fi)
-{
- int spatial_index, primary_key;
- char stmt[DB_SQL_MAX];
- char *geom_type, *def_file;
-
- PGresult *result;
-
- def_file = getenv("GRASS_VECTOR_PGFILE");
-
- /* by default create spatial index & add primary key */
- spatial_index = primary_key = TRUE;
- if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
- FILE *fp;
- const char *p;
-
- struct Key_Value *key_val;
-
- fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
- if (!fp) {
- G_warning(_("Unable to open PG file"));
- }
- else {
- key_val = G_fread_key_value(fp);
- fclose(fp);
-
- /* disable spatial index ? */
- p = G_find_key_value("spatial_index", key_val);
- if (p && G_strcasecmp(p, "no") == 0)
- spatial_index = FALSE;
-
- /* disable primary key ? */
- p = G_find_key_value("primary_key", key_val);
- if (p && G_strcasecmp(p, "no") == 0)
- primary_key = FALSE;
-
- /* PostGIS topology enabled ? */
- p = G_find_key_value("topology", key_val);
- if (p && G_strcasecmp(p, "yes") == 0) {
- /* define topology name
- this should be configurable by the user
- */
- G_asprintf(&(pg_info->toposchema_name), "topo_%s",
- pg_info->table_name);
- }
- }
- }
-
- /* create schema if not exists */
- if (G_strcasecmp(pg_info->schema_name, "public") != 0) {
- if (check_schema(pg_info) != 0)
- return -1;
- }
-
- /* prepare CREATE TABLE statement */
- sprintf(stmt, "CREATE TABLE \"%s\".\"%s\" (%s SERIAL",
- pg_info->schema_name, pg_info->table_name, pg_info->fid_column);
-
- /* add primary key ? */
- if (primary_key)
- strcat(stmt, " PRIMARY KEY");
-
- if (Fi) {
- /* append attributes */
- int col, ncols, sqltype, length;
- char stmt_col[DB_SQL_MAX];
- const char *colname;
-
- dbString dbstmt;
- dbHandle handle;
- dbDriver *driver;
- dbCursor cursor;
- dbTable *table;
- dbColumn *column;
-
- db_init_string(&dbstmt);
- db_init_handle(&handle);
-
- pg_info->dbdriver = driver = db_start_driver(Fi->driver);
- if (!driver) {
- G_warning(_("Unable to start driver <%s>"), Fi->driver);
- return -1;
- }
- db_set_handle(&handle, Fi->database, NULL);
- if (db_open_database(driver, &handle) != DB_OK) {
- G_warning(_("Unable to open database <%s> by driver <%s>"),
- Fi->database, Fi->driver);
- db_close_database_shutdown_driver(driver);
- pg_info->dbdriver = NULL;
- return -1;
- }
-
- /* describe table */
- db_set_string(&dbstmt, "select * from ");
- db_append_string(&dbstmt, Fi->table);
- db_append_string(&dbstmt, " where 0 = 1");
-
- if (db_open_select_cursor(driver, &dbstmt,
- &cursor, DB_SEQUENTIAL) != DB_OK) {
- G_warning(_("Unable to open select cursor: '%s'"),
- db_get_string(&dbstmt));
- db_close_database_shutdown_driver(driver);
- pg_info->dbdriver = NULL;
- return -1;
- }
-
- table = db_get_cursor_table(&cursor);
- ncols = db_get_table_number_of_columns(table);
-
- G_debug(3,
- "copying attributes: driver = %s database = %s table = %s cols = %d",
- Fi->driver, Fi->database, Fi->table, ncols);
-
- for (col = 0; col < ncols; col++) {
- column = db_get_table_column(table, col);
- colname = db_get_column_name(column);
- sqltype = db_get_column_sqltype(column);
- length = db_get_column_length(column);
-
- G_debug(3, "\tcolumn = %d name = %s type = %d length = %d",
- col, colname, sqltype, length);
-
- if (strcmp(pg_info->fid_column, colname) == 0) {
- /* skip fid column if exists */
- G_debug(3, "\t%s skipped", pg_info->fid_column);
- continue;
- }
-
- /* append column */
- sprintf(stmt_col, ",%s %s", colname, db_sqltype_name(sqltype));
- strcat(stmt, stmt_col);
- if (sqltype == DB_SQL_TYPE_CHARACTER) {
- /* length only for string columns */
- sprintf(stmt_col, "(%d)", length);
- strcat(stmt, stmt_col);
- }
- }
-
- db_free_string(&dbstmt);
- }
- strcat(stmt, ")"); /* close CREATE TABLE statement */
-
- /* begin transaction (create table) */
- if (Vect__execute_pg(pg_info->conn, "BEGIN") == -1) {
- return -1;
- }
-
- /* create table */
- G_debug(2, "SQL: %s", stmt);
- if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
-
- /* determine geometry type (string) */
- switch (pg_info->feature_type) {
- case (SF_POINT):
- geom_type = "POINT";
- break;
- case (SF_LINESTRING):
- geom_type = "LINESTRING";
- break;
- case (SF_POLYGON):
- geom_type = "POLYGON";
- break;
- default:
- G_warning(_("Unsupported feature type %d"), pg_info->feature_type);
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
-
- /* add geometry column */
- sprintf(stmt, "SELECT AddGeometryColumn('%s', '%s', "
- "'%s', %d, '%s', %d)",
- pg_info->schema_name, pg_info->table_name,
- pg_info->geom_column, pg_info->srid,
- geom_type, pg_info->coor_dim);
- G_debug(2, "SQL: %s", stmt);
- result = PQexec(pg_info->conn, stmt);
-
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
- G_warning("%s", PQresultErrorMessage(result));
- PQclear(result);
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
-
- /* create index ? */
- if (spatial_index) {
- G_verbose_message(_("Building spatial index on <%s>..."),
- pg_info->geom_column);
- sprintf(stmt,
- "CREATE INDEX %s_%s_idx ON \"%s\".\"%s\" USING GIST (%s)",
- pg_info->table_name, pg_info->geom_column,
- pg_info->schema_name, pg_info->table_name,
- pg_info->geom_column);
- G_debug(2, "SQL: %s", stmt);
-
- if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
- }
-
- /* close transaction (create table) */
- if (Vect__execute_pg(pg_info->conn, "COMMIT") == -1) {
- return -1;
- }
-
- return 0;
-}
-
-/*!
- \brief Create new PostGIS topology schema
-
- - create topology schema
- - add topology column to the feature table
-
- \param pg_info pointer to Format_info_pg
-
- \return 0 on success
- \return 1 topology disable, nothing to do
- \return -1 on failure
-*/
-int create_topo_schema(struct Format_info_pg *pg_info, int with_z)
-{
- double tolerance;
- char stmt[DB_SQL_MAX];
- char *def_file;
-
- PGresult *result;
-
- def_file = getenv("GRASS_VECTOR_PGFILE");
-
- /* read default values from PG file*/
- tolerance = 0.;
- if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
- FILE *fp;
- const char *p;
-
- struct Key_Value *key_val;
-
- fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
- if (!fp) {
- G_fatal_error(_("Unable to open PG file"));
- }
- key_val = G_fread_key_value(fp);
- fclose(fp);
-
- /* tolerance */
- p = G_find_key_value("tolerance", key_val);
- if (p)
- tolerance = atof(p);
-
- /* topogeom column */
- p = G_find_key_value("topogeom_column", key_val);
- if (p)
- pg_info->topogeom_column = G_store(p);
- else
- pg_info->topogeom_column = G_store(TOPOGEOM_COLUMN);
- }
-
- /* begin transaction (create topo schema) */
- if (Vect__execute_pg(pg_info->conn, "BEGIN") == -1) {
- return -1;
- }
-
- /* create topology schema */
- G_verbose_message(_("Creating topology schema <%s>..."),
- pg_info->toposchema_name);
- sprintf(stmt, "SELECT topology.createtopology('%s', "
- "find_srid('%s', '%s', '%s'), %f, '%s')",
- pg_info->toposchema_name, pg_info->schema_name,
- pg_info->table_name, pg_info->geom_column, tolerance,
- with_z == WITH_Z ? "t" : "f");
- G_debug(2, "SQL: %s", stmt);
-
- result = PQexec(pg_info->conn, stmt);
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
- G_warning(_("Execution failed: %s"), PQerrorMessage(pg_info->conn));
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
- /* store toposchema id */
- pg_info->toposchema_id = atoi(PQgetvalue(result, 0, 0));
-
- /* add topo column to the feature table */
- G_verbose_message(_("Adding new topology column <%s>..."),
- pg_info->topogeom_column);
- sprintf(stmt, "SELECT topology.AddTopoGeometryColumn('%s', '%s', '%s', "
- "'%s', '%s')", pg_info->toposchema_name, pg_info->schema_name,
- pg_info->table_name, pg_info->topogeom_column,
- get_sftype(pg_info->feature_type));
- G_debug(2, "SQL: %s", stmt);
-
- result = PQexec(pg_info->conn, stmt);
- if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
- G_warning(_("Execution failed: %s"), PQerrorMessage(pg_info->conn));
- Vect__execute_pg(pg_info->conn, "ROLLBACK");
- return -1;
- }
-
- /* close transaction (create topo schema) */
- if (Vect__execute_pg(pg_info->conn, "COMMIT") == -1) {
- return -1;
- }
-
- return 0;
-}
-
-/*!
\brief Establish PG connection (pg_info->conninfo)
\param pg_info pointer to Format_info_pg
@@ -1677,31 +1200,4 @@
fprintf(stderr, "%s", message);
}
}
-
-/*!
- \brief Get simple feature type as a string
-
- Used for AddTopoGeometryColumn().
-
- Valid types:
- - SF_POINT
- - SF_LINESTRING
- - SF_POLYGON
-
- \return string with feature type
- \return empty string
-*/
-char *get_sftype(SF_FeatureType sftype)
-{
- if (sftype == SF_POINT)
- return "POINT";
- else if (sftype == SF_LINESTRING)
- return "LINE";
- else if (sftype == SF_POLYGON)
- return "POLYGON";
- else
- G_warning(_("Unsupported feature type %d"), sftype);
-
- return "";
-}
#endif
Modified: grass/trunk/lib/vector/Vlib/write_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_ogr.c 2013-04-10 18:38:57 UTC (rev 55691)
+++ grass/trunk/lib/vector/Vlib/write_ogr.c 2013-04-10 20:35:47 UTC (rev 55692)
@@ -19,11 +19,15 @@
#include <grass/vector.h>
#include <grass/dbmi.h>
+#include <grass/gprojects.h>
#include <grass/glocale.h>
#ifdef HAVE_OGR
#include <ogr_api.h>
+#include <cpl_string.h>
+static dbDriver *create_table(OGRLayerH, const struct field_info *);
+static int create_ogr_layer(struct Map_info *, int);
static off_t write_feature(struct Map_info *, int, const struct line_pnts **, int,
const struct line_cats *);
static int write_attributes(dbDriver *, int, const struct field_info *,
@@ -163,7 +167,191 @@
return write_feature(Map, GV_BOUNDARY, points, nparts, cats);
}
+dbDriver *create_table(OGRLayerH hLayer, const struct field_info *Fi)
+{
+ int col, ncols;
+ int sqltype, ogrtype, length;
+
+ const char *colname;
+
+ dbDriver *driver;
+ dbHandle handle;
+ dbCursor cursor;
+ dbTable *table;
+ dbColumn *column;
+ dbString sql;
+
+ OGRFieldDefnH hFieldDefn;
+ OGRFeatureDefnH hFeatureDefn;
+
+ db_init_string(&sql);
+ db_init_handle(&handle);
+
+ driver = db_start_driver(Fi->driver);
+ if (!driver) {
+ G_warning(_("Unable to start driver <%s>"), Fi->driver);
+ return NULL;
+ }
+ db_set_handle(&handle, Fi->database, NULL);
+ if (db_open_database(driver, &handle) != DB_OK) {
+ G_warning(_("Unable to open database <%s> by driver <%s>"),
+ Fi->database, Fi->driver);
+ db_close_database_shutdown_driver(driver);
+ return NULL;
+ }
+
+ /* to get no data */
+ db_set_string(&sql, "select * from ");
+ db_append_string(&sql, Fi->table);
+ db_append_string(&sql, " where 0 = 1");
+
+ if (db_open_select_cursor(driver, &sql, &cursor, DB_SEQUENTIAL) !=
+ DB_OK) {
+ G_warning(_("Unable to open select cursor: '%s'"),
+ db_get_string(&sql));
+ db_close_database_shutdown_driver(driver);
+ return NULL;
+ }
+
+ table = db_get_cursor_table(&cursor);
+ ncols = db_get_table_number_of_columns(table);
+
+ hFeatureDefn = OGR_L_GetLayerDefn(hLayer);
+
+ for (col = 0; col < ncols; col++) {
+ column = db_get_table_column(table, col);
+ colname = db_get_column_name(column);
+ sqltype = db_get_column_sqltype(column);
+ ogrtype = sqltype_to_ogrtype(sqltype);
+ length = db_get_column_length(column);
+
+ if (strcmp(OGR_L_GetFIDColumn(hLayer), colname) == 0 ||
+ OGR_FD_GetFieldIndex(hFeatureDefn, colname) > -1) {
+ /* field already exists */
+ continue;
+ }
+
+ hFieldDefn = OGR_Fld_Create(colname, ogrtype);
+ /* GDAL 1.9.0 (r22968) uses VARCHAR instead of CHAR */
+ if (ogrtype == OFTString && length > 0)
+ OGR_Fld_SetWidth(hFieldDefn, length);
+ if (OGR_L_CreateField(hLayer, hFieldDefn, TRUE) != OGRERR_NONE) {
+ G_warning(_("Creating field <%s> failed"), colname);
+ db_close_database_shutdown_driver(driver);
+ return NULL;
+ }
+
+ OGR_Fld_Destroy(hFieldDefn);
+ }
+
+ return driver;
+}
+
/*!
+ \brief Create new OGR layer in given OGR datasource (internal use only)
+
+ V1_open_new_ogr() is required to be called before this function.
+
+ List of currently supported types:
+ - GV_POINT (wkbPoint)
+ - GV_LINE (wkbLineString)
+ - GV_BOUNDARY (wkb_Polygon)
+ \param[in,out] Map pointer to Map_info structure
+ \param type feature type (GV_POINT, GV_LINE, ...)
+
+ \return 0 success
+ \return -1 error
+*/
+int create_ogr_layer(struct Map_info *Map, int type)
+{
+ int ndblinks;
+ OGRLayerH Ogr_layer;
+ OGRSpatialReferenceH Ogr_spatial_ref;
+
+ struct field_info *Fi;
+ struct Key_Value *projinfo, *projunits;
+ struct Format_info_ogr *ogr_info;
+
+ OGRwkbGeometryType Ogr_geom_type;
+ char **Ogr_layer_options;
+
+ ogr_info = &(Map->fInfo.ogr);
+
+ if (!ogr_info->driver_name ||
+ !ogr_info->layer_name ||
+ !ogr_info->ds)
+ return -1;
+
+ /* get spatial reference */
+ projinfo = G_get_projinfo();
+ projunits = G_get_projunits();
+ Ogr_spatial_ref = GPJ_grass_to_osr(projinfo, projunits);
+ G_free_key_value(projinfo);
+ G_free_key_value(projunits);
+
+ /* determine geometry type */
+ switch(type) {
+ case GV_POINT:
+ Ogr_geom_type = wkbPoint;
+ break;
+ case GV_LINE:
+ Ogr_geom_type = wkbLineString;
+ break;
+ case GV_BOUNDARY:
+ Ogr_geom_type = wkbPolygon;
+ break;
+ default:
+ G_warning(_("Unsupported geometry type (%d)"), type);
+ return -1;
+ }
+
+ /* check creation options */
+ Ogr_layer_options = ogr_info->layer_options;
+ if (Vect_is_3d(Map)) {
+ if (strcmp(ogr_info->driver_name, "PostgreSQL") == 0) {
+ Ogr_layer_options = CSLSetNameValue(Ogr_layer_options, "DIM", "3");
+ }
+ }
+ else {
+ if (strcmp(ogr_info->driver_name, "PostgreSQL") == 0) {
+ Ogr_layer_options = CSLSetNameValue(Ogr_layer_options, "DIM", "2");
+ }
+ }
+
+ /* create new OGR layer */
+ Ogr_layer = OGR_DS_CreateLayer(ogr_info->ds, ogr_info->layer_name,
+ Ogr_spatial_ref, Ogr_geom_type, Ogr_layer_options);
+ CSLDestroy(Ogr_layer_options);
+ if (!Ogr_layer) {
+ G_warning(_("Unable to create OGR layer <%s> in '%s'"),
+ ogr_info->layer_name, ogr_info->dsn);
+ return -1;
+ }
+ ogr_info->layer = Ogr_layer;
+
+ ndblinks = Vect_get_num_dblinks(Map);
+ if (ndblinks > 0) {
+ /* write also attributes */
+ Fi = Vect_get_dblink(Map, 0);
+ if (Fi) {
+ if (ndblinks > 1)
+ G_warning(_("More layers defined, using driver <%s> and "
+ "database <%s>"), Fi->driver, Fi->database);
+ ogr_info->dbdriver = create_table(ogr_info->layer, Fi);
+ G_free(Fi);
+ }
+ else
+ G_warning(_("Database connection not defined. "
+ "Unable to write attributes."));
+ }
+
+ if (OGR_L_TestCapability(ogr_info->layer, OLCTransactions))
+ OGR_L_StartTransaction(ogr_info->layer);
+
+ return 0;
+}
+
+/*!
\brief Write OGR feature
\param Map pointer to Map_info structure
@@ -204,10 +392,13 @@
if (!ogr_info->layer) {
/* create OGR layer if doesn't exist */
- if (V2_open_new_ogr(Map, type) < 0)
+ if (create_ogr_layer(Map, type) < 0)
return -1;
}
+ if (!points)
+ return 0;
+
cat = -1; /* no attributes to be written */
if (cats->n_cats > 0 && Vect_get_num_dblinks(Map) > 0) {
/* check for attributes */
Modified: grass/trunk/lib/vector/Vlib/write_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_pg.c 2013-04-10 18:38:57 UTC (rev 55691)
+++ grass/trunk/lib/vector/Vlib/write_pg.c 2013-04-10 20:35:47 UTC (rev 55692)
@@ -33,11 +33,18 @@
#define WKBSRIDFLAG 0x20000000
+#define TOPOGEOM_COLUMN "topo"
+
/*! Use SQL statements from PostGIS Topology extension (this options
is quite slow. By default are used simple SQL statements (INSERT, UPDATE)
*/
#define USE_TOPO_STMT 0
+static int create_table(struct Format_info_pg *, const struct field_info *);
+static int check_schema(const struct Format_info_pg *);
+static int create_topo_schema(struct Format_info_pg *, int);
+static int create_pg_layer(struct Map_info *, int);
+static char *get_sftype(SF_FeatureType);
static off_t write_line_sf(struct Map_info *, int,
const struct line_pnts **, int,
const struct line_cats *);
@@ -97,10 +104,13 @@
if (pg_info->feature_type == SF_UNKNOWN) {
/* create PostGIS table if doesn't exist */
- if (V2_open_new_pg(Map, type) < 0)
+ if (create_pg_layer(Map, type) < 0)
return -1;
}
+ if (!points)
+ return 0;
+
if (!pg_info->toposchema_name) { /* simple features access */
return write_line_sf(Map, type, &points, 1, cats);
}
@@ -213,6 +223,7 @@
char *stmt, *geom_data;
struct Format_info_pg *pg_info;
+ struct P_line *Line;
geom_data = NULL;
stmt = NULL;
@@ -223,11 +234,24 @@
return -1;
}
- if (type != V2_read_line_pg(Map, NULL, NULL, line)) {
+ Line = Map->plus.Line[line];
+ if (Line == NULL) {
+ G_warning(_("Attempt to access dead feature %d"), line);
+ return -1;
+ }
+
+ if (!Points)
+ Points = Vect_new_line_struct();
+
+ if (type != V2_read_line_pg(Map, Points, NULL, line)) {
G_warning(_("Unable to rewrite feature (incompatible feature types)"));
return -1;
}
+ /* remove line from topology */
+ if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
+ return -1;
+
if (pg_info->toposchema_name) { /* PostGIS Topology */
schema_name = pg_info->toposchema_name;
if (type & GV_POINTS) {
@@ -255,7 +279,9 @@
return -1;
}
- return old_offset; /* offset not changed */
+ /* update topology
+ note: offset is not changed */
+ return V2__add_line_to_topo_nat(Map, old_offset, type, points, cats, -1, NULL);
#else
G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
return -1;
@@ -397,9 +423,9 @@
}
/* read the line */
- if (!Points) {
+ if (!Points)
Points = Vect_new_line_struct();
- }
+
type = V2_read_line_pg(Map, Points, NULL, line);
if (type < 0)
return -1;
@@ -492,6 +518,503 @@
}
/*!
+ \brief Create new feature table
+
+ \param pg_info pointer to Format_info_pg
+ \param Fi pointer to field_info
+
+ \return -1 on error
+ \return 0 on success
+*/
+int create_table(struct Format_info_pg *pg_info, const struct field_info *Fi)
+{
+ int spatial_index, primary_key;
+ char stmt[DB_SQL_MAX];
+ char *geom_type, *def_file;
+
+ PGresult *result;
+
+ def_file = getenv("GRASS_VECTOR_PGFILE");
+
+ /* by default create spatial index & add primary key */
+ spatial_index = primary_key = TRUE;
+ if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
+ FILE *fp;
+ const char *p;
+
+ struct Key_Value *key_val;
+
+ fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
+ if (!fp) {
+ G_warning(_("Unable to open PG file"));
+ }
+ else {
+ key_val = G_fread_key_value(fp);
+ fclose(fp);
+
+ /* disable spatial index ? */
+ p = G_find_key_value("spatial_index", key_val);
+ if (p && G_strcasecmp(p, "no") == 0)
+ spatial_index = FALSE;
+
+ /* disable primary key ? */
+ p = G_find_key_value("primary_key", key_val);
+ if (p && G_strcasecmp(p, "no") == 0)
+ primary_key = FALSE;
+
+ /* PostGIS topology enabled ? */
+ p = G_find_key_value("topology", key_val);
+ if (p && G_strcasecmp(p, "yes") == 0) {
+ /* define topology name
+ this should be configurable by the user
+ */
+ G_asprintf(&(pg_info->toposchema_name), "topo_%s",
+ pg_info->table_name);
+ }
+ }
+ }
+
+ /* create schema if not exists */
+ if (G_strcasecmp(pg_info->schema_name, "public") != 0) {
+ if (check_schema(pg_info) != 0)
+ return -1;
+ }
+
+ /* prepare CREATE TABLE statement */
+ sprintf(stmt, "CREATE TABLE \"%s\".\"%s\" (%s SERIAL",
+ pg_info->schema_name, pg_info->table_name, pg_info->fid_column);
+
+ /* add primary key ? */
+ if (primary_key)
+ strcat(stmt, " PRIMARY KEY");
+
+ if (Fi) {
+ /* append attributes */
+ int col, ncols, sqltype, length;
+ char stmt_col[DB_SQL_MAX];
+ const char *colname;
+
+ dbString dbstmt;
+ dbHandle handle;
+ dbDriver *driver;
+ dbCursor cursor;
+ dbTable *table;
+ dbColumn *column;
+
+ db_init_string(&dbstmt);
+ db_init_handle(&handle);
+
+ pg_info->dbdriver = driver = db_start_driver(Fi->driver);
+ if (!driver) {
+ G_warning(_("Unable to start driver <%s>"), Fi->driver);
+ return -1;
+ }
+ db_set_handle(&handle, Fi->database, NULL);
+ if (db_open_database(driver, &handle) != DB_OK) {
+ G_warning(_("Unable to open database <%s> by driver <%s>"),
+ Fi->database, Fi->driver);
+ db_close_database_shutdown_driver(driver);
+ pg_info->dbdriver = NULL;
+ return -1;
+ }
+
+ /* describe table */
+ db_set_string(&dbstmt, "select * from ");
+ db_append_string(&dbstmt, Fi->table);
+ db_append_string(&dbstmt, " where 0 = 1");
+
+ if (db_open_select_cursor(driver, &dbstmt,
+ &cursor, DB_SEQUENTIAL) != DB_OK) {
+ G_warning(_("Unable to open select cursor: '%s'"),
+ db_get_string(&dbstmt));
+ db_close_database_shutdown_driver(driver);
+ pg_info->dbdriver = NULL;
+ return -1;
+ }
+
+ table = db_get_cursor_table(&cursor);
+ ncols = db_get_table_number_of_columns(table);
+
+ G_debug(3,
+ "copying attributes: driver = %s database = %s table = %s cols = %d",
+ Fi->driver, Fi->database, Fi->table, ncols);
+
+ for (col = 0; col < ncols; col++) {
+ column = db_get_table_column(table, col);
+ colname = db_get_column_name(column);
+ sqltype = db_get_column_sqltype(column);
+ length = db_get_column_length(column);
+
+ G_debug(3, "\tcolumn = %d name = %s type = %d length = %d",
+ col, colname, sqltype, length);
+
+ if (strcmp(pg_info->fid_column, colname) == 0) {
+ /* skip fid column if exists */
+ G_debug(3, "\t%s skipped", pg_info->fid_column);
+ continue;
+ }
+
+ /* append column */
+ sprintf(stmt_col, ",%s %s", colname, db_sqltype_name(sqltype));
+ strcat(stmt, stmt_col);
+ if (sqltype == DB_SQL_TYPE_CHARACTER) {
+ /* length only for string columns */
+ sprintf(stmt_col, "(%d)", length);
+ strcat(stmt, stmt_col);
+ }
+ }
+
+ db_free_string(&dbstmt);
+ }
+ strcat(stmt, ")"); /* close CREATE TABLE statement */
+
+ /* begin transaction (create table) */
+ if (Vect__execute_pg(pg_info->conn, "BEGIN") == -1) {
+ return -1;
+ }
+
+ /* create table */
+ G_debug(2, "SQL: %s", stmt);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+
+ /* determine geometry type (string) */
+ switch (pg_info->feature_type) {
+ case (SF_POINT):
+ geom_type = "POINT";
+ break;
+ case (SF_LINESTRING):
+ geom_type = "LINESTRING";
+ break;
+ case (SF_POLYGON):
+ geom_type = "POLYGON";
+ break;
+ default:
+ G_warning(_("Unsupported feature type %d"), pg_info->feature_type);
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+
+ /* add geometry column */
+ sprintf(stmt, "SELECT AddGeometryColumn('%s', '%s', "
+ "'%s', %d, '%s', %d)",
+ pg_info->schema_name, pg_info->table_name,
+ pg_info->geom_column, pg_info->srid,
+ geom_type, pg_info->coor_dim);
+ G_debug(2, "SQL: %s", stmt);
+ result = PQexec(pg_info->conn, stmt);
+
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
+ G_warning("%s", PQresultErrorMessage(result));
+ PQclear(result);
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+
+ /* create index ? */
+ if (spatial_index) {
+ G_verbose_message(_("Building spatial index on <%s>..."),
+ pg_info->geom_column);
+ sprintf(stmt,
+ "CREATE INDEX %s_%s_idx ON \"%s\".\"%s\" USING GIST (%s)",
+ pg_info->table_name, pg_info->geom_column,
+ pg_info->schema_name, pg_info->table_name,
+ pg_info->geom_column);
+ G_debug(2, "SQL: %s", stmt);
+
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+ }
+
+ /* close transaction (create table) */
+ if (Vect__execute_pg(pg_info->conn, "COMMIT") == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ \brief Creates new schema for feature table if not exists
+
+ \param pg_info pointer to Format_info_pg
+
+ \return -1 on error
+ \return 0 on success
+*/
+int check_schema(const struct Format_info_pg *pg_info)
+{
+ int i, found, nschema;
+ char stmt[DB_SQL_MAX];
+
+ PGresult *result;
+
+ /* add geometry column */
+ sprintf(stmt, "SELECT nspname FROM pg_namespace");
+ G_debug(2, "SQL: %s", stmt);
+ result = PQexec(pg_info->conn, stmt);
+
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
+ PQclear(result);
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+
+ found = FALSE;
+ nschema = PQntuples(result);
+ for (i = 0; i < nschema && !found; i++) {
+ if (strcmp(pg_info->schema_name, PQgetvalue(result, i, 0)) == 0)
+ found = TRUE;
+ }
+
+ PQclear(result);
+
+ if (!found) {
+ sprintf(stmt, "CREATE SCHEMA %s", pg_info->schema_name);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+ G_warning(_("Schema <%s> doesn't exist, created"),
+ pg_info->schema_name);
+ }
+
+ return 0;
+}
+
+/*!
+ \brief Create new PostGIS topology schema
+
+ - create topology schema
+ - add topology column to the feature table
+
+ \param pg_info pointer to Format_info_pg
+
+ \return 0 on success
+ \return 1 topology disable, nothing to do
+ \return -1 on failure
+*/
+int create_topo_schema(struct Format_info_pg *pg_info, int with_z)
+{
+ double tolerance;
+ char stmt[DB_SQL_MAX];
+ char *def_file;
+
+ PGresult *result;
+
+ def_file = getenv("GRASS_VECTOR_PGFILE");
+
+ /* read default values from PG file*/
+ tolerance = 0.;
+ if (G_find_file2("", def_file ? def_file : "PG", G_mapset())) {
+ FILE *fp;
+ const char *p;
+
+ struct Key_Value *key_val;
+
+ fp = G_fopen_old("", def_file ? def_file : "PG", G_mapset());
+ if (!fp) {
+ G_fatal_error(_("Unable to open PG file"));
+ }
+ key_val = G_fread_key_value(fp);
+ fclose(fp);
+
+ /* tolerance */
+ p = G_find_key_value("tolerance", key_val);
+ if (p)
+ tolerance = atof(p);
+
+ /* topogeom column */
+ p = G_find_key_value("topogeom_column", key_val);
+ if (p)
+ pg_info->topogeom_column = G_store(p);
+ else
+ pg_info->topogeom_column = G_store(TOPOGEOM_COLUMN);
+ }
+
+ /* begin transaction (create topo schema) */
+ if (Vect__execute_pg(pg_info->conn, "BEGIN") == -1) {
+ return -1;
+ }
+
+ /* create topology schema */
+ G_verbose_message(_("Creating topology schema <%s>..."),
+ pg_info->toposchema_name);
+ sprintf(stmt, "SELECT topology.createtopology('%s', "
+ "find_srid('%s', '%s', '%s'), %f, '%s')",
+ pg_info->toposchema_name, pg_info->schema_name,
+ pg_info->table_name, pg_info->geom_column, tolerance,
+ with_z == WITH_Z ? "t" : "f");
+ G_debug(2, "SQL: %s", stmt);
+
+ result = PQexec(pg_info->conn, stmt);
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
+ G_warning(_("Execution failed: %s"), PQerrorMessage(pg_info->conn));
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+ /* store toposchema id */
+ pg_info->toposchema_id = atoi(PQgetvalue(result, 0, 0));
+
+ /* add topo column to the feature table */
+ G_verbose_message(_("Adding new topology column <%s>..."),
+ pg_info->topogeom_column);
+ sprintf(stmt, "SELECT topology.AddTopoGeometryColumn('%s', '%s', '%s', "
+ "'%s', '%s')", pg_info->toposchema_name, pg_info->schema_name,
+ pg_info->table_name, pg_info->topogeom_column,
+ get_sftype(pg_info->feature_type));
+ G_debug(2, "SQL: %s", stmt);
+
+ result = PQexec(pg_info->conn, stmt);
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
+ G_warning(_("Execution failed: %s"), PQerrorMessage(pg_info->conn));
+ Vect__execute_pg(pg_info->conn, "ROLLBACK");
+ return -1;
+ }
+
+ /* close transaction (create topo schema) */
+ if (Vect__execute_pg(pg_info->conn, "COMMIT") == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*!
+ \brief Create new PostGIS layer in given database (internal use only)
+
+ V1_open_new_pg() must be called before this function.
+
+ List of currently supported types:
+ - GV_POINT (SF_POINT)
+ - GV_LINE (SF_LINESTRING)
+ - GV_BOUNDARY (SF_POLYGON)
+
+ When PostGIS Topology the map level is updated to topological level
+ and build level set to GV_BUILD_BASE.
+
+ \param[in,out] Map pointer to Map_info structure
+ \param type feature type (GV_POINT, GV_LINE, ...)
+
+ \return 0 success
+ \return -1 error
+ */
+int create_pg_layer(struct Map_info *Map, int type)
+{
+ int ndblinks;
+
+ struct Format_info_pg *pg_info;
+ struct field_info *Fi;
+
+ Fi = NULL;
+
+ pg_info = &(Map->fInfo.pg);
+ if (!pg_info->conninfo) {
+ G_warning(_("Connection string not defined"));
+ return -1;
+ }
+
+ if (!pg_info->table_name) {
+ G_warning(_("PostGIS feature table not defined"));
+ return -1;
+ }
+
+ G_debug(1, "Vect__open_new_pg(): conninfo='%s' table='%s' -> type = %d",
+ pg_info->conninfo, pg_info->table_name, type);
+
+ /* determine geometry type */
+ switch (type) {
+ case GV_POINT:
+ pg_info->feature_type = SF_POINT;
+ break;
+ case GV_LINE:
+ pg_info->feature_type = SF_LINESTRING;
+ break;
+ case GV_BOUNDARY:
+ pg_info->feature_type = SF_POLYGON;
+ break;
+ default:
+ G_warning(_("Unsupported geometry type (%d)"), type);
+ return -1;
+ }
+
+ /* coordinate dimension */
+ pg_info->coor_dim = Vect_is_3d(Map) ? 3 : 2;
+
+ /* create new PostGIS table */
+ ndblinks = Vect_get_num_dblinks(Map);
+ if (ndblinks > 0) {
+ Fi = Vect_get_dblink(Map, 0);
+ if (Fi) {
+ if (ndblinks > 1)
+ G_warning(_("More layers defined, using driver <%s> and "
+ "database <%s>"), Fi->driver, Fi->database);
+ }
+ else {
+ G_warning(_("Database connection not defined. "
+ "Unable to write attributes."));
+ }
+ }
+
+ /* create new feature table */
+ if (create_table(pg_info, Fi) == -1) {
+ G_warning(_("Unable to create new PostGIS feature table"));
+ return -1;
+ }
+
+ /* create new topology schema (if PostGIS topology support is enabled) */
+ if (pg_info->toposchema_name) {
+ /* force topological level */
+ Map->level = LEVEL_2;
+ Map->plus.built = GV_BUILD_BASE;
+
+ /* track updated features, used in V2__add_line_to_topo_nat() */
+ Vect_set_updated(Map, TRUE);
+
+ if (create_topo_schema(pg_info, Vect_is_3d(Map)) == -1) {
+ G_warning(_("Unable to create new PostGIS topology schema"));
+ return -1;
+ }
+ }
+
+ if (Fi)
+ G_free(Fi);
+
+ return 0;
+}
+
+/*!
+ \brief Get simple feature type as a string
+
+ Used for AddTopoGeometryColumn().
+
+ Valid types:
+ - SF_POINT
+ - SF_LINESTRING
+ - SF_POLYGON
+
+ \return string with feature type
+ \return empty string
+*/
+char *get_sftype(SF_FeatureType sftype)
+{
+ if (sftype == SF_POINT)
+ return "POINT";
+ else if (sftype == SF_LINESTRING)
+ return "LINE";
+ else if (sftype == SF_POLYGON)
+ return "POLYGON";
+ else
+ G_warning(_("Unsupported feature type %d"), sftype);
+
+ return "";
+}
+
+/*!
\brief Write vector features as PostGIS simple feature element
\param Map pointer to Map_info structure
@@ -534,7 +1057,7 @@
/* create PostGIS table if doesn't exist */
if (pg_info->feature_type == SF_UNKNOWN) {
- if (V2_open_new_pg(Map, type) < 0)
+ if (create_pg_layer(Map, type) < 0)
return -1;
}
@@ -639,7 +1162,7 @@
\param points feature geometry
\param is_node TRUE for nodes (written as points)
- \return 0 on success
+ \return 0 feature offset
\return -1 on error
*/
off_t write_line_tp(struct Map_info *Map, int type, int is_node,
@@ -677,7 +1200,7 @@
/* create PostGIS table if doesn't exist */
if (pg_info->feature_type == SF_UNKNOWN) {
- if (V2_open_new_pg(Map, type) < 0)
+ if (create_pg_layer(Map, type) < 0)
return -1;
}
@@ -765,7 +1288,7 @@
if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY)
update_topo_face(Map, line);
- return 0;
+ return line;
}
/*!
More information about the grass-commit
mailing list