mirror of
https://github.com/postgres/postgres.git
synced 2026-04-03 16:26:40 -04:00
Make cast function from circle to polygon error safe
Previously, the function casting type circle to type polygon could not be made error safe, because it is an SQL language function. This refactors it as a C/internal function, by sharing code with the C/internal function that the SQL function previously wrapped, and soft error support is added. Author: jian he <jian.universality@gmail.com> Reviewed-by: Amul Sul <sulamul@gmail.com> Reviewed-by: Corey Huinker <corey.huinker@gmail.com> Discussion: Discussion: https://www.postgresql.org/message-id/flat/CADkLM%3Dfv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ%40mail.gmail.com
This commit is contained in:
parent
2497dac556
commit
26f9012bee
4 changed files with 49 additions and 22 deletions
|
|
@ -99,12 +99,6 @@ CREATE OR REPLACE FUNCTION path_contain_pt(path, point)
|
|||
IMMUTABLE PARALLEL SAFE STRICT COST 1
|
||||
RETURN on_ppath($2, $1);
|
||||
|
||||
CREATE OR REPLACE FUNCTION polygon(circle)
|
||||
RETURNS polygon
|
||||
LANGUAGE sql
|
||||
IMMUTABLE PARALLEL SAFE STRICT COST 1
|
||||
RETURN polygon(12, $1);
|
||||
|
||||
CREATE OR REPLACE FUNCTION age(timestamptz)
|
||||
RETURNS interval
|
||||
LANGUAGE sql
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ static float8 circle_ar(CIRCLE *circle);
|
|||
|
||||
/* Routines for polygons */
|
||||
static void make_bound_box(POLYGON *poly);
|
||||
static POLYGON *circle_poly_internal(int32 npts, const CIRCLE *circle, FunctionCallInfo fcinfo);
|
||||
static void poly_to_circle(CIRCLE *result, POLYGON *poly, Node *escontext);
|
||||
static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
|
||||
static bool poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly);
|
||||
|
|
@ -5317,11 +5318,9 @@ fail:
|
|||
}
|
||||
|
||||
|
||||
Datum
|
||||
circle_poly(PG_FUNCTION_ARGS)
|
||||
static POLYGON *
|
||||
circle_poly_internal(int32 npts, const CIRCLE *circle, FunctionCallInfo fcinfo)
|
||||
{
|
||||
int32 npts = PG_GETARG_INT32(0);
|
||||
CIRCLE *circle = PG_GETARG_CIRCLE_P(1);
|
||||
POLYGON *poly;
|
||||
int base_size,
|
||||
size;
|
||||
|
|
@ -5330,12 +5329,12 @@ circle_poly(PG_FUNCTION_ARGS)
|
|||
float8 anglestep;
|
||||
|
||||
if (FPzero(circle->radius))
|
||||
ereport(ERROR,
|
||||
ereturn(fcinfo->context, NULL,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot convert circle with radius zero to polygon")));
|
||||
|
||||
if (npts < 2)
|
||||
ereport(ERROR,
|
||||
ereturn(fcinfo->context, NULL,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("must request at least 2 points")));
|
||||
|
||||
|
|
@ -5344,7 +5343,7 @@ circle_poly(PG_FUNCTION_ARGS)
|
|||
|
||||
/* Check for integer overflow */
|
||||
if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
|
||||
ereport(ERROR,
|
||||
ereturn(fcinfo->context, NULL,
|
||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||
errmsg("too many points requested")));
|
||||
|
||||
|
|
@ -5356,17 +5355,51 @@ circle_poly(PG_FUNCTION_ARGS)
|
|||
|
||||
for (i = 0; i < npts; i++)
|
||||
{
|
||||
angle = float8_mul(anglestep, i);
|
||||
float8 temp;
|
||||
|
||||
poly->p[i].x = float8_mi(circle->center.x,
|
||||
float8_mul(circle->radius, cos(angle)));
|
||||
poly->p[i].y = float8_pl(circle->center.y,
|
||||
float8_mul(circle->radius, sin(angle)));
|
||||
angle = float8_mul_safe(anglestep, i, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
return NULL;
|
||||
|
||||
temp = float8_mul_safe(circle->radius, cos(angle), fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
return NULL;
|
||||
|
||||
poly->p[i].x = float8_mi_safe(circle->center.x, temp, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
return NULL;
|
||||
|
||||
temp = float8_mul_safe(circle->radius, sin(angle), fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
return NULL;
|
||||
|
||||
poly->p[i].y = float8_pl_safe(circle->center.y, temp, fcinfo->context);
|
||||
if (SOFT_ERROR_OCCURRED(fcinfo->context))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
make_bound_box(poly);
|
||||
|
||||
PG_RETURN_POLYGON_P(poly);
|
||||
return poly;
|
||||
}
|
||||
|
||||
Datum
|
||||
circle_poly(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 npts = PG_GETARG_INT32(0);
|
||||
CIRCLE *circle = PG_GETARG_CIRCLE_P(1);
|
||||
|
||||
PG_RETURN_POLYGON_P(circle_poly_internal(npts, circle, fcinfo));
|
||||
}
|
||||
|
||||
/* convert circle to 12-vertex polygon */
|
||||
Datum
|
||||
circle_to_poly(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 npts = 12;
|
||||
CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
|
||||
|
||||
PG_RETURN_POLYGON_P(circle_poly_internal(npts, circle, fcinfo));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -57,6 +57,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 202603241
|
||||
#define CATALOG_VERSION_NO 202603301
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3390,8 +3390,8 @@
|
|||
proname => 'center', prorettype => 'point', proargtypes => 'circle',
|
||||
prosrc => 'circle_center' },
|
||||
{ oid => '1544', descr => 'convert circle to 12-vertex polygon',
|
||||
proname => 'polygon', prolang => 'sql', prorettype => 'polygon',
|
||||
proargtypes => 'circle', prosrc => 'see system_functions.sql' },
|
||||
proname => 'polygon', prorettype => 'polygon',
|
||||
proargtypes => 'circle', prosrc => 'circle_to_poly' },
|
||||
{ oid => '1545', descr => 'number of points',
|
||||
proname => 'npoints', prorettype => 'int4', proargtypes => 'path',
|
||||
prosrc => 'path_npoints' },
|
||||
|
|
|
|||
Loading…
Reference in a new issue