Como utilizar un array dinámico en función plpgsql

Lists: pgsql-es-ayuda
From: Conxita Marín <cmarin(at)dims(dot)com>
To: <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 07:29:10
Message-ID: 86D81900A3164F978746F096076C5F53@pc13
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Buenas.

Necesitaria utilizar un array de 2 dimensiones que puede tener de 1 a 999 elementos.

Algo así:

DROP FUNCTION pepe (integer);
CREATE FUNCTION pepe(tamano integer) RETURNS integer
AS $_$
declare
matriz integer[][];
i integer;
BEGIN
for i in 1..tamano loop
matriz[i][1] = 1;
matriz[i][2] = 2;
end loop;
return 0;
END;
$_$
LANGUAGE plpgsql;

Al intentar rellenar el array sale este error:

select pepe(10);
ERROR: invalid array subscripts
CONTEXT: PL/pgSQL function "pepe" line 7 at assignment

Buscando en los foros, parece ser que hay que inicializar el array en la declaración, és así?, si así es, ¿hay alguna manera de inicializar sin tener que declarar todos los elementos?

Saludos.

Conxita Marín
Desarrollos Informáticos Modulares de Software, S.L.
www.dims.com


From: Emanuel Calvo Franco <postgres(dot)arg(at)gmail(dot)com>
To: Conxita Marín <cmarin(at)dims(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 15:17:33
Message-ID: f205bb120904010817q747f39a0n10b665d0101c3f28@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

El día 1 de abril de 2009 4:29, Conxita Marín <cmarin(at)dims(dot)com> escribió:
> Buenas.
>
> Necesitaria utilizar un array de 2 dimensiones que puede tener de 1 a 999
> elementos.
>
> Algo así:
>
> DROP FUNCTION pepe (integer);
> CREATE FUNCTION pepe(tamano integer) RETURNS integer
>     AS $_$
> declare
>  matriz integer[][];
>  i integer;
> BEGIN
>   for i in 1..tamano loop
>    matriz[i][1] = 1;
>    matriz[i][2] = 2;
>   end loop;
>   return 0;
> END;
> $_$
>     LANGUAGE plpgsql;
>

No se si te sirve, lo hice con plperl.

CREATE OR REPLACE FUNCTION matriz(integer) returns integer language
'plperl' as $_$
$array = ();
my $numero = 0;
for ($numero;$numero < $_[0]; $numero++){
$array[$numero][1] = 1;
$array[$numero][2] = 2;
}
return 0;
$_$;

> Al intentar rellenar el array sale este error:
>
> select pepe(10);
> ERROR:  invalid array subscripts
> CONTEXT:  PL/pgSQL function "pepe" line 7 at assignment
> Buscando en los foros, parece ser que hay que inicializar el array en la
> declaración, és así?, si así es, ¿hay alguna manera de inicializar sin tener
> que declarar todos los elementos?
>
> Saludos.
>
> Conxita Marín
> Desarrollos Informáticos Modulares de Software, S.L.
> www.dims.com

--
Emanuel Calvo Franco
Sumate al ARPUG !
(www.postgres-arg.org -
www.arpug.com.ar)
ArPUG / AOSUG Member
Postgresql Support & Admin


From: Conxita Marín <cmarin(at)dims(dot)com>
To: "Emanuel Calvo Franco" <postgres(dot)arg(at)gmail(dot)com>
Cc: <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: [pgsql-es-ayuda] Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 17:08:28
Message-ID: 7B8496C873C24E4C87220EAFA7E68746@pc13
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Gracias por tu solución, el problema és que el código del resto de la
función es bastante complejo y ya està escrito en plpgsql.
Esperaré aun poco a ver si alguien me da otra solución simple en plpgsql,
sino tiraré de tablas temporales para implementar el vector.

Un saludo.

Conxita Marín
Desarrollos Informáticos Modulares de Software, S.L.
www.dims.com

----- Original Message -----
From: "Emanuel Calvo Franco" <postgres(dot)arg(at)gmail(dot)com>
To: "Conxita Marín" <cmarin(at)dims(dot)com>
Cc: <pgsql-es-ayuda(at)postgresql(dot)org>
Sent: Wednesday, April 01, 2009 5:17 PM
Subject: [pgsql-es-ayuda] Re: [pgsql-es-ayuda] Como utilizar un array
dinámico en función plpgsql

El día 1 de abril de 2009 4:29, Conxita Marín <cmarin(at)dims(dot)com> escribió:
> Buenas.
>
> Necesitaria utilizar un array de 2 dimensiones que puede tener de 1 a 999
> elementos.
>
> Algo así:
>
> DROP FUNCTION pepe (integer);
> CREATE FUNCTION pepe(tamano integer) RETURNS integer
> AS $_$
> declare
> matriz integer[][];
> i integer;
> BEGIN
> for i in 1..tamano loop
> matriz[i][1] = 1;
> matriz[i][2] = 2;
> end loop;
> return 0;
> END;
> $_$
> LANGUAGE plpgsql;
>

No se si te sirve, lo hice con plperl.

CREATE OR REPLACE FUNCTION matriz(integer) returns integer language
'plperl' as $_$
$array = ();
my $numero = 0;
for ($numero;$numero < $_[0]; $numero++){
$array[$numero][1] = 1;
$array[$numero][2] = 2;
}
return 0;
$_$;

> Al intentar rellenar el array sale este error:
>
> select pepe(10);
> ERROR: invalid array subscripts
> CONTEXT: PL/pgSQL function "pepe" line 7 at assignment
> Buscando en los foros, parece ser que hay que inicializar el array en la
> declaración, és así?, si así es, ¿hay alguna manera de inicializar sin
> tener
> que declarar todos los elementos?
>
> Saludos.
>
> Conxita Marín
> Desarrollos Informáticos Modulares de Software, S.L.
> www.dims.com

--
Emanuel Calvo Franco
Sumate al ARPUG !
(www.postgres-arg.org -
www.arpug.com.ar)
ArPUG / AOSUG Member
Postgresql Support & Admin
--
TIP 8: explain analyze es tu amigo


From: Miguel Angel <mvillagomez(at)sayab(dot)com(dot)mx>
To: Conxita Marín <cmarin(at)dims(dot)com>
Cc: Emanuel Calvo Franco <postgres(dot)arg(at)gmail(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Re: [pgsql-es-ayuda] Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 17:37:06
Message-ID: 1238607426.3469.1.camel@debian.gateway.2wire.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

El mié, 01-04-2009 a las 19:08 +0200, Conxita Marín escribió:
> Gracias por tu solución, el problema és que el código del resto de la
> función es bastante complejo y ya està escrito en plpgsql.
> Esperaré aun poco a ver si alguien me da otra solución simple en plpgsql,
> sino tiraré de tablas temporales para implementar el vector.

Algo más feo pero supongo que podrías considerar esto:

CREATE OR REPLACE FUNCTION pepe_master (integer) RETURNS VOID AS $BODY$
DECLARE
nombre_funcion VARCHAR:= 'pepe_child';
notificacion VARCHAR:= $$RAISE NOTICE 'Elemento:%
(%)',elemento,array[elemento];$$;
funcion VARCHAR:=
'
CREATE OR REPLACE FUNCTION ' || nombre_funcion || ' ()
RETURNS VOID AS $$
DECLARE
array INTEGER[' || $1 || '];
elemento INTEGER;
BEGIN
FOR elemento IN 1..' || $1 || ' LOOP
array[elemento]:=elemento;
' || notificacion || '
END LOOP;
END;
$$ LANGUAGE PLPGSQL;
';
garbage VARCHAR;
BEGIN
EXECUTE funcion;
EXECUTE 'SELECT ' || nombre_funcion || '()';
END;
$BODY$ LANGUAGE PLPGSQL;
SELECT pepe_master(10);

De hecho la otra solución que te dieron se me hizo mejor, pero bueno
aquí solo se aportan ideas.


From: Carlos Bazán <infobaz(at)vtr(dot)net>
To: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 17:47:47
Message-ID: 200904011347.48435.infobaz@vtr.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Yo lo acabo de hacer así:

DECLARE
mi_arreglo TEXT[] := '{}';
BEGIN
...
...
-- y lo alimento con
mi_arreglo := mi_arreglo || ARRAY[[rec.dato1::text, rec.dato2::text]];
...
etc.
Obviamente hay que preocuparse de los tipos de datos (entero, texto etc.)
dependiendo del tipo de arreglo.

Saludos
Carlos Bazán

El Wednesday 01 April 2009 13:08:28 Conxita Marín escribió:
> Gracias por tu solución, el problema és que el código del resto de la
> función es bastante complejo y ya està escrito en plpgsql.
> Esperaré aun poco a ver si alguien me da otra solución simple en plpgsql,
> sino tiraré de tablas temporales para implementar el vector.
>
> Un saludo.
>
> Conxita Marín
> Desarrollos Informáticos Modulares de Software, S.L.
> www.dims.com
>
> ----- Original Message -----
> From: "Emanuel Calvo Franco" <postgres(dot)arg(at)gmail(dot)com>
> To: "Conxita Marín" <cmarin(at)dims(dot)com>
> Cc: <pgsql-es-ayuda(at)postgresql(dot)org>
> Sent: Wednesday, April 01, 2009 5:17 PM
> Subject: [pgsql-es-ayuda] Re: [pgsql-es-ayuda] Como utilizar un array
> dinámico en función plpgsql
>
> El día 1 de abril de 2009 4:29, Conxita Marín <cmarin(at)dims(dot)com> escribió:
> > Buenas.
> >
> > Necesitaria utilizar un array de 2 dimensiones que puede tener de 1 a 999
> > elementos.
> >
> > Algo así:
> >
> > DROP FUNCTION pepe (integer);
> > CREATE FUNCTION pepe(tamano integer) RETURNS integer
> > AS $_$
> > declare
> > matriz integer[][];
> > i integer;
> > BEGIN
> > for i in 1..tamano loop
> > matriz[i][1] = 1;
> > matriz[i][2] = 2;
> > end loop;
> > return 0;
> > END;
> > $_$
> > LANGUAGE plpgsql;
>
> No se si te sirve, lo hice con plperl.
>
> CREATE OR REPLACE FUNCTION matriz(integer) returns integer language
> 'plperl' as $_$
> $array = ();
> my $numero = 0;
> for ($numero;$numero < $_[0]; $numero++){
> $array[$numero][1] = 1;
> $array[$numero][2] = 2;
> }
> return 0;
> $_$;
>
> > Al intentar rellenar el array sale este error:
> >
> > select pepe(10);
> > ERROR: invalid array subscripts
> > CONTEXT: PL/pgSQL function "pepe" line 7 at assignment
> > Buscando en los foros, parece ser que hay que inicializar el array en la
> > declaración, és así?, si así es, ¿hay alguna manera de inicializar sin
> > tener
> > que declarar todos los elementos?
> >
> > Saludos.
> >
> > Conxita Marín
> > Desarrollos Informáticos Modulares de Software, S.L.
> > www.dims.com


From: Emanuel Calvo Franco <postgres(dot)arg(at)gmail(dot)com>
To: Miguel Angel <mvillagomez(at)sayab(dot)com(dot)mx>
Cc: Conxita Marín <cmarin(at)dims(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: [pgsql-es-ayuda] Re: [pgsql-es-ayuda] Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 17:55:03
Message-ID: f205bb120904011055s8965b09ta72fa730fcaba1d6@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

El día 1 de abril de 2009 14:37, Miguel Angel
<mvillagomez(at)sayab(dot)com(dot)mx> escribió:
> El mié, 01-04-2009 a las 19:08 +0200, Conxita Marín escribió:
>> Gracias por tu solución, el problema és que el código del resto de la
>> función es bastante complejo y ya està escrito en plpgsql.
>> Esperaré  aun poco a ver si alguien me da otra solución simple en plpgsql,
>> sino tiraré de tablas temporales para implementar el vector.
>
> Algo más feo pero supongo que podrías considerar esto:
>
> CREATE OR REPLACE FUNCTION pepe_master (integer) RETURNS VOID AS $BODY$
> DECLARE
>  nombre_funcion VARCHAR:= 'pepe_child';
>  notificacion VARCHAR:= $$RAISE NOTICE 'Elemento:%
> (%)',elemento,array[elemento];$$;
>  funcion VARCHAR:=
>                  '
>                  CREATE OR REPLACE FUNCTION ' || nombre_funcion || ' ()
> RETURNS VOID AS $$
>                  DECLARE
>                   array INTEGER[' || $1 || '];
>                   elemento INTEGER;
>                  BEGIN
>                   FOR elemento IN 1..' || $1 || ' LOOP
>                     array[elemento]:=elemento;
>                     ' || notificacion || '
>                   END LOOP;
>                  END;
>                  $$ LANGUAGE PLPGSQL;
>                 ';
>  garbage VARCHAR;
> BEGIN
>  EXECUTE funcion;
>  EXECUTE 'SELECT ' || nombre_funcion || '()';
> END;
> $BODY$ LANGUAGE PLPGSQL;
> SELECT pepe_master(10);
>
>

Aca declaras una matriz de una sola dimension, calculo que
modificando un poco de codigo obtendrías un array multidimensional
variable.
Sin embargo si es una matriz unidimensional dinamica la siguiente
funcion anda:

CREATE OR REPLACE FUNCTION pepe(integer) RETURNS integer AS $_$
DECLARE
tamano alias for $1;
matriz integer[][]; -- no me equivoque
i integer ;
BEGIN
for i in 1..tamano loop
matriz[i] := 1;
RAISE NOTICE 'number: %', matriz[i];
end loop;

return i;
END;
$_$ LANGUAGE plpgsql;

Sin embargo, si modificamos el RAISE y ponemos
matriz[i][0] devuelve NULL (eso tiene sentido), pero
cuando le queremos asignar valor a esa variable, tira
el error de out of range (!)

> De hecho la otra solución que te dieron se me hizo mejor, pero bueno
> aquí solo se aportan ideas.
>
>

--
Emanuel Calvo Franco
Sumate al ARPUG !
(www.postgres-arg.org -
www.arpug.com.ar)
ArPUG / AOSUG Member
Postgresql Support & Admin


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Conxita Marín <cmarin(at)dims(dot)com>
Cc: pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 18:23:15
Message-ID: 20090401182315.GC7629@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Conxita Marín escribió:

> CREATE FUNCTION pepe(tamano integer) RETURNS integer
> AS $_$
> declare
> matriz integer[][];
> i integer;
> BEGIN
> for i in 1..tamano loop
> matriz[i][1] = 1;
> matriz[i][2] = 2;
> end loop;
> return 0;
> END;
> $_$
> LANGUAGE plpgsql;

Creo que esto debería poder hacerse de alguna forma sencilla pero no
tengo tiempo de buscarla en este momento; lo que conseguí fue lo
siguiente: (atención, código sin probar)

declare
matriz integer[] = '{{1,2}}';
i integer;
begin
for i in 1 .. tamano loop
matriz := matriz || '{1,2}'::integer[];
end loop;
end;

BTW es más fácil hacer "create or replace pepe" que "drop function;
create function".

--
Alvaro Herrera http://www.advogato.org/person/alvherre
"Hay que recordar que la existencia en el cosmos, y particularmente la
elaboración de civilizaciones dentro de él no son, por desgracia,
nada idílicas" (Ijon Tichy)


From: Emanuel Calvo Franco <postgres(dot)arg(at)gmail(dot)com>
To: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
Cc: Conxita Marín <cmarin(at)dims(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-01 18:35:45
Message-ID: f205bb120904011135v5f361927mf5a77fc44d215a27@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

El día 1 de abril de 2009 15:23, Alvaro Herrera
<alvherre(at)alvh(dot)no-ip(dot)org> escribió:
> Conxita Marín escribió:
>
>
> Creo que esto debería poder hacerse de alguna forma sencilla pero no
> tengo tiempo de buscarla en este momento; lo que conseguí fue lo
> siguiente: (atención, código sin probar)
>
> declare
>  matriz integer[] = '{{1,2}}';
>  i integer;
> begin
>  for i in 1 .. tamano loop
>    matriz := matriz || '{1,2}'::integer[];
>  end loop;
> end;
>

ubuntu=# CREATE OR REPLACE FUNCTION pepe(tamano integer) RETURNS integer AS $_$
ubuntu$# declare
ubuntu$# matriz integer[] = '{{1,2}}';
ubuntu$# i integer;
ubuntu$# begin
ubuntu$# for i in 1 .. tamano loop
ubuntu$# matriz := matriz || '{1,2}'::integer[];
ubuntu$# -- matriz[i] := 1;
ubuntu$# RAISE NOTICE 'matriz: %', matriz[i];
ubuntu$# end loop;
ubuntu$# return matriz[1];
ubuntu$# end;
ubuntu$# $_$ LANGUAGE plpgsql;
CREATE FUNCTION
ubuntu=# select pepe(8);
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
NOTICE: matriz: <NULL>
pepe
------

(1 row)

Faltaría asignarle los valores, pero no probé la asignación de
valores aún.

> BTW es más fácil hacer "create or replace pepe" que "drop function;
> create function".

seguro! :)

--
Emanuel Calvo Franco
Sumate al ARPUG !
(www.postgres-arg.org -
www.arpug.com.ar)
ArPUG / AOSUG Member
Postgresql Support & Admin


From: Conxita Marín <cmarin(at)dims(dot)com>
To: "Alvaro Herrera" <alvherre(at)alvh(dot)no-ip(dot)org>
Cc: <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-02 08:46:31
Message-ID: 4E2335F8EB5747218C693BA5F63312C1@pc13
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Alvaro Herrera escribió:

> Creo que esto debería poder hacerse de alguna forma sencilla pero no
> tengo tiempo de buscarla en este momento; lo que conseguí fue lo
> siguiente: (atención, código sin probar)
>
> declare
> matriz integer[] = '{{1,2}}';
> i integer;
> begin
> for i in 1 .. tamano loop
> matriz := matriz || '{1,2}'::integer[];
> end loop;
> end;
>

Perfecto, ya me sirve.

Gracias a todos por vuestras respuestas.

> BTW es más fácil hacer "create or replace pepe" que "drop function;
> create function".
>

Gracias también por el consejo ;).

Conxita Marín
Desarrollos Informáticos Modulares de Software, S.L.
www.dims.com


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Emanuel Calvo Franco <postgres(dot)arg(at)gmail(dot)com>
Cc: Conxita Marín <cmarin(at)dims(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Como utilizar un array dinámico en función plpgsql
Date: 2009-04-02 14:12:40
Message-ID: 20090402141240.GE3163@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

Emanuel Calvo Franco escribió:

> ubuntu$# begin
> ubuntu$# for i in 1 .. tamano loop
> ubuntu$# matriz := matriz || '{1,2}'::integer[];
> ubuntu$# -- matriz[i] := 1;
> ubuntu$# RAISE NOTICE 'matriz: %', matriz[i];
> ubuntu$# end loop;

Pero matriz es un array bidimensional ... esto funciona:

CREATE OR REPLACE FUNCTION pepe(tamano integer) RETURNS integer AS $_$
declare
matriz integer[] = '{{1,2}}';
i integer;
begin
for i in 1 .. tamano loop
matriz := matriz || '{1,2}'::integer[];
-- matriz[i] := 1;
RAISE NOTICE 'matriz: % %', matriz[i][1], matriz[i][2];
end loop;
return matriz[1];
end;
$_$ LANGUAGE plpgsql;

O si quieres ver el elemento i-ésimo completo,

RAISE NOTICE 'matriz: %', matriz[i:i][1:2];
(esto se llama un "slice" del array).

Si no sabes el tamaño de la segunda dimensión, puedes usar array_upper()
para pedirlo:
RAISE NOTICE 'matriz: %', matriz[i:i][array_upper(matriz, 2)];

Observa que esto es equivalente a
RAISE NOTICE 'matriz: %', matriz[i:i][1:array_upper(matriz, 2)];

puesto que The Fine Manual dice

If any dimension is written as a slice, i.e. contains a colon,
then all dimensions are treated as slices. Any dimension that
has only a single number (no colon) is treated as being from 1
to the number specified.

Normalmente los elementos empiezan de 1, pero puedes tener arreglos
raros que empiezan en otra subíndice, en cuyo caso lo que necesitas es
array_lower():
RAISE NOTICE 'matriz: %', matriz[i:i][array_lower(matriz, 2):array_upper(matriz, 2)];

Lo cual se puede probar si modificas el literal con que inicializas el
array:

CREATE OR REPLACE FUNCTION pepe(tamano integer) RETURNS integer AS $_$
declare
matriz integer[] = '[1:1][-1:0]={{1,2}}';
i integer;
begin
for i in 1 .. tamano loop
matriz := matriz || '[-1:0]={1,2}'::integer[];
-- matriz[i] := 1;
RAISE NOTICE 'matriz: %', matriz[i:i][array_lower(matriz, 2):array_upper(matriz, 2)];
end loop;
raise notice 'matriz: %', matriz;
return matriz[1];
end;
$_$ LANGUAGE plpgsql ;

alvherre=# select pepe(10);
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: {{1,2}}
NOTICE: matriz: [1:11][-1:0]={{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}}
pepe
------

(1 fila)

--
Alvaro Herrera Developer, http://www.PostgreSQL.org/
"Crear es tan difícil como ser libre" (Elsa Triolet)


From: Emanuel Calvo Franco <postgres(dot)arg(at)gmail(dot)com>
To: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
Cc: Conxita Marín <cmarin(at)dims(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: [pgsql-es-ayuda] Como utilizar un array dinámico en función plpgsql
Date: 2009-04-03 12:50:58
Message-ID: f205bb120904030550v23224336q179400f0a90b6b45@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-es-ayuda

El día 2 de abril de 2009 11:12, Alvaro Herrera
<alvherre(at)alvh(dot)no-ip(dot)org> escribió:
> Emanuel Calvo Franco escribió:
>
>> ubuntu$# begin
>> ubuntu$#  for i in 1 .. tamano loop
>> ubuntu$#    matriz := matriz || '{1,2}'::integer[];
>> ubuntu$#    -- matriz[i] := 1;
>> ubuntu$#    RAISE NOTICE 'matriz: %', matriz[i];
>> ubuntu$#  end loop;
>
> Pero matriz es un array bidimensional ... esto funciona:
>
> CREATE OR REPLACE FUNCTION pepe(tamano integer) RETURNS integer AS $_$
> declare
>  matriz integer[] = '{{1,2}}';
>  i integer;
> begin
>  for i in 1 .. tamano loop
>   matriz := matriz || '{1,2}'::integer[];
>   -- matriz[i] := 1;
>   RAISE NOTICE 'matriz: % %', matriz[i][1], matriz[i][2];
>  end loop;
>  return matriz[1];
> end;
> $_$ LANGUAGE plpgsql;
>
> O si quieres ver el elemento i-ésimo completo,
>
>        RAISE NOTICE 'matriz: %', matriz[i:i][1:2];
> (esto se llama un "slice" del array).
>
> Si no sabes el tamaño de la segunda dimensión, puedes usar array_upper()
> para pedirlo:
>        RAISE NOTICE 'matriz: %', matriz[i:i][array_upper(matriz, 2)];
>
> Observa que esto es equivalente a
>        RAISE NOTICE 'matriz: %', matriz[i:i][1:array_upper(matriz, 2)];
>
> puesto que The Fine Manual dice
>
>        If any dimension is written as a slice, i.e. contains a colon,
>        then all dimensions are treated as slices. Any dimension that
>        has only a single number (no colon) is treated as being from 1
>        to the number specified.
>
> Normalmente los elementos empiezan de 1, pero puedes tener arreglos
> raros que empiezan en otra subíndice, en cuyo caso lo que necesitas es
> array_lower():
>        RAISE NOTICE 'matriz: %', matriz[i:i][array_lower(matriz, 2):array_upper(matriz, 2)];
>
> Lo cual se puede probar si modificas el literal con que inicializas el
> array:
>
> CREATE OR REPLACE FUNCTION pepe(tamano integer) RETURNS integer AS $_$
> declare
>  matriz integer[] = '[1:1][-1:0]={{1,2}}';
>  i integer;
> begin
>  for i in 1 .. tamano loop
>   matriz := matriz || '[-1:0]={1,2}'::integer[];
>   -- matriz[i] := 1;
>   RAISE NOTICE 'matriz: %', matriz[i:i][array_lower(matriz, 2):array_upper(matriz, 2)];
>  end loop;
>  raise notice 'matriz: %', matriz;
>  return matriz[1];
> end;
> $_$ LANGUAGE plpgsql ;
>
> alvherre=# select pepe(10);
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: {{1,2}}
> NOTICE:  matriz: [1:11][-1:0]={{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}}
>  pepe
> ------
>
> (1 fila)
>
> --
> Alvaro Herrera                          Developer, http://www.PostgreSQL.org/
> "Crear es tan difícil como ser libre" (Elsa Triolet)
>

Genial explicación Alvaro!
Gracias!

--
Emanuel Calvo Franco
Sumate al ARPUG !
(www.postgres-arg.org -
www.arpug.com.ar)
ArPUG / AOSUG Member
Postgresql Support & Admin