2016-04-15 6 views
1

Ich benutze häufig variable_conflict use_variable, und bis jetzt hatte ich noch nie irgendwelche Probleme damit. Es funktioniert jedoch nicht mit ON CONFLICT Klausel von UPSERT. Hier ist meine Repro:Funktioniert variable_conflict use_variable nicht mit ON CONFLICT-Klausel von UPSERT?

CREATE TABLE test(id serial not null, 
    CONSTRAINT test_pk PRIMARY KEY(id), 
    category_id INT NOT NULL, 
    tname TEXT NOT NULL, 
    CONSTRAINT test_unq UNIQUE(category_id, tname), 
    some_info TEXT NOT NULL); 
CREATE OR REPLACE FUNCTION insert_test(category_id INT, tname TEXT, some_info TEXT) 
    RETURNS void AS 
$BODY$ 
#variable_conflict use_variable 
DECLARE 
    resultId INTEGER; 
BEGIN 
    INSERT INTO test(category_id, tname, some_info) 
     SELECT category_id, tname, some_info 
     ON CONFLICT(category_id, tname) DO NOTHING; 
END 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 

SELECT insert_test(1, 'Colors', 'Blue'); 

ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 
CONTEXT: SQL statement "INSERT INTO test(category_id, tname, some_info) 
     SELECT category_id, tname, some_info 
     ON CONFLICT(category_id, tname) DO NOTHING" 

Ohne #variable_conflict use_variable alles funktioniert:

CREATE OR REPLACE FUNCTION insert_test2(p_category_id INT, p_tname TEXT, p_some_info TEXT) 
    RETURNS void AS 
$BODY$ 
DECLARE 
    resultId INTEGER; 
BEGIN 
    INSERT INTO test(category_id, tname, some_info) 
     SELECT p_category_id, p_tname, p_some_info 
     ON CONFLICT(category_id, tname) DO NOTHING; 
END 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 

SELECT insert_test2(1, 'Colors', 'Blue'); 
SELECT insert_test2(2, 'Colors', 'Red'); 

Was bin ich?

+0

Sie sollten das in die Postgres (Bugs-) Mailing-Liste veröffentlichen. Aber im Allgemeinen ist es nicht empfehlenswert, Parameter zu verwenden, die sowieso den gleichen Namen wie Spalten haben. Daher sehe ich das Problem hier nicht. –

Antwort

1

ON CONFLICT Die Klausel stützt sich auf Indexdefinitionen, und die Indizes können in ihren Definitionen beliebige Ausdrücke verwenden (die sich nicht unbedingt auf die Tabellenspalten beziehen).

Sie können diese 9.5.2 in PostgreSQL tun:

test=# CREATE TABLE test (id BIGSERIAL NOT NULL PRIMARY KEY, value INT); 
CREATE TABLE 

test=# CREATE UNIQUE INDEX ix_test ON test (value, (1)); 
CREATE INDEX 

test=# INSERT INTO test (value) VALUES (1); 
INSERT 0 1 

test=# INSERT INTO test (value) VALUES (1); 
ERROR: duplicate key value violates unique constraint "ix_test" 
ПОДРОБНОСТИ: Key (value, (1))=(1, 1) already exists. 

test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (1)) DO NOTHING; 
INSERT 0 0 

test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (2)) DO NOTHING; 
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 

test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (id)) DO NOTHING; 
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 

test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (no_such_column)) DO NOTHING; 
ERROR: column "no_such_column" does not exist 
СТРОКА 1: ...INTO test (value) VALUES (1) ON CONFLICT (value, (no_such_co... 

test=# INSERT INTO test (value) SELECT * FROM (VALUES (1)) q (n) ON CONFLICT (value, (n)) DO NOTHING; 
ERROR: column "n" does not exist 
СТРОКА 1: ...CT * FROM (VALUES (1)) q (n) ON CONFLICT (value, (n)) DO NOT... 
ПОДСКАЗКА: There is a column named "n" in table "*SELECT*", but it cannot be referenced from this part of the query. 

test=# DROP FUNCTION IF EXISTS fn_test(INT); CREATE FUNCTION fn_test(n INT) RETURNS VOID AS $$ INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (n)) DO NOTHING; $$ LANGUAGE 'sql'; 
DROP FUNCTION 
CREATE FUNCTION 

test=# SELECT * FROM fn_test(1); 
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification 
КОНТЕКСТ: SQL function "fn_test" during startup 

Aus irgendeinem Grund, wenn eindeutigen Index Inferenz zu tun, erlaubt PostgreSQL Variablen in Indexausdrücke.

Es ist wahrscheinlich ein Fehler, weil ich keinen Grund denken kann, der gerechtfertigt wäre.

+0

Ihre Beschreibung ist am nützlichsten. Ich stimme zu: Das Feature macht wenig Sinn, könnte ein Fehler sein. Vielen Dank! – AlexC

+0

@AlexC: Ich habe es auf pgsql-Bugs veröffentlicht – Quassnoi