diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index 1c5b6d6df05..c3c0a6e84ed 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -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 diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index cbc4621e9b2..cc5ce013d0f 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -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)); } /* diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 4d9ccc5789c..81b2bf39b3f 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202603241 +#define CATALOG_VERSION_NO 202603301 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 0118e970dda..3579cec5744 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -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' },