INSERT RULE beim Schreiben in View

Probleme und Fragen zum Thema Trigger und Funktionen.

INSERT RULE beim Schreiben in View

Beitragvon buzztea » Di 4. Nov 2008, 01:38

Hallo zusammen!

Ich hoffe ich hab mit dieser Frage das richtige Unterforum getroffen...

Ich schreibe eine rails-anwendung und ich habe folgendes Problem an dem ich mir im Moment die Zähne ausbeisse:

Ich habe einen View bestehend aus 2 Tabellen angelegt. Damit ich auch konsistent schreiben kann, habe ich die folgende INSERT RULE angelegt.

Code: Alles auswählen
    CREATE RULE extended_view_insert AS ON INSERT TO extended_view
        DO INSTEAD
        INSERT INTO base VALUES (
               DEFAULT,
               NEW.contact_first_name,
               NEW.contact_last_name,
               NEW.description,
        )
        RETURNING CAST(currval('base_id_seq'::text) AS integer);
die beiden Tabellen sind:

base:
id - serial
contact_first_name - string
contact_last_name - string
description - string

extension1:
base_id - integer
version - string

Ich würde gerne noch in die zweite Tabelle schreiben in der Rule, aber schon hier schreit der Ruby-Interpreter beim RAKE-Job rum.

Wenn ich kein Returning rausschreibe bei der INSERT-Operation meckert das ActiveRecord beim Einfügen mit folgender Meldung:

Mcannot perform INSERT RETURNING on relation "extended_view" HYou need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause.

Also versuche ich jetzt in meiner Rule die automatisch zugewiesene id aus base zurückzugeben, was jedoch leider nicht klappt.

Wenn ich in der letzten Zeile der Rule einfach schreibe "RETURNING id", bekomme ich die Meldung "RETURNING list has too few entries", genau wie bei der letzten Codezeile oben. Hat irgendjemand eine Ahnung was diese Meldung zu bedeuten hat?

Ich interpretiere dass momentan (in meiner totalen Unwissenheit) so, dass der interpreter versucht, die Rückgabe in Form eines Datensatzes von extended_view zurückzugeben, aber wie zum Henker gebe ich denn nur die id zurück, denn mehr brauche ich ja nicht.

Ich hoffe ihr könnt mir helfen, auf jeden Fall schonmal vielen Dank!

Grüße,

Buzztea
buzztea
Neuer Benutzer
 
Beiträge: 3
Registriert: Di 4. Nov 2008, 01:06

Beitragvon symbiont » Di 4. Nov 2008, 09:59

was soll denn ein RAKE-Job sein?
symbiont
Erfahrener Benutzer
 
Beiträge: 1328
Registriert: Mo 17. Mär 2008, 12:45
Wohnort: NULL

Beitragvon akretschmer » Di 4. Nov 2008, 10:10

buzztea hat geschrieben:Wenn ich in der letzten Zeile der Rule einfach schreibe "RETURNING id", bekomme ich die Meldung "RETURNING list has too few entries", genau wie bei der letzten Codezeile oben. Hat irgendjemand eine Ahnung was diese Meldung zu bedeuten hat?


Zu wenig Einträge. Frag mich jetzt nicht warum, aber offensichtlich muß eine RULE auf eine VIEW und RETURNIG bei Returning alle Felder des Views liefern:

Code: Alles auswählen
test=# create table foo1 (id serial primary key, t text);
NOTICE:  CREATE TABLE will create implicit sequence "foo1_id_seq" for serial column "foo1.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo1_pkey" for table "foo1"
CREATE TABLE
test=# create table foo2 (id int references foo1, s text);
CREATE TABLE
test=# create view view_foo as select foo1.*, foo2.s from foo1 left join foo2 on (foo1.id=foo2.id);
CREATE VIEW
test=# create or replace rule my_role_on_view_foo as on insert to view_foo do instead (insert into foo1 (id,t) values (NEW.id, NEW.t); insert into foo2 (id,s) values (NEW.id, NEW.s) returning  foo2.id, 'test1'::text,'test2'::text);
CREATE RULE
test=# insert into view_foo values (3, 'x','y');
INSERT 0 1


Du kannst in dieser Konstellation offensichtlich nicht gescheit mit Returning arbeiten.

Ich interpretiere dass momentan (in meiner totalen Unwissenheit) so, dass der interpreter versucht, die Rückgabe in Form eines Datensatzes von extended_view zurückzugeben, aber wie zum Henker gebe ich denn nur die id zurück, denn mehr brauche ich ja nicht.

Anschließend currval() aufrufen?

Andreas
--
ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)

https://www.xing.com/profile/Andreas_Kretschmer7
Hosting-Provider mit PostgreSQL-Support gesucht? Mich fragen!
akretschmer
Erfahrener Benutzer
 
Beiträge: 5938
Registriert: So 29. Okt 2006, 14:35
Wohnort: Kaufbach, Sachsen, Germany, Germany

Beitragvon buzztea » Di 4. Nov 2008, 11:09

Hallo und danke für euer Feedback!

@symbiont: mit Rake kannst du in einer Rails-Umgebung Operationen durchführen, z.B. wie in meinem Fall Datenmodell-Migration...

@akretschmer: Danke für deine Hilfe! Dein Beispiel hat mich schon einen Schritt weiter gebracht vom Verständnis. Ich habe also jetzt auch wie im Beispiel meine RETURNING-Klausel an die INSERT-Operation für die 2.Tabelle gehängt. Jetzt habe ich nur das Problem, dass ich nicht mehr an die Werte aus der ersten INSERT-Operation komme. Du schlägst currval() vor, kannst du mir sagen wie ich damit die geschriebenen Werte bekommen kann?

Ausserdem bekomme ich dauernd Fehler ala:

Code: Alles auswählen
RETURNING list's entry 2 has different type from column "contact_first_name"


Anscheinend passt die RETURNING-Klausel nicht auf den view, aber wie kann ich da genauere Infos bekommen?

Grüße und vielen Dank!
buzztea
Neuer Benutzer
 
Beiträge: 3
Registriert: Di 4. Nov 2008, 01:06

Beitragvon akretschmer » Di 4. Nov 2008, 11:41

buzztea hat geschrieben:Hallo und danke für euer Feedback!

@symbiont: mit Rake kannst du in einer Rails-Umgebung Operationen durchführen, z.B. wie in meinem Fall Datenmodell-Migration...

@akretschmer: Danke für deine Hilfe! Dein Beispiel hat mich schon einen Schritt weiter gebracht vom Verständnis. Ich habe also jetzt auch wie im Beispiel meine RETURNING-Klausel an die INSERT-Operation für die 2.Tabelle gehängt. Jetzt habe ich nur das Problem, dass ich nicht mehr an die Werte aus der ersten INSERT-Operation komme. Du schlägst currval() vor, kannst du mir sagen wie ich damit die geschriebenen Werte bekommen kann?


select currval('base_id_seq');

Ausserdem bekomme ich dauernd Fehler ala:

Code: Alles auswählen
RETURNING list's entry 2 has different type from column "contact_first_name"


Anscheinend passt die RETURNING-Klausel nicht auf den view, aber wie kann ich da genauere Infos bekommen?

Grüße und vielen Dank!


Ja, laß das RETURNING doch einfach weg, oder aber returniere alle Spalten des VIEWS.

Andreas
--
ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)

https://www.xing.com/profile/Andreas_Kretschmer7
Hosting-Provider mit PostgreSQL-Support gesucht? Mich fragen!
akretschmer
Erfahrener Benutzer
 
Beiträge: 5938
Registriert: So 29. Okt 2006, 14:35
Wohnort: Kaufbach, Sachsen, Germany, Germany

Beitragvon buzztea » Di 4. Nov 2008, 12:37

Hi Andreas,

es funktioniert endlich! Deine Tipps haben mir geholfen und ich zusammen mit ein paar Ungereimtheiten doie ich dazu schreiben musste klappt es jetzt.

Vielleicht hilft das hier mal irgendjemandem:

Ich habe immer die Meldung bekommen "RETURNING list's entry [nummer] has different type from column "[name der spalte]" "

Das Ganze hat letztendlich zu meiner totalen Verwirrung geführt. Es scheint bei der RETURNING-Klausel für VIEW INSERTs so zu sein, dass man präziser casten muss. In meinem Fall musste ich immer noch das casting von text zu varchar machen, obwohl das eigentlich von PostgreSQL erledigt werden sollte.

Eine letzte Frage hab ich noch. Kann ich currval() auch auf Nicht-sequenztypen anwenden, mir also normale Spaltenwerte die ich in die erste Tabelle geschrieben habe für die RETURNING-Klausel im 2. INSERT zurückholen? Muss ich dann einfach das _seq weglassen?

Entsprechend müsste ja folgendes richtig sein:

CAST(currval('opportunities_contact_first_name') AS varchar)



Viele Grüße,

Sebastian
buzztea
Neuer Benutzer
 
Beiträge: 3
Registriert: Di 4. Nov 2008, 01:06

Beitragvon akretschmer » Di 4. Nov 2008, 13:21

buzztea hat geschrieben:
Eine letzte Frage hab ich noch. Kann ich currval() auch auf Nicht-sequenztypen anwenden, mir also normale Spaltenwerte die ich in die erste Tabelle geschrieben habe für die RETURNING-Klausel im 2. INSERT zurückholen? Muss ich dann einfach das _seq weglassen?



Nein.

Aber zu Deinem Glück wurde select schon erfunden...

Andreas
--
ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)

https://www.xing.com/profile/Andreas_Kretschmer7
Hosting-Provider mit PostgreSQL-Support gesucht? Mich fragen!
akretschmer
Erfahrener Benutzer
 
Beiträge: 5938
Registriert: So 29. Okt 2006, 14:35
Wohnort: Kaufbach, Sachsen, Germany, Germany


Zurück zu Trigger und Funktionen

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste

cron