mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-23 08:32:42 +00:00
Improve query performance in cb_getEdgeByFace
Avoids 1 output and 1 parse calls for hexwkb, 2 output and parse calls for integer arrays. Was found reducing runtime from 16 seconds to 10 seconds for adding a single polygon with a large shell and 129 holes to an empty topology. git-svn-id: http://svn.osgeo.org/postgis/trunk@14926 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
parent
78020c81ad
commit
133dd71def
|
@ -14,6 +14,8 @@
|
|||
#include "fmgr.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/memutils.h" /* for TopMemoryContext */
|
||||
#include "utils/array.h" /* for ArrayType */
|
||||
#include "catalog/pg_type.h" /* for INT4OID */
|
||||
#include "lib/stringinfo.h"
|
||||
#include "access/xact.h" /* for RegisterXactCallback */
|
||||
#include "funcapi.h" /* for FuncCallContext */
|
||||
|
@ -114,15 +116,13 @@ _lwtype_upper_name(int type, char *buf, size_t buflen)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return lwalloc'ed hexwkb representation for a GBOX */
|
||||
static char *
|
||||
_box2d_to_hexwkb(const GBOX *bbox, int srid)
|
||||
/* Return an lwalloc'ed geometrical representation of the box */
|
||||
static LWGEOM *
|
||||
_box2d_to_lwgeom(const GBOX *bbox, int srid)
|
||||
{
|
||||
POINTARRAY *pa = ptarray_construct(0, 0, 2);
|
||||
POINT4D p;
|
||||
LWLINE *line;
|
||||
char *hex;
|
||||
size_t sz;
|
||||
|
||||
p.x = bbox->xmin;
|
||||
p.y = bbox->ymin;
|
||||
|
@ -131,8 +131,18 @@ _box2d_to_hexwkb(const GBOX *bbox, int srid)
|
|||
p.y = bbox->ymax;
|
||||
ptarray_set_point4d(pa, 1, &p);
|
||||
line = lwline_construct(srid, NULL, pa);
|
||||
hex = lwgeom_to_hexwkb( lwline_as_lwgeom(line), WKT_EXTENDED, &sz);
|
||||
lwline_free(line);
|
||||
return lwline_as_lwgeom(line);
|
||||
}
|
||||
|
||||
/* Return lwalloc'ed hexwkb representation for a GBOX */
|
||||
static char *
|
||||
_box2d_to_hexwkb(const GBOX *bbox, int srid)
|
||||
{
|
||||
char *hex;
|
||||
size_t sz;
|
||||
LWGEOM *geom = _box2d_to_lwgeom(bbox, srid);
|
||||
hex = lwgeom_to_hexwkb(geom, WKT_EXTENDED, &sz);
|
||||
lwgeom_free(geom);
|
||||
assert(hex[sz-1] == '\0');
|
||||
return hex;
|
||||
}
|
||||
|
@ -872,34 +882,47 @@ cb_getEdgeByFace(const LWT_BE_TOPOLOGY* topo,
|
|||
StringInfoData sqldata;
|
||||
StringInfo sql = &sqldata;
|
||||
int i;
|
||||
char *hexbox;
|
||||
ArrayType *array_ids;
|
||||
Datum *datum_ids;
|
||||
Datum values[2];
|
||||
Oid argtypes[2];
|
||||
int nargs = 1;
|
||||
GSERIALIZED *gser = NULL;
|
||||
|
||||
datum_ids = palloc(sizeof(Datum)*(*numelems));
|
||||
for (i=0; i<*numelems; ++i) datum_ids[i] = Int32GetDatum(ids[i]);
|
||||
array_ids = construct_array(datum_ids, *numelems, INT4OID, 4, true, 's');
|
||||
|
||||
initStringInfo(sql);
|
||||
appendStringInfoString(sql, "SELECT ");
|
||||
addEdgeFields(sql, fields, 0);
|
||||
appendStringInfo(sql, " FROM \"%s\".edge_data", topo->name);
|
||||
appendStringInfoString(sql, " WHERE ( left_face IN (");
|
||||
// add all identifiers here
|
||||
for (i=0; i<*numelems; ++i) {
|
||||
appendStringInfo(sql, "%s%" LWTFMT_ELEMID, (i?",":""), ids[i]);
|
||||
}
|
||||
appendStringInfoString(sql, ") OR right_face IN (");
|
||||
// add all identifiers here
|
||||
for (i=0; i<*numelems; ++i) {
|
||||
appendStringInfo(sql, "%s%" LWTFMT_ELEMID, (i?",":""), ids[i]);
|
||||
}
|
||||
appendStringInfoString(sql, ") )");
|
||||
appendStringInfo(sql, " FROM \"%s\".edge_data"
|
||||
" WHERE ( left_face = ANY($1) "
|
||||
" OR right_face = ANY ($1) )",
|
||||
topo->name);
|
||||
|
||||
values[0] = PointerGetDatum(array_ids);
|
||||
argtypes[0] = INT4ARRAYOID;
|
||||
|
||||
if ( box )
|
||||
{
|
||||
hexbox = _box2d_to_hexwkb(box, topo->srid);
|
||||
appendStringInfo(sql, " AND geom && '%s'::geometry", hexbox);
|
||||
lwfree(hexbox);
|
||||
LWGEOM *g = _box2d_to_lwgeom(box, topo->srid);
|
||||
gser = geometry_serialize(g);
|
||||
lwgeom_free(g);
|
||||
appendStringInfo(sql, " AND geom && $2");
|
||||
|
||||
values[1] = PointerGetDatum(gser);
|
||||
argtypes[1] = topo->geometryOID;
|
||||
++nargs;
|
||||
}
|
||||
|
||||
POSTGIS_DEBUGF(1, "cb_getEdgeByFace query: %s", sql->data);
|
||||
POSTGIS_DEBUGF(1, "data_changed is %d", topo->be_data->data_changed);
|
||||
|
||||
spi_result = SPI_execute(sql->data, !topo->be_data->data_changed, 0);
|
||||
spi_result = SPI_execute_with_args(sql->data, nargs, argtypes, values, NULL,
|
||||
!topo->be_data->data_changed, 0);
|
||||
pfree(array_ids); /* not needed anymore */
|
||||
if ( gser ) pfree(gser); /* not needed anymore */
|
||||
MemoryContextSwitchTo( oldcontext ); /* switch back */
|
||||
if ( spi_result != SPI_OK_SELECT ) {
|
||||
cberror(topo->be_data, "unexpected return (%d) from query execution: %s", spi_result, sql->data);
|
||||
|
@ -2422,8 +2445,6 @@ cb_getFaceContainingPoint( const LWT_BE_TOPOLOGY* topo, const LWPOINT* pt )
|
|||
bool isnull;
|
||||
Datum dat;
|
||||
LWT_ELEMID face_id;
|
||||
size_t hexewkb_size;
|
||||
SPIPlanPtr plan;
|
||||
GSERIALIZED *pts;
|
||||
Datum values[1];
|
||||
Oid argtypes[1];
|
||||
|
|
Loading…
Reference in a new issue