Virtuelle Felder ?!

ahoi nochmal …

also unter Virtuellen Feldern möchte ich Felder verstehen die man zwar “verwenden” kann aber keinen physischen Speicher-Ort besitzen.

Die Idee wäre, einen INSERT / COPY Befehl ein solches Feld befüllen zu lassen, dass physisch nicht existiert und in einem BEFORE INSERT Trigger auseinander zu tüteln und auf existierende Felder zu verteilen - fürs Insert etc.

Ist ein derartiges Konstrukt möglich? So könnte ich auf eine Dummy-Spalte verzichten.

Wenn nicht, dann Frage 2:
Wenn ich eine Spalte (character var…) mit der Länge 1 in einer Tabelle definiere, diese Spalte dann in einem INSERT bzw UPDATE etc. mit einem “beliebig” langen String befülle.
Wieviel davon kommt bei einem BEFORE INSERT / UPDATE an? Sind dort bereits Die Daten truncated worden bzw. werden vorher Fehler gemeldet?

Gruß

Kannst Du das nicht mit einer Funktion machen? Brauchst Du doch nicht ein “virtuelles Feld” oder einen Trigger dazu.

Anlass ist ja meine Import-Problematik mit COPY … sehr effizient dieser Befehl.

Idee ist es eben die ganze CSV - Zeile in 1 Spalte zu “inserten” (die nicht existieren muss - wenns sowas wie virtuelle Spalten an Tables gibt) und dann bei einem BEFORE INSERT Trigger aufzutröseln.

Wenn Du ne Idee hast wie COPY ne Funktion aufrufen kann? Immer her damit :slight_smile:

Kurze Antwort: warum probierst Du es nicht?
Lange Antwort: Nein.
Ganz lange Antwort:

test=# create table my_foo(field2 int);
CREATE TABLE
test=*# create function my_trigger() returns trigger as $$begin NEW.field2 = field1*2; return NEW;end; $$ language plpgsql;
CREATE FUNCTION
test=*# create trigger trg1 before insert on my_foo for each row execute procedure my_trigger();
CREATE TRIGGER
test=*# copy my_foo(field1) from stdin;
ERROR:  column "field1" of relation "my_foo" does not exist



Wenn nicht, dann Frage 2:
Wenn ich eine Spalte (character var…) mit der Länge 1 in einer Tabelle definiere, diese Spalte dann in einem INSERT bzw UPDATE etc. mit einem “beliebig” langen String befülle.
Wieviel davon kommt bei einem BEFORE INSERT / UPDATE an? Sind dort bereits Die Daten truncated worden bzw. werden vorher Fehler gemeldet?

Gruß

Geht auch nicht, weil vorher ein Fehler kommt. Das hier ist nicht MySQL, welches versucht, für Dich zu denken und daran scheitert.

Andreas

was haelst Du davon?

das View definiert dann eine Text - Spalte die kann ja virtual sein - was Views ja im grunde ohnehin sind.

und ein Rule uebernimmt dann das INSERT auf diese Spalte … hmm … da muss ich mal ein wenig experimentieren.

ich geb noch nicht auf :slight_smile: irgendwo muss doch PG toll sein … seine qualitäten verstecken g

Experimentiere mal und berichte uns, wie man mit einem select-statement, welches ja Daten liefert, gleichzeitig Daten speichern kann.

Andreas

Witzigerweise geht das sogar, zumindest ein wenig…

test=# create table my_foo(field1 int,field2 int);
CREATE TABLE
test=*# create view my_view as select ''::text as leere_spalte, * from my_foo;
CREATE VIEW
test=*# create rule my_rule as on insert to my_view do instead insert into my_foo(field2) values (new.leere_spalte::int);
CREATE RULE
test=*# insert into my_view values ('3',3,3);
INSERT 0 1
test=*# select * from my_foo;
 field1 | field2
--------+--------
        |      3
(1 row)

test=*# copy my_view from stdin;
ERROR:  cannot copy to view "my_view"

So ein Pech aber auch, gell?


Andreas

Du brauchst:

nen Table:

CREATE TABLE test.tbl
(
  "name" character varying(10),
  wert integer
)

ein View:

CREATE OR REPLACE VIEW test.imp AS 
 SELECT ''::text as data;

eine Funktion

create or replace function doInsert (text) returns int8
 as $BODY$ 

BEGIN 
  insert into test.tbl("name", wert) values ('hallo', 1);
  return 0; // TODO .. id .. wenn man eine in der Table haette
END; $BODY$  LANGUAGE 'plpgsql' VOLATILE;

eine Rule

CREATE OR REPLACE RULE imp_insert AS ON INSERT  TO test.imp 
    DO INSTEAD 
    SELECT doInsert(NEW.data::text);

… dann kannst du mit

insert into test.imp(data) values ('bla blub');

die inserts ausloesen …
ok … ich habe den text nicht aufgeloest … aber das funzt auch

dass COPY auf dieses View net will :angry:

tell news.

Andreas

Schreib mir einen Patch :slight_smile: … Immerhin behauptest Du ja immer, dass PG so fortschrittlich sei … es gibt keinen vernünftigen Grund warum COPY auf UPDATE-faehige VIEWs nicht funktionieren könne g

Dies Lösung für Dein Problem nannte ich Dir schon - mit einer Dummy-Tabelle hantieren.

Andreas

nur leider scheint COPY auf einer table auch die Rules nicht auszuloesen …
da bleibt nur zu hoffen, dass Trigger(-Funktionen) funzen

Sicher alles Lösbar - aber ohne Eleganz

Hab ne import-tabelle mit einem TEXT feld.
Darauf nen BEFORE INSERT Trigger mit folgender Funktion:

CREATE OR REPLACE FUNCTION test.doinsert()
  RETURNS "trigger" AS
$BODY$ 

BEGIN 
  insert into test.dataTbl("name", wert) values ('hallo', 1);
  return null;
END; $BODY$  LANGUAGE 'plpgsql' VOLATILE;

Und bei einem COPY bleibt die import-Table leer …
dataTbl wird gefuellt … naja … ein wenig Eleganz kann ich dem noch abgewinnen :slight_smile:

im Handbuch steht aber auch, dass Rules bei COPY nicht ausgelöst werden, Trigger jedoch schon. COPY ist halt schneller als INSERT und irgendeinen Preis wird man wohl oder übel für den Geschwindigkeitsvorteil zahlen müssen…

freilich ist es eben wie es ist … und sicher ist COPY sehr effizient wie es ist - was auch so bleiben soll.

Ich ordnet die Funktion in die Kategorie wie pg_dump ein - da kann man ja auch allen möglichen Quark abschalten … sowas koennte ich mir bei COPY auch vorstellen … der eine moechte die Trigger der andere die Rules ein dritter weder das Eine noch das Andere … wäre doch super, wenn das COPY noch ein wenig mehr an Generözität gewinne.

Eine Hand voll mehr optionale Funktionalität wird der Performance sicher nicht abträglich sein.

Wie dem auch sei - ich hab ne Lösung mit der ich leben kann