* Aggregate function svec_pivot takes its float8 argument and appends it * to the state variable (an svec) to produce the concatenated return variable. * The StringInfo variables within the state variable svec are used in a way * that minimizes the number of memory re-allocations. * * Note that the first time this is called, the state variable should be null. */
| 707 | * Note that the first time this is called, the state variable should be null. |
| 708 | */ |
| 709 | Datum svec_pivot(PG_FUNCTION_ARGS) |
| 710 | { |
| 711 | SvecType *svec; |
| 712 | SparseData sdata; |
| 713 | float8 value; |
| 714 | |
| 715 | if (PG_ARGISNULL(1)) value = NVP; |
| 716 | else value = PG_GETARG_FLOAT8(1); |
| 717 | |
| 718 | if (! PG_ARGISNULL(0)) |
| 719 | { |
| 720 | svec = PG_GETARG_SVECTYPE_P_COPY(0); |
| 721 | } else { //first call, construct a new svec |
| 722 | /* |
| 723 | * Allocate space for the unique values and index |
| 724 | * |
| 725 | * Note that we do this manually because we are going to |
| 726 | * manage the memory allocations for the StringInfo structures |
| 727 | * manually within this aggregate so that we can preserve |
| 728 | * the intermediate state without re-serializing until there is |
| 729 | * a need to re-alloc, at which point we will re-serialize to |
| 730 | * form the returned state variable. |
| 731 | */ |
| 732 | svec = makeEmptySvec(1); |
| 733 | } |
| 734 | sdata = sdata_from_svec(svec); |
| 735 | |
| 736 | /* |
| 737 | * Add the incoming float8 value to the svec. |
| 738 | * |
| 739 | * First check to see if there is room in both the data area and index |
| 740 | * and if there isn't, re-alloc and recreate the svec |
| 741 | */ |
| 742 | if ( ((Size) (sdata->vals->len + sizeof(float8)+1) > (Size) sdata->vals->maxlen) |
| 743 | || ((Size) (sdata->index->len + 9 +1) > (Size) sdata->index->maxlen) ) |
| 744 | { |
| 745 | svec = reallocSvec(svec); |
| 746 | sdata = sdata_from_svec(svec); |
| 747 | } |
| 748 | |
| 749 | /* |
| 750 | * Now let's check to see if we're adding a new value or appending to |
| 751 | * the last run. If the incoming value is the same as the last value, |
| 752 | * just increment the last run. Note that we need to use the index |
| 753 | * cursor to find where the last index counter is located. |
| 754 | */ |
| 755 | { |
| 756 | char *index_location; |
| 757 | int old_index_storage_size; |
| 758 | int64 run_count; |
| 759 | float8 last_value=-100000; |
| 760 | bool new_run; |
| 761 | |
| 762 | if (sdata->index->len==0) //New vector |
| 763 | { |
| 764 | new_run=true; |
| 765 | index_location = sdata->index->data; |
| 766 | sdata->index->cursor = 0; |
nothing calls this directly
no test coverage detected