aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/acl.c11
-rw-r--r--src/backend/utils/adt/array_userfuncs.c289
-rw-r--r--src/backend/utils/adt/arrayfuncs.c824
-rw-r--r--src/backend/utils/adt/varlena.c196
4 files changed, 286 insertions, 1034 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index cfef2db349d..415a086b7dd 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.89 2003/06/24 23:14:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.90 2003/06/25 21:30:32 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -427,15 +427,6 @@ aclitemeq(const AclItem *a1, const AclItem *a2)
a1->ai_grantor == a2->ai_grantor;
}
-/*
- * user-facing version of aclitemeq() for use as the
- * aclitem equality operator
- */
-Datum
-aclitem_eq(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(aclitemeq(PG_GETARG_ACLITEM_P(0), PG_GETARG_ACLITEM_P(1)));
-}
/*
* acldefault() --- create an ACL describing default access permissions
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index f5e50771b13..519ac8d1885 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -6,7 +6,7 @@
* Copyright (c) 2003, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.2 2003/06/24 23:14:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.3 2003/06/25 21:30:32 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,35 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+
+/*-----------------------------------------------------------------------------
+ * singleton_array :
+ * Form a multi-dimensional array given one starting element.
+ *
+ * - first argument is the datum with which to build the array
+ * - second argument is the number of dimensions the array should have;
+ * defaults to 1 if no second argument is provided
+ *----------------------------------------------------------------------------
+ */
+Datum
+singleton_array(PG_FUNCTION_ARGS)
+{
+ Oid elem_type = get_fn_expr_argtype(fcinfo, 0);
+ int ndims;
+
+ if (elem_type == InvalidOid)
+ elog(ERROR, "Cannot determine input datatype");
+
+ if (PG_NARGS() == 2)
+ ndims = PG_GETARG_INT32(1);
+ else
+ ndims = 1;
+
+ PG_RETURN_ARRAYTYPE_P(create_singleton_array(elem_type,
+ PG_GETARG_DATUM(0),
+ ndims));
+}
+
/*-----------------------------------------------------------------------------
* array_push :
* push an element onto either end of a one-dimensional array
@@ -41,7 +70,6 @@ array_push(PG_FUNCTION_ARGS)
Oid arg1_typeid = get_fn_expr_argtype(fcinfo, 1);
Oid arg0_elemid;
Oid arg1_elemid;
- ArrayMetaState *my_extra;
if (arg0_typeid == InvalidOid || arg1_typeid == InvalidOid)
elog(ERROR, "array_push: cannot determine input data types");
@@ -67,61 +95,28 @@ array_push(PG_FUNCTION_ARGS)
PG_RETURN_NULL(); /* keep compiler quiet */
}
- if (ARR_NDIM(v) == 1)
- {
- lb = ARR_LBOUND(v);
- dimv = ARR_DIMS(v);
-
- if (arg0_elemid != InvalidOid)
- {
- /* append newelem */
- int ub = dimv[0] + lb[0] - 1;
- indx = ub + 1;
- }
- else
- {
- /* prepend newelem */
- indx = lb[0] - 1;
- }
- }
- else if (ARR_NDIM(v) == 0)
- indx = 1;
- else
- elog(ERROR, "only empty and one-dimensional arrays are supported");
-
-
- /*
- * We arrange to look up info about element type only once per series
- * of calls, assuming the element type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
+ /* Sanity check: do we have a one-dimensional array */
+ if (ARR_NDIM(v) != 1)
+ elog(ERROR, "Arrays greater than one-dimension are not supported");
- if (my_extra->element_type != element_type)
+ lb = ARR_LBOUND(v);
+ dimv = ARR_DIMS(v);
+ if (arg0_elemid != InvalidOid)
{
- /* Get info about element type */
- get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typalign = typalign;
+ /* append newelem */
+ int ub = dimv[0] + lb[0] - 1;
+ indx = ub + 1;
}
else
{
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typalign = my_extra->typalign;
+ /* prepend newelem */
+ indx = lb[0] - 1;
}
- result = array_set(v, 1, &indx, newelem, -1, typlen, typbyval,
- typalign, &isNull);
+ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
+
+ result = array_set(v, 1, &indx, newelem, -1,
+ typlen, typbyval, typalign, &isNull);
PG_RETURN_ARRAYTYPE_P(result);
}
@@ -150,28 +145,13 @@ array_cat(PG_FUNCTION_ARGS)
/*
* We must have one of the following combinations of inputs:
- * 1) one empty array, and one non-empty array
- * 2) both arrays empty
- * 3) two arrays with ndims1 == ndims2
- * 4) ndims1 == ndims2 - 1
- * 5) ndims1 == ndims2 + 1
+ * 1) two arrays with ndims1 == ndims2
+ * 2) ndims1 == ndims2 - 1
+ * 3) ndims1 == ndims2 + 1
*/
ndims1 = ARR_NDIM(v1);
ndims2 = ARR_NDIM(v2);
- /*
- * short circuit - if one input array is empty, and the other is not,
- * we return the non-empty one as the result
- *
- * if both are empty, return the first one
- */
- if (ndims1 == 0 && ndims2 > 0)
- PG_RETURN_ARRAYTYPE_P(v2);
-
- if (ndims2 == 0)
- PG_RETURN_ARRAYTYPE_P(v1);
-
- /* the rest fall into combo 2, 3, or 4 */
if (ndims1 != ndims2 && ndims1 != ndims2 - 1 && ndims1 != ndims2 + 1)
elog(ERROR, "Cannot concatenate incompatible arrays of %d and "
"%d dimensions", ndims1, ndims2);
@@ -286,15 +266,147 @@ array_cat(PG_FUNCTION_ARGS)
PG_RETURN_ARRAYTYPE_P(result);
}
+/*----------------------------------------------------------------------------
+ * array_accum :
+ * accumulator to build a 1-D array from input values -- this can be used
+ * to create custom aggregates.
+ *
+ * This function is not marked strict, so we have to be careful about nulls.
+ *----------------------------------------------------------------------------
+ */
+Datum
+array_accum(PG_FUNCTION_ARGS)
+{
+ /* return NULL if both arguments are NULL */
+ if (PG_ARGISNULL(0) && PG_ARGISNULL(1))
+ PG_RETURN_NULL();
+
+ /* create a new 1-D array from the new element if the array is NULL */
+ if (PG_ARGISNULL(0))
+ {
+ Oid tgt_type = get_fn_expr_rettype(fcinfo);
+ Oid tgt_elem_type;
+
+ if (tgt_type == InvalidOid)
+ elog(ERROR, "Cannot determine target array type");
+ tgt_elem_type = get_element_type(tgt_type);
+ if (tgt_elem_type == InvalidOid)
+ elog(ERROR, "Target type is not an array");
+
+ PG_RETURN_ARRAYTYPE_P(create_singleton_array(tgt_elem_type,
+ PG_GETARG_DATUM(1),
+ 1));
+ }
+
+ /* return the array if the new element is NULL */
+ if (PG_ARGISNULL(1))
+ PG_RETURN_ARRAYTYPE_P(PG_GETARG_ARRAYTYPE_P_COPY(0));
+
+ /*
+ * Otherwise this is equivalent to array_push. We hack the call a little
+ * so that array_push can see the fn_expr information.
+ */
+ return array_push(fcinfo);
+}
+
+/*-----------------------------------------------------------------------------
+ * array_assign :
+ * assign an element of an array to a new value and return the
+ * redefined array
+ *----------------------------------------------------------------------------
+ */
+Datum
+array_assign(PG_FUNCTION_ARGS)
+{
+ ArrayType *v;
+ int idx_to_chg;
+ Datum newelem;
+ int *dimv,
+ *lb, ub;
+ ArrayType *result;
+ bool isNull;
+ Oid element_type;
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+
+ v = PG_GETARG_ARRAYTYPE_P(0);
+ idx_to_chg = PG_GETARG_INT32(1);
+ newelem = PG_GETARG_DATUM(2);
+
+ /* Sanity check: do we have a one-dimensional array */
+ if (ARR_NDIM(v) != 1)
+ elog(ERROR, "Arrays greater than one-dimension are not supported");
+
+ lb = ARR_LBOUND(v);
+ dimv = ARR_DIMS(v);
+ ub = dimv[0] + lb[0] - 1;
+ if (idx_to_chg < lb[0] || idx_to_chg > ub)
+ elog(ERROR, "Cannot alter nonexistent array element: %d", idx_to_chg);
+
+ element_type = ARR_ELEMTYPE(v);
+ /* Sanity check: do we have a non-zero element type */
+ if (element_type == 0)
+ elog(ERROR, "Invalid array element type: %u", element_type);
+
+ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
+
+ result = array_set(v, 1, &idx_to_chg, newelem, -1,
+ typlen, typbyval, typalign, &isNull);
+
+ PG_RETURN_ARRAYTYPE_P(result);
+}
+
+/*-----------------------------------------------------------------------------
+ * array_subscript :
+ * return specific element of an array
+ *----------------------------------------------------------------------------
+ */
+Datum
+array_subscript(PG_FUNCTION_ARGS)
+{
+ ArrayType *v;
+ int idx;
+ int *dimv,
+ *lb, ub;
+ Datum result;
+ bool isNull;
+ Oid element_type;
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+
+ v = PG_GETARG_ARRAYTYPE_P(0);
+ idx = PG_GETARG_INT32(1);
+
+ /* Sanity check: do we have a one-dimensional array */
+ if (ARR_NDIM(v) != 1)
+ elog(ERROR, "Arrays greater than one-dimension are not supported");
+
+ lb = ARR_LBOUND(v);
+ dimv = ARR_DIMS(v);
+ ub = dimv[0] + lb[0] - 1;
+ if (idx < lb[0] || idx > ub)
+ elog(ERROR, "Cannot return nonexistent array element: %d", idx);
+
+ element_type = ARR_ELEMTYPE(v);
+ /* Sanity check: do we have a non-zero element type */
+ if (element_type == 0)
+ elog(ERROR, "Invalid array element type: %u", element_type);
+
+ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
+
+ result = array_ref(v, 1, &idx, -1, typlen, typbyval, typalign, &isNull);
+
+ PG_RETURN_DATUM(result);
+}
/*
- * used by text_to_array() in varlena.c
+ * actually does the work for singleton_array(), and array_accum() if it is
+ * given a null input array.
*/
ArrayType *
-create_singleton_array(FunctionCallInfo fcinfo,
- Oid element_type,
- Datum element,
- int ndims)
+create_singleton_array(Oid element_type, Datum element, int ndims)
{
Datum dvalues[1];
int16 typlen;
@@ -303,7 +415,6 @@ create_singleton_array(FunctionCallInfo fcinfo,
int dims[MAXDIM];
int lbs[MAXDIM];
int i;
- ArrayMetaState *my_extra;
if (element_type == 0)
elog(ERROR, "Invalid array element type: %u", element_type);
@@ -318,35 +429,7 @@ create_singleton_array(FunctionCallInfo fcinfo,
lbs[i] = 1;
}
- /*
- * We arrange to look up info about element type only once per series
- * of calls, assuming the element type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- /* Get info about element type */
- get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typalign = typalign;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typalign = my_extra->typalign;
- }
+ get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
return construct_md_array(dvalues, ndims, dims, lbs, element_type,
typlen, typbyval, typalign);
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 27a805d9b28..c03d8c861d1 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.90 2003/06/24 23:14:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.91 2003/06/25 21:30:32 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,10 +21,8 @@
#include "catalog/pg_type.h"
#include "libpq/pqformat.h"
#include "parser/parse_coerce.h"
-#include "parser/parse_oper.h"
#include "utils/array.h"
#include "utils/builtins.h"
-#include "utils/datum.h"
#include "utils/memutils.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -72,6 +70,16 @@
#define RETURN_NULL(type) do { *isNull = true; return (type) 0; } while (0)
+/* I/O function selector for system_cache_lookup */
+typedef enum IOFuncSelector
+{
+ IOFunc_input,
+ IOFunc_output,
+ IOFunc_receive,
+ IOFunc_send
+} IOFuncSelector;
+
+
static int ArrayCount(char *str, int *dim, char typdelim);
static Datum *ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,
FmgrInfo *inputproc, Oid typelem, int32 typmod,
@@ -85,6 +93,10 @@ static Datum *ReadArrayBinary(StringInfo buf, int nitems,
static void CopyArrayEls(char *p, Datum *values, int nitems,
int typlen, bool typbyval, char typalign,
bool freedata);
+static void system_cache_lookup(Oid element_type, IOFuncSelector which_func,
+ int *typlen, bool *typbyval,
+ char *typdelim, Oid *typelem,
+ Oid *proc, char *typalign);
static Datum ArrayCast(char *value, bool byval, int len);
static int ArrayCastAndSet(Datum src,
int typlen, bool typbyval, char typalign,
@@ -107,7 +119,7 @@ static void array_insert_slice(int ndim, int *dim, int *lb,
char *destPtr,
int *st, int *endp, char *srcPtr,
int typlen, bool typbyval, char typalign);
-static int array_cmp(FunctionCallInfo fcinfo);
+
/*---------------------------------------------------------------------
* array_in :
@@ -142,49 +154,12 @@ array_in(PG_FUNCTION_ARGS)
dim[MAXDIM],
lBound[MAXDIM];
char typalign;
- ArrayMetaState *my_extra;
-
- /*
- * We arrange to look up info about element type, including its input
- * conversion proc only once per series of calls, assuming the element
- * type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
- if (my_extra->element_type != element_type)
- {
- /* Get info about element type, including its input conversion proc */
- get_type_metadata(element_type, IOFunc_input,
- &typlen, &typbyval, &typdelim,
- &typelem, &typinput, &typalign);
- fmgr_info(typinput, &inputproc);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = typinput;
- my_extra->typalign = typalign;
- my_extra->proc = inputproc;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typdelim = my_extra->typdelim;
- typelem = my_extra->typelem;
- typinput = my_extra->typiofunc;
- typalign = my_extra->typalign;
- inputproc = my_extra->proc;
- }
+ /* Get info about element type, including its input conversion proc */
+ system_cache_lookup(element_type, IOFunc_input,
+ &typlen, &typbyval, &typdelim,
+ &typelem, &typinput, &typalign);
+ fmgr_info(typinput, &inputproc);
/* Make a modifiable copy of the input */
/* XXX why are we allocating an extra 2 bytes here? */
@@ -661,51 +636,12 @@ array_out(PG_FUNCTION_ARGS)
indx[MAXDIM];
int ndim,
*dim;
- ArrayMetaState *my_extra;
element_type = ARR_ELEMTYPE(v);
-
- /*
- * We arrange to look up info about element type, including its input
- * conversion proc only once per series of calls, assuming the element
- * type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- /* Get info about element type, including its output conversion proc */
- get_type_metadata(element_type, IOFunc_output,
- &typlen, &typbyval, &typdelim,
- &typelem, &typoutput, &typalign);
- fmgr_info(typoutput, &outputproc);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = typoutput;
- my_extra->typalign = typalign;
- my_extra->proc = outputproc;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typdelim = my_extra->typdelim;
- typelem = my_extra->typelem;
- typoutput = my_extra->typiofunc;
- typalign = my_extra->typalign;
- outputproc = my_extra->proc;
- }
+ system_cache_lookup(element_type, IOFunc_output,
+ &typlen, &typbyval, &typdelim,
+ &typelem, &typoutput, &typalign);
+ fmgr_info(typoutput, &outputproc);
ndim = ARR_NDIM(v);
dim = ARR_DIMS(v);
@@ -864,7 +800,6 @@ array_recv(PG_FUNCTION_ARGS)
dim[MAXDIM],
lBound[MAXDIM];
char typalign;
- ArrayMetaState *my_extra;
/* Get the array header information */
ndim = pq_getmsgint(buf, 4);
@@ -896,50 +831,14 @@ array_recv(PG_FUNCTION_ARGS)
PG_RETURN_ARRAYTYPE_P(retval);
}
- /*
- * We arrange to look up info about element type, including its receive
- * conversion proc only once per series of calls, assuming the element
- * type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- /* Get info about element type, including its receive conversion proc */
- get_type_metadata(element_type, IOFunc_receive,
- &typlen, &typbyval, &typdelim,
- &typelem, &typreceive, &typalign);
- if (!OidIsValid(typreceive))
- elog(ERROR, "No binary input function available for type %s",
- format_type_be(element_type));
- fmgr_info(typreceive, &receiveproc);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = typreceive;
- my_extra->typalign = typalign;
- my_extra->proc = receiveproc;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typdelim = my_extra->typdelim;
- typelem = my_extra->typelem;
- typreceive = my_extra->typiofunc;
- typalign = my_extra->typalign;
- receiveproc = my_extra->proc;
- }
+ /* Get info about element type, including its receive conversion proc */
+ system_cache_lookup(element_type, IOFunc_receive,
+ &typlen, &typbyval, &typdelim,
+ &typelem, &typreceive, &typalign);
+ if (!OidIsValid(typreceive))
+ elog(ERROR, "No binary input function available for type %s",
+ format_type_be(element_type));
+ fmgr_info(typreceive, &receiveproc);
dataPtr = ReadArrayBinary(buf, nitems, &receiveproc, typelem,
typlen, typbyval, typalign,
@@ -1077,54 +976,15 @@ array_send(PG_FUNCTION_ARGS)
int ndim,
*dim;
StringInfoData buf;
- ArrayMetaState *my_extra;
/* Get information about the element type and the array dimensions */
element_type = ARR_ELEMTYPE(v);
-
- /*
- * We arrange to look up info about element type, including its send
- * proc only once per series of calls, assuming the element
- * type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- /* Get info about element type, including its send proc */
- get_type_metadata(element_type, IOFunc_send, &typlen, &typbyval,
- &typdelim, &typelem, &typsend, &typalign);
- if (!OidIsValid(typsend))
- elog(ERROR, "No binary output function available for type %s",
- format_type_be(element_type));
- fmgr_info(typsend, &sendproc);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = typsend;
- my_extra->typalign = typalign;
- my_extra->proc = sendproc;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typdelim = my_extra->typdelim;
- typelem = my_extra->typelem;
- typsend = my_extra->typiofunc;
- typalign = my_extra->typalign;
- sendproc = my_extra->proc;
- }
+ system_cache_lookup(element_type, IOFunc_send, &typlen, &typbyval,
+ &typdelim, &typelem, &typsend, &typalign);
+ if (!OidIsValid(typsend))
+ elog(ERROR, "No binary output function available for type %s",
+ format_type_be(element_type));
+ fmgr_info(typsend, &sendproc);
ndim = ARR_NDIM(v);
dim = ARR_DIMS(v);
@@ -1616,26 +1476,6 @@ array_set(ArrayType *array,
array = DatumGetArrayTypeP(PointerGetDatum(array));
ndim = ARR_NDIM(array);
-
- /*
- * if number of dims is zero, i.e. an empty array, create an array
- * with nSubscripts dimensions, and set the lower bounds to the supplied
- * subscripts
- */
- if (ndim == 0)
- {
- Oid elmtype = ARR_ELEMTYPE(array);
-
- for (i = 0; i < nSubscripts; i++)
- {
- dim[i] = 1;
- lb[i] = indx[i];
- }
-
- return construct_md_array(&dataValue, nSubscripts, dim, lb, elmtype,
- elmlen, elmbyval, elmalign);
- }
-
if (ndim != nSubscripts || ndim <= 0 || ndim > MAXDIM)
elog(ERROR, "Invalid array subscripts");
@@ -1792,31 +1632,6 @@ array_set_slice(ArrayType *array,
/* note: we assume srcArray contains no toasted elements */
ndim = ARR_NDIM(array);
-
- /*
- * if number of dims is zero, i.e. an empty array, create an array
- * with nSubscripts dimensions, and set the upper and lower bounds
- * to the supplied subscripts
- */
- if (ndim == 0)
- {
- Datum *dvalues;
- int nelems;
- Oid elmtype = ARR_ELEMTYPE(array);
-
- deconstruct_array(srcArray, elmtype, elmlen, elmbyval, elmalign,
- &dvalues, &nelems);
-
- for (i = 0; i < nSubscripts; i++)
- {
- dim[i] = 1 + upperIndx[i] - lowerIndx[i];
- lb[i] = lowerIndx[i];
- }
-
- return construct_md_array(dvalues, nSubscripts, dim, lb, elmtype,
- elmlen, elmbyval, elmalign);
- }
-
if (ndim < nSubscripts || ndim <= 0 || ndim > MAXDIM)
elog(ERROR, "Invalid array subscripts");
@@ -1996,13 +1811,6 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
Oid typelem;
Oid proc;
char *s;
- typedef struct {
- ArrayMetaState *inp_extra;
- ArrayMetaState *ret_extra;
- } am_extra;
- am_extra *my_extra;
- ArrayMetaState *inp_extra;
- ArrayMetaState *ret_extra;
/* Get input array */
if (fcinfo->nargs < 1)
@@ -2021,81 +1829,11 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType)
if (nitems <= 0)
PG_RETURN_ARRAYTYPE_P(v);
- /*
- * We arrange to look up info about input and return element types only
- * once per series of calls, assuming the element type doesn't change
- * underneath us.
- */
- my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(am_extra));
- my_extra = (am_extra *) fcinfo->flinfo->fn_extra;
-
- my_extra->inp_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- inp_extra = my_extra->inp_extra;
- inp_extra->element_type = InvalidOid;
-
- my_extra->ret_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- ret_extra = my_extra->ret_extra;
- ret_extra->element_type = InvalidOid;
- }
- else
- {
- inp_extra = my_extra->inp_extra;
- ret_extra = my_extra->ret_extra;
- }
-
- if (inp_extra->element_type != inpType)
- {
- /* Lookup source and result types. Unneeded variables are reused. */
- get_type_metadata(inpType, IOFunc_input, &inp_typlen, &inp_typbyval,
- &typdelim, &typelem, &proc, &inp_typalign);
-
- inp_extra->element_type = inpType;
- inp_extra->typlen = inp_typlen;
- inp_extra->typbyval = inp_typbyval;
- inp_extra->typdelim = typdelim;
- inp_extra->typelem = typelem;
- inp_extra->typiofunc = proc;
- inp_extra->typalign = inp_typalign;
- }
- else
- {
- inp_typlen = inp_extra->typlen;
- inp_typbyval = inp_extra->typbyval;
- typdelim = inp_extra->typdelim;
- typelem = inp_extra->typelem;
- proc = inp_extra->typiofunc;
- inp_typalign = inp_extra->typalign;
- }
-
- if (ret_extra->element_type != retType)
- {
- /* Lookup source and result types. Unneeded variables are reused. */
- get_type_metadata(retType, IOFunc_input, &typlen, &typbyval,
- &typdelim, &typelem, &proc, &typalign);
-
- ret_extra->element_type = retType;
- ret_extra->typlen = typlen;
- ret_extra->typbyval = typbyval;
- ret_extra->typdelim = typdelim;
- ret_extra->typelem = typelem;
- ret_extra->typiofunc = proc;
- ret_extra->typalign = typalign;
- }
- else
- {
- typlen = ret_extra->typlen;
- typbyval = ret_extra->typbyval;
- typdelim = ret_extra->typdelim;
- typelem = ret_extra->typelem;
- proc = ret_extra->typiofunc;
- typalign = ret_extra->typalign;
- }
+ /* Lookup source and result types. Unneeded variables are reused. */
+ system_cache_lookup(inpType, IOFunc_input, &inp_typlen, &inp_typbyval,
+ &typdelim, &typelem, &proc, &inp_typalign);
+ system_cache_lookup(retType, IOFunc_input, &typlen, &typbyval,
+ &typdelim, &typelem, &proc, &typalign);
/* Allocate temporary array for new values */
values = (Datum *) palloc(nitems * sizeof(Datum));
@@ -2311,6 +2049,8 @@ deconstruct_array(ArrayType *array,
* compares two arrays for equality
* result :
* returns true if the arrays are equal, false otherwise.
+ *
+ * XXX bitwise equality is pretty bogus ...
*-----------------------------------------------------------------------------
*/
Datum
@@ -2318,118 +2058,12 @@ array_eq(PG_FUNCTION_ARGS)
{
ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1);
- char *p1 = (char *) ARR_DATA_PTR(array1);
- char *p2 = (char *) ARR_DATA_PTR(array2);
- int ndims1 = ARR_NDIM(array1);
- int ndims2 = ARR_NDIM(array2);
- int *dims1 = ARR_DIMS(array1);
- int *dims2 = ARR_DIMS(array2);
- int nitems1 = ArrayGetNItems(ndims1, dims1);
- int nitems2 = ArrayGetNItems(ndims2, dims2);
- Oid element_type = ARR_ELEMTYPE(array1);
- FmgrInfo *ae_fmgr_info = fcinfo->flinfo;
bool result = true;
- int typlen;
- bool typbyval;
- char typdelim;
- Oid typelem;
- char typalign;
- Oid typiofunc;
- int i;
- ArrayMetaState *my_extra;
- FunctionCallInfoData locfcinfo;
- /* fast path if the arrays do not have the same number of elements */
- if (nitems1 != nitems2)
+ if (ARR_SIZE(array1) != ARR_SIZE(array2))
+ result = false;
+ else if (memcmp(array1, array2, ARR_SIZE(array1)) != 0)
result = false;
- else
- {
- /*
- * We arrange to look up the equality function only once per series of
- * calls, assuming the element type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra;
- if (my_extra == NULL)
- {
- ae_fmgr_info->fn_extra = MemoryContextAlloc(ae_fmgr_info->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- Oid opfuncid = equality_oper_funcid(element_type);
-
- if (OidIsValid(opfuncid))
- fmgr_info_cxt(opfuncid, &my_extra->proc, ae_fmgr_info->fn_mcxt);
- else
- elog(ERROR,
- "array_eq: cannot find equality operator for type: %u",
- element_type);
-
- get_type_metadata(element_type, IOFunc_output,
- &typlen, &typbyval, &typdelim,
- &typelem, &typiofunc, &typalign);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = typiofunc;
- my_extra->typalign = typalign;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typdelim = my_extra->typdelim;
- typelem = my_extra->typelem;
- typiofunc = my_extra->typiofunc;
- typalign = my_extra->typalign;
- }
-
- /*
- * apply the operator to each pair of array elements.
- */
- MemSet(&locfcinfo, 0, sizeof(locfcinfo));
- locfcinfo.flinfo = &my_extra->proc;
- locfcinfo.nargs = 2;
-
- /* Loop over source data */
- for (i = 0; i < nitems1; i++)
- {
- Datum elt1;
- Datum elt2;
- bool oprresult;
-
- /* Get element pair */
- elt1 = fetch_att(p1, typbyval, typlen);
- elt2 = fetch_att(p2, typbyval, typlen);
-
- p1 = att_addlength(p1, typlen, PointerGetDatum(p1));
- p1 = (char *) att_align(p1, typalign);
-
- p2 = att_addlength(p2, typlen, PointerGetDatum(p2));
- p2 = (char *) att_align(p2, typalign);
-
- /*
- * Apply the operator to the element pair
- */
- locfcinfo.arg[0] = elt1;
- locfcinfo.arg[1] = elt2;
- locfcinfo.argnull[0] = false;
- locfcinfo.argnull[1] = false;
- locfcinfo.isnull = false;
- oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
- if (!oprresult)
- {
- result = false;
- break;
- }
- }
- }
/* Avoid leaking memory when handed toasted input. */
PG_FREE_IF_COPY(array1, 0);
@@ -2439,190 +2073,53 @@ array_eq(PG_FUNCTION_ARGS)
}
-/*-----------------------------------------------------------------------------
- * array-array bool operators:
- * Given two arrays, iterate comparison operators
- * over the array. Uses logic similar to text comparison
- * functions, except element-by-element instead of
- * character-by-character.
- *----------------------------------------------------------------------------
- */
-Datum
-array_ne(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(!DatumGetBool(array_eq(fcinfo)));
-}
-
-Datum
-array_lt(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(array_cmp(fcinfo) < 0);
-}
-
-Datum
-array_gt(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(array_cmp(fcinfo) > 0);
-}
-
-Datum
-array_le(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(array_cmp(fcinfo) <= 0);
-}
-
-Datum
-array_ge(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(array_cmp(fcinfo) >= 0);
-}
-
-Datum
-btarraycmp(PG_FUNCTION_ARGS)
-{
- PG_RETURN_INT32(array_cmp(fcinfo));
-}
-
-/*
- * array_cmp()
- * Internal comparison function for arrays.
- *
- * Returns -1, 0 or 1
- */
-static int
-array_cmp(FunctionCallInfo fcinfo)
-{
- ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0);
- ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1);
- FmgrInfo *ac_fmgr_info = fcinfo->flinfo;
- Datum opresult;
- int result = 0;
- Oid element_type = InvalidOid;
- int typlen;
- bool typbyval;
- char typdelim;
- Oid typelem;
- char typalign;
- Oid typiofunc;
- Datum *dvalues1;
- int nelems1;
- Datum *dvalues2;
- int nelems2;
- int min_nelems;
- int i;
- typedef struct
- {
- Oid element_type;
- int typlen;
- bool typbyval;
- char typdelim;
- Oid typelem;
- Oid typiofunc;
- char typalign;
- FmgrInfo eqproc;
- FmgrInfo ordproc;
- } ac_extra;
- ac_extra *my_extra;
-
- element_type = ARR_ELEMTYPE(array1);
-
- /*
- * We arrange to look up the element type operator function only once
- * per series of calls, assuming the element type and opname don't
- * change underneath us.
- */
- my_extra = (ac_extra *) ac_fmgr_info->fn_extra;
- if (my_extra == NULL)
- {
- ac_fmgr_info->fn_extra = MemoryContextAlloc(ac_fmgr_info->fn_mcxt,
- sizeof(ac_extra));
- my_extra = (ac_extra *) ac_fmgr_info->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- Oid eqfuncid = equality_oper_funcid(element_type);
- Oid ordfuncid = ordering_oper_funcid(element_type);
-
- fmgr_info_cxt(eqfuncid, &my_extra->eqproc, ac_fmgr_info->fn_mcxt);
- fmgr_info_cxt(ordfuncid, &my_extra->ordproc, ac_fmgr_info->fn_mcxt);
-
- if (my_extra->eqproc.fn_nargs != 2)
- elog(ERROR, "Equality operator does not take 2 arguments: %u",
- eqfuncid);
- if (my_extra->ordproc.fn_nargs != 2)
- elog(ERROR, "Ordering operator does not take 2 arguments: %u",
- ordfuncid);
-
- get_type_metadata(element_type, IOFunc_output,
- &typlen, &typbyval, &typdelim,
- &typelem, &typiofunc, &typalign);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = InvalidOid;
- my_extra->typalign = typalign;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typalign = my_extra->typalign;
- }
-
- /* extract a C array of arg array datums */
- deconstruct_array(array1, element_type, typlen, typbyval, typalign,
- &dvalues1, &nelems1);
-
- deconstruct_array(array2, element_type, typlen, typbyval, typalign,
- &dvalues2, &nelems2);
-
- min_nelems = Min(nelems1, nelems2);
- for (i = 0; i < min_nelems; i++)
- {
- /* are they equal */
- opresult = FunctionCall2(&my_extra->eqproc,
- dvalues1[i], dvalues2[i]);
-
- if (!DatumGetBool(opresult))
- {
- /* nope, see if arg1 is less than arg2 */
- opresult = FunctionCall2(&my_extra->ordproc,
- dvalues1[i], dvalues2[i]);
- if (DatumGetBool(opresult))
- {
- /* arg1 is less than arg2 */
- result = -1;
- break;
- }
- else
- {
- /* arg1 is greater than arg2 */
- result = 1;
- break;
- }
- }
- }
-
- if ((result == 0) && (nelems1 != nelems2))
- result = (nelems1 < nelems2) ? -1 : 1;
-
- /* Avoid leaking memory when handed toasted input. */
- PG_FREE_IF_COPY(array1, 0);
- PG_FREE_IF_COPY(array2, 1);
-
- return result;
-}
-
-
/***************************************************************************/
/******************| Support Routines |*****************/
/***************************************************************************/
+static void
+system_cache_lookup(Oid element_type,
+ IOFuncSelector which_func,
+ int *typlen,
+ bool *typbyval,
+ char *typdelim,
+ Oid *typelem,
+ Oid *proc,
+ char *typalign)
+{
+ HeapTuple typeTuple;
+ Form_pg_type typeStruct;
+
+ typeTuple = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(element_type),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(typeTuple))
+ elog(ERROR, "cache lookup failed for type %u", element_type);
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
+
+ *typlen = typeStruct->typlen;
+ *typbyval = typeStruct->typbyval;
+ *typdelim = typeStruct->typdelim;
+ *typelem = typeStruct->typelem;
+ *typalign = typeStruct->typalign;
+ switch (which_func)
+ {
+ case IOFunc_input:
+ *proc = typeStruct->typinput;
+ break;
+ case IOFunc_output:
+ *proc = typeStruct->typoutput;
+ break;
+ case IOFunc_receive:
+ *proc = typeStruct->typreceive;
+ break;
+ case IOFunc_send:
+ *proc = typeStruct->typsend;
+ break;
+ }
+ ReleaseSysCache(typeTuple);
+}
+
/*
* Fetch array element at pointer, converted correctly to a Datum
*/
@@ -2926,18 +2423,6 @@ array_type_coerce(PG_FUNCTION_ARGS)
if (tgt_elem_type == InvalidOid)
elog(ERROR, "Target type is not an array");
- /*
- * We don't deal with domain constraints yet, so bail out.
- * This isn't currently a problem, because we also don't
- * support arrays of domain type elements either. But in the
- * future we might. At that point consideration should be given
- * to removing the check below and adding a domain constraints
- * check to the coercion.
- */
- if (getBaseType(tgt_elem_type) != tgt_elem_type)
- elog(ERROR, "array coercion to domain type elements not " \
- "currently supported");
-
if (!find_coercion_pathway(tgt_elem_type, src_elem_type,
COERCION_EXPLICIT, &funcId))
{
@@ -2954,16 +2439,10 @@ array_type_coerce(PG_FUNCTION_ARGS)
}
/*
- * If it's binary-compatible, modify the element type in the array header,
- * but otherwise leave the array as we received it.
+ * If it's binary-compatible, return the array unmodified.
*/
if (my_extra->coerce_finfo.fn_oid == InvalidOid)
- {
- ArrayType *result = DatumGetArrayTypePCopy(PG_GETARG_DATUM(0));
-
- ARR_ELEMTYPE(result) = my_extra->desttype;
- PG_RETURN_ARRAYTYPE_P(result);
- }
+ PG_RETURN_ARRAYTYPE_P(src);
/*
* Use array_map to apply the function to each array element.
@@ -2975,118 +2454,3 @@ array_type_coerce(PG_FUNCTION_ARGS)
return array_map(&locfcinfo, my_extra->srctype, my_extra->desttype);
}
-
-/*
- * accumArrayResult - accumulate one (more) Datum for an ARRAY_SUBLINK
- *
- * astate is working state (NULL on first call)
- * rcontext is where to keep working state
- */
-ArrayBuildState *
-accumArrayResult(ArrayBuildState *astate,
- Datum dvalue, bool disnull,
- Oid element_type,
- MemoryContext rcontext)
-{
- MemoryContext arr_context,
- oldcontext;
-
- if (astate == NULL)
- {
- /* First time through --- initialize */
-
- /* Make a temporary context to hold all the junk */
- arr_context = AllocSetContextCreate(rcontext,
- "accumArrayResult",
- ALLOCSET_DEFAULT_MINSIZE,
- ALLOCSET_DEFAULT_INITSIZE,
- ALLOCSET_DEFAULT_MAXSIZE);
- oldcontext = MemoryContextSwitchTo(arr_context);
- astate = (ArrayBuildState *) palloc(sizeof(ArrayBuildState));
- astate->mcontext = arr_context;
- astate->dvalues = (Datum *)
- palloc(ARRAY_ELEMS_CHUNKSIZE * sizeof(Datum));
- astate->nelems = 0;
- astate->element_type = element_type;
- get_typlenbyvalalign(element_type,
- &astate->typlen,
- &astate->typbyval,
- &astate->typalign);
- }
- else
- {
- oldcontext = MemoryContextSwitchTo(astate->mcontext);
- Assert(astate->element_type == element_type);
- /* enlarge dvalues[] if needed */
- if ((astate->nelems % ARRAY_ELEMS_CHUNKSIZE) == 0)
- astate->dvalues = (Datum *)
- repalloc(astate->dvalues,
- (astate->nelems + ARRAY_ELEMS_CHUNKSIZE) * sizeof(Datum));
- }
-
- if (disnull)
- elog(ERROR, "NULL elements not allowed in Arrays");
-
- /* Use datumCopy to ensure pass-by-ref stuff is copied into mcontext */
- astate->dvalues[astate->nelems++] =
- datumCopy(dvalue, astate->typbyval, astate->typlen);
-
- MemoryContextSwitchTo(oldcontext);
-
- return astate;
-}
-
-/*
- * makeArrayResult - produce final result of accumArrayResult
- *
- * astate is working state (not NULL)
- * rcontext is where to construct result
- */
-Datum
-makeArrayResult(ArrayBuildState *astate,
- MemoryContext rcontext)
-{
- int dims[1];
- int lbs[1];
-
- dims[0] = astate->nelems;
- lbs[0] = 1;
-
- return makeMdArrayResult(astate, 1, dims, lbs, rcontext);
-}
-
-/*
- * makeMdArrayResult - produce md final result of accumArrayResult
- *
- * astate is working state (not NULL)
- * rcontext is where to construct result
- */
-Datum
-makeMdArrayResult(ArrayBuildState *astate,
- int ndims,
- int *dims,
- int *lbs,
- MemoryContext rcontext)
-{
- ArrayType *result;
- MemoryContext oldcontext;
-
- /* Build the final array result in rcontext */
- oldcontext = MemoryContextSwitchTo(rcontext);
-
- result = construct_md_array(astate->dvalues,
- ndims,
- dims,
- lbs,
- astate->element_type,
- astate->typlen,
- astate->typbyval,
- astate->typalign);
-
- MemoryContextSwitchTo(oldcontext);
-
- /* Clean up all the junk */
- MemoryContextDelete(astate->mcontext);
-
- return PointerGetDatum(result);
-}
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index aca19d17e89..ce6443647e2 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.99 2003/06/24 23:14:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.100 2003/06/25 21:30:32 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,14 +19,11 @@
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "access/tuptoaster.h"
-#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "libpq/crypt.h"
#include "libpq/pqformat.h"
-#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/pg_locale.h"
-#include "utils/lsyscache.h"
typedef struct varlena unknown;
@@ -1986,7 +1983,8 @@ split_text(PG_FUNCTION_ARGS)
if (fldnum == 1) /* first field - just return the input
* string */
PG_RETURN_TEXT_P(inputstring);
- else /* otherwise return an empty string */
+ else
+/* otherwise return an empty string */
PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
}
@@ -2006,7 +2004,8 @@ split_text(PG_FUNCTION_ARGS)
if (fldnum == 1) /* first field - just return the input
* string */
PG_RETURN_TEXT_P(inputstring);
- else /* otherwise return an empty string */
+ else
+/* otherwise return an empty string */
PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
}
else if ((start_posn != 0) && (end_posn == 0))
@@ -2029,191 +2028,6 @@ split_text(PG_FUNCTION_ARGS)
}
}
-/*
- * text_to_array
- * parse input string
- * return text array of elements
- * based on provided field separator
- */
-Datum
-text_to_array(PG_FUNCTION_ARGS)
-{
- text *inputstring = PG_GETARG_TEXT_P(0);
- int inputstring_len = TEXTLEN(inputstring);
- text *fldsep = PG_GETARG_TEXT_P(1);
- int fldsep_len = TEXTLEN(fldsep);
- int fldnum;
- int start_posn = 0;
- int end_posn = 0;
- text *result_text = NULL;
- ArrayBuildState *astate = NULL;
- MemoryContext oldcontext = CurrentMemoryContext;
-
- /* return NULL for empty input string */
- if (inputstring_len < 1)
- PG_RETURN_NULL();
-
- /* empty field separator
- * return one element, 1D, array using the input string */
- if (fldsep_len < 1)
- PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
- CStringGetDatum(inputstring), 1));
-
- /* start with end position holding the initial start position */
- end_posn = 0;
- for (fldnum=1;;fldnum++) /* field number is 1 based */
- {
- Datum dvalue;
- bool disnull = false;
-
- start_posn = end_posn;
- end_posn = text_position(PointerGetDatum(inputstring),
- PointerGetDatum(fldsep),
- fldnum);
-
- if ((start_posn == 0) && (end_posn == 0)) /* fldsep not found */
- {
- if (fldnum == 1)
- {
- /* first element
- * return one element, 1D, array using the input string */
- PG_RETURN_ARRAYTYPE_P(create_singleton_array(fcinfo, TEXTOID,
- CStringGetDatum(inputstring), 1));
- }
- else
- {
- /* otherwise create array and exit */
- PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, oldcontext));
- }
- }
- else if ((start_posn != 0) && (end_posn == 0))
- {
- /* last field requested */
- result_text = text_substring(PointerGetDatum(inputstring), start_posn + fldsep_len, -1, true);
- }
- else if ((start_posn == 0) && (end_posn != 0))
- {
- /* first field requested */
- result_text = LEFT(inputstring, fldsep);
- }
- else
- {
- /* prior to last field requested */
- result_text = text_substring(PointerGetDatum(inputstring), start_posn + fldsep_len, end_posn - start_posn - fldsep_len, false);
- }
-
- /* stash away current value */
- dvalue = PointerGetDatum(result_text);
- astate = accumArrayResult(astate, dvalue,
- disnull, TEXTOID, oldcontext);
-
- }
-
- /* never reached -- keep compiler quiet */
- PG_RETURN_NULL();
-}
-
-/*
- * array_to_text
- * concatenate Cstring representation of input array elements
- * using provided field separator
- */
-Datum
-array_to_text(PG_FUNCTION_ARGS)
-{
- ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
- char *fldsep = PG_TEXTARG_GET_STR(1);
- int nitems, *dims, ndims;
- char *p;
- Oid element_type;
- int typlen;
- bool typbyval;
- char typdelim;
- Oid typoutput,
- typelem;
- FmgrInfo outputproc;
- char typalign;
- StringInfo result_str = makeStringInfo();
- int i;
- ArrayMetaState *my_extra;
-
- p = ARR_DATA_PTR(v);
- ndims = ARR_NDIM(v);
- dims = ARR_DIMS(v);
- nitems = ArrayGetNItems(ndims, dims);
-
- /* if there are no elements, return an empty string */
- if (nitems == 0)
- PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
-
- element_type = ARR_ELEMTYPE(v);
-
- /*
- * We arrange to look up info about element type, including its output
- * conversion proc only once per series of calls, assuming the element
- * type doesn't change underneath us.
- */
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- if (my_extra == NULL)
- {
- fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- /* Get info about element type, including its output conversion proc */
- get_type_metadata(element_type, IOFunc_output,
- &typlen, &typbyval, &typdelim,
- &typelem, &typoutput, &typalign);
- fmgr_info(typoutput, &outputproc);
-
- my_extra->element_type = element_type;
- my_extra->typlen = typlen;
- my_extra->typbyval = typbyval;
- my_extra->typdelim = typdelim;
- my_extra->typelem = typelem;
- my_extra->typiofunc = typoutput;
- my_extra->typalign = typalign;
- my_extra->proc = outputproc;
- }
- else
- {
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typdelim = my_extra->typdelim;
- typelem = my_extra->typelem;
- typoutput = my_extra->typiofunc;
- typalign = my_extra->typalign;
- outputproc = my_extra->proc;
- }
-
- for (i = 0; i < nitems; i++)
- {
- Datum itemvalue;
- char *value;
-
- itemvalue = fetch_att(p, typbyval, typlen);
-
- value = DatumGetCString(FunctionCall3(&outputproc,
- itemvalue,
- ObjectIdGetDatum(typelem),
- Int32GetDatum(-1)));
-
- if (i > 0)
- appendStringInfo(result_str, "%s%s", fldsep, value);
- else
- appendStringInfo(result_str, "%s", value);
-
- p = att_addlength(p, typlen, PointerGetDatum(p));
- p = (char *) att_align(p, typalign);
- }
-
- PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));
-}
-
#define HEXBASE 16
/*
* Convert a int32 to a string containing a base 16 (hex) representation of