Use CallerFInfoFunctionCallN infrastructure

Closes #4347


git-svn-id: http://svn.osgeo.org/postgis/trunk@17332 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Paul Ramsey 2019-03-11 17:58:07 +00:00
parent 0a4a7fa9bd
commit bf1c0826f9
4 changed files with 149 additions and 65 deletions

View file

@ -321,3 +321,101 @@ postgis_guc_find_option(const char *name)
return 1;
}
#if POSTGIS_PGSQL_VERSION < 100
Datum
CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1)
{
FunctionCallInfoData fcinfo;
Datum result;
InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
fcinfo.arg[0] = arg1;
fcinfo.argnull[0] = false;
result = (*func) (&fcinfo);
/* Check for null result, since caller is clearly not expecting one */
if (fcinfo.isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
}
Datum
CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
{
FunctionCallInfoData fcinfo;
Datum result;
InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
fcinfo.arg[0] = arg1;
fcinfo.arg[1] = arg2;
fcinfo.argnull[0] = false;
fcinfo.argnull[1] = false;
result = (*func) (&fcinfo);
/* Check for null result, since caller is clearly not expecting one */
if (fcinfo.isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
}
#else
#if POSTGIS_PGSQL_VERSION < 120
Datum
CallerFInfoFunctionCall3(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
{
FunctionCallInfoData fcinfo;
Datum result;
InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL);
fcinfo.arg[0] = arg1;
fcinfo.arg[1] = arg2;
fcinfo.arg[2] = arg3;
fcinfo.argnull[0] = false;
fcinfo.argnull[1] = false;
fcinfo.argnull[2] = false;
result = (*func) (&fcinfo);
/* Check for null result, since caller is clearly not expecting one */
if (fcinfo.isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
}
#else
/* PgSQL 12+ still lacks 3-argument version of these functions */
Datum
CallerFInfoFunctionCall3(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
{
LOCAL_FCINFO(fcinfo, 3);
Datum result;
InitFunctionCallInfoData(*fcinfo, flinfo, 3, collation, NULL, NULL);
fcinfo->args[0].value = arg1;
fcinfo->args[0].isnull = false;
fcinfo->args[1].value = arg2;
fcinfo->args[1].isnull = false;
fcinfo->args[2].value = arg3;
fcinfo->args[2].isnull = false;
result = (*func) (fcinfo);
/* Check for null result, since caller is clearly not expecting one */
if (fcinfo->isnull)
elog(ERROR, "function %p returned NULL", (void *) func);
return result;
}
#endif
#endif

View file

@ -189,4 +189,12 @@ void lwpgerror(const char *fmt, ...);
void lwpgnotice(const char *fmt, ...);
void lwpgwarning(const char *fmt, ...);
#if POSTGIS_PGSQL_VERSION < 100
Datum CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1);
Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2);
#endif
Datum CallerFInfoFunctionCall3(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3);
#endif /* !defined _LWGEOM_PG_H */

View file

@ -214,6 +214,8 @@ Datum geography_distance(PG_FUNCTION_ARGS)
/* Get our geometry objects loaded into memory. */
g1 = PG_GETARG_GSERIALIZED_P(0);
g2 = PG_GETARG_GSERIALIZED_P(1);
if (PG_NARGS() > 2)
use_spheroid = PG_GETARG_BOOL(2);
@ -266,14 +268,29 @@ Datum geography_distance(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT8(distance);
}
static bool
geography_dwithin_impl(FunctionCallInfo fcinfo, GSERIALIZED *g1, GSERIALIZED *g2, double tolerance, bool use_spheroid)
/*
** geography_dwithin(GSERIALIZED *g1, GSERIALIZED *g2, double tolerance, boolean use_spheroid)
** returns double distance in meters
*/
PG_FUNCTION_INFO_V1(geography_dwithin);
Datum geography_dwithin(PG_FUNCTION_ARGS)
{
double distance;
GSERIALIZED *g1 = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *g2 = PG_GETARG_GSERIALIZED_P(1);
SPHEROID s;
double tolerance = 0.0;
bool use_spheroid = true;
double distance;
int dwithin = LW_FALSE;
/* Read our tolerance value. */
if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
tolerance = PG_GETARG_FLOAT8(2);
/* Read our calculation type. */
if ( PG_NARGS() > 3 && ! PG_ARGISNULL(3) )
use_spheroid = PG_GETARG_BOOL(3);
error_if_srid_mismatch(gserialized_get_srid(g1), gserialized_get_srid(g2));
/* Initialize spheroid */
@ -285,7 +302,7 @@ geography_dwithin_impl(FunctionCallInfo fcinfo, GSERIALIZED *g1, GSERIALIZED *g2
/* Return FALSE on empty arguments. */
if ( gserialized_is_empty(g1) || gserialized_is_empty(g2) )
return false;
PG_RETURN_BOOL(false);
/* Do the brute force calculation if the cached calculation doesn't tick over */
if ( LW_FAILURE == geography_dwithin_cache(fcinfo, g1, g2, &s, tolerance, &dwithin) )
@ -301,32 +318,6 @@ geography_dwithin_impl(FunctionCallInfo fcinfo, GSERIALIZED *g1, GSERIALIZED *g2
lwgeom_free(lwgeom2);
}
return dwithin;
}
/*
** geography_dwithin(GSERIALIZED *g1, GSERIALIZED *g2, double tolerance, boolean use_spheroid)
** returns double distance in meters
*/
PG_FUNCTION_INFO_V1(geography_dwithin);
Datum geography_dwithin(PG_FUNCTION_ARGS)
{
GSERIALIZED *g1 = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *g2 = PG_GETARG_GSERIALIZED_P(1);
double tolerance = 0.0;
bool use_spheroid = true;
bool dwithin = false;
/* Read our tolerance value. */
if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
tolerance = PG_GETARG_FLOAT8(2);
/* Read our calculation type. */
if ( PG_NARGS() > 3 && ! PG_ARGISNULL(3) )
use_spheroid = PG_GETARG_BOOL(3);
dwithin = geography_dwithin_impl(fcinfo, g1, g2, tolerance, use_spheroid);
PG_FREE_IF_COPY(g1, 0);
PG_FREE_IF_COPY(g2, 1);
PG_RETURN_BOOL(dwithin);
@ -335,14 +326,9 @@ Datum geography_dwithin(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(geography_intersects);
Datum geography_intersects(PG_FUNCTION_ARGS)
{
GSERIALIZED *g1 = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *g2 = PG_GETARG_GSERIALIZED_P(1);
double tolerance = 0.0;
bool use_spheroid = true;
bool dwithin = geography_dwithin_impl(fcinfo, g1, g2, tolerance, use_spheroid);
PG_FREE_IF_COPY(g1, 0);
PG_FREE_IF_COPY(g2, 1);
PG_RETURN_BOOL(dwithin);
PG_RETURN_BOOL(CallerFInfoFunctionCall2(
geography_dwithin, fcinfo->flinfo, InvalidOid,
PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
}
/*

View file

@ -1598,20 +1598,23 @@ Datum overlaps(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(result);
}
static bool
containsImpl(FunctionCallInfo fcinfo, GSERIALIZED *geom1, GSERIALIZED *geom2)
PG_FUNCTION_INFO_V1(contains);
Datum contains(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
int result;
GEOSGeometry *g1, *g2;
GBOX box1, box2;
int result;
PrepGeomCache *prep_cache;
errorIfGeometryCollection(geom1,geom2);
errorIfGeometryCollection(geom1, geom2);
error_if_srid_mismatch(gserialized_get_srid(geom1), gserialized_get_srid(geom2));
/* A.Contains(Empty) == FALSE */
if ( gserialized_is_empty(geom1) || gserialized_is_empty(geom2) )
return false;
if (gserialized_is_empty(geom1) || gserialized_is_empty(geom2))
PG_RETURN_BOOL(false);
POSTGIS_DEBUG(3, "contains called.");
@ -1623,7 +1626,7 @@ containsImpl(FunctionCallInfo fcinfo, GSERIALIZED *geom1, GSERIALIZED *geom2)
gserialized_get_gbox_p(geom2, &box2))
{
if (!gbox_contains_2d(&box1, &box2))
return false;
PG_RETURN_BOOL(false);
}
/*
@ -1678,7 +1681,7 @@ containsImpl(FunctionCallInfo fcinfo, GSERIALIZED *geom1, GSERIALIZED *geom2)
{
/* Never get here */
elog(ERROR,"Type isn't point or multipoint!");
return false;
PG_RETURN_BOOL(false);
}
return retval > 0;
@ -1720,32 +1723,21 @@ containsImpl(FunctionCallInfo fcinfo, GSERIALIZED *geom1, GSERIALIZED *geom2)
if (result == 2) HANDLE_GEOS_ERROR("GEOSContains");
return result > 0;
PG_FREE_IF_COPY(geom1, 0);
PG_FREE_IF_COPY(geom2, 1);
PG_RETURN_BOOL(result > 0);
}
PG_FUNCTION_INFO_V1(contains);
Datum contains(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom0 = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(1);
bool result = containsImpl(fcinfo, geom0, geom1);
PG_FREE_IF_COPY(geom0, 0);
PG_FREE_IF_COPY(geom1, 1);
PG_RETURN_BOOL(result);
}
PG_FUNCTION_INFO_V1(within);
Datum within(PG_FUNCTION_ARGS)
{
GSERIALIZED *geom0 = PG_GETARG_GSERIALIZED_P(0);
GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(1);
bool result = containsImpl(fcinfo, geom1, geom0);
PG_FREE_IF_COPY(geom0, 0);
PG_FREE_IF_COPY(geom1, 1);
PG_RETURN_BOOL(result);
PG_RETURN_DATUM(CallerFInfoFunctionCall2(contains, fcinfo->flinfo, InvalidOid,
PG_GETARG_DATUM(1), PG_GETARG_DATUM(0)));
}
PG_FUNCTION_INFO_V1(containsproperly);
Datum containsproperly(PG_FUNCTION_ARGS)
{