[GRASS-SVN] r53979 - in grass/trunk: include/vect lib/vector/Vlib vector/v.out.postgis

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Nov 23 04:42:35 PST 2012


Author: martinl
Date: 2012-11-23 04:42:35 -0800 (Fri, 23 Nov 2012)
New Revision: 53979

Modified:
   grass/trunk/include/vect/dig_structs.h
   grass/trunk/lib/vector/Vlib/build_pg.c
   grass/trunk/lib/vector/Vlib/open_pg.c
   grass/trunk/lib/vector/Vlib/write_pg.c
   grass/trunk/vector/v.out.postgis/main.c
Log:
vlib (PostGIS topo access): full support for lines (work in progress)


Modified: grass/trunk/include/vect/dig_structs.h
===================================================================
--- grass/trunk/include/vect/dig_structs.h	2012-11-23 12:03:32 UTC (rev 53978)
+++ grass/trunk/include/vect/dig_structs.h	2012-11-23 12:42:35 UTC (rev 53979)
@@ -666,9 +666,10 @@
     */
     char    *topogeom_column;
     /*!
-      \brief Topology schema name
+      \brief Topology schema name and id
     */
     char    *toposchema_name;
+    int      toposchema_id;
 };
 
 /*!

Modified: grass/trunk/lib/vector/Vlib/build_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build_pg.c	2012-11-23 12:03:32 UTC (rev 53978)
+++ grass/trunk/lib/vector/Vlib/build_pg.c	2012-11-23 12:42:35 UTC (rev 53979)
@@ -24,6 +24,7 @@
 #include "pg_local_proto.h"
 
 static int build_topo(struct Map_info *, int);
+static int build_topogeom_stmt(const struct Format_info_pg *, int, int, char *);
 #endif
 
 /*!
@@ -118,9 +119,14 @@
 */
 int build_topo(struct Map_info *Map, int build)
 {
+    int i, type;
+    char stmt[DB_SQL_MAX];
+    
     struct Plus_head *plus;
+    struct Format_info_pg *pg_info;
     
     plus = &(Map->plus);
+    pg_info = &(Map->fInfo.pg);
     
     /* check if upgrade or downgrade */
     if (build < plus->built) { 
@@ -130,6 +136,7 @@
     }
     
     if (build != GV_BUILD_ALL) {
+        /* TODO: implement all build levels */
         G_warning(_("Only %s is supported for PostGIS topology"),
                   "GV_BUILD_ALL");
         return 0;
@@ -142,12 +149,93 @@
     }
     */
 
-    /* build GRASS-like topology from PostGIS topological
-       primitives */
-    if (Vect_build_nat(Map, build) != 1)
+    /* update TopoGeometry based on GRASS-like topology */
+    if (build < GV_BUILD_BASE)
+        return 1; /* nothing to print */
+    
+    if (plus->built < GV_BUILD_BASE) {
+        Vect_build_nat(Map, build);
+    }
+    
+    i = 0;
+    Vect_rewind(Map);
+    if (Vect__execute_pg(pg_info->conn, "BEGIN"))
         return 0;
     
-    /* update PostGIS topology based on GRASS-like topology */
+    G_message(_("Updating TopoGeometry data..."));
+    while (TRUE) {
+        type = Vect_read_next_line(Map, NULL, NULL);
+        if (type == -1) {
+            G_warning(_("Unable to read vector map"));
+            return 0;
+        }
+        else if (type == -2) {
+            break;
+        }
+        G_progress(++i, 1e3);
+        
+        /* update topogeometry elements in feature table */
+        if (type == GV_POINT || type == GV_LINE) {
+            if (build_topogeom_stmt(pg_info, i, type, stmt) &&
+                Vect__execute_pg(pg_info->conn, stmt) == -1) {
+                Vect__execute_pg(pg_info->conn, "ROLLBACK");
+                return 0;
+            }
+        }
+    }
+    G_progress(1, 1);
+    
+    if (Vect__execute_pg(pg_info->conn, "COMMIT") == -1)
+        return 0;
+
     return 1;
 }
+
+/*! 
+  \brief Build UPDATE statement for topo geometry element stored in
+  feature table
+
+  \param pg_info so pointer to Format_info_pg
+  \param type feature type (GV_POINT, ...)
+  \param id topology element id
+  \param[out] stmt string buffer
+  
+  \return 1 on success
+  \return 0 on failure
+*/
+int build_topogeom_stmt(const struct Format_info_pg *pg_info,
+                        int id, int type, char *stmt)
+{
+    int topogeom_type;
+    
+    if (type == GV_POINT)
+        topogeom_type = 1;
+    else if (type & GV_LINES)
+        topogeom_type = 2;
+    else {
+        G_warning(_("Unsupported topo geometry type %d"), type);
+        return 0;
+    }
+    
+    /* it's quite slow...
+       
+    sprintf(stmt, "UPDATE \"%s\".\"%s\" SET %s = "
+            "topology.CreateTopoGeom('%s', %d, 1,"
+            "'{{%d, %d}}'::topology.topoelementarray) "
+            "WHERE %s = %d",
+            pg_info->schema_name, pg_info->table_name,
+            pg_info->topogeom_column, pg_info->toposchema_name,
+            topogeom_type, id, topogeom_type,
+            pg_info->fid_column, id);
+    */
+
+    sprintf(stmt, "UPDATE \"%s\".\"%s\" SET %s = "
+            "'(%d, 1, %d, %d)'::topology.TopoGeometry "
+            "WHERE %s = %d",
+            pg_info->schema_name, pg_info->table_name,
+            pg_info->topogeom_column, pg_info->toposchema_id,
+            id, topogeom_type, pg_info->fid_column, id);
+
+    return 1;
+}
 #endif

Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c	2012-11-23 12:03:32 UTC (rev 53978)
+++ grass/trunk/lib/vector/Vlib/open_pg.c	2012-11-23 12:42:35 UTC (rev 53979)
@@ -162,22 +162,39 @@
 {
 #ifdef HAVE_POSTGRES
     struct Format_info_pg *pg_info;
-    
+
+    PGresult *res;
+
     G_debug(3, "V2_open_old_pg(): name = %s mapset = %s", Map->name,
             Map->mapset);
 
     pg_info = &(Map->fInfo.pg);
     
-    if (pg_info->toposchema_name)
-        /* no fidx file needed for PostGIS topology access */
-        return 0;
-    
-    if (Vect_open_fidx(Map, &(pg_info->offset)) != 0) {
-        G_warning(_("Unable to open feature index file for vector map <%s>"),
-                  Vect_get_full_name(Map));
-        G_zero(&(pg_info->offset), sizeof(struct Format_info_offset));
+    if (pg_info->toposchema_name) {
+        char stmt[DB_SQL_MAX];
+
+        /* get topo schema id */
+        sprintf(stmt, "SELECT id FROM topology.topology WHERE name = '%s'",
+                pg_info->toposchema_name);
+        res = PQexec(pg_info->conn, stmt);
+        if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
+            G_warning("%s\n%s", _("Topology schema not found."),
+                      PQresultErrorMessage(res));
+            if (res)
+                PQclear(res);
+            return -1;
+        }
+        pg_info->toposchema_id = atoi(PQgetvalue(res, 0, 0));
+        PQclear(res);
     }
-
+    else {
+        /* fidx file needed only for simple features access */
+        if (Vect_open_fidx(Map, &(pg_info->offset)) != 0) {
+            G_warning(_("Unable to open feature index file for vector map <%s>"),
+                      Vect_get_full_name(Map));
+            G_zero(&(pg_info->offset), sizeof(struct Format_info_offset));
+        }
+    }
     return 0;
 #else
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
@@ -918,7 +935,9 @@
         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);
@@ -985,7 +1004,7 @@
     
     /* check if topology layer/schema exists */
     sprintf(stmt,
-            "SELECT t.name,t.hasz,l.feature_column FROM topology.layer "
+            "SELECT t.id,t.name,t.hasz,l.feature_column FROM topology.layer "
             "AS l JOIN topology.topology AS t ON l.topology_id = t.id "
             "WHERE schema_name = '%s' AND table_name = '%s'",
             pg_info->schema_name, pg_info->table_name);
@@ -1002,14 +1021,15 @@
         return 1;
     }
 
-    pg_info->toposchema_name = G_store(PQgetvalue(res, 0, 0));
-    pg_info->topogeom_column = G_store(PQgetvalue(res, 0, 2));
+    pg_info->toposchema_id   = atoi(PQgetvalue(res, 0, 0));
+    pg_info->toposchema_name = G_store(PQgetvalue(res, 0, 1));
+    pg_info->topogeom_column = G_store(PQgetvalue(res, 0, 3));
 
     G_debug(1, "PostGIS topology detected: schema = %s column = %s",
             pg_info->toposchema_name, pg_info->topogeom_column);
     
     /* check for 3D */
-    if (strcmp(PQgetvalue(res, 0, 1), "t") == 0)
+    if (strcmp(PQgetvalue(res, 0, 2), "t") == 0)
         plus->with_z = WITH_Z;
     PQclear(res);
     

Modified: grass/trunk/lib/vector/Vlib/write_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/write_pg.c	2012-11-23 12:03:32 UTC (rev 53978)
+++ grass/trunk/lib/vector/Vlib/write_pg.c	2012-11-23 12:42:35 UTC (rev 53979)
@@ -33,27 +33,33 @@
 
 #define WKBSRIDFLAG 0x20000000
 
+/*! 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 off_t write_line_sf(struct Map_info *, int,
                            const struct line_pnts **, int,
                            const struct line_cats *);
 static off_t write_line_tp(struct Map_info *, int, int,
-                           const struct line_pnts *);
+                           const struct line_pnts *,
+                           const struct line_cats *);
 static char *binary_to_hex(int, const unsigned char *);
 static unsigned char *point_to_wkb(int, const struct line_pnts *, int, int *);
 static unsigned char *linestring_to_wkb(int, const struct line_pnts *,
                                         int, int *);
 static unsigned char *polygon_to_wkb(int, const struct line_pnts **, int,
                                      int, int *);
-static int write_feature(struct Format_info_pg *,
+static int write_feature(struct Map_info *,
                          int, const struct line_pnts **, int, int,
                          const struct P_line *,
                          int, const struct field_info *);
 static char *build_insert_stmt(const struct Format_info_pg *, const char *,
                                int, const struct field_info *);
-static char *build_topo_stmt(struct Format_info_pg *, int,
+static char *build_topo_stmt(struct Map_info *, int,
                              const struct P_line *, const char *);
-static char *build_topogeom_stmt(const struct Format_info_pg *, int, int, int);
 static int execute_topo(PGconn *, const char *);
+static int update_next_line(struct Map_info*, int, int, int*, int *);
 #endif
 
 /*!
@@ -120,10 +126,14 @@
 
     pg_info = &(Map->fInfo.pg);
     
-    if (!pg_info->toposchema_name) /* pseudo-topology */
+    if (!pg_info->toposchema_name) { /* pseudo-topology */
         return V2_write_line_sfa(Map, type, points, cats);
-    else                           /* PostGIS topology */
-        return write_line_tp(Map, type, FALSE, points);
+    }
+    else {                          /* PostGIS topology */
+        if (Map->plus.built < GV_BUILD_BASE)
+            Map->plus.built = GV_BUILD_BASE;
+        return write_line_tp(Map, type, FALSE, points, cats);
+    }
 #else
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
     return -1;
@@ -242,7 +252,7 @@
     if (!pg_info->toposchema_name)
         return -1; /* PostGIS Topology required */
     
-    return write_line_tp(Map, GV_POINT, TRUE, points);
+    return write_line_tp(Map, GV_POINT, TRUE, points, NULL);
 #else
     G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
     return -1;
@@ -333,7 +343,7 @@
             return -1;
     }
     
-    Fi = NULL;                  /* no attributes to be written */
+    Fi = NULL; /* no attributes to be written */
     cat = -1;
     if (cats->n_cats > 0 && Vect_get_num_dblinks(Map) > 0) {
         /* check for attributes */
@@ -400,7 +410,7 @@
     }
 
     /* write feature's geometry and fid */
-    if (-1 == write_feature(pg_info, type, points, nparts,
+    if (-1 == write_feature(Map, type, points, nparts,
                             Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, NULL, cat, Fi)) {
         Vect__execute_pg(pg_info->conn, "ROLLBACK");
         return -1;
@@ -439,8 +449,12 @@
   \return -1 on error
 */
 off_t write_line_tp(struct Map_info *Map, int type, int is_node,
-                    const struct line_pnts *points)
+                    const struct line_pnts *points,
+                    const struct line_cats *cats)
 {
+    int cat;
+
+    struct field_info *Fi;
     struct Format_info_pg *pg_info;
     struct Plus_head *plus;
     struct P_line *Line;
@@ -477,6 +491,26 @@
     G_debug(3, "write_line_pg(): type = %d n_points = %d",
             type, points->n_points);
 
+    Fi = NULL; /* no attributes to be written */
+    cat = -1;
+    if (cats && cats->n_cats > 0) {
+        if (Vect_get_num_dblinks(Map) > 0) {
+            /* check for attributes */
+            Fi = Vect_get_dblink(Map, 0);
+            if (Fi) {
+                if (!Vect_cat_get(cats, Fi->number, &cat))
+                    G_warning(_("No category defined for layer %d"), Fi->number);
+                if (cats->n_cats > 1) {
+                    G_warning(_("Feature has more categories, using "
+                                "category %d (from layer %d)"),
+                              cat, cats->field[0]);
+                }
+            }
+        }
+        /* assume layer=1 */
+        Vect_cat_get(cats, 1, &cat);
+    }
+
     /* update topology before writing feature */
     Line = NULL;
     if (is_node) {
@@ -499,9 +533,9 @@
     }
     
     /* write feature geometry and fid */
-    if (-1 == write_feature(pg_info, type, &points, 1,
+    if (-1 == write_feature(Map, type, &points, 1,
                             Vect_is_3d(Map) ? WITH_Z : WITHOUT_Z, Line,
-                            -1, NULL)) {
+                            cat, Fi)) {
         Vect__execute_pg(pg_info->conn, "ROLLBACK");
         return -1;
     }
@@ -784,7 +818,7 @@
 /*!
    \brief Insert feature into table
 
-   \param pg_info pointer to Format_info_pg struct
+   \param Map pointer to Map_info structure
    \param type feature type (GV_POINT, GV_LINE, ...)
    \param points pointer to line_pnts struct
    \param nparts number of parts (rings for polygon)
@@ -795,7 +829,7 @@
    \return -1 on error
    \retirn 0 on success
  */
-int write_feature(struct Format_info_pg *pg_info, int type,
+int write_feature(struct Map_info *Map, int type,
                   const struct line_pnts **points, int nparts, int with_z,
                   const struct P_line *Line,
                   int cat, const struct field_info *Fi)
@@ -805,6 +839,10 @@
     unsigned char *wkb_data;
     char *stmt, *text_data, *text_data_p, *hex_data;
 
+    struct Format_info_pg *pg_info;
+
+    pg_info = &(Map->fInfo.pg);
+    
     if (with_z && pg_info->coor_dim != 3) {
         G_warning(_("Trying to insert 3D data into feature table "
                     "which store 2D data only"));
@@ -916,22 +954,17 @@
     /* write feature in PostGIS topology schema if enabled */
     if (pg_info->toposchema_name) {
         /* insert feature into topology schema (node or edge) */
-        stmt = build_topo_stmt(pg_info, type, Line, text_data);
+        stmt = build_topo_stmt(Map, type, Line, text_data);
+#if USE_TOPO_STMT
+        if (stmt && execute_topo(pg_info->conn, stmt) == -1) {
+#else
         if (stmt && Vect__execute_pg(pg_info->conn, stmt) == -1) {
+#endif
             /* rollback transaction */
             Vect__execute_pg(pg_info->conn, "ROLLBACK");
             return -1;
         }
         G_free(stmt);
-        
-        /* insert topoelement into feature table
-        stmt = build_topogeom_stmt(pg_info, id, type, do_update);
-        if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
-            Vect__execute_pg(pg_info->conn, "ROLLBACK");
-            return -1;
-        }
-        G_free(stmt);
-        */
     }
 
     G_free(wkb_data);
@@ -941,9 +974,13 @@
 }
 
 /*!
-   \brief Build INSERT statement to insert new feature to the table
+   \brief Build INSERT statement to add new feature to the feature
+   table
 
+   Note: Allocated string should be freed.
+   
    \param pg_info pointer to Format_info_pg structure
+   \param geom_data geometry data
    \param cat category number (or -1 for no category)
    \param Fi pointer to field_info structure (NULL for no attributes)
 
@@ -956,7 +993,7 @@
     char *stmt, buf[DB_SQL_MAX];
 
     stmt = NULL;
-    if (Fi && cat > -1) {
+    if (Fi && cat > -1) { /* write attributes (simple features and topology elements) */
         int col, ncol, more;
         int sqltype, ctype;
         char buf_val[DB_SQL_MAX], buf_tmp[DB_SQL_MAX];
@@ -1075,17 +1112,21 @@
             }
         }
     }
-    else if (pg_info->toposchema_name)
-        return NULL; /* don't write simple feature element */
-
-    if (!stmt) {
-        /* no attributes */
-        G_asprintf(&stmt, "INSERT INTO \"%s\".\"%s\" (%s) VALUES "
-                   "('%s'::GEOMETRY)",
-                   pg_info->schema_name, pg_info->table_name,
-                   pg_info->geom_column, geom_data);
+    else {
+        if (!pg_info->toposchema_name) {
+            /* no attributes (simple features access) */
+            G_asprintf(&stmt, "INSERT INTO \"%s\".\"%s\" (%s) VALUES "
+                       "('%s'::GEOMETRY)",
+                       pg_info->schema_name, pg_info->table_name,
+                       pg_info->geom_column, geom_data);
+        }
+        else if (cat > 0)
+            /* no attributes (topology elements) */
+            G_asprintf(&stmt, "INSERT INTO \"%s\".\"%s\" (%s) VALUES (NULL)",
+                       pg_info->schema_name, pg_info->table_name,
+                       pg_info->geom_column); 
     }
-
+    
     return stmt;
 }
 
@@ -1093,44 +1134,85 @@
   \brief Build SELECT statement to insert new element into PostGIS
   topology schema
 
-  \param pg_info so pointer to Format_info_pg
+  \param Map pointer to Map_info struct
   \param Line pointer to P_line struct (topo)
   \param geom_data geometry in wkb
 
   \return pointer to allocated string buffer with SQL statement
   \return NULL on error
 */
-char *build_topo_stmt(struct Format_info_pg *pg_info, int type,
+char *build_topo_stmt(struct Map_info *Map, int type,
                       const struct P_line *Line, const char *geom_data)
 {
     char *stmt;
+    struct Format_info_pg *pg_info;
+
+    pg_info = &(Map->fInfo.pg);
     
     stmt = NULL;
     switch(type) {
     case GV_POINT: {
-#if 1
-        G_asprintf(&stmt, "INSERT INTO \"%s\".node (geom) VALUES ('%s'::GEOMETRY)",
+#if USE_TOPO_STMT
+        G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
                    pg_info->toposchema_name, geom_data);
 #else
-        G_asprintf(&stmt, "SELECT topology.AddNode('%s', '%s'::GEOMETRY)",
+        G_asprintf(&stmt, "INSERT INTO \"%s\".node (geom) VALUES ('%s'::GEOMETRY)",
                    pg_info->toposchema_name, geom_data);
 #endif
         break;
     }
     case GV_LINE: {
+        int line;
+        int n1, n2;
+        int nle, nre; /* next left | right edge */
+        
+        /*
+         * isolated lines
+              next left  edge: -fid 
+              next right edge:  fid
+              
+         * connected lines
+             next left  edge: next line or -fid
+             next right edge: next line or  fid
+        */ 
         if (!Line) {
             G_warning(_("Topology not available. Unable to insert new edge."));
             return NULL;
         }
         
         struct P_topo_l *topo = (struct P_topo_l *) Line->topo;
+                
+#if USE_TOPO_STMT
+        G_asprintf(&stmt, "SELECT topology.AddEdge('%s', '%s'::GEOMETRY)",
+                   pg_info->toposchema_name, geom_data);
+#else
+        line = Vect_get_num_lines(Map);
         
+        /* get number of lines for each node */
+        n1 = Vect_get_node_n_lines(Map, topo->N1);
+        n2 = Vect_get_node_n_lines(Map, topo->N2);
+
+        /* assuming isolated lines */
+        nle = -line;
+        nre = line;
+        
+        /* check for line connection */
+        if (n1 > 1) {
+            update_next_line(Map, n1, line, &nle, &nre);
+        }
+        if (n2 > 1) {
+            update_next_line(Map, n2, -line, &nle, &nre);
+        }
+        
+        G_debug(3, "build_topo_stmt(): line=%d type=line nle=%d nre=%d", line, nle, nre);
+        
         G_asprintf(&stmt, "INSERT INTO \"%s\".edge_data (geom, start_node, end_node, "
-                   "next_left_edge, next_right_edge, abs_next_left_edge, abs_next_right_edge, "
+                   "next_left_edge, abs_next_left_edge, next_right_edge, abs_next_right_edge, "
                    "left_face, right_face) "
-                   "VALUES ('%s'::GEOMETRY, %d, %d, %d, %d, %d, %d, %d, %d)",
-                   pg_info->toposchema_name, geom_data, topo->N1, topo->N2, 0, 0, 0, 0, 0, 0);
-
+                   "VALUES ('%s'::GEOMETRY, %d, %d, %d, %d, %d, %d, 0, 0)",
+                   pg_info->toposchema_name, geom_data, topo->N1, topo->N2, nle, abs(nle),
+                   nre, abs(nre));
+#endif
         break;
     }
     case GV_CENTROID: {
@@ -1154,57 +1236,6 @@
 }
 
 /*!
-  \brief Build INSERT / UPDATE statement to insert topo geometry
-  object into feature table
-
-  Allocated string should be freed by G_free()
-  
-  \param pg_info so pointer to Format_info_pg
-  \param type feature type (GV_POINT, ...)
-  \param id topology element id
-  \param do_update TRUE for UPDATE otherwise build SELECT statement
-  
-  \return pointer to allocated string buffer with SQL statement
-  \return NULL on error
-*/
-char *build_topogeom_stmt(const struct Format_info_pg *pg_info,
-                          int id, int type, int do_update)
-{
-    int topogeom_type;
-    char *stmt;
-    
-    stmt = NULL;
-
-    if (type == GV_POINT)
-        topogeom_type = 1;
-    else if (type & GV_LINES)
-        topogeom_type = 2;
-    else {
-        G_warning(_("Unsupported topo geometry type %d"), type);
-        return NULL;
-    }
-    
-    if (!do_update)
-        G_asprintf(&stmt, "INSERT INTO \"%s\".\"%s\" (%s) VALUES "
-                   "(topology.CreateTopoGeom('%s', 1, %d, "
-                   "'{{%d, %d}}'::topology.topoelementarray))",
-                   pg_info->schema_name, pg_info->table_name,
-                   pg_info->topogeom_column, pg_info->toposchema_name,
-                   topogeom_type, id, topogeom_type);
-    else
-        G_asprintf(&stmt, "UPDATE \"%s\".\"%s\" SET %s = "
-                   "topology.CreateTopoGeom('%s', 1, %d, "
-                   "'{{%d, %d}}'::topology.topoelementarray) "
-                   "WHERE %s = %d",
-                   pg_info->schema_name, pg_info->table_name,
-                   pg_info->topogeom_column, pg_info->toposchema_name,
-                   topogeom_type, id, topogeom_type,
-                   pg_info->fid_column, id);
-    
-    return stmt;
-}
-
-/*!
    \brief Execute SQL topo select statement
 
    \param conn pointer to PGconn
@@ -1235,5 +1266,72 @@
     
     return ret;
 }
-   
+
+/*!
+  \brief Find next line (topo only) 
+
+  \param Map pointer to Map_info struct
+  \param nlines number of lines
+  \param line current line (negative for backward direction - ie. end node)
+  \param[out] left left line
+  \param[out] right right line
+  \return line id (left or right)
+
+  \return 0 on success
+  \return -1 on failure
+*/
+int update_next_line(struct Map_info* Map, int nlines, int line,
+                     int *left, int *right)
+{
+    int next_line;
+    char stmt[DB_SQL_MAX];
+    
+    struct Format_info_pg *pg_info;
+    
+    pg_info = &(Map->fInfo.pg);
+    
+    /* update left line side */
+    next_line = dig_angle_next_line(&(Map->plus), line,
+                                    line < 0 ? GV_LEFT : GV_RIGHT, GV_LINE, NULL);
+    if (line > 0)
+        *right = next_line;
+    else
+        *left  = next_line;
+    sprintf(stmt, "UPDATE \"%s\".edge_data SET next_left_edge = %d, "
+            "abs_next_left_edge = %d WHERE edge_id = %d",
+            pg_info->toposchema_name, line, abs(line), abs(next_line));
+    G_debug(4, "build_topo_stmt(): line=%d nle=%d | line=%d nle=%d",
+            line, next_line, abs(next_line), line);
+    
+    if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+        /* rollback transaction */
+        Vect__execute_pg(pg_info->conn, "ROLLBACK");
+        return -1;
+    }
+    
+    if (nlines > 2) {
+        /* update right line side */
+        next_line = dig_angle_next_line(&(Map->plus), line,
+                                        line < 0 ? GV_RIGHT : GV_LEFT, GV_LINE, NULL);
+        if (line > 0)
+            *right = next_line;
+        else
+            *left  = next_line;
+        G_debug(4, "line=%d nre=%d", line, next_line);
+        /*
+        sprintf(stmt, "UPDATE \"%s\".edge_data SET next_right_edge = %d, "
+                "abs_next_right_edge = %d WHERE edge_id = %d",
+                pg_info->toposchema_name, line, abs(line), abs(next_line));
+        G_debug(0, "build_topo_stmt(): line=%d nre=%d", abs(next_line), line);
+
+        if(Vect__execute_pg(pg_info->conn, stmt) == -1) {
+        Vect__execute_pg(pg_info->conn, "ROLLBACK");
+            return -1;
+        }
+        */
+    }
+    
+    return 0;
+}
+
 #endif

Modified: grass/trunk/vector/v.out.postgis/main.c
===================================================================
--- grass/trunk/vector/v.out.postgis/main.c	2012-11-23 12:03:32 UTC (rev 53978)
+++ grass/trunk/vector/v.out.postgis/main.c	2012-11-23 12:42:35 UTC (rev 53979)
@@ -121,6 +121,9 @@
     if (Vect_copy_map_lines_field(&In, field, &Out) != 0)
         G_fatal_error(_("Copying features failed"));
     
+    if (flags.topo->answer) 
+        Vect_build_partial(&Out, GV_BUILD_NONE); /* build from scratch */
+    
     Vect_close(&In);
     
     if (Vect_build(&Out) != 1)



More information about the grass-commit mailing list