|
6 | 6 | * Copyright (c) 2003-2008, PostgreSQL Global Development Group
|
7 | 7 | *
|
8 | 8 | * IDENTIFICATION
|
9 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.24 2008/11/13 15:59:50 petere Exp $ |
| 9 | + * $PostgreSQL: pgsql/src/backend/utils/adt/array_userfuncs.c,v 1.25 2008/11/14 00:12:08 tgl Exp $ |
10 | 10 | *
|
11 | 11 | *-------------------------------------------------------------------------
|
12 | 12 | */
|
@@ -467,33 +467,57 @@ create_singleton_array(FunctionCallInfo fcinfo,
|
467 | 467 | typlen,typbyval,typalign);
|
468 | 468 | }
|
469 | 469 |
|
| 470 | + |
| 471 | +/* |
| 472 | + * ARRAY_AGG aggregate function |
| 473 | + */ |
470 | 474 | Datum
|
471 | 475 | array_agg_transfn(PG_FUNCTION_ARGS)
|
472 | 476 | {
|
473 | 477 | Oidarg1_typeid=get_fn_expr_argtype(fcinfo->flinfo,1);
|
| 478 | +ArrayBuildState*state; |
| 479 | +Datumelem; |
474 | 480 |
|
475 | 481 | if (arg1_typeid==InvalidOid)
|
476 |
| -ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
477 |
| -errmsg("could not determine input data type"))); |
| 482 | +ereport(ERROR, |
| 483 | +(errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 484 | +errmsg("could not determine input data type"))); |
478 | 485 |
|
479 | 486 | /* cannot be called directly because of internal-type argument */
|
480 | 487 | Assert(fcinfo->context&&IsA(fcinfo->context,AggState));
|
481 | 488 |
|
482 |
| -PG_RETURN_POINTER(accumArrayResult(PG_ARGISNULL(0) ?NULL : (ArrayBuildState*)PG_GETARG_POINTER(0), |
483 |
| -PG_ARGISNULL(1) ? (Datum)0 :PG_GETARG_DATUM(1), |
484 |
| -PG_ARGISNULL(1), |
485 |
| -arg1_typeid, |
486 |
| - ((AggState*)fcinfo->context)->aggcontext)); |
| 489 | +state=PG_ARGISNULL(0) ?NULL : (ArrayBuildState*)PG_GETARG_POINTER(0); |
| 490 | +elem=PG_ARGISNULL(1) ? (Datum)0 :PG_GETARG_DATUM(1); |
| 491 | +state=accumArrayResult(state, |
| 492 | +elem, |
| 493 | +PG_ARGISNULL(1), |
| 494 | +arg1_typeid, |
| 495 | + ((AggState*)fcinfo->context)->aggcontext); |
| 496 | + |
| 497 | +/* |
| 498 | + * We cheat quite a lot here by assuming that a pointer datum will be |
| 499 | + * preserved intact when nodeAgg.c thinks it is a value of type "internal". |
| 500 | + * This will in fact work because internal is stated to be pass-by-value |
| 501 | + * in pg_type.h, and nodeAgg will never do anything with a pass-by-value |
| 502 | + * transvalue except pass it around in Datum form. But it's mighty |
| 503 | + * shaky seeing that internal is also stated to be 4 bytes wide in |
| 504 | + * pg_type.h. If nodeAgg did put the value into a tuple this would |
| 505 | + * crash and burn on 64-bit machines. |
| 506 | + */ |
| 507 | +PG_RETURN_POINTER(state); |
487 | 508 | }
|
488 | 509 |
|
489 | 510 | Datum
|
490 | 511 | array_agg_finalfn(PG_FUNCTION_ARGS)
|
491 | 512 | {
|
| 513 | +ArrayBuildState*state; |
| 514 | + |
492 | 515 | /* cannot be called directly because of internal-type argument */
|
493 | 516 | Assert(fcinfo->context&&IsA(fcinfo->context,AggState));
|
494 | 517 |
|
495 | 518 | if (PG_ARGISNULL(0))
|
496 | 519 | PG_RETURN_NULL();/* returns null iff no input values */
|
497 | 520 |
|
498 |
| -PG_RETURN_ARRAYTYPE_P(makeArrayResult((ArrayBuildState*)PG_GETARG_POINTER(0),CurrentMemoryContext)); |
| 521 | +state= (ArrayBuildState*)PG_GETARG_POINTER(0); |
| 522 | +PG_RETURN_ARRAYTYPE_P(makeArrayResult(state,CurrentMemoryContext)); |
499 | 523 | }
|