[GRASS-SVN] r58290 - in grass/trunk: include/vect lib/vector/Vlib
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Nov 24 08:26:40 PST 2013
Author: martinl
Date: 2013-11-24 08:26:40 -0800 (Sun, 24 Nov 2013)
New Revision: 58290
Modified:
grass/trunk/include/vect/dig_structs.h
grass/trunk/lib/vector/Vlib/area.c
grass/trunk/lib/vector/Vlib/build_pg.c
grass/trunk/lib/vector/Vlib/close.c
grass/trunk/lib/vector/Vlib/close_ogr.c
grass/trunk/lib/vector/Vlib/close_pg.c
grass/trunk/lib/vector/Vlib/local_proto.h
grass/trunk/lib/vector/Vlib/open_pg.c
grass/trunk/lib/vector/Vlib/pg_local_proto.h
grass/trunk/lib/vector/Vlib/read_pg.c
grass/trunk/lib/vector/Vlib/rewind_pg.c
Log:
vlib/pg: speed up PostGIS Topology by caching lines (experimental, work in progress)
Modified: grass/trunk/include/vect/dig_structs.h
===================================================================
--- grass/trunk/include/vect/dig_structs.h 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/include/vect/dig_structs.h 2013-11-24 16:26:40 UTC (rev 58290)
@@ -465,8 +465,13 @@
/*!
\brief Lines array
- Some features requires more allocated lines (eg. polygon
+ Some simple features require more allocated lines (eg. polygon
with more rings, multipoint, or geometrycollection)
+
+ Line cache is also used for PostGIS Topology to store single
+ topological element (ctype == CACHE_FEATURE) or all elements
+ from the map (ctype == CACHE_MAP) to avoid random access which
+ is very costly.
*/
struct line_pnts **lines;
/*!
@@ -497,6 +502,12 @@
\brief Simple feature type (currently used only by PG format)
*/
SF_FeatureType sf_type;
+ /*!
+ \brief Cache type
+
+ Currenly used only by PostGIS Topology which allows to cache the
+ whole map (CACHE_MAP) */
+ int ctype;
};
/*!
Modified: grass/trunk/lib/vector/Vlib/area.c
===================================================================
--- grass/trunk/lib/vector/Vlib/area.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/area.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -85,7 +85,8 @@
G_debug(3, " n_lines = %d", Isle->n_lines);
if (Map->format == GV_FORMAT_POSTGIS &&
- Map->fInfo.pg.toposchema_name) {
+ Map->fInfo.pg.toposchema_name &&
+ Map->fInfo.pg.cache.ctype != CACHE_MAP) {
#ifdef HAVE_POSTGRES
/* PostGIS Topology */
return Vect__get_area_points_pg(Map, Isle->lines, Isle->n_lines, BPoints);
@@ -456,7 +457,8 @@
struct line_pnts *BPoints)
{
if (Map->format == GV_FORMAT_POSTGIS &&
- Map->fInfo.pg.toposchema_name) {
+ Map->fInfo.pg.toposchema_name &&
+ Map->fInfo.pg.cache.ctype != CACHE_MAP) {
#ifdef HAVE_POSTGRES
/* PostGIS Topology */
return Vect__get_area_points_pg(Map, lines, n_lines, BPoints);
Modified: grass/trunk/lib/vector/Vlib/build_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build_pg.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/build_pg.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -547,8 +547,10 @@
const struct Format_info_offset *offset;
offset = &(pg_info->offset);
- if (plus->n_nodes != offset->array_num)
+ if (plus->n_nodes != offset->array_num) {
+ G_warning(_("Unable to write nodes, offset array mismatch"));
return -1;
+ }
stmt_size = 2 * DB_SQL_MAX + 512;
stmt = (char *) G_malloc(stmt_size);
@@ -575,6 +577,7 @@
"%d, '{%s}', '{%s}')", pg_info->toposchema_name, TOPO_TABLE_NODE,
node_id, stmt_lines, stmt_angles);
if (Vect__execute_pg(pg_info->conn, stmt) == -1) {
+ G_warning(_("Unable to write nodes"));
return -1;
}
}
Modified: grass/trunk/lib/vector/Vlib/close.c
===================================================================
--- grass/trunk/lib/vector/Vlib/close.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/close.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -292,6 +292,21 @@
return 1;
}
+/*! Free memory of line cache
+
+ \param cache pointer to lines cache to be freed
+*/
+void Vect__free_cache(struct Format_info_cache *cache) {
+ int i;
+ /* destroy lines in cache */
+ for (i = 0; i < cache->lines_alloc; i++) {
+ Vect_destroy_line_struct(cache->lines[i]);
+ }
+ G_free(cache->lines);
+ G_free(cache->lines_types);
+ G_free(cache->lines_cats);
+}
+
void unlink_file(const struct Map_info *Map, const char *name)
{
char *path;
Modified: grass/trunk/lib/vector/Vlib/close_ogr.c
===================================================================
--- grass/trunk/lib/vector/Vlib/close_ogr.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/close_ogr.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -22,6 +22,8 @@
#include <ogr_api.h>
#endif
+#include "local_proto.h"
+
/*!
\brief Close vector map (OGR dsn & layer) on level 1
@@ -33,8 +35,6 @@
int V1_close_ogr(struct Map_info *Map)
{
#ifdef HAVE_OGR
- int i;
-
struct Format_info_ogr *ogr_info;
G_debug(3, "V1_close_ogr() name = %s mapset = %s", Map->name, Map->mapset);
@@ -58,14 +58,9 @@
/* destroy OGR datasource */
OGR_DS_Destroy(ogr_info->ds);
+
+ Vect__free_cache(&(ogr_info->cache));
- /* destroy lines in cache */
- for (i = 0; i < ogr_info->cache.lines_alloc; i++) {
- Vect_destroy_line_struct(ogr_info->cache.lines[i]);
- }
- G_free(ogr_info->cache.lines);
- G_free(ogr_info->cache.lines_types);
-
/* close DB connection (for atgtributes) */
if (ogr_info->dbdriver) {
db_close_database_shutdown_driver(ogr_info->dbdriver);
Modified: grass/trunk/lib/vector/Vlib/close_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/close_pg.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/close_pg.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -19,6 +19,8 @@
#include <grass/dbmi.h>
#include <grass/glocale.h>
+#include "local_proto.h"
+
#ifdef HAVE_POSTGRES
#include "pg_local_proto.h"
#endif
@@ -34,7 +36,6 @@
int V1_close_pg(struct Map_info *Map)
{
#ifdef HAVE_POSTGRES
- int i;
struct Format_info_pg *pg_info;
G_debug(3, "V2_close_pg() name = %s mapset = %s", Map->name, Map->mapset);
@@ -77,13 +78,8 @@
db_close_database_shutdown_driver(pg_info->dbdriver);
}
- /* free allocated space */
- for (i = 0; i < pg_info->cache.lines_alloc; i++) {
- Vect_destroy_line_struct(pg_info->cache.lines[i]);
- }
- if (pg_info->cache.lines)
- G_free(pg_info->cache.lines);
-
+ Vect__free_cache(&(pg_info->cache));
+
G_free(pg_info->db_name);
G_free(pg_info->schema_name);
G_free(pg_info->geom_column);
Modified: grass/trunk/lib/vector/Vlib/local_proto.h
===================================================================
--- grass/trunk/lib/vector/Vlib/local_proto.h 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/local_proto.h 2013-11-24 16:26:40 UTC (rev 58290)
@@ -10,6 +10,9 @@
int Vect__get_area_points(const struct Map_info *, const plus_t *, int, struct line_pnts *);
int Vect__get_area_points_nat(const struct Map_info *, const plus_t *, int, struct line_pnts *);
+/* close.c */
+void Vect__free_cache(struct Format_info_cache *);
+
/* map.c */
int Vect__delete(const char *, int);
Modified: grass/trunk/lib/vector/Vlib/open_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/open_pg.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/open_pg.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -20,11 +20,14 @@
#include <grass/dbmi.h>
#include <grass/glocale.h>
+#include "local_proto.h"
+
#ifdef HAVE_POSTGRES
#include "pg_local_proto.h"
-struct edge_data {
+struct line_data {
int id;
+ int fid;
int start_node;
int end_node;
int left_face;
@@ -42,7 +45,7 @@
const char *, const char *, const char *,
struct Format_info_pg *);
static struct P_line *read_p_line(struct Plus_head *, int,
- const struct edge_data *,
+ const struct line_data *,
struct Format_info_cache *);
static struct P_area *read_p_area(struct Plus_head *, int,
const char *, int, const char *);
@@ -52,7 +55,8 @@
static void notice_processor(void *, const char *);
static char **scan_array(const char *);
static int remap_node(const struct Format_info_offset *, int);
-static int remap_line(const struct Plus_head*, int, int);
+static int remap_line(const struct Plus_head*, off_t, int);
+static void reset_cache(struct Format_info_cache *);
#endif
/*!
@@ -137,7 +141,7 @@
if (!found) {
G_warning(_("Feature table <%s> not found in 'geometry_columns'"),
pg_info->table_name);
- return -1;
+ return 0; /* avoid calling G_fatal_error() */
}
/* check for topo schema */
@@ -805,10 +809,10 @@
\return NULL on error
*/
struct P_line *read_p_line(struct Plus_head *plus, int n,
- const struct edge_data *data,
+ const struct line_data *data,
struct Format_info_cache *cache)
{
- int tp, itype;
+ int tp;
struct P_line *line;
struct line_pnts *points;
@@ -875,14 +879,10 @@
}
}
- /* update spatial index */
- Vect__cache_feature_pg(data->wkb_geom, FALSE, FALSE, cache, NULL);
- itype = cache->lines_types[0];
- if ((line->type & GV_POINTS && itype != GV_POINT) ||
- (line->type & GV_LINES && itype != GV_LINE))
- G_warning(_("Inconsistency in topology: line %d - unexpected feature type"), n);
-
- points = cache->lines[0];
+ Vect__cache_feature_pg(data->wkb_geom, FALSE, tp, cache, NULL);
+ cache->lines_cats[cache->lines_num-1] = data->fid > 0 ? data->fid : -1;
+
+ points = cache->lines[cache->lines_num-1];
dig_line_box(points, &box);
dig_spidx_add_line(plus, n, &box);
@@ -949,7 +949,7 @@
/* set centroid */
area->centroid = remap_line(plus, centroid, GV_CENTROID);
-
+
G_free_tokens(lines);
G_free_tokens(isles);
@@ -1194,7 +1194,7 @@
{
int i, side, line, id, ntuples;
char stmt[DB_SQL_MAX];
- struct edge_data line_data;
+ struct line_data line_data;
struct Format_info_pg *pg_info;
struct Format_info_offset *offset;
@@ -1217,7 +1217,7 @@
Points = Vect_new_line_struct();
List = Vect_new_list();
-
+
/* read nodes (GRASS Topo)
note: standalone nodes (ie. points/centroids) are ignored
*/
@@ -1276,18 +1276,25 @@
*/
if (pg_info->topo_geo_only)
sprintf(stmt,
- "SELECT node_id,geom FROM \"%s\".node WHERE containing_face "
+ "SELECT tt.node_id,tt.geom,ft.%s FROM \"%s\".node AS tt "
+ "LEFT JOIN \"%s\" AS ft ON "
+ "(%s).type = 1 AND (%s).id = node_id WHERE containing_face "
"IS NULL AND node_id NOT IN "
"(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
"GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
"\"%s\".edge GROUP BY end_node) AS foo) ORDER BY node_id",
- pg_info->toposchema_name, pg_info->toposchema_name,
+ "fid", pg_info->toposchema_name, pg_info->table_name,
+ pg_info->topogeom_column, pg_info->topogeom_column, pg_info->toposchema_name,
pg_info->toposchema_name);
else
sprintf(stmt,
- "SELECT node.node_id,geom FROM \"%s\".node AS node WHERE node_id NOT IN "
+ "SELECT tt.node_id,tt.geom,ft.%s "
+ "FROM \"%s\".node AS tt LEFT JOIN \"%s\" AS ft ON "
+ "(%s).type = 1 AND (%s).id = node_id WHERE node_id NOT IN "
"(SELECT node_id FROM \"%s\".%s) AND containing_face IS NULL ORDER BY node_id",
- pg_info->toposchema_name, pg_info->toposchema_name, TOPO_TABLE_NODE);
+ "fid", pg_info->toposchema_name, pg_info->table_name,
+ pg_info->topogeom_column, pg_info->topogeom_column,
+ pg_info->toposchema_name, TOPO_TABLE_NODE);
G_debug(2, "SQL: %s", stmt);
res = PQexec(pg_info->conn, stmt);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
@@ -1300,12 +1307,17 @@
return -1;
}
+ reset_cache(&(pg_info->cache));
+ pg_info->cache.ctype = CACHE_MAP; /* experimental - cache all features */
+
ntuples = PQntuples(res); /* plus->n_plines */
- G_zero(&line_data, sizeof(struct edge_data));
+ G_zero(&line_data, sizeof(struct line_data));
for (i = 0; i < ntuples; i++) {
/* process standalone nodes (PostGIS Topo) */
line_data.id = atoi(PQgetvalue(res, i, 0));
line_data.wkb_geom = (char *) PQgetvalue(res, i, 1);
+ line_data.fid = atoi(PQgetvalue(res, i, 2)); /* feature id */
+
read_p_line(plus, i + 1, &line_data, &(pg_info->cache));
}
PQclear(res);
@@ -1314,10 +1326,12 @@
-> lines
-> boundaries
*/
- sprintf(stmt,
- "SELECT edge_id,start_node,end_node,left_face,right_face,geom "
- "FROM \"%s\".edge ORDER BY edge_id",
- pg_info->toposchema_name);
+ sprintf(stmt, /* fix fid column */
+ "SELECT edge_id,start_node,end_node,left_face,right_face,tt.geom,ft.%s "
+ "FROM \"%s\".edge AS tt LEFT JOIN \"%s\" AS ft ON (%s).type = 2 AND "
+ "(%s).id = edge_id ORDER BY edge_id",
+ "fid", pg_info->toposchema_name, pg_info->table_name,
+ pg_info->topogeom_column, pg_info->topogeom_column);
G_debug(2, "SQL: %s", stmt);
res = PQexec(pg_info->conn, stmt);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
@@ -1339,7 +1353,8 @@
line_data.left_face = atoi(PQgetvalue(res, i, 3));
line_data.right_face = atoi(PQgetvalue(res, i, 4));
line_data.wkb_geom = (char *) PQgetvalue(res, i, 5);
-
+ line_data.fid = atoi(PQgetvalue(res, i, 6)); /* feature id */
+
id = plus->n_plines + i + 1; /* points already registered */
read_p_line(plus, id, &line_data, &(pg_info->cache));
/* TODO: update category index */
@@ -1351,19 +1366,27 @@
*/
if (pg_info->topo_geo_only)
sprintf(stmt,
- "SELECT node_id,geom,containing_face FROM \"%s\".node WHERE containing_face "
+ "SELECT node_id,tt.geom,containing_face,ft.%s FROM "
+ "\"%s\".node AS tt LEFT JOIN \"%s\" AS ft ON "
+ "(%s).type = 3 AND (%s).id = containing_face WHERE containing_face"
"IS NOT NULL AND node_id NOT IN "
"(SELECT node FROM (SELECT start_node AS node FROM \"%s\".edge "
"GROUP BY start_node UNION ALL SELECT end_node AS node FROM "
"\"%s\".edge GROUP BY end_node) AS foo) ORDER BY node_id",
- pg_info->toposchema_name, pg_info->toposchema_name,
+ "fid", pg_info->toposchema_name, pg_info->table_name,
+ pg_info->topogeom_column, pg_info->topogeom_column,
+ pg_info->toposchema_name,
pg_info->toposchema_name);
else
sprintf(stmt,
- "SELECT node.node_id,geom,containing_face FROM \"%s\".node AS node WHERE "
+ "SELECT tt.node_id,tt.geom,containing_face,ft.%s FROM "
+ "\"%s\".node AS tt LEFT JOIN \"%s\" AS ft ON "
+ "(%s).type = 3 AND (%s).id = containing_face WHERE "
"node_id NOT IN (SELECT node_id FROM \"%s\".%s) AND containing_face "
"IS NOT NULL ORDER BY node_id",
- pg_info->toposchema_name, pg_info->toposchema_name, TOPO_TABLE_NODE);
+ "fid", pg_info->toposchema_name, pg_info->table_name,
+ pg_info->topogeom_column, pg_info->topogeom_column,
+ pg_info->toposchema_name, TOPO_TABLE_NODE);
G_debug(2, "SQL: %s", stmt);
res = PQexec(pg_info->conn, stmt);
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
@@ -1376,12 +1399,13 @@
return -1;
}
- G_zero(&line_data, sizeof(struct edge_data));
+ G_zero(&line_data, sizeof(struct line_data));
id = plus->n_plines + plus->n_llines + plus->n_blines + 1;
for (i = 0; i < plus->n_clines; i++) {
line_data.id = atoi(PQgetvalue(res, i, 0));
line_data.wkb_geom = (char *)PQgetvalue(res, i, 1);
line_data.left_face = atoi(PQgetvalue(res, i, 2)); /* face id */
+ line_data.fid = atoi(PQgetvalue(res, i, 3)); /* feature id */
/* area id and face id can be different */
read_p_line(plus, id + i, &line_data, &(pg_info->cache));
@@ -1431,6 +1455,12 @@
for (i = 0; i < plus->n_areas; i++) {
read_p_area(plus, i + 1, (char *)PQgetvalue(res, i, 1),
atoi(PQgetvalue(res, i, 2)), (char *)PQgetvalue(res, i, 3));
+
+ /* update spatial index -- needed ?
+ Vect_get_area_points(Map, i+1, Points);
+ dig_line_box(Points, &box);
+ dig_spidx_add_area(&(Map->plus), i+1, &box);
+ */
}
PQclear(res);
}
@@ -1463,6 +1493,12 @@
for (i = 0; i < plus->n_isles; i++) {
read_p_isle(plus, i + 1, (char *)PQgetvalue(res, i, 1),
atoi(PQgetvalue(res, i, 2)));
+
+ /* update spatial index -- needed ?
+ Vect_get_isle_points(Map, i+1, Points);
+ dig_line_box(Points, &box);
+ dig_spidx_add_isle(&(Map->plus), i+1, &box);
+ */
}
PQclear(res);
}
@@ -1544,8 +1580,6 @@
/*!
\brief Get node id from offset
- \todo speed up
-
\param offset pointer to Format_info_offset struct
\param node node to find
@@ -1554,44 +1588,53 @@
*/
int remap_node(const struct Format_info_offset *offset, int node)
{
+ /* probably not needed
int i;
-
- for (i = 0; i < offset->array_num; i++) {
+ for (i = node-1; i < offset->array_num; i++) {
if (offset->array[i] == node)
- return i + 1; /* node id starts at 1 */
+ return i + 1;
}
+
+ return -1;
+ */
- return -1;
+ return offset->array[node-1];
}
/*!
\brief Get line id from offset
- \todo Do it better, speed up
-
\param plus pointer to Plus_head struct
- \param line line to find
+ \param offset line offset
\param type line type
\return line id
\return -1 not found
*/
-int remap_line(const struct Plus_head* plus, int line, int type)
+int remap_line(const struct Plus_head* plus, off_t offset, int type)
{
int i;
struct P_line *Line;
- for (i = 1; i <= plus->n_lines; i++) {
+ for (i = (int) offset; i <= plus->n_lines; i++) {
Line = plus->Line[i];
if (!Line || Line->type != type)
continue;
- if ((int) Line->offset == line)
+ if ((int) Line->offset == offset)
return i;
}
return -1;
}
+
+/*! Reset lines cache */
+void reset_cache(struct Format_info_cache *cache)
+{
+ Vect__free_cache(cache);
+ G_zero(cache, sizeof(struct Format_info_cache));
+ cache->fid = -1;
+}
#endif
Modified: grass/trunk/lib/vector/Vlib/pg_local_proto.h
===================================================================
--- grass/trunk/lib/vector/Vlib/pg_local_proto.h 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/pg_local_proto.h 2013-11-24 16:26:40 UTC (rev 58290)
@@ -8,6 +8,9 @@
#define CURSOR_PAGE 500
+#define CACHE_FEATURE 0
+#define CACHE_MAP 1
+
/*! Topological access */
#define TOPO_SCHEMA "topology"
#define TOPO_ID "topology_id"
Modified: grass/trunk/lib/vector/Vlib/read_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/read_pg.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/read_pg.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -51,7 +51,7 @@
struct Format_info_cache *,
struct feat_parts *);
static int error_corrupted_data(const char *);
-static void reallocate_cache(struct Format_info_cache *, int);
+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 *);
@@ -319,7 +319,7 @@
struct line_cats *line_c, int line)
{
#ifdef HAVE_POSTGRES
- int fid;
+ int fid, cache_idx;
struct Format_info_pg *pg_info;
struct P_line *Line;
@@ -357,8 +357,18 @@
fid = pg_info->offset.array[Line->offset];
/* read feature */
- get_feature(pg_info, fid, Line->type);
-
+ if (pg_info->cache.ctype == CACHE_MAP) {
+ cache_idx = line - 1;
+
+ if (pg_info->cache.lines_types[cache_idx] != Line->type)
+ G_warning(_("Feature %d: unexpected type (%d) - should be %d"),
+ line, pg_info->cache.lines_types[cache_idx], Line->type);
+ }
+ else {
+ get_feature(pg_info, fid, Line->type);
+ cache_idx = 0;
+ }
+
/* check sf type */
if (pg_info->cache.sf_type == SF_NONE) {
G_warning(_("Feature %d without geometry skipped"), line);
@@ -371,16 +381,31 @@
int cat;
Vect_reset_cats(line_c);
- if (!pg_info->toposchema_name) /* simple features access */
+ if (!pg_info->toposchema_name) { /* simple features access */
cat = (int) Line->offset;
- else /* PostGIS Topology (cats are cached) */
- cat = pg_info->cache.lines_cats[0];
- if (cat != -1)
+ }
+ else { /* PostGIS Topology (cats are cached) */
+ cat = pg_info->cache.lines_cats[cache_idx];
+ if (cat == 0) { /* not cached yet */
+ int col_idx;
+
+ Vect__select_line_pg(pg_info, fid, Line->type);
+
+ col_idx = Line->type & GV_POINTS ? 2 : 3;
+
+ if (!PQgetisnull(pg_info->res, 0, col_idx))
+ cat = pg_info->cache.lines_cats[cache_idx] =
+ atoi(PQgetvalue(pg_info->res, 0, col_idx));
+ else
+ pg_info->cache.lines_cats[cache_idx] = -1; /* no cat */
+ }
+ }
+ if (cat > 0)
Vect_cat_set(line_c, 1, cat);
}
if (line_p)
- Vect_append_points(line_p, pg_info->cache.lines[0], GV_FORWARD);
+ Vect_append_points(line_p, pg_info->cache.lines[cache_idx], GV_FORWARD);
return Line->type;
#else
@@ -428,7 +453,8 @@
Vect_reset_cats(line_c);
/* read feature to cache if necessary */
- while (pg_info->cache.lines_next == pg_info->cache.lines_num) {
+ while (pg_info->cache.ctype != CACHE_MAP &&
+ pg_info->cache.lines_next == pg_info->cache.lines_num) {
/* cache feature -> line_p & line_c */
sf_type = get_feature(pg_info, -1, -1);
@@ -480,11 +506,24 @@
if (line_c) {
int cat;
- if (!pg_info->toposchema_name) /* simple features access */
+ if (!pg_info->toposchema_name) { /* simple features access */
cat = (int)pg_info->cache.fid;
- else /* PostGIS Topology (cats are cached) */
+ }
+ else { /* PostGIS Topology (cats are cached) */
cat = pg_info->cache.lines_cats[pg_info->cache.lines_next];
- if (cat != -1)
+ if (cat == 0) { /* not cached yet */
+ int col_idx;
+
+ col_idx = itype & GV_POINTS ? 2 : 3;
+
+ if (!PQgetisnull(pg_info->res, pg_info->cache.lines_next, col_idx))
+ cat = pg_info->cache.lines_cats[Map->next_line-1] =
+ atoi(PQgetvalue(pg_info->res, pg_info->cache.lines_next, col_idx));
+ else
+ pg_info->cache.lines_cats[Map->next_line-1] = -1; /* no cat */
+ }
+ }
+ if (cat > 0)
Vect_cat_set(line_c, 1, cat);
}
@@ -663,8 +702,7 @@
*nbytes = length - 1;
for (i = 0; i < (*nbytes); i++) {
wkb_data[i] =
- (unsigned
- char)((hex_data[2 * i] >
+ (unsigned char)((hex_data[2 * i] >
'F' ? hex_data[2 * i] - 0x57 : hex_data[2 * i] >
'9' ? hex_data[2 * i] - 0x37 : hex_data[2 * i] -
0x30) << 4);
@@ -707,7 +745,10 @@
SF_FeatureType ftype;
/* reset cache */
- cache->lines_num = 0;
+ if (cache->ctype == CACHE_MAP)
+ cache->lines_num++;
+ else
+ cache->lines_num = 1;
cache->fid = -1;
/* next to be read from cache */
cache->lines_next = 0;
@@ -782,28 +823,32 @@
more lines require eg. polygon with more rings, multi-features
or geometry collections
*/
- if (!cache->lines) {
- reallocate_cache(cache, 1);
+ if (cache->ctype == CACHE_MAP) {
+ reallocate_cache(cache, 1, TRUE);
}
-
+ else {
+ if (!cache->lines) {
+ reallocate_cache(cache, 1, FALSE);
+ }
+ }
+
ret = -1;
if (ftype == SF_POINT) {
- cache->lines_num = 1;
- cache->lines_types[0] = force_type == GV_CENTROID ? force_type : GV_POINT;
+ cache->lines_types[cache->lines_num-1] = force_type == GV_CENTROID ? force_type : GV_POINT;
ret = point_from_wkb(wkb_data, nbytes, byte_order,
- is3D, cache->lines[0]);
+ is3D, cache->lines[cache->lines_num-1]);
add_fpart(fparts, ftype, 0, 1);
}
else if (ftype == SF_LINESTRING) {
- cache->lines_num = 1;
- cache->lines_types[0] = force_type == GV_BOUNDARY ? force_type : GV_LINE;
+ cache->lines_types[cache->lines_num-1] = force_type == GV_BOUNDARY ? force_type : GV_LINE;
ret = linestring_from_wkb(wkb_data, nbytes, byte_order,
- is3D, cache->lines[0], FALSE);
+ is3D, cache->lines[cache->lines_num-1], FALSE);
add_fpart(fparts, ftype, 0, 1);
}
else if (ftype == SF_POLYGON && !skip_polygon) {
int nrings;
+ cache->lines_num = 0; /* reset before reading rings */
ret = polygon_from_wkb(wkb_data, nbytes, byte_order,
is3D, cache, &nrings);
add_fpart(fparts, ftype, 0, nrings);
@@ -988,7 +1033,7 @@
}
/* reallocate space for islands if needed */
- reallocate_cache(cache, *nrings);
+ reallocate_cache(cache, *nrings, FALSE);
cache->lines_num += *nrings;
/* each ring has a minimum of 4 bytes (point count) */
@@ -1072,7 +1117,7 @@
nbytes -= data_offset;
/* reallocate space for parts if needed */
- reallocate_cache(cache, nparts);
+ reallocate_cache(cache, nparts, FALSE);
/* get parts */
for (ipart = 0; ipart < nparts; ipart++) {
@@ -1476,14 +1521,14 @@
/*!
\brief Reallocate lines cache
*/
-void reallocate_cache(struct Format_info_cache *cache, int num)
+void reallocate_cache(struct Format_info_cache *cache, int num, int incr)
{
int i;
- if (cache->lines_alloc >= num)
+ if (!incr && cache->lines_alloc >= num)
return;
- if (!cache->lines) {
+ if (!incr && !cache->lines) {
/* most of features requires only one line cache */
cache->lines_alloc = 1;
}
Modified: grass/trunk/lib/vector/Vlib/rewind_pg.c
===================================================================
--- grass/trunk/lib/vector/Vlib/rewind_pg.c 2013-11-24 15:46:40 UTC (rev 58289)
+++ grass/trunk/lib/vector/Vlib/rewind_pg.c 2013-11-24 16:26:40 UTC (rev 58290)
@@ -42,7 +42,9 @@
pg_info->next_line = 0;
/* reset cache */
- pg_info->cache.lines_num = pg_info->cache.lines_next = 0;
+ if (pg_info->cache.ctype != CACHE_MAP)
+ pg_info->cache.lines_num = 0;
+ pg_info->cache.lines_next = 0;
pg_info->cache.fid = -1;
/* close DB cursor if necessary */
More information about the grass-commit
mailing list