@@ -176,6 +176,7 @@ static int extract_variadic_args_min(FunctionCallInfo fcinfo,
176176 int min_num_args );
177177static agtype_value * agtype_build_map_as_agtype_value (FunctionCallInfo fcinfo );
178178agtype_value * agtype_composite_to_agtype_value_binary (agtype * a );
179+ static agtype_value * tostring_helper (Datum arg , Oid type , char * msghdr );
179180
180181/* global storage of OID for agtype and _agtype */
181182static Oid g_AGTYPEOID = InvalidOid ;
@@ -2379,6 +2380,7 @@ static agtype_value *agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo)
23792380 result .res = push_agtype_value (& result .parse_state , WAGT_BEGIN_OBJECT ,
23802381 NULL );
23812382
2383+ /* iterate through the arguments and build the object */
23822384 for (i = 0 ; i < nargs ; i += 2 )
23832385 {
23842386 /* process key */
@@ -2389,7 +2391,25 @@ static agtype_value *agtype_build_map_as_agtype_value(FunctionCallInfo fcinfo)
23892391 errmsg ("argument %d: key must not be null" , i + 1 )));
23902392 }
23912393
2392- add_agtype (args [i ], false, & result , types [i ], true);
2394+ /*
2395+ * If the key is agtype, we need to extract it as an agtype string and
2396+ * push the value.
2397+ */
2398+ if (types [i ] == AGTYPEOID )
2399+ {
2400+ agtype_value * agtv = NULL ;
2401+
2402+ agtv = tostring_helper (args [i ], types [i ],
2403+ "agtype_build_map_as_agtype_value" );
2404+ result .res = push_agtype_value (& result .parse_state , WAGT_KEY , agtv );
2405+
2406+ /* free the agtype_value from tostring_helper */
2407+ pfree (agtv );
2408+ }
2409+ else
2410+ {
2411+ add_agtype (args [i ], false, & result , types [i ], true);
2412+ }
23932413
23942414 /* process value */
23952415 add_agtype (args [i + 1 ], nulls [i + 1 ], & result , types [i + 1 ], false);
@@ -6748,16 +6768,12 @@ PG_FUNCTION_INFO_V1(age_tostring);
67486768Datum age_tostring (PG_FUNCTION_ARGS )
67496769{
67506770 int nargs ;
6751- Datum * args ;
67526771 Datum arg ;
6753- bool * nulls ;
6754- Oid * types ;
6755- agtype_value agtv_result ;
6756- char * string = NULL ;
6757- Oid type ;
6772+ Oid type = InvalidOid ;
6773+ agtype * agt = NULL ;
6774+ agtype_value * agtv = NULL ;
67586775
6759- /* extract argument values */
6760- nargs = extract_variadic_args (fcinfo , 0 , true, & args , & types , & nulls );
6776+ nargs = PG_NARGS ();
67616777
67626778 /* check number of args */
67636779 if (nargs > 1 )
@@ -6767,19 +6783,70 @@ Datum age_tostring(PG_FUNCTION_ARGS)
67676783 }
67686784
67696785 /* check for null */
6770- if (nargs < 0 || nulls [ 0 ] )
6786+ if (nargs < 1 || PG_ARGISNULL ( 0 ) )
67716787 {
67726788 PG_RETURN_NULL ();
67736789 }
67746790
6791+ /* get the argument and type */
6792+ arg = PG_GETARG_DATUM (0 );
6793+ type = get_fn_expr_argtype (fcinfo -> flinfo , 0 );
6794+
6795+ /* verify that if the type is UNKNOWNOID it can be converted */
6796+ if (type == UNKNOWNOID && !get_fn_expr_arg_stable (fcinfo -> flinfo , 0 ))
6797+ {
6798+ ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
6799+ errmsg ("toString() UNKNOWNOID and not stable" )));
6800+ }
6801+
67756802 /*
67766803 * toString() supports integer, float, numeric, text, cstring, boolean,
67776804 * regtype or the agtypes: integer, float, numeric, string, boolean input
67786805 */
6779- arg = args [0 ];
6780- type = types [0 ];
6806+ agtv = tostring_helper (arg , type , "toString()" );
67816807
6782- if (type != AGTYPEOID )
6808+ /* if we get a NULL back we need to return NULL */
6809+ if (agtv == NULL )
6810+ {
6811+ PG_RETURN_NULL ();
6812+ }
6813+
6814+ /* convert to agtype and free the agtype_value */
6815+ agt = agtype_value_to_agtype (agtv );
6816+ pfree (agtv );
6817+
6818+ PG_RETURN_POINTER (agt );
6819+ }
6820+
6821+ /*
6822+ * Helper function to take any valid type and convert it to an agtype string.
6823+ * Returns NULL for NULL output.
6824+ */
6825+ static agtype_value * tostring_helper (Datum arg , Oid type , char * msghdr )
6826+ {
6827+ agtype_value * agtv_result = NULL ;
6828+ char * string = NULL ;
6829+
6830+ agtv_result = palloc0 (sizeof (agtype_value ));
6831+
6832+ /*
6833+ * toString() supports: unknown, integer, float, numeric, text, cstring,
6834+ * boolean, regtype or the agtypes: integer, float, numeric, string, and
6835+ * boolean input.
6836+ */
6837+
6838+ /*
6839+ * If the type is UNKNOWNOID convert it to a cstring. Prior to passing an
6840+ * UNKNOWNOID it should be verified to be stable.
6841+ */
6842+ if (type == UNKNOWNOID )
6843+ {
6844+ char * str = DatumGetPointer (arg );
6845+
6846+ string = pnstrdup (str , strlen (str ));
6847+ }
6848+ /* if it is not an AGTYPEOID */
6849+ else if (type != AGTYPEOID )
67836850 {
67846851 if (type == INT2OID )
67856852 {
@@ -6826,11 +6893,12 @@ Datum age_tostring(PG_FUNCTION_ARGS)
68266893 else
68276894 {
68286895 ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
6829- errmsg ("toString() unsupported argument type %d" ,
6830- type )));
6896+ errmsg ("%s unsupported argument type %d" ,
6897+ msghdr , type )));
68316898 }
68326899 }
6833- else
6900+ /* if it is an AGTYPEOID */
6901+ else if (type == AGTYPEOID )
68346902 {
68356903 agtype * agt_arg ;
68366904 agtype_value * agtv_value ;
@@ -6841,14 +6909,15 @@ Datum age_tostring(PG_FUNCTION_ARGS)
68416909 if (!AGT_ROOT_IS_SCALAR (agt_arg ))
68426910 {
68436911 ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
6844- errmsg ("toString() only supports scalar arguments" )));
6912+ errmsg ("%s only supports scalar arguments" ,
6913+ msghdr )));
68456914 }
68466915
68476916 agtv_value = get_ith_agtype_value_from_container (& agt_arg -> root , 0 );
68486917
68496918 if (agtv_value -> type == AGTV_NULL )
68506919 {
6851- PG_RETURN_NULL () ;
6920+ return NULL ;
68526921 }
68536922 else if (agtv_value -> type == AGTV_INTEGER )
68546923 {
@@ -6877,17 +6946,24 @@ Datum age_tostring(PG_FUNCTION_ARGS)
68776946 else
68786947 {
68796948 ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
6880- errmsg ("toString() unsupported argument agtype %d" ,
6881- agtv_value -> type )));
6949+ errmsg ("%s unsupported argument agtype %d" ,
6950+ msghdr , agtv_value -> type )));
68826951 }
68836952 }
6953+ /* it is an unknown type */
6954+ else
6955+ {
6956+ ereport (ERROR , (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
6957+ errmsg ("%s unknown argument agtype %d" ,
6958+ msghdr , type )));
6959+ }
68846960
68856961 /* build the result */
6886- agtv_result . type = AGTV_STRING ;
6887- agtv_result . val .string .val = string ;
6888- agtv_result . val .string .len = strlen (string );
6962+ agtv_result -> type = AGTV_STRING ;
6963+ agtv_result -> val .string .val = string ;
6964+ agtv_result -> val .string .len = strlen (string );
68896965
6890- PG_RETURN_POINTER ( agtype_value_to_agtype ( & agtv_result )) ;
6966+ return agtv_result ;
68916967}
68926968
68936969PG_FUNCTION_INFO_V1 (age_tostringlist );
0 commit comments