|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.174 2010/01/25 20:55:32 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.175 2010/02/01 03:14:43 itagaki Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
21 | 21 | #include"libpq/md5.h"
|
22 | 22 | #include"libpq/pqformat.h"
|
23 | 23 | #include"miscadmin.h"
|
| 24 | +#include"nodes/execnodes.h" |
24 | 25 | #include"parser/scansup.h"
|
25 | 26 | #include"regex/regex.h"
|
26 | 27 | #include"utils/builtins.h"
|
@@ -73,6 +74,7 @@ static bytea *bytea_substring(Datum str,
|
73 | 74 | intL,
|
74 | 75 | boollength_not_specified);
|
75 | 76 | staticbytea*bytea_overlay(bytea*t1,bytea*t2,intsp,intsl);
|
| 77 | +staticStringInfomakeStringAggState(fmNodePtrcontext); |
76 | 78 |
|
77 | 79 |
|
78 | 80 | /*****************************************************************************
|
@@ -3315,3 +3317,105 @@ pg_column_size(PG_FUNCTION_ARGS)
|
3315 | 3317 |
|
3316 | 3318 | PG_RETURN_INT32(result);
|
3317 | 3319 | }
|
| 3320 | + |
| 3321 | +/* |
| 3322 | + * string_agg - Concatenates values and returns string. |
| 3323 | + * |
| 3324 | + * Syntax: string_agg(value text, delimiter text = '') RETURNS text |
| 3325 | + * |
| 3326 | + * Note: Any NULL values are ignored. The first-call delimiter isn't |
| 3327 | + * actually used at all, and on subsequent calls the delimiter precedes |
| 3328 | + * the associated value. |
| 3329 | + */ |
| 3330 | +staticStringInfo |
| 3331 | +makeStringAggState(fmNodePtrcontext) |
| 3332 | +{ |
| 3333 | +StringInfostate; |
| 3334 | +MemoryContextaggcontext; |
| 3335 | +MemoryContextoldcontext; |
| 3336 | + |
| 3337 | +if (context&&IsA(context,AggState)) |
| 3338 | +aggcontext= ((AggState*)context)->aggcontext; |
| 3339 | +elseif (context&&IsA(context,WindowAggState)) |
| 3340 | +aggcontext= ((WindowAggState*)context)->wincontext; |
| 3341 | +else |
| 3342 | +{ |
| 3343 | +/* cannot be called directly because of internal-type argument */ |
| 3344 | +elog(ERROR,"string_agg_transfn called in non-aggregate context"); |
| 3345 | +aggcontext=NULL;/* keep compiler quiet */ |
| 3346 | +} |
| 3347 | + |
| 3348 | +/* Create state in aggregate context */ |
| 3349 | +oldcontext=MemoryContextSwitchTo(aggcontext); |
| 3350 | +state=makeStringInfo(); |
| 3351 | +MemoryContextSwitchTo(oldcontext); |
| 3352 | + |
| 3353 | +returnstate; |
| 3354 | +} |
| 3355 | + |
| 3356 | +Datum |
| 3357 | +string_agg_transfn(PG_FUNCTION_ARGS) |
| 3358 | +{ |
| 3359 | +StringInfostate; |
| 3360 | + |
| 3361 | +state=PG_ARGISNULL(0) ?NULL : (StringInfo)PG_GETARG_POINTER(0); |
| 3362 | + |
| 3363 | +/* Append the element unless not null. */ |
| 3364 | +if (!PG_ARGISNULL(1)) |
| 3365 | +{ |
| 3366 | +if (state==NULL) |
| 3367 | +state=makeStringAggState(fcinfo->context); |
| 3368 | +appendStringInfoText(state,PG_GETARG_TEXT_PP(1));/* value */ |
| 3369 | +} |
| 3370 | + |
| 3371 | +/* |
| 3372 | + * The transition type for string_agg() is declared to be "internal", which |
| 3373 | + * is a pass-by-value type the same size as a pointer. |
| 3374 | + */ |
| 3375 | +PG_RETURN_POINTER(state); |
| 3376 | +} |
| 3377 | + |
| 3378 | +Datum |
| 3379 | +string_agg_delim_transfn(PG_FUNCTION_ARGS) |
| 3380 | +{ |
| 3381 | +StringInfostate; |
| 3382 | + |
| 3383 | +state=PG_ARGISNULL(0) ?NULL : (StringInfo)PG_GETARG_POINTER(0); |
| 3384 | + |
| 3385 | +/* Append the value unless not null. */ |
| 3386 | +if (!PG_ARGISNULL(1)) |
| 3387 | +{ |
| 3388 | +if (state==NULL) |
| 3389 | +state=makeStringAggState(fcinfo->context); |
| 3390 | +elseif (!PG_ARGISNULL(2)) |
| 3391 | +appendStringInfoText(state,PG_GETARG_TEXT_PP(2));/* delimiter */ |
| 3392 | + |
| 3393 | +appendStringInfoText(state,PG_GETARG_TEXT_PP(1));/* value */ |
| 3394 | +} |
| 3395 | + |
| 3396 | +/* |
| 3397 | + * The transition type for string_agg() is declared to be "internal", which |
| 3398 | + * is a pass-by-value type the same size as a pointer. |
| 3399 | + */ |
| 3400 | +PG_RETURN_POINTER(state); |
| 3401 | +} |
| 3402 | + |
| 3403 | +Datum |
| 3404 | +string_agg_finalfn(PG_FUNCTION_ARGS) |
| 3405 | +{ |
| 3406 | +StringInfostate; |
| 3407 | + |
| 3408 | +if (PG_ARGISNULL(0)) |
| 3409 | +PG_RETURN_NULL(); |
| 3410 | + |
| 3411 | +/* cannot be called directly because of internal-type argument */ |
| 3412 | +Assert(fcinfo->context&& |
| 3413 | + (IsA(fcinfo->context,AggState)|| |
| 3414 | +IsA(fcinfo->context,WindowAggState))); |
| 3415 | + |
| 3416 | +state= (StringInfo)PG_GETARG_POINTER(0); |
| 3417 | +if (state!=NULL) |
| 3418 | +PG_RETURN_TEXT_P(cstring_to_text(state->data)); |
| 3419 | +else |
| 3420 | +PG_RETURN_NULL(); |
| 3421 | +} |