Browse Source

vlib/pg: fix adding new features into PostGIS Topology

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@58355 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa 11 years ago
parent
commit
19f61c8765

+ 4 - 1
lib/vector/Vlib/build.c

@@ -832,7 +832,10 @@ int Vect_build_partial(struct Map_info *Map, int build)
      * so that lines will be read by V1_read_ (all lines) */
     Map->level = LEVEL_1; /* may be not needed, because V1_read is used
                              directly by Vect_build_ */
-    if (Map->format != GV_FORMAT_OGR_DIRECT)
+
+    if (Map->format != GV_FORMAT_OGR_DIRECT &&
+        !(Map->format == GV_FORMAT_POSTGIS && Map->fInfo.pg.toposchema_name))
+        /* don't write support files for OGR direct and PostGIS Topology */
 	Map->support_updated = TRUE;
 
     if (!Map->plus.Spidx_built)

+ 6 - 3
lib/vector/Vlib/open.c

@@ -346,7 +346,8 @@ int Vect__open_old(struct Map_info *Map, const char *name, const char *mapset,
             if (ret == 1) {     /* sidx file is not available */
                 G_debug(1, "sidx file for vector '%s' not available.",
                         Vect_get_full_name(Map));
-                level = 1;
+                if (!Map->fInfo.pg.toposchema_name) /* optional for PostGIS Topology */
+                  level = 1;
             }
             else if (ret == -1) {
                 G_fatal_error(_("Unable to open spatial index file for vector map <%s>"),
@@ -369,8 +370,10 @@ int Vect__open_old(struct Map_info *Map, const char *name, const char *mapset,
                 G_debug(1,
                         "cidx file for vector '%s' not available.",
                         Vect_get_full_name(Map));
-                dig_free_plus(&(Map->plus));    /* free topology */
-                level = 1;
+                if (!Map->fInfo.pg.toposchema_name) /* optional for PostGIS Topology */ {
+                    dig_free_plus(&(Map->plus));    /* free topology */
+                    level = 1;
+                }
             }
             else if (ret == -1) {       /* file exists, but cannot be opened */
                 G_fatal_error(_("Unable to open category index file for vector map <%s>"),

+ 3 - 2
lib/vector/Vlib/open_pg.c

@@ -347,9 +347,10 @@ int Vect__open_topo_pg(struct Map_info *Map, int head_only, int update)
     /* free and init plus structure, update spatial and category
      * indeces  */
     dig_init_plus(plus);
-    plus->Spidx_new = TRUE;   
+    plus->Spidx_new = TRUE;        /* force building spatial and category indeces */
     plus->update_cidx = TRUE; 
-    
+    Map->support_updated = FALSE;  /* don't write support files */
+
     ret = Vect__load_plus_pg(Map, head_only);
 
     if (update)

+ 1 - 0
lib/vector/Vlib/pg_local_proto.h

@@ -74,6 +74,7 @@ int Vect__close_cursor_pg(struct Format_info_pg *);
 int Vect__select_line_pg(struct Format_info_pg *, int, int);
 int Vect__execute_pg(PGconn *, const char *);
 int Vect__execute_get_value_pg(PGconn *, const char *);
+void Vect__reallocate_cache(struct Format_info_cache *, int, int);
 
 /* write_pg.c */
 off_t V2__write_node_pg(struct Map_info *, const struct line_pnts *);

+ 5 - 6
lib/vector/Vlib/read_pg.c

@@ -53,7 +53,6 @@ static int geometry_collection_from_wkb(const unsigned char *, int, int, int,
                                         struct Format_info_cache *,
                                         struct feat_parts *);
 static int error_corrupted_data(const char *);
-static void reallocate_cache(struct Format_info_cache *, int, int);
 static void add_fpart(struct feat_parts *, SF_FeatureType, int, int);
 static int get_centroid(struct Map_info *, int, struct line_pnts *);
 static void error_tuples(struct Format_info_pg *);
@@ -840,11 +839,11 @@ SF_FeatureType Vect__cache_feature_pg(const char *data, int skip_polygon,
        or geometry collections
      */
     if (cache->ctype == CACHE_MAP) {
-        reallocate_cache(cache, 1, TRUE);
+        Vect__reallocate_cache(cache, 1, TRUE);
     }
     else {
         if (!cache->lines) {
-            reallocate_cache(cache, 1, FALSE);
+            Vect__reallocate_cache(cache, 1, FALSE);
         }
     }
     
@@ -1051,7 +1050,7 @@ int polygon_from_wkb(const unsigned char *wkb_data, int nbytes,
     }
 
     /* reallocate space for islands if needed */
-    reallocate_cache(cache, *nrings, FALSE);
+    Vect__reallocate_cache(cache, *nrings, FALSE);
     cache->lines_num += *nrings;
 
     /* each ring has a minimum of 4 bytes (point count) */
@@ -1135,7 +1134,7 @@ int geometry_collection_from_wkb(const unsigned char *wkb_data, int nbytes,
         nbytes -= data_offset;
 
     /* reallocate space for parts if needed */
-    reallocate_cache(cache, nparts, FALSE);
+    Vect__reallocate_cache(cache, nparts, FALSE);
 
     /* get parts */
     for (ipart = 0; ipart < nparts; ipart++) {
@@ -1543,7 +1542,7 @@ int Vect__execute_get_value_pg(PGconn *conn, const char *stmt)
 /*!
    \brief Reallocate lines cache
  */
-void reallocate_cache(struct Format_info_cache *cache, int num, int incr)
+void Vect__reallocate_cache(struct Format_info_cache *cache, int num, int incr)
 {
     int i;
 

+ 53 - 16
lib/vector/Vlib/write_pg.c

@@ -70,6 +70,7 @@ static int add_line_to_topo_pg(struct Map_info *, off_t, int, const struct line_
 static int delete_line_from_topo_pg(struct Map_info *, int, int, const struct line_pnts *);
 static int set_constraint_to_deferrable(struct Format_info_pg *, const char *, const char *,
                                         const char *, const char *, const char *);
+static dbDriver *open_db(struct Format_info_pg *, const struct field_info *);
 #endif
 
 static struct line_pnts *Points;
@@ -579,27 +580,16 @@ int create_table(struct Format_info_pg *pg_info, const struct field_info *Fi)
         const char *colname;
 
         dbString dbtable_name;
-        dbHandle handle;
+
         dbDriver *driver;
         dbTable *table;
         dbColumn *column;
 
         db_init_string(&dbtable_name);
-        db_init_handle(&handle);
 
-        pg_info->dbdriver = driver = db_start_driver(Fi->driver);
-        if (!driver) {
-            G_warning(_("Unable to start driver <%s>"), Fi->driver);
+        driver = open_db(pg_info, Fi);
+        if (driver == NULL)
             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(&dbtable_name, Fi->table);
@@ -1314,6 +1304,8 @@ off_t write_line_tp(struct Map_info *Map, int type, int is_node,
             /* check for attributes */
             Fi = Vect_get_dblink(Map, 0);
             if (Fi) {
+                if (!pg_info->dbdriver)
+                    open_db(pg_info, Fi);
                 if (!Vect_cat_get(cats, Fi->number, &cat))
                     G_warning(_("No category defined for layer %d"), Fi->number);
                 if (cats->n_cats > 1) {
@@ -1360,6 +1352,14 @@ off_t write_line_tp(struct Map_info *Map, int type, int is_node,
         return -1;
     }
 
+    if (pg_info->cache.ctype == CACHE_MAP) {
+        /* add line to the cache */
+        Vect__reallocate_cache(&(pg_info->cache), 1, TRUE);
+        pg_info->cache.lines[line-1] = Vect_new_line_struct();
+        pg_info->cache.lines_types[line-1] = type;
+        pg_info->cache.lines_cats[line-1] = cat;
+   }
+
     /* update offset array for nodes */    
     if (is_node) {
         int node;
@@ -1885,7 +1885,9 @@ char *build_insert_stmt(const struct Format_info_pg *pg_info,
     }
 
     stmt = NULL;
-    if (Fi && cat > -1) { /* write attributes (simple features and topology elements) */
+    if (Fi && strcmp(pg_info->table_name, Fi->table) != 0 && /* skip PostGIS Topology in write mode */
+        cat > -1) {
+        /* write attributes (simple features and topology elements) */
         int col, ncol, more;
         int sqltype, ctype, is_fid;
         char buf_val[DB_SQL_MAX], buf_tmp[DB_SQL_MAX];
@@ -1906,7 +1908,7 @@ char *build_insert_stmt(const struct Format_info_pg *pg_info,
                 cat);
         G_debug(4, "SQL: %s", buf);
         db_set_string(&dbstmt, buf);
-
+        
         /* prepare INSERT statement */
         sprintf(buf, "INSERT INTO \"%s\".\"%s\" (",
                 pg_info->schema_name, pg_info->table_name);
@@ -2731,6 +2733,9 @@ int delete_line_from_topo_pg(struct Map_info *Map, int line, int type,
     
     Vect_reset_updated(Map);
 
+    if (!(type & GV_LINES))
+        return 0;
+
     Vect_get_line_nodes(Map, line, &N1, &N2);
     if (0 != V2__delete_line_from_topo_nat(Map, line, type, Points, NULL))
         return -1;
@@ -2788,4 +2793,36 @@ int set_constraint_to_deferrable(struct Format_info_pg *pg_info,
 
     return 0;
 }
+
+/*!
+  \brief Open database connection with attribute table
+
+  \param pg_info pointer to Format_info_pg struct
+  \param Fi pointer to field_info struct 
+
+  \return pointer to dbDriver on succes
+  \return NULL on failure
+*/
+dbDriver *open_db(struct Format_info_pg *pg_info, const struct field_info *Fi) {
+    dbDriver *driver;
+    dbHandle handle;
+    
+    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 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);
+        pg_info->dbdriver = NULL;
+        return NULL;
+    }
+
+    return pg_info->dbdriver;
+}
 #endif