This is an automated email from the ASF dual-hosted git repository.
mtaha pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/master by this push:
new 9c0960ef Fix memory leaks in functions part 1 (#2066)
9c0960ef is described below
commit 9c0960efbe5e03c470f3d9b2b1048faa5c81222e
Author: John Gemignani <[email protected]>
AuthorDate: Mon Aug 26 02:50:04 2024 -0700
Fix memory leaks in functions part 1 (#2066)
Fixing memory leaks in functions due to contexts not clearing out
the memory soon enough.
Background: Destroying a context will free up its associated memory.
However, before that happens, a process can still accumulate a lot of
memory working on large data sets if it expects the context free to do
it for it. For example, when PG does quicksort the context isn't
destroyed until after the qs has finished. This can cause memory to be
exhausted.
Put in more aggressive freeing of memory. However, there are a lot of
areas that need this applied. So, this is part 1 of at least 3 or 4
parts.
Worked mainly on `agtype.c` However, dealt with linked functions in
other files.
modified: src/backend/utils/adt/age_vle.c
modified: src/backend/utils/adt/agtype.c
modified: src/backend/utils/adt/agtype_util.c
modified: src/include/utils/agtype.h
---
src/backend/utils/adt/age_vle.c | 1 -
src/backend/utils/adt/agtype.c | 417 ++++++++++++++++++++++++++++--------
src/backend/utils/adt/agtype_util.c | 3 +-
src/include/utils/agtype.h | 1 +
4 files changed, 324 insertions(+), 98 deletions(-)
diff --git a/src/backend/utils/adt/age_vle.c b/src/backend/utils/adt/age_vle.c
index ed094e95..6f7efbbc 100644
--- a/src/backend/utils/adt/age_vle.c
+++ b/src/backend/utils/adt/age_vle.c
@@ -2147,7 +2147,6 @@ agtype_value *agtv_materialize_vle_edges(agtype
*agt_arg_vpc)
/* build the AGTV_ARRAY of edges from the VLE_path_container */
agtv_array = build_edge_list(vpc);
- /* convert the agtype_value to agtype and return it */
return agtv_array;
}
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index 345cb653..c1266df3 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -242,8 +242,11 @@ PG_FUNCTION_INFO_V1(graphid_recv);
Datum graphid_recv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ int64 result = pq_getmsgint64(buf);
- PG_RETURN_INT64(pq_getmsgint64(buf));
+ PG_FREE_IF_COPY(buf, 0);
+
+ PG_RETURN_INT64(result);
}
/*
@@ -281,6 +284,7 @@ Datum agtype_recv(PG_FUNCTION_ARGS)
int version = pq_getmsgint(buf, 1);
char *str = NULL;
int nbytes = 0;
+ Datum result;
if (version == 1)
{
@@ -291,7 +295,12 @@ Datum agtype_recv(PG_FUNCTION_ARGS)
elog(ERROR, "unsupported agtype version number %d", version);
}
- return agtype_from_cstring(str, nbytes);
+ result = agtype_from_cstring(str, nbytes);
+
+ PG_FREE_IF_COPY(buf, 0);
+ pfree(str);
+
+ return result;
}
/*
@@ -317,6 +326,8 @@ Datum agtype_send(PG_FUNCTION_ARGS)
pfree(agtype_text->data);
pfree(agtype_text);
+ PG_FREE_IF_COPY(agt, 0);
+
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
@@ -328,8 +339,11 @@ PG_FUNCTION_INFO_V1(agtype_in);
Datum agtype_in(PG_FUNCTION_ARGS)
{
char *str = PG_GETARG_CSTRING(0);
+ Datum result = agtype_from_cstring(str, strlen(str));
+
+ PG_FREE_IF_COPY(str, 0);
- return agtype_from_cstring(str, strlen(str));
+ return result;
}
PG_FUNCTION_INFO_V1(agtype_out);
@@ -346,6 +360,8 @@ Datum agtype_out(PG_FUNCTION_ARGS)
out = agtype_to_cstring(NULL, &agt->root, VARSIZE(agt));
+ PG_FREE_IF_COPY(agt, 0);
+
PG_RETURN_CSTRING(out);
}
@@ -2152,6 +2168,7 @@ Datum _agtype_build_path(PG_FUNCTION_ARGS)
Datum make_path(List *path)
{
+ agtype *agt_result;
ListCell *lc;
agtype_in_state result;
int i = 1;
@@ -2177,7 +2194,7 @@ Datum make_path(List *path)
foreach (lc, path)
{
- agtype *agt= DATUM_GET_AGTYPE_P(PointerGetDatum(lfirst(lc)));
+ agtype *agt = DATUM_GET_AGTYPE_P(PointerGetDatum(lfirst(lc)));
agtype_value *elem;
elem = get_ith_agtype_value_from_container(&agt->root, 0);
@@ -2202,6 +2219,12 @@ Datum make_path(List *path)
add_agtype((Datum)agt, false, &result, AGTYPEOID, false);
+ if ((Pointer) (agt) != lfirst(lc))
+ {
+ pfree(agt);
+ }
+ pfree_agtype_value(elem);
+
i++;
}
@@ -2209,7 +2232,11 @@ Datum make_path(List *path)
result.res->type = AGTV_PATH;
- PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
+ agt_result = agtype_value_to_agtype(result.res);
+
+ pfree_agtype_in_state(&result);
+
+ PG_RETURN_POINTER(agt_result);
}
PG_FUNCTION_INFO_V1(_agtype_build_vertex);
@@ -2276,6 +2303,9 @@ Datum _agtype_build_vertex(PG_FUNCTION_ARGS)
rawscalar = build_agtype(bstate);
pfree_agtype_build_state(bstate);
+ PG_FREE_IF_COPY(label, 1);
+ PG_FREE_IF_COPY(properties, 2);
+
PG_RETURN_POINTER(rawscalar);
}
@@ -2375,6 +2405,10 @@ Datum _agtype_build_edge(PG_FUNCTION_ARGS)
write_extended(bstate, edge, AGT_HEADER_EDGE);
rawscalar = build_agtype(bstate);
pfree_agtype_build_state(bstate);
+
+ PG_FREE_IF_COPY(label, 3);
+ PG_FREE_IF_COPY(properties, 4);
+
PG_RETURN_POINTER(rawscalar);
}
@@ -2493,13 +2527,18 @@ PG_FUNCTION_INFO_V1(agtype_build_map_noargs);
Datum agtype_build_map_noargs(PG_FUNCTION_ARGS)
{
agtype_in_state result;
+ agtype *agt_result;
memset(&result, 0, sizeof(agtype_in_state));
push_agtype_value(&result.parse_state, WAGT_BEGIN_OBJECT, NULL);
result.res = push_agtype_value(&result.parse_state, WAGT_END_OBJECT, NULL);
- PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
+ agt_result = agtype_value_to_agtype(result.res);
+
+ pfree_agtype_in_state(&result);
+
+ PG_RETURN_POINTER(agt_result);
}
PG_FUNCTION_INFO_V1(agtype_build_map_nonull);
@@ -2510,6 +2549,7 @@ PG_FUNCTION_INFO_V1(agtype_build_map_nonull);
Datum agtype_build_map_nonull(PG_FUNCTION_ARGS)
{
agtype_value *result = NULL;
+ agtype *agt_result;
result = agtype_build_map_as_agtype_value(fcinfo);
if (result == NULL)
@@ -2518,8 +2558,11 @@ Datum agtype_build_map_nonull(PG_FUNCTION_ARGS)
}
remove_null_from_agtype_object(result);
+ agt_result = agtype_value_to_agtype(result);
- PG_RETURN_POINTER(agtype_value_to_agtype(result));
+ pfree_agtype_value(result);
+
+ PG_RETURN_POINTER(agt_result);
}
PG_FUNCTION_INFO_V1(agtype_build_list);
@@ -2535,12 +2578,15 @@ Datum agtype_build_list(PG_FUNCTION_ARGS)
Datum *args;
bool *nulls;
Oid *types;
+ agtype *agt_result;
/*build argument values to build the array */
nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
if (nargs < 0)
+ {
PG_RETURN_NULL();
+ }
memset(&result, 0, sizeof(agtype_in_state));
@@ -2548,11 +2594,17 @@ Datum agtype_build_list(PG_FUNCTION_ARGS)
NULL);
for (i = 0; i < nargs; i++)
+ {
add_agtype(args[i], nulls[i], &result, types[i], false);
+ PG_FREE_IF_COPY(DatumGetPointer(args[i]), i);
+ }
result.res = push_agtype_value(&result.parse_state, WAGT_END_ARRAY, NULL);
+ agt_result = agtype_value_to_agtype(result.res);
+
+ pfree_agtype_in_state(&result);
- PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
+ PG_RETURN_POINTER(agt_result);
}
PG_FUNCTION_INFO_V1(agtype_build_list_noargs);
@@ -2563,13 +2615,18 @@ PG_FUNCTION_INFO_V1(agtype_build_list_noargs);
Datum agtype_build_list_noargs(PG_FUNCTION_ARGS)
{
agtype_in_state result;
+ agtype *agt_result;
memset(&result, 0, sizeof(agtype_in_state));
push_agtype_value(&result.parse_state, WAGT_BEGIN_ARRAY, NULL);
result.res = push_agtype_value(&result.parse_state, WAGT_END_ARRAY, NULL);
- PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
+ agt_result = agtype_value_to_agtype(result.res);
+
+ pfree_agtype_in_state(&result);
+
+ PG_RETURN_POINTER(agt_result);
}
/*
@@ -2682,6 +2739,7 @@ Datum agtype_to_int8(PG_FUNCTION_ARGS)
agtype_value *container = NULL;
int64 result = 0x0;
agtype *arg_agt = NULL;
+ bool is_scalar = false;
/* get the agtype equivalence of any convertable input type */
arg_agt = get_one_agtype_from_variadic_args(fcinfo, 0, 1);
@@ -2692,7 +2750,11 @@ Datum agtype_to_int8(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
- if (!agtype_extract_scalar(&arg_agt->root, &agtv) ||
+ /* get the scalar value if it is one and set the flag accordingly */
+ is_scalar = agtype_extract_scalar(&arg_agt->root, &agtv);
+
+ /* if it isn't something that can be cast error out */
+ if (!is_scalar ||
(agtv.type != AGTV_FLOAT &&
agtv.type != AGTV_INTEGER &&
agtv.type != AGTV_NUMERIC &&
@@ -2729,7 +2791,7 @@ Datum agtype_to_int8(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid agtype string to int8 type: %d",
- (int)temp->type)));
+ temp->type)));
}
/* save the top agtype_value */
@@ -2748,7 +2810,7 @@ Datum agtype_to_int8(PG_FUNCTION_ARGS)
else
{
elog(ERROR, "unexpected string type: %d in agtype_to_int8",
- (int)temp->type);
+ temp->type);
}
}
@@ -2776,7 +2838,7 @@ Datum agtype_to_int8(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid conversion type in agtype_to_int8: %d",
- (int)agtv_p->type)));
+ agtv_p->type)));
}
/* free the container, if it was used */
@@ -3112,18 +3174,25 @@ Datum agtype_to_text(PG_FUNCTION_ARGS)
/* Return null if arg_agt is null. This covers SQL and Agtype NULLS */
if (arg_agt == NULL)
+ {
PG_RETURN_NULL();
+ }
/* check that we have a scalar value */
if (!AGT_ROOT_IS_SCALAR(arg_agt))
+ {
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("agtype argument must resolve to a scalar value")));
+ }
/* get the arg parameter */
arg_value = get_ith_agtype_value_from_container(&arg_agt->root, 0);
+ PG_FREE_IF_COPY(arg_agt, 0);
text_value = agtype_value_to_text(arg_value, true);
+ pfree_agtype_value(arg_value);
+
if (text_value == NULL)
{
PG_RETURN_NULL();
@@ -3369,6 +3438,7 @@ static agtype_value *execute_array_access_operator(agtype
*array,
agtype *array_index)
{
agtype_value *array_index_value = NULL;
+ agtype_value *result = NULL;
/* unpack the array index value */
array_index_value = get_ith_agtype_value_from_container(&array_index->root,
@@ -3377,6 +3447,7 @@ static agtype_value *execute_array_access_operator(agtype
*array,
/* if AGTV_NULL return NULL */
if (array_index_value->type == AGTV_NULL)
{
+ pfree_agtype_value(array_index_value);
return NULL;
}
@@ -3387,8 +3458,11 @@ static agtype_value
*execute_array_access_operator(agtype *array,
(errmsg("array index must resolve to an integer value")));
}
- return execute_array_access_operator_internal(
- array, array_value, array_index_value->val.int_value);
+ result = execute_array_access_operator_internal(array, array_value,
+
array_index_value->val.int_value);
+
+ pfree_agtype_value(array_index_value);
+ return result;
}
static agtype_value *execute_array_access_operator_internal(agtype *array,
@@ -3768,32 +3842,44 @@ Datum agtype_object_field_agtype(PG_FUNCTION_ARGS)
{
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
agtype *key = AG_GET_ARG_AGTYPE_P(1);
- agtype_value *key_value;
- if (!AGT_ROOT_IS_SCALAR(key))
+ if (AGT_ROOT_IS_SCALAR(key))
{
- PG_RETURN_NULL();
- }
+ agtype_value *key_value;
- key_value = get_ith_agtype_value_from_container(&key->root, 0);
+ key_value = get_ith_agtype_value_from_container(&key->root, 0);
- if (key_value->type == AGTV_INTEGER)
- {
- PG_RETURN_TEXT_P((const void*)agtype_array_element_impl(fcinfo, agt,
+ if (key_value->type == AGTV_INTEGER ||
+ key_value->type == AGTV_STRING)
+ {
+ Datum retval = 0;
+
+ if (key_value->type == AGTV_INTEGER)
+ {
+ retval = agtype_array_element_impl(fcinfo, agt,
key_value->val.int_value,
- false));
- }
- else if (key_value->type == AGTV_STRING)
- {
- AG_RETURN_AGTYPE_P((const void*)agtype_object_field_impl(fcinfo, agt,
- key_value->val.string.val,
- key_value->val.string.len,
- false));
- }
- else
- {
- PG_RETURN_NULL();
+ false);
+ }
+ else if (key_value->type == AGTV_STRING)
+ {
+ retval = agtype_object_field_impl(fcinfo, agt,
+ key_value->val.string.val,
+ key_value->val.string.len,
+ false);
+ }
+
+ pfree_agtype_value(key_value);
+ PG_FREE_IF_COPY(agt, 0);
+ PG_FREE_IF_COPY(key, 1);
+
+ PG_RETURN_POINTER((const void*) retval);
+ }
+ pfree_agtype_value(key_value);
}
+
+ PG_FREE_IF_COPY(agt, 0);
+ PG_FREE_IF_COPY(key, 1);
+ PG_RETURN_NULL();
}
PG_FUNCTION_INFO_V1(agtype_object_field_text_agtype);
@@ -3802,32 +3888,43 @@ Datum agtype_object_field_text_agtype(PG_FUNCTION_ARGS)
{
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
agtype *key = AG_GET_ARG_AGTYPE_P(1);
- agtype_value *key_value;
- if (!AGT_ROOT_IS_SCALAR(key))
+ if (AGT_ROOT_IS_SCALAR(key))
{
- PG_RETURN_NULL();
- }
+ agtype_value *key_value;
- key_value = get_ith_agtype_value_from_container(&key->root, 0);
+ key_value = get_ith_agtype_value_from_container(&key->root, 0);
- if (key_value->type == AGTV_INTEGER)
- {
- PG_RETURN_TEXT_P((const void*)agtype_array_element_impl(fcinfo, agt,
+ if (key_value->type == AGTV_INTEGER || key_value->type == AGTV_STRING)
+ {
+ Datum retval = 0;
+
+ if (key_value->type == AGTV_INTEGER)
+ {
+ retval = agtype_array_element_impl(fcinfo, agt,
key_value->val.int_value,
- true));
- }
- else if (key_value->type == AGTV_STRING)
- {
- AG_RETURN_AGTYPE_P((const void*)agtype_object_field_impl(fcinfo, agt,
- key_value->val.string.val,
- key_value->val.string.len,
- true));
- }
- else
- {
- PG_RETURN_NULL();
+ true);
+ }
+ else if (key_value->type == AGTV_STRING)
+ {
+ retval = agtype_object_field_impl(fcinfo, agt,
+ key_value->val.string.val,
+ key_value->val.string.len,
+ true);
+ }
+
+ pfree_agtype_value(key_value);
+ PG_FREE_IF_COPY(agt, 0);
+ PG_FREE_IF_COPY(key, 1);
+
+ PG_RETURN_POINTER((const void*) retval);
+ }
+ pfree_agtype_value(key_value);
}
+
+ PG_FREE_IF_COPY(agt, 0);
+ PG_FREE_IF_COPY(key, 1);
+ PG_RETURN_NULL();
}
PG_FUNCTION_INFO_V1(agtype_object_field);
@@ -3836,10 +3933,14 @@ Datum agtype_object_field(PG_FUNCTION_ARGS)
{
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
text *key = PG_GETARG_TEXT_PP(1);
+ Datum retval;
- AG_RETURN_AGTYPE_P((const void*)agtype_object_field_impl(fcinfo, agt,
VARDATA_ANY(key),
- VARSIZE_ANY_EXHDR(key),
- false));
+ retval = agtype_object_field_impl(fcinfo, agt, VARDATA_ANY(key),
+ VARSIZE_ANY_EXHDR(key), false);
+ PG_FREE_IF_COPY(agt, 0);
+ PG_FREE_IF_COPY(key, 1);
+
+ AG_RETURN_AGTYPE_P((const void*) retval);
}
PG_FUNCTION_INFO_V1(agtype_object_field_text);
@@ -3848,9 +3949,14 @@ Datum agtype_object_field_text(PG_FUNCTION_ARGS)
{
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
text *key = PG_GETARG_TEXT_PP(1);
+ Datum retval;
+
+ retval = agtype_object_field_impl(fcinfo, agt, VARDATA_ANY(key),
+ VARSIZE_ANY_EXHDR(key), true);
+ PG_FREE_IF_COPY(agt, 0);
+ PG_FREE_IF_COPY(key, 1);
- PG_RETURN_TEXT_P((const void*)agtype_object_field_impl(fcinfo, agt,
VARDATA_ANY(key),
- VARSIZE_ANY_EXHDR(key), true));
+ PG_RETURN_TEXT_P((const void*) retval);
}
PG_FUNCTION_INFO_V1(agtype_array_element);
@@ -3859,9 +3965,13 @@ Datum agtype_array_element(PG_FUNCTION_ARGS)
{
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
int elem = PG_GETARG_INT32(1);
+ Datum retval;
+
+ retval = agtype_array_element_impl(fcinfo, agt, elem, false);
+
+ PG_FREE_IF_COPY(agt, 0);
- AG_RETURN_AGTYPE_P((const void*)
- agtype_array_element_impl(fcinfo, agt, elem, false));
+ AG_RETURN_AGTYPE_P((const void*) retval);
}
PG_FUNCTION_INFO_V1(agtype_array_element_text);
@@ -3870,9 +3980,13 @@ Datum agtype_array_element_text(PG_FUNCTION_ARGS)
{
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
int elem = PG_GETARG_INT32(1);
+ Datum retval;
- PG_RETURN_TEXT_P((const void*)
- agtype_array_element_impl(fcinfo, agt, elem, true));
+ retval = agtype_array_element_impl(fcinfo, agt, elem, true);
+
+ PG_FREE_IF_COPY(agt, 0);
+
+ PG_RETURN_TEXT_P((const void*) retval);
}
PG_FUNCTION_INFO_V1(agtype_access_operator);
@@ -3888,6 +4002,7 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS)
int nargs = 0;
agtype *container = NULL;
agtype_value *container_value = NULL;
+ agtype *result = NULL;
int i = 0;
/* extract our args, we need at least 2 */
@@ -3905,6 +4020,10 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS)
*/
if (args == NULL || nargs == 0 || nulls[0] == true)
{
+ pfree(args);
+ pfree(types);
+ pfree(nulls);
+
PG_RETURN_NULL();
}
@@ -3914,6 +4033,9 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS)
/* if we have a NULL, return NULL */
if (nulls[i] == true)
{
+ pfree(args);
+ pfree(types);
+ pfree(nulls);
PG_RETURN_NULL();
}
}
@@ -3929,6 +4051,7 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS)
/* retrieve an array of edges from the vpc */
container_value = agtv_materialize_vle_edges(container);
/* clear the container reference */
+
container = NULL;
}
else
@@ -4031,8 +4154,14 @@ Datum agtype_access_operator(PG_FUNCTION_ARGS)
container = NULL;
}
+ pfree(args);
+ pfree(types);
+ pfree(nulls);
+
/* serialize and return the result */
- return AGTYPE_P_GET_DATUM(agtype_value_to_agtype(container_value));
+ result = agtype_value_to_agtype(container_value);
+
+ return AGTYPE_P_GET_DATUM(result);
}
PG_FUNCTION_INFO_V1(agtype_access_slice);
@@ -4044,7 +4173,10 @@ Datum agtype_access_slice(PG_FUNCTION_ARGS)
agtype_value *lidx_value = NULL;
agtype_value *uidx_value = NULL;
agtype_in_state result;
+ agtype *agt_result = NULL;
agtype *agt_array = NULL;
+ agtype *agt_lidx = NULL;
+ agtype *agt_uidx = NULL;
agtype_value *agtv_array = NULL;
int64 upper_index = 0;
int64 lower_index = 0;
@@ -4093,8 +4225,8 @@ Datum agtype_access_slice(PG_FUNCTION_ARGS)
}
else
{
- lidx_value = get_ith_agtype_value_from_container(
- &(AG_GET_ARG_AGTYPE_P(1))->root, 0);
+ agt_lidx = AG_GET_ARG_AGTYPE_P(1);
+ lidx_value = get_ith_agtype_value_from_container(&agt_lidx->root, 0);
/* adjust for AGTV_NULL */
if (lidx_value->type == AGTV_NULL)
{
@@ -4110,8 +4242,8 @@ Datum agtype_access_slice(PG_FUNCTION_ARGS)
}
else
{
- uidx_value = get_ith_agtype_value_from_container(
- &(AG_GET_ARG_AGTYPE_P(2))->root, 0);
+ agt_uidx = AG_GET_ARG_AGTYPE_P(2);
+ uidx_value = get_ith_agtype_value_from_container(&agt_uidx->root, 0);
/* adjust for AGTV_NULL */
if (uidx_value->type == AGTV_NULL)
{
@@ -4139,10 +4271,12 @@ Datum agtype_access_slice(PG_FUNCTION_ARGS)
if (lidx_value)
{
lower_index = lidx_value->val.int_value;
+ pfree_agtype_value(lidx_value);
}
if (uidx_value)
{
upper_index = uidx_value->val.int_value;
+ pfree_agtype_value(uidx_value);
}
/* adjust for negative and out of bounds index values */
@@ -4198,7 +4332,14 @@ Datum agtype_access_slice(PG_FUNCTION_ARGS)
result.res = push_agtype_value(&result.parse_state, WAGT_END_ARRAY, NULL);
- PG_RETURN_POINTER(agtype_value_to_agtype(result.res));
+ agt_result = agtype_value_to_agtype(result.res);
+
+ pfree_agtype_in_state(&result);
+ PG_FREE_IF_COPY(agt_array, 0);
+ PG_FREE_IF_COPY(agt_lidx, 1);
+ PG_FREE_IF_COPY(agt_uidx, 2);
+
+ PG_RETURN_POINTER(agt_result);
}
PG_FUNCTION_INFO_V1(agtype_in_operator);
@@ -4357,6 +4498,7 @@ Datum agtype_string_match_starts_with(PG_FUNCTION_ARGS)
{
agtype *lhs = AG_GET_ARG_AGTYPE_P(0);
agtype *rhs = AG_GET_ARG_AGTYPE_P(1);
+ bool result = false;
if (AGT_ROOT_IS_SCALAR(lhs) && AGT_ROOT_IS_SCALAR(rhs))
{
@@ -4369,17 +4511,33 @@ Datum agtype_string_match_starts_with(PG_FUNCTION_ARGS)
if (lhs_value->type == AGTV_STRING && rhs_value->type == AGTV_STRING)
{
if (lhs_value->val.string.len < rhs_value->val.string.len)
- return boolean_to_agtype(false);
-
- if (strncmp(lhs_value->val.string.val, rhs_value->val.string.val,
- rhs_value->val.string.len) == 0)
- return boolean_to_agtype(true);
+ {
+ result = false;
+ }
+ else if (strncmp(lhs_value->val.string.val,
+ rhs_value->val.string.val,
+ rhs_value->val.string.len) == 0)
+ {
+ result = true;
+ }
else
- return boolean_to_agtype(false);
+ {
+ result = false;
+ }
}
+ pfree_agtype_value(lhs_value);
+ pfree_agtype_value(rhs_value);
}
- ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("agtype string values expected")));
+ else
+ {
+ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("agtype string values expected")));
+ }
+
+ PG_FREE_IF_COPY(lhs, 0);
+ PG_FREE_IF_COPY(rhs, 1);
+
+ return boolean_to_agtype(result);
}
PG_FUNCTION_INFO_V1(agtype_string_match_ends_with);
@@ -4390,6 +4548,7 @@ Datum agtype_string_match_ends_with(PG_FUNCTION_ARGS)
{
agtype *lhs = AG_GET_ARG_AGTYPE_P(0);
agtype *rhs = AG_GET_ARG_AGTYPE_P(1);
+ bool result = false;
if (AGT_ROOT_IS_SCALAR(lhs) && AGT_ROOT_IS_SCALAR(rhs))
{
@@ -4402,19 +4561,35 @@ Datum agtype_string_match_ends_with(PG_FUNCTION_ARGS)
if (lhs_value->type == AGTV_STRING && rhs_value->type == AGTV_STRING)
{
if (lhs_value->val.string.len < rhs_value->val.string.len)
- return boolean_to_agtype(false);
-
- if (strncmp(lhs_value->val.string.val + lhs_value->val.string.len -
- rhs_value->val.string.len,
- rhs_value->val.string.val,
- rhs_value->val.string.len) == 0)
- return boolean_to_agtype(true);
+ {
+ result = false;
+ }
+ else if (strncmp((lhs_value->val.string.val +
+ lhs_value->val.string.len -
+ rhs_value->val.string.len),
+ rhs_value->val.string.val,
+ rhs_value->val.string.len) == 0)
+ {
+ result = true;
+ }
else
- return boolean_to_agtype(false);
+ {
+ result = false;
+ }
}
+ pfree_agtype_value(lhs_value);
+ pfree_agtype_value(rhs_value);
}
- ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("agtype string values expected")));
+ else
+ {
+ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("agtype string values expected")));
+ }
+
+ PG_FREE_IF_COPY(lhs, 0);
+ PG_FREE_IF_COPY(rhs, 1);
+
+ return boolean_to_agtype(result);
}
PG_FUNCTION_INFO_V1(agtype_string_match_contains);
@@ -4425,6 +4600,7 @@ Datum agtype_string_match_contains(PG_FUNCTION_ARGS)
{
agtype *lhs = AG_GET_ARG_AGTYPE_P(0);
agtype *rhs = AG_GET_ARG_AGTYPE_P(1);
+ bool result = false;
if (AGT_ROOT_IS_SCALAR(lhs) && AGT_ROOT_IS_SCALAR(rhs))
{
@@ -4440,19 +4616,37 @@ Datum agtype_string_match_contains(PG_FUNCTION_ARGS)
char *r;
if (lhs_value->val.string.len < rhs_value->val.string.len)
- return boolean_to_agtype(false);
+ {
+ result = false;
+ }
l = pnstrdup(lhs_value->val.string.val, lhs_value->val.string.len);
r = pnstrdup(rhs_value->val.string.val, rhs_value->val.string.len);
if (strstr(l, r) == NULL)
- return boolean_to_agtype(false);
+ {
+ result = false;
+ }
else
- return boolean_to_agtype(true);
+ {
+ result = true;
+ }
+ pfree(l);
+ pfree(r);
}
+ pfree_agtype_value(lhs_value);
+ pfree_agtype_value(rhs_value);
}
- ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("agtype string values expected")));
+ else
+ {
+ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("agtype string values expected")));
+ }
+
+ PG_FREE_IF_COPY(lhs, 0);
+ PG_FREE_IF_COPY(rhs, 1);
+
+ return boolean_to_agtype(result);
}
#define LEFT_ROTATE(n, i) ((n << i) | (n >> (64 - i)))
@@ -4497,6 +4691,9 @@ Datum agtype_hash_cmp(PG_FUNCTION_ARGS)
seed = LEFT_ROTATE(seed, 1);
}
+ pfree(r);
+ PG_FREE_IF_COPY(agt, 0);
+
PG_RETURN_INT32(hash);
}
@@ -4546,23 +4743,31 @@ Datum agtype_typecast_numeric(PG_FUNCTION_ARGS)
agtype_value result_value;
Datum numd;
char *string = NULL;
+ agtype *result = NULL;
/* get the agtype equivalence of any convertable input type */
arg_agt = get_one_agtype_from_variadic_args(fcinfo, 0, 1);
/* Return null if arg_agt is null. This covers SQL and Agtype NULLS */
if (arg_agt == NULL)
+ {
PG_RETURN_NULL();
+ }
/* check that we have a scalar value */
if (!AGT_ROOT_IS_SCALAR(arg_agt))
+ {
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("typecast argument must resolve to a scalar value")));
+ }
/* get the arg parameter */
arg_value = get_ith_agtype_value_from_container(&arg_agt->root, 0);
+ /* we don't need to agtype arg anymore */
+ PG_FREE_IF_COPY(arg_agt, 0);
+
/* the input type drives the casting */
switch(arg_value->type)
{
@@ -4576,7 +4781,9 @@ Datum agtype_typecast_numeric(PG_FUNCTION_ARGS)
break;
case AGTV_NUMERIC:
/* it is already a numeric so just return it */
- PG_RETURN_POINTER(agtype_value_to_agtype(arg_value));
+ result = agtype_value_to_agtype(arg_value);
+ pfree_agtype_value(arg_value);
+ PG_RETURN_POINTER(result);
break;
/* this allows string numbers and NaN */
case AGTV_STRING:
@@ -4602,11 +4809,16 @@ Datum agtype_typecast_numeric(PG_FUNCTION_ARGS)
break;
}
+ pfree_agtype_value(arg_value);
+
/* fill in and return our result */
result_value.type = AGTV_NUMERIC;
result_value.val.numeric = DatumGetNumeric(numd);
- PG_RETURN_POINTER(agtype_value_to_agtype(&result_value));
+ result = agtype_value_to_agtype(&result_value);
+ pfree_agtype_value_content(&result_value);
+
+ PG_RETURN_POINTER(result);
}
PG_FUNCTION_INFO_V1(agtype_typecast_int);
@@ -10145,6 +10357,9 @@ agtype
*get_one_agtype_from_variadic_args(FunctionCallInfo fcinfo,
/* if null, return null */
if (nulls[0])
{
+ pfree(args);
+ pfree(nulls);
+ pfree(types);
return NULL;
}
@@ -10163,6 +10378,11 @@ agtype
*get_one_agtype_from_variadic_args(FunctionCallInfo fcinfo,
if (AGTYPE_CONTAINER_IS_SCALAR(agtc) &&
AGTE_IS_NULL(agtc->children[0]))
{
+ PG_FREE_IF_COPY(agtype_result, variadic_offset);
+
+ pfree(args);
+ pfree(nulls);
+ pfree(types);
return NULL;
}
}
@@ -10182,7 +10402,14 @@ agtype
*get_one_agtype_from_variadic_args(FunctionCallInfo fcinfo,
datum_to_agtype(args[0], false, &state, tcategory, outfuncoid, false);
/* convert it to an agtype */
agtype_result = agtype_value_to_agtype(state.res);
+
+ pfree_agtype_in_state(&state);
}
+
+ pfree(args);
+ pfree(nulls);
+ pfree(types);
+
return agtype_result;
}
diff --git a/src/backend/utils/adt/agtype_util.c
b/src/backend/utils/adt/agtype_util.c
index dd590f09..878f1844 100644
--- a/src/backend/utils/adt/agtype_util.c
+++ b/src/backend/utils/adt/agtype_util.c
@@ -87,7 +87,6 @@ static agtype_value
*push_agtype_value_scalar(agtype_parse_state **pstate,
agtype_value *scalar_val);
static int compare_two_floats_orderability(float8 lhs, float8 rhs);
static int get_type_sort_priority(enum agtype_value_type type);
-static void pfree_agtype_value_content(agtype_value* value);
static void pfree_iterator_agtype_value_token(agtype_iterator_token token,
agtype_value *agtv);
@@ -2447,7 +2446,7 @@ void pfree_agtype_value(agtype_value* value)
* of the passed agtype_value only. It does not deallocate
* `value` itself.
*/
-static void pfree_agtype_value_content(agtype_value* value)
+void pfree_agtype_value_content(agtype_value* value)
{
int i;
diff --git a/src/include/utils/agtype.h b/src/include/utils/agtype.h
index bafed698..e77f0453 100644
--- a/src/include/utils/agtype.h
+++ b/src/include/utils/agtype.h
@@ -553,6 +553,7 @@ agtype_iterator *get_next_list_element(agtype_iterator *it,
agtype_container *agtc,
agtype_value *elem);
void pfree_agtype_value(agtype_value* value);
+void pfree_agtype_value_content(agtype_value* value);
void pfree_agtype_in_state(agtype_in_state* value);
agtype_value *agtype_value_from_cstring(char *str, int len);
/* Oid accessors for AGTYPE */