Conflicto de nomenclatura entre el parámetro de función y el resultado de UNIRSE con la cláusula USING

17

Dada esta configuración en Postgres 9.4 actual ( de esta pregunta relacionada ):

CREATE TABLE foo (ts, foo) AS 
VALUES (1, 'A')  -- int, text
     , (7, 'B');

CREATE TABLE bar (ts, bar) AS
VALUES (3, 'C')
     , (5, 'D')
     , (9, 'E');

También hay un SQL Fiddle de la pregunta anterior.

Escribí un SELECTcon un FULL JOINpara lograr el objetivo de la pregunta referenciada. Simplificado:

SELECT ts, f.foo, b.bar
FROM   foo f
FULL   JOIN bar b USING (ts);

Según las especificaciones, la forma correcta de abordar la columna tses sin calificación de tabla. Cualquiera de los valores de entrada ( f.tso b.ts) puede ser NULL. La USINGcláusula crea un caso extraño: presenta una columna de "entrada" que en realidad no está presente en la entrada. Hasta ahora muy elegante.

Puse esto en una función plpgsql. Por conveniencia (o requisitos) quiero los mismos nombres de columna para el resultado de la función de tabla. Por lo tanto, debemos evitar conflictos de nombres entre nombres de columna idénticos y parámetros de función. Debería evitarse eligiendo diferentes nombres, pero aquí estamos:

CREATE OR REPLACE FUNCTION f_merge_foobar()
  RETURNS TABLE(ts int, foo text, bar text) AS
$func$
BEGIN
   FOR ts, foo, bar IN
      SELECT COALESCE(f.ts, b.ts), f.foo, b.bar
      FROM   foo f
      FULL   JOIN bar b USING (ts)
   LOOP
      -- so something
      RETURN NEXT;
   END LOOP;
END
$func$ LANGUAGE plpgsql;

Negrita énfasis para resaltar el problema . No puedo usar tssin calificación de tabla como antes, porque plpgsql generaría una excepción (no estrictamente necesario, pero probablemente útil en la mayoría de los casos):

ERROR:  column reference "ts" is ambiguous
LINE 1: SELECT ts, f.foo, b.bar
               ^
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.

Sé que puedo usar diferentes nombres o una subconsulta o usar otra función. Pero me pregunto si hay una manera de hacer referencia a la columna. No puedo usar la calificación de tabla. Uno pensaría que debería haber un camino.
¿Esta ahí?

Erwin Brandstetter
fuente

Respuestas:

19

De acuerdo con los documentos PL / pgSQL Under the Hood , puede usar el parámetro de configuración plpgsql.variable_conflict, ya sea antes de crear la función o al comienzo de la definición de la función, declarando cómo desea que se resuelvan dichos conflictos (los 3 valores posibles son error(el valor predeterminado ) use_variabley use_column):

CREATE OR REPLACE FUNCTION pg_temp.f_merge_foobar()
  RETURNS TABLE(ts int, foo text, bar text) AS
$func$
#variable_conflict use_column             -- how to resolve conflicts
BEGIN
   FOR ts, foo, bar IN
      SELECT ts, f.foo, b.bar
      FROM   foo f
      FULL   JOIN bar b USING (ts)
   LOOP
      -- do something
      RETURN NEXT;
   END LOOP;
END
$func$ LANGUAGE plpgsql;
ypercubeᵀᴹ
fuente
1
Perfecto. Tuve la molesta sensación de que me faltaba algo. De hecho, recuerdo haber usado eso en el pasado. ¡Gracias!
Erwin Brandstetter