[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