[GRASS-SVN] r53990 - grass/trunk/lib/vector/Vlib
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Nov 23 07:32:34 PST 2012
Author: martinl
Date: 2012-11-23 07:32:33 -0800 (Fri, 23 Nov 2012)
New Revision: 53990
Modified:
grass/trunk/lib/vector/Vlib/build_pg.c
grass/trunk/lib/vector/Vlib/open_pg.c
grass/trunk/lib/vector/Vlib/pg_local_proto.h
Log:
vlib/PostGIS Topology: store map bounding box in 'topology.grass' table
calculating map bbox from TopoGeometry objects is quite time consuming
Modified: grass/trunk/lib/vector/Vlib/build_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build_pg.c 2012-11-23 14:54:53 UTC (rev 53989)
+++ grass/trunk/lib/vector/Vlib/build_pg.c 2012-11-23 15:32:33 UTC (rev 53990)
@@ -25,6 +25,9 @@
static int build_topo(struct Map_info *, int);
static int build_topogeom_stmt(const struct Format_info_pg *, int, int, char *);
+static int save_map_bbox(const struct Format_info_pg *, const struct bound_box*);
+static int create_topo_grass(const struct Format_info_pg *);
+static int has_topo_grass(const struct Format_info_pg *);
#endif
/*!
@@ -157,6 +160,9 @@
Vect_build_nat(Map, build);
}
+ /* store map boundig box in DB */
+ save_map_bbox(pg_info, &(plus->box));
+
i = 0;
Vect_rewind(Map);
if (Vect__execute_pg(pg_info->conn, "BEGIN"))
@@ -238,4 +244,139 @@
return 1;
}
+
+/*!
+ \brief Store map bounding box in DB head table
+
+ \param pg_info pointer to Format_info_pg struct
+ \param box pointer to bounding box
+
+ \return 1 on success
+ \return 0 on failure
+*/
+int save_map_bbox(const struct Format_info_pg *pg_info, const struct bound_box *box)
+{
+ char stmt[DB_SQL_MAX];
+
+ /* create if not exists */
+ if (create_topo_grass(pg_info) == -1) {
+ G_warning(_("Unable to create <%s.%s>"), TOPO_SCHEMA, TOPO_TABLE);
+ return 0;
+ }
+
+ /* update bbox */
+ if (has_topo_grass(pg_info)) {
+ /* -> update */
+ sprintf(stmt, "UPDATE \"%s\".\"%s\" SET %s = "
+ "'BOX3D(%.12f %.12f %.12f, %.12f %.12f %.12f)'::box3d WHERE %s = %d",
+ TOPO_SCHEMA, TOPO_TABLE, TOPO_BBOX,
+ box->W, box->S, box->B, box->E, box->N, box->T,
+ TOPO_ID, pg_info->toposchema_id);
+ }
+ else {
+ /* -> insert */
+ sprintf(stmt, "INSERT INTO \"%s\".\"%s\" (%s, %s) "
+ "VALUES(%d, 'BOX3D(%.12f %.12f %.12f, %.12f %.12f %.12f)'::box3d)",
+ TOPO_SCHEMA, TOPO_TABLE, TOPO_ID, TOPO_BBOX, pg_info->toposchema_id,
+ box->W, box->S, box->B, box->E, box->N, box->T);
+ }
+
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ return -1;
+ }
+
+ return 1;
+}
+
+/*!
+ \brief Creates 'topology.grass' table if not exists
+
+ \return 0 table already exists
+ \return 1 table successfully added
+ \return -1 on error
+*/
+int create_topo_grass(const struct Format_info_pg *pg_info)
+{
+ char stmt[DB_SQL_MAX];
+
+ PGresult *result;
+
+ /* check if table exists */
+ sprintf(stmt, "SELECT COUNT(*) FROM information_schema.tables "
+ "WHERE table_schema = '%s' AND table_name = '%s'",
+ TOPO_SCHEMA, TOPO_TABLE);
+ result = PQexec(pg_info->conn, stmt);
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
+ PQclear(result);
+ return -1;
+ }
+
+ if (atoi(PQgetvalue(result, 0, 0)) == 1) {
+ /* table already exists */
+ PQclear(result);
+ return 1;
+ }
+ PQclear(result);
+
+ G_debug(1, "<%s.%s> created", TOPO_SCHEMA, TOPO_TABLE);
+
+ /* create table */
+ sprintf(stmt, "CREATE TABLE \"%s\".\"%s\" (%s INTEGER, %s box3d)",
+ TOPO_SCHEMA, TOPO_TABLE, TOPO_ID, TOPO_BBOX);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ return -1;
+ }
+ /* add primary key */
+ sprintf(stmt, "ALTER TABLE \"%s\".\"%s\" ADD PRIMARY KEY (%s)",
+ TOPO_SCHEMA, TOPO_TABLE, TOPO_ID);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ return -1;
+ }
+
+ /* add constraint */
+ sprintf(stmt, "ALTER TABLE \"%s\".\"%s\" ADD CONSTRAINT \"%s_%s_fkey\" "
+ "FOREIGN KEY (%s) REFERENCES topology.topology(id)",
+ TOPO_SCHEMA, TOPO_TABLE, TOPO_TABLE, TOPO_ID, TOPO_ID);
+ if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ return -1;
+ }
+
+ return 1;
+}
+
+/*!
+ \brief Check if 'topology_id' exists in 'topology.grass'
+
+ \param pg_info pointer to Format_info_pg struct
+
+ \return TRUE if exists
+ \return FALSE otherwise
+ \return -1 on error
+*/
+int has_topo_grass(const struct Format_info_pg *pg_info)
+{
+ int has_topo;
+ char stmt[DB_SQL_MAX];
+
+ PGresult *result;
+
+ sprintf(stmt, "SELECT COUNT(*) FROM \"%s\".\"%s\" "
+ "WHERE %s = %d",
+ TOPO_SCHEMA, TOPO_TABLE, TOPO_ID, pg_info->toposchema_id);
+ result = PQexec(pg_info->conn, stmt);
+ if (!result || PQresultStatus(result) != PGRES_TUPLES_OK) {
+ PQclear(result);
+ return -1;
+ }
+
+ has_topo = FALSE;
+ if (atoi(PQgetvalue(result, 0, 0)) == 1) {
+ /* table already exists */
+ has_topo = TRUE;
+ }
+ PQclear(result);
+
+ return has_topo;
+}
+
#endif
Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c 2012-11-23 14:54:53 UTC (rev 53989)
+++ grass/trunk/lib/vector/Vlib/open_pg.c 2012-11-23 15:32:33 UTC (rev 53990)
@@ -1350,19 +1350,30 @@
plus->off_t_size = -1;
- /* get map bounding box */
+ /* fisrt try to get info from 'topology.grass */
sprintf(stmt,
- "SELECT ST_3DExtent(%s) FROM \"%s\".\"%s\"",
- pg_info->topogeom_column, pg_info->schema_name, pg_info->table_name);
+ "SELECT %s FROM \"%s\".\"%s\" WHERE %s = %d",
+ TOPO_BBOX, TOPO_SCHEMA, TOPO_TABLE, TOPO_ID, pg_info->toposchema_id);
G_debug(2, "SQL: %s", stmt);
res = PQexec(pg_info->conn, stmt);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
PQntuples(res) != 1) {
- G_warning(_("Unable to get map bounding box from topology"));
- if (res)
+ PQclear(res);
+
+ /* try to calculate bbox from TopoGeometry elements */
+ sprintf(stmt,
+ "SELECT ST_3DExtent(%s) FROM \"%s\".\"%s\"",
+ pg_info->topogeom_column, pg_info->schema_name, pg_info->table_name);
+ G_debug(2, "SQL: %s", stmt);
+ res = PQexec(pg_info->conn, stmt);
+ if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
+ PQntuples(res) != 1 || strlen(PQgetvalue(res, 0, 0)) < 1) {
+ G_warning(_("Unable to get map bounding box from topology"));
PQclear(res);
- return -1;
+ return -1;
+ }
}
+
if (parse_bbox(PQgetvalue(res, 0, 0), &(plus->box)) != 0) {
G_warning(_("Unable to parse map bounding box:\n%s"),
PQgetvalue(res, 0, 0));
Modified: grass/trunk/lib/vector/Vlib/pg_local_proto.h
===================================================================
--- grass/trunk/lib/vector/Vlib/pg_local_proto.h 2012-11-23 14:54:53 UTC (rev 53989)
+++ grass/trunk/lib/vector/Vlib/pg_local_proto.h 2012-11-23 15:32:33 UTC (rev 53990)
@@ -9,8 +9,15 @@
#define CURSOR_PAGE 500
#define FID_COLUMN "fid"
+/*! Simple features access */
#define GEOMETRY_COLUMN "geom"
+/*! Topological access */
+#define TOPO_SCHEMA "topology"
+#define TOPO_ID "topology_id"
+#define TOPO_TABLE "grass"
+#define TOPO_BBOX "bbox"
+
#define SWAP32(x) \
((unsigned int)( \
(((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
More information about the grass-commit
mailing list