Обсуждение: Aggregate not working as expected

Поиск
Список
Период
Сортировка

Aggregate not working as expected

От
Craig Barnes
Дата:
Hello,

I have created a text concatenation function

CREATE OR REPLACE FUNCTION commacat(acc text, instr text) RETURNS text
    LANGUAGE plpgsql
    AS $$
  declare
    x text;
  BEGIN
    x := trim(both from acc);
    IF char_length(x) < 1  THEN
      RETURN instr;
    ELSE
      RETURN instr || ', ' || x;
    END IF;
  END;
$$;

Which when called works as expected.

SELECT commacat(' ','z')

> "z"

I have created an aggregate which calls the function.

CREATE AGGREGATE textcat_all (text)(
    SFUNC = commacat,
    STYPE = text,
    INITCOND = ''
);

But when called does not produce expected results

begin;
create temporary table x (y text);
insert into x values(' ');
insert into x values('abc');
insert into x values('def');
insert into x values('');
insert into x values('z');

> Query returned successfully: 1 row affected, 15 ms execution time.

select textcat_all(y) from x;

> "z, , def, abc"


I cannot find what it is that I am doing wrong.

Version string    PostgreSQL 9.0.1 on x86_64-unknown-linux-gnu,
compiled by GCC gcc (GCC) 4.4.5 20110214 (Red Hat 4.4.5-6), 64-bit

Re: Aggregate not working as expected

От
Thom Brown
Дата:
On 13 October 2011 10:06, Craig Barnes <cjbarnes18@gmail.com> wrote:
> Hello,
>
> I have created a text concatenation function
>
> CREATE OR REPLACE FUNCTION commacat(acc text, instr text) RETURNS text
>     LANGUAGE plpgsql
>     AS $$
>   declare
>     x text;
>   BEGIN
>     x := trim(both from acc);
>     IF char_length(x) < 1  THEN
>       RETURN instr;
>     ELSE
>       RETURN instr || ', ' || x;
>     END IF;
>   END;
> $$;
>
> Which when called works as expected.
>
> SELECT commacat(' ','z')
>
>> "z"
>
> I have created an aggregate which calls the function.
>
> CREATE AGGREGATE textcat_all (text)(
>     SFUNC = commacat,
>     STYPE = text,
>     INITCOND = ''
> );
>
> But when called does not produce expected results
>
> begin;
> create temporary table x (y text);
> insert into x values(' ');
> insert into x values('abc');
> insert into x values('def');
> insert into x values('');
> insert into x values('z');
>
>> Query returned successfully: 1 row affected, 15 ms execution time.
>
> select textcat_all(y) from x;
>
>> "z, , def, abc"
>
>
> I cannot find what it is that I am doing wrong.

If you're wondering why you've got a blank entry in the output, the
problem is that you are checking to see whether your accumulated
aggregate is empty, but not your input.

--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

Re: Aggregate not working as expected

От
Craig Barnes
Дата:
On 13 October 2011 11:04, Thom Brown <thom@linux.com> wrote:
> On 13 October 2011 10:06, Craig Barnes <cjbarnes18@gmail.com> wrote:
>> Hello,
>>
>> I have created a text concatenation function
>>
>> CREATE OR REPLACE FUNCTION commacat(acc text, instr text) RETURNS text
>>     LANGUAGE plpgsql
>>     AS $$
>>   declare
>>     x text;
>>   BEGIN
>>     x := trim(both from acc);
>>     IF char_length(x) < 1  THEN
>>       RETURN instr;
>>     ELSE
>>       RETURN instr || ', ' || x;
>>     END IF;
>>   END;
>> $$;
>>
>> Which when called works as expected.
>>
>> SELECT commacat(' ','z')
>>
>>> "z"
>>
>> I have created an aggregate which calls the function.
>>
>> CREATE AGGREGATE textcat_all (text)(
>>     SFUNC = commacat,
>>     STYPE = text,
>>     INITCOND = ''
>> );
>>
>> But when called does not produce expected results
>>
>> begin;
>> create temporary table x (y text);
>> insert into x values(' ');
>> insert into x values('abc');
>> insert into x values('def');
>> insert into x values('');
>> insert into x values('z');
>>
>>> Query returned successfully: 1 row affected, 15 ms execution time.
>>
>> select textcat_all(y) from x;
>>
>>> "z, , def, abc"
>>
>>
>> I cannot find what it is that I am doing wrong.
>
> If you're wondering why you've got a blank entry in the output, the
> problem is that you are checking to see whether your accumulated
> aggregate is empty, but not your input.
>
> --
> Thom Brown
> Twitter: @darkixion
> IRC (freenode): dark_ixion
> Registered Linux user: #516935
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>

Thanks Thom,

I understand what this snippet was intended to do now.

My result is.

CREATE OR REPLACE FUNCTION commacat(acc text, instr text) RETURNS text
   LANGUAGE plpgsql
   AS $$
 BEGIN
   IF acc IS NULL OR trim(both from acc) = '' THEN
     RETURN instr;
   ELSIF instr IS NULL OR trim(both ' ' from instr) = ''  THEN
     RETURN acc;
   ELSE
     RETURN acc || ', ' || instr;
   END IF;
 END;
$$;


Thanks Again

Craig