[caracas-pm] Como verificar la sintaxis de una función plPerl en postgres

Ernesto Hernández-Novich emhnemhn at gmail.com
Thu Aug 21 20:11:16 PDT 2014


On Tue, 2014-08-19 at 10:05 -0430, Monica Tahan wrote:
[...]
> Si, de hecho el script lo hicimos en pl/perlU.

Antes que comentar sobre la función en PL/perlU es pertinente aclarar
que la *única* razón para usar Perl como lenguaje almacenado en
PostgreSQL, es porque la manipulación que se va a hacer de los datos
requiere expresiones regulares *avanzadas* o alguna librería externa
provista con Perl para algo que no se puede hacer con PL/pgSQL.

PL/pgSQL tiene toda la funcionalidad necesaria para manipular datos,
aplicar expresiones regulares, operar sobre cadenas y números, efectuar
consultas estáticas o dinámicas paralelizables, y cuenta con las
estructuras de control para expresar algoritmos generales, con un
desempeño que ha de ser superior al de Perl porque se ahorra el paso de
datos a una máquina virtual diferente. No es necesario que den más
detalles sobre lo que intentan hacer con PL/perlU, pero reflexionen al
respecto porque es posible que lo que traten de hacer salga mucho más
fácil con PL/pgSQL.

Al final, PL/pgSQL debe ser el primer lenguaje almacenado a usar en
PostgreSQL, y PL/R el segundo, con cualquier otro en un *distante*
tercero.

>  Cuando corro la función desarrollada en pl/perlu me da error de
> sintaxis cerda de "xxxx". Con lo que no estamos muy claros es con
> spi_exec_query, me explico:

> Estamos haciendo una función que consulta unas tablas, y el resultado
> de la consulta devuelve un dato, es decir, no es un arreglo, sino un
> valor, para ello coloqué algo así:
> 
> 
> my $tabla_id = spi_exec_query("SELECT esquema.tabla.id from
> esquema.tabla WHERE esquema.tabla.nombre LIKE '% $valor%'") or
> elog(ERROR, qq{$tabla_id $!});

Interpolar $valor no es buena idea, pues se presta a ataques de
inyección de SQL. Es mejor usar quote_literal() o quote_ident() según el
caso, aunque lo realmente correcto es usar la familia

spi_prepare
spi_query_prepared
spi_exec_prepared
spi_freeplan

para que la consulta sea reutilizable. El código que presentan va a
hacerle daño al caché de instrucciones de PostgreSQL porque cada
invocación va a corresponder a una instrucción "diferente" cuando se
podría tener un plan de ejecución único reutilizable.

El error de sintaxis ocurre por usar 'or' como conector en una
expresión, pues el 'or' es una *instrucción* y no un *operador*. Citando
el manual 'perlop': Using "or" for assignment is unlikely to do what you
want; see below. Y cuando uno 'sees below' comprende que

my $variable = spi_exec_query(...) or elog(...)

en realidad es interpretado como

my ($variable = spi_exec_query(...)) or elog(...)

que es un error de sintaxis. Cambien 'or' por '||' o '//'.

> Deseo guardar en $tabla_id el valor que retorna el select, el cual no
> es un conjunto de datos, sino un solo dato, para ello es correcta la
> forma como está escrita la instrucción??? 

No.

> O debo hacer $datoquequiero = $tabla->{rows}; ????

Tampoco.

my $r = spi_exec_query(...)

Revisar el manual de PL/perl para PostgreSQL revela que el resultado de
spi_exec_query() es una referencia a un hash, una de cuyas claves es

$r->{rows}

que contiene todas las filas como un *arreglo de referencias a hashes*,
de manera que si quiero la columna 'foo' de la fila 42

$r->{rows}[42]->{foo}

Incidentalmente, un debugger no habría servido de nada, porque el error
fundamental aquí es de sintaxis, consecuencia de usar un 'or', así que
nunca habría llegado a ejecutar ni una instrucción. Personalmente,
hubiera seleccionado el trozo de Perl en mi editor (vim) e invocado
'perl -c' para confirmar la sintaxis, habría obtenido un

Found = in conditional, should be == at foo.pl line ...

y de allí se deduce el error que involucra el 'or'.
-- 
Ernesto Hernández-Novich - @iamemhn - Unix: Live free or die!
Geek by nature, Linux by choice, Debian of course.
If you can't aptitude it, it isn't useful or doesn't exist.
GPG Key Fingerprint = 0064 ADF5 EB5C DE16 99C1 6C56 F2A3 86B5 A757 E5A1



More information about the caracas-pm mailing list