View oder Tabelle je nach User

Ich hätte noch zwei Fragen: Kann man denn nicht die Regel die du auf die View gelegt hast auch auf die Tabelle legen?? Ich hab das Versucht allerdings scheint er Case nicht zu kennen. Gibts hier ne alternative??

Bei der Regel wird doch immer der current_user() abgefragt. Gibt es hier auch sowas wie current_role()? Current_role() zumindest hat nicht funktioniert.

Das war ein VIEW. Ein VIEW ist an sich nur ein hinterlegtes SELECT. Bei einem SELECT foo FROM myview; wird dies dann auf das dem View myview zugrundeliegende Select angewendet. Ich vermute mal, Du hast mit dem Case nur einen Syntaxfehler gebaut

Bei der Regel wird doch immer der current_user() abgefragt. Gibt es hier auch sowas wie current_role()? Current_role() zumindest hat nicht funktioniert.

Naja, eine Rule ist mehr als ein User. Ein User kann z.B. mehreren Rules angehören. Insofern macht es wenig sinn, nach einer current_rule zu fragen. Vielleicht ist dies für Dich aber interessant:

Gruß aus Chemnitz vom PostgreSL-Stand:
http://ads.wars-nicht.de/pictures/v/events/chemnitzer_linuxtage_2007/

Andreas

Das war ein VIEW. Ein VIEW ist an sich nur ein hinterlegtes SELECT. Bei einem SELECT foo FROM myview; wird dies dann auf das dem View myview zugrundeliegende Select angewendet. Ich vermute mal, Du hast mit dem Case nur einen Syntaxfehler gebaut

Die Regel auf der View hat ja einwandfrei funktioniert. Ich wollte die Regel aber nicht auf die View sondern auf die Tabelle legen. Deshalb auch die Frage.

Naja, eine Rule ist mehr als ein User. Ein User kann z.B. mehreren Rules angehören. Insofern macht es wenig sinn, nach einer current_rule zu fragen. Vielleicht ist dies für Dich aber interessant:

Ich meinte nicht eine rUle sondern eine rOle. Eine Gruppe. Aber in PG heist das doch role oder bin ich falsch informiert??

Für mich wäre das schon interressant denn so könnte ich sagen das diese und diese Benutzer die in der Rolle xyz sind alles sehen dürfen. Der Rest darf nur die hälfte sehen. Ansonsten muss ich alle Benutzer angeben die alles sehen dürfen.

Ist es denn so furchtbar was ich verlange. Sowas kommt doch im harten Alltag auch vor das manche Benutzer nicht alle Daten einer Tabelle sehen dürfen. Wie machen denn die des??

Du kannst Dir auch eine SRF (Set Returning Function) schreiben, Du mußt eben NICHT mal auf table und mal auf view selecten oder so.

Aufgrund von dieser Aussage hab ich mich mal mit SRF beschäftigt und binn so weit gekommen. Ich weis nicht ob ich da total auf dem Holzweg bin.

CREATE OR REPLACE FUNCTION personentabelle() RETURNS SETOF date AS $$
        BEGIN
                IF      has_table_privilege(person, 'select') 
                THEN
                        SELECT * FROM person;
		ELSE
			SELECT * FROM view_geheim
                END IF;
        END;
$$ LANGUAGE 'plpgsql';

Er meckert hier das ein Syntax Error bei “END” sei. Ich muss weiterhin einen Return Typ definieren welcher Typ ist das wenn ich, wie in meinem fall eine Tabelle oder View anzeigen lassen will?? Vielleicht kann mir einer Helfen wenigstens ein bisschen auf die richtige Spur zu kommen. Kann man das denn überhaupt so machen? Oder ist das weniger geeignet??

Man kann es so machen, man muß es aber richtig machen. Eine SRF muß ‘return next’ aufrufen, und Du mußt in einer Schleife durch das Reultat ‘latschen’.

Ich geb Dir hier mal ein simples Beispiel:

test=*# select * from foo;
 id | a | b
----+---+---
  1 | 1 | 1
  2 | 1 | 2
  3 | 2 | 2
  4 | 2 | 3
  5 | 2 | 2
(5 rows)

Time: 0.429 ms
test=*# create or replace function rt_foo(OUT i int, OUT j int) returns setof record as $$
declare r record; 
begin 
  for r in select a,b from foo loop 
    i=r.a;
    j=r.b;
    return next; 
  end loop; 
end;
$$language plpgsql;
CREATE FUNCTION
Time: 1.027 ms
test=*# select * from rt_foo();
 i | j
---+---
 1 | 1
 1 | 2
 2 | 2
 2 | 3
 2 | 2
(5 rows)

Andreas

Wunderbar nurn och eine kleine Frage.

rt_foo(OUT i int, OUT j int)

Hier muss ich angeben wie viele Spalten die Rückgabe hat. Ich hab aber mal 2 und mal mehrere kann ich da nicht einfach r zurückgebenlassen?? Oder wie kann ich das sonst machen??

Dann bräuchtest Du mehrere Funktionen, je nach Anzahl der Rückgabewerte. Alternative: gib ein Array zurück (bei gleichen Typen).

Wobei: vielleicht geht es auch mit Record:
To return a composite (row) value, you must write a record or row variable as the expression.

Probier es aus!

Andreas

Also ich habe wie du schon gesagt hast mit 2 Funktionen gearbeitet. Habe die beiden erstellt und solo funktionieren die 1a.

Jetzt hängt es aber hier er meckert mir einen Syntaxfehler beim IF an. Nach dem Motto wieso weshalb warum… Ich frag warum…geht das nicht. Wenn ich den Befehl

SELECT has_table_privilege(person.*, 'select')

alleine ausführe bekomm ich t als Ergebnis.

CREATE OR REPLACE FUNCTION personentabelle()
	IF SELECT has_table_privilege(person.*, 'select')
	THEN
		EXECUTE 'SELECT * FROM getperson()'
	ELSE
		EXECUTE 'SELECT * FROM getpersonview()'
	END IF;
  LANGUAGE 'plpgsql' VOLATILE;

Tja, ist halt syntaktisch flasch. Weder eine Deklaration der Return-Werte noch ein begin, nicht mal ein AS $$ oder ein RETURN NEXT oder so. Ich als Parser würd mich da auch schütteln…

Davon abgesehen: Du willst jetzt ganz bestimmt noch mal in Ruhe die Beispiele von mir und die Doku lesen, stimmts? Daher sage ich nix weiter.

Btw.: der nächste Syntax-Error kommt wohl spätestens bei user.* im Aufruf von has_table_privilege().


Andreas

Liebster Akretschmer. Ich glaube momentan ist es an der Zeit dir einmal ein Dankeschön auszusprechen. Danke das du immer noch mitliest. Dankeschön für die Zeit die du schon geopfert hast und die Gehirnzellen die du für mich verbraten hast.

Es ligt in meiner Natur immer widersprechen zu müssen. Also jetzt auch hier.
Ich habe die Doku schon gewälzt und die Beispiele von dir angeschaut. In der Doku finde ich kein Beispiel das sich auf mich anwenden lässt. Ich finde kein Beispiel wo ein einfaches SELECT nach einer Bedingung ausgeführt wird.

Der grundlegende Unterschied von deinem Beispiel und meinem Problem ist doch das ich gar keine Rückgabe habe sondern nur einen Aufruf.

Mit BEGIN und END habe ich schon experimentiert, das Ergebnis sah so aus:

CREATE OR REPLACE FUNCTION personentabelle()
  RETURNS SETOF record AS
$BODY$
	DECLARE r record; 
        BEGIN
                IF      has_table_privilege('person', 'select') 
                THEN
                        SELECT * FROM getperson();
		ELSE
			SELECT * FROM getpersonview();
                END IF;
        END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Dies lässt sich ausführen aber das Abfrageergebnis lautet: ERROR: a column definition list is required for functions returning “record”. Sorry da hört mein Latein auf. Ich würd ja mit Rückgaben arbeiten. Aber bitte sag mir doch mal einer was ich als Rückgabe für eine Abfrage angeben muss.

Wenn ich nun widerum durch die Abfrage latschen muss wie du schon oben beschrieben hast, dann ist das alles umsonst weil ich eine unterschiedliche Anzahl von Spalten habe. Und somit würden wir uns immer im Kreis bewegen.

Naja so ich hoffe das jetzt klar ist wo das Problem liegt. Ich komm auf jeden Fall nicht mehr weiter. Wenn du hier angekommen bist: Nochmal dankeschön

Mag sein. Nur, das, was zurück kommt (oder kommen soll) hat eine Tabellenstruktur, und diese muß irknwie bekannt sein.

Dies lässt sich ausführen aber das Abfrageergebnis lautet: ERROR: a column definition list is required for functions returning “record”. Sorry da hört mein Latein auf. Ich würd ja mit Rückgaben arbeiten. Aber bitte sag mir doch mal einer was ich als Rückgabe für eine Abfrage angeben muss.

Guggst Du: PostgreSQL: Re: a column definition list is required for functions returning "record"
Siehst nur auf den ersten Blick spanisch aus :wink:

Wenn ich nun widerum durch die Abfrage latschen muss wie du schon oben beschrieben hast, dann ist das alles umsonst weil ich eine unterschiedliche Anzahl von Spalten habe. Und somit würden wir uns immer im Kreis bewegen.


test=# select * from foo;
 a | b | c
---+---+---
 1 |   | 3
(1 row)

Time: 0.686 ms
test=*# create or replace function abc() returns setof record as $$begin select * from foo; end; $$language plpgsql;
CREATE FUNCTION
Time: 3.803 ms
test=*# select *  from abc() as (a int, b int, c int);
ERROR:  SELECT query has no destination for result data
HINT:  If you want to discard the results, use PERFORM instead.



Naja so ich hoffe das jetzt klar ist wo das Problem liegt. Ich komm auf jeden Fall nicht mehr weiter. Wenn du hier angekommen bist: Nochmal dankeschön

Meinst Du hier?

Vielleicht bin ich auch zu müde, außerdem hab ich grad noch was anderes vor um diese Zeit. Ich versuch morgen noch mal, Dein Problem chronologisch zu erfassen…

Andreas

Vielleicht kommst Du einfach zum Ziel, wenn Du für die Leute aus Y ein eigenes Schema anlegst, in dem der View liegt und diese auch keinen Zugriff auf das Schema mit der Table haben.

Dazu dann halt den Parameter SEARCH_PATH passend setzen:

ALTER ROLE name SET parameter { TO | = } { value | DEFAULT }

Andreas

Guggst Du: > http://archives.postgresql.org/pgsql...1/msg00904.php
Siehst nur auf den ersten Blick spanisch aus :wink:

Stimmt auf den ersten Blick. Und auf den zweiten auch. Ich bezieh mich hier auf die 3. Antwort. Ich denke mal das da die Antwort drinsteht.

regsalida (deptid int, deptname text);

Ich soll so eine Funktion erstellen. Aber was hat die für einen Sinn?

Pero al ver tu funcion veo que devuelves un select * from osea toda la tabla y si es asi te recomiendo que cambias el tipo devuelto de tu funcion a el tipo de la tabla que haces el select RETURNS SETOF record AS cambialo a setof nota(o como se llame tu tabla)

Davon versteh ich auch nichts. Kann einer von euch Spanisch?

declare  resultado record;
cambialo por
declare resultado nota%rowtype;
y debe funcionar

1 ist klar, 2 das ist spanisch, 3 vom sinn her: ich soll resultado (also
ein record) deklarieren mit tabellenname%rowtype , 4 es sollte dann
funktionieren??

2 versteh ich nicht
3 so?? r person%rowtype; Das funktioniert nicht. Syntax error

r tabellename%rowtype funktioniert. Bringt aber nichts gleiche Fehlermeldung.

Ziehe das mal bitte nicht so aus dem Kontext, wo ich die Antwort gab. Ich meinte exakt die Mail, die ich nannte, und auch nicht das dort zitierte, sondern das geschriebene. Ganz konkret, ich habe nur Deine Fehlermeldung an Google verfüttert und u.a. das erhalten. Und ganz konkret meinte ich dies hier:

select * from f_a_prrueba3() as (campo1 int, campo2 varchar(30), etc, etc);

Ich kann kein spanisch, leidlich englisch und a bissl deutsch, aber diese Antwort bezog sich auf:

> > ----------------------------------------------------------------------
> > -------- ERROR : a column definition list is required for functions
> > returning "record"
> > ----------------------------------------------------------------------

Und exakt dieses Problem hattest Du geschildert.


Ich zeigte Dir dann noch einen kleinen Schnellschuß von mir, hier noch einmal:

test=# select * from foo;
 a | b | c
---+---+---
 1 |   | 3
(1 row)

Time: 0.686 ms
test=*# create or replace function abc() returns setof record as $$begin select * from foo; end; $$language plpgsql;
CREATE FUNCTION
Time: 3.803 ms
test=*# select *  from abc() as (a int, b int, c int);
ERROR:  SELECT query has no destination for result data
HINT:  If you want to discard the results, use PERFORM instead.

Da hab ich das, was in der spanischen Mail stand, demonstriert. Und dazu noch die nächste Fehlermeldung, die Du bei Deinem gezeigten Code bekommen wirst, wenn Du das eben behandelte Problem gelöst hast:

ERROR:  SELECT query has no destination for result data
HINT:  If you want to discard the results, use PERFORM instead.

Du willst aber etwas rückgeben, also ‘mußt Du durch das Ergebnis latschen’.

Aber auch, wenn Du das geschafft hast, wirst Du ein Problem haben: Deine Zielstellung, irgend was schwammig formuliertes als Frage der DB vorzuwerfen und je nach Mondphase und Windrichtung was passendes als Antwort zu bekommen, wird so nicht gehen.

Deshalb hatte ich einen neuen Thread gemacht, um ausgehend von der allerersten Frage und dem bisher gesammelten Wissen vielleicht einen Weg aus dem Irrgarten zu zeigen. Schade, daß zwar die letzte Antwort in diesem neuen Thread war, sich aber auf den alten bezog.


Andreas, noch reichlich 1 Woche bis zum Urlaub…

So habe das Problem gelöst. Auf meine Weise aber es funktioniert. Ist vielleicht auch nicht ganz sauber…aber es funktioniert. Meinungen dazu interressieren mich auf jeden Fall. Besonders die von dir Akretschmer. Vielen Dank nochmal für deine Geduld.

Also.
Ich habe:
1 Tabelle person in der alles steht
1 View->Select * from person

Es gibt 2 Gruppen die einen sind Stäbe die anderen Leiter. Leiter dürfen nicht alles von Person sehen, Stäbe aber schon.

Stäbe bekommen Select auf Person
Leiter nicht, aber Select auf die View

Hier mein Script:

CREATE OR REPLACE FUNCTION getperson(OUT peid integer, OUT vorname character varying, OUT nachname character varying, OUT gebdat date, OUT strasse text, OUT plz text, OUT ort text, OUT telnr text, OUT email text, OUT jahrgang integer, OUT geschlecht integer)
  RETURNS SETOF record AS
$BODY$
	declare r record; 
	begin 
		IF has_table_privilege('person', 'select') 
		THEN
			 for r in select * from person 
				loop 
					peid=r.peid;
					vorname=r.vorname;
					nachname=r.nachname;
					gebdat=r.gebdat;
					strasse=r.strasse;
					plz=r.plz;
					ort=r.ort;
					telnr=r.telnr;
					email=r.email;
					jahrgang=r.jahrgang;
					geschlecht=r.geschlecht;
					return next; 
				end loop; 
		ELSE
			for r in select * from person 
				loop 
					peid=r.peid;
					vorname=r.vorname;
					nachname=r.nachname;
					geschlecht=r.geschlecht;
					gebdat=null;
					strasse=null;
					plz=null;
					ort=null;
					telnr=null;
					email=null;
					jahrgang=null;
					return next; 
				end loop; 
		END IF;
	end;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Funktioniert.

Ja, ist okay. Man kann sowas im übrigen auch direkt in SQL machen, mit CASE …, und damit einen VIEW erstellen. Aber letztendlich ist das egal. Hättest Du gleich das so klar beschrieben wie oben zitiert, hätte man Dir schneller helfen können.

Andreas

Andreas

Hi nochmal

wollte gerade mal die Sache mit dem case testen so wie du es vor ein paar postings geschrieben hast. Ich denke das ist auch eine interressante Lösung. Mein Problem ist nur ich kann nicht mehr als eine Spalte leer anzeigen lassen. Ich hab mir in der Doku das angeschaut, aber geholfen hat es nichts. Kannst du das hier auch noch schnell posten??

Ganz schnell:

test=*# select * from foo;
 a | b | c
---+---+---
 1 |   | 3
 2 | 3 | 4
 1 | 1 | 1
(3 rows)

Time: 1.381 ms
test=*# select a, case when a =1 then 0 else b end, case when a=1 then 0 else c end from foo;
 a | b | c
---+---+---
 1 | 0 | 0
 2 | 3 | 4
 1 | 0 | 0
(3 rows)

Anstelle der Bedingung a=1 kannst Du Deine Bedingung einsetzen.

Andreas

Hi, hab den Thread mal verfolgt und muss sagen wirklich interessant.

Seh ich das richtig, dass die User dann keine Rechte auf den view oder auf die tabelle haben, sondern “nur” die funktion aufrufen “getperson”?

Zusatzfrage: Kann ich einem Benutzer/gruppe Rechte geben eine Funktion auszuführen?