Synonyme in PostgreSQL

HI zusammen,

wie schön öfter hier erwähnt habe wir ein Applikation von Gupta SQL-Base nach PostgreSQL umgestellt. Inzwischen sind wir (ich) daran hier ein Tool zu entwickeln, das einen möglichst problemfreien Umstieg auf die PostgreSQL anbietet, da wir noch mehr Kunden haben, die diesen Weg gehen wollen.
Jatzt habe ich folgendes Problem, und zwar mit Synonymen. Hier habe ich in der PostgreSQL gar nichts gefunden. Deswegen kurz zur Erläuterung, worum es hier geht.
Ich lege in dem Schema A eine Tabelle Kunde an, damit der User B (In der SQL-Base sind Schema und User identisch) nicht mit A.Kunde auf die Tabelle zugreifen muss, sondern mit B.Kunde, kann ich ein Synonym anlegen (Create Synonym B.Kunde for A.Kunde).

Noch besser (schlimmer?) sind sogenannte Public-Synonyme. Hier muss ich nicht ein Synonym einzeln für jeden User anlegen, sondern es reicht ein Public Synonym anzulegen (Create Public Synonym Kunde for A.Kunde) und jeder User kann dann mit seinem User in der Form User.Kunde auf die Tabelle zugreifen.

Jetzt die Frage: Kann ich so etwas in PostgreSQL nachbilden ? Die einzige Idee, die ich hatte waren Views anzulegen, aber das ist natürlich nicht gerade der Brüller, vor allem wenn Public Synonyme verwendet werden. Denn hier müßte ich ja für jede Kobination User x Objekt einen View anlegen, was rein rechnerisch bei 500 Tabellen und 100 User schon in 50.000 Views ausartet. Das kann ja keiner pflegen.

Habt ihr da noch eine Idee, wie gesagt ist mir leider nichts anderes eingefallen.

Vielen Dank und Grüße

Jürgen Spatz
fecher

So ganz hab ich es nicht verstanden, aber möglicherweise geht es mit Rollen.
PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: Database Roles and Privileges

Andreas

Könntest du vielleicht noch genauer erklären, was die Synonyme bewirken - wenn es keine Views sind?

Vielleicht aber auch search_path und Schemas. Deine PUBLIC-beschreibung klingt zumindest etwas danach…

Andreas

Hi zusammen,

anscheinend muss ich das mit den Synonymen besser erklären:
Wie gesagt sind in der Quelldatenbank User und Schema identisch. D.h. Ein User A kann die Tabelle Kunde anlegen und mit A.Kunde oder Kunde darauf zugreifen.
User B kann auch eine Tabelle Kunde anlegen und mit B.Kunde oder Kunde darauf zugreifen. Er kann aber auch (wenn er die Rechte hat) auf die Tabelle des User A mit A.Kunde zugreifen.
So weit so gut, das kann ich auch mit Schemas abbilden.

Normalerweise ist es jedoch in dieser Datenbank so, dass alle Tabellen für den User SYSADM angeleget werden und alle User dann mit Sysadm.Kunde auf diese Tabellen zugreifen müssen. Jetzt kann es aber natürlich noch sein, dass ein User A zusätzlilch noch eigene Tabellen hat z.B. Auftrag. Jetzt müsste er auf Kunde mit SYSADM.Kunde zugreifen und auf Auftrag mit A.Auftrag.
Damit jetzt der Programmierer nicht bei jeder Tabelle nachschauen muss, in welchem Schema diese steht, kann ich ein Synonym anlegen, welches mir die Tabelle Kunde in den Namensraum von A einblendet, so als wäre diese in seinem Schema enthalten.
Das sieht so aus: Create Synonym A.Kunde for sysadm.Kunde
Damit kann User A auf die Tabelle Kunden mit A.Kunde zugreifen (man könnte hier sogar den Namen ändern, das wird aber selten gemacht)
Mit dieser Methode kann ich jedes Objekt in den Namensraum jeden Users einblenden.
Public Synonyms sind jetzt noch eine Erweiterung dieses Konzepts. Hier muss ich nicht für jeden User einzeln ein Synonym anlegen, sondern kann dieses einmal definieren (Create Public Synonym Kunde for sysadm.Kunde) und alle User können dann mit dieser einen Definition auf diese Tabelle mit User.Kunde zugreifen. Also z.B. der User A mit A.Kunde und der User B mit B.Kunde, ohne dass ich das alles einzeln angeben muss.

Die Idee mit den Pfaden ist insofern nicht machbar, da ich ja in den bestehenden Programmen (die ich, wenn möglich, gar nicht ändern will) immer mit Username.Tabelle auf die Tabellen zugegriffen wird. Das ist eigentlich die genau Umkehrung meines Problems.

Sorry für den langen Roman, aber ich hoffe, jetzt ist die Funktion deutlicher geworden,

Ja.

Normalerweise ist es jedoch in dieser Datenbank so, dass alle Tabellen für den User > SYSADM > angeleget werden und alle User dann mit > Sysadm.Kunde > auf diese Tabellen zugreifen müssen. Jetzt kann es aber natürlich noch sein, dass ein > User A > zusätzlilch noch eigene Tabellen hat z.B. > Auftrag. > Jetzt müsste er auf Kunde mit > SYSADM.Kunde > zugreifen und auf Auftrag mit > A.Auftrag.
Damit jetzt der Programmierer nicht bei jeder Tabelle nachschauen muss, in welchem Schema diese steht, kann ich ein Synonym anlegen, welches mir die Tabelle Kunde in den Namensraum von A einblendet, so als wäre diese in seinem Schema enthalten.

Dafür kann man ein eigenes Schema nehmen und den search_path so legen, daß (auch) dort gesucht wird.

Das sieht so aus: > Create Synonym A.Kunde for sysadm.Kunde
Damit kann User A auf die Tabelle Kunden mit > A.Kunde > zugreifen (man könnte hier sogar den Namen ändern, das wird aber selten gemacht)
Mit dieser Methode kann ich jedes Objekt in den Namensraum jeden Users einblenden.

Wie ist das mit den Rechten einklich?

Public Synonyms > sind jetzt noch eine Erweiterung dieses Konzepts. Hier muss ich nicht für jeden User einzeln ein Synonym anlegen, sondern kann dieses einmal definieren > (Create Public Synonym Kunde for sysadm.Kunde) > und alle User können dann mit dieser einen Definition auf diese Tabelle mit User.Kunde zugreifen. Also z.B. der User A mit > A.Kunde > und der User B mit > B.Kunde> , ohne dass ich das alles einzeln angeben muss.

Ich denke, daß kannst Du ähnlich mit Schemas und search_path abbilden.

Die Idee mit den Pfaden ist insofern nicht machbar, da ich ja in den bestehenden Programmen (die ich, wenn möglich, gar nicht ändern will) immer mit Username.Tabelle auf die Tabellen zugegriffen wird. Das ist eigentlich die genau Umkehrung meines Problems.

Den search_path kannst Du mit ALTER USER auch setzen



Andreas, grad in Zeitnot…

Der andere Andreas hat Recht, das ist eigentlich eine gute Arbeit für Schemas + search_path setzen. Damit sollten sich deine Probleme erledigen lassen.

Wenn ich den Lösungsvorschlag richtig verstehe kann man also pro Schema einen search_path setzen ? (Hab ich leider nichts in der Doku dazu gefunden, dort steht nur, dass man den SearchPath global setzen kann.)

Damit das ganze funktioniert und ich eine Tabelle mit dem Schemanamen referenziere müsste dann, wenn die Tabelle in diesem Schema nicht gefunden wird der SearchPath in Aktion treten und dort weitergesucht werden.
Ich dachte allerdings, dass dieses Verhalten nur dann gilt, wenn ich kein Schema angeben.

Die Referenzierung Schema.Objekt ist für mich so etwas wie die absolute Pfadangabe und alle Versuche, die ich jetzt in der Richtung angestellt habe sind eigentlich schiefgegangen.

Wie gesagt: Das Problem ist nicht, dass ich eine Tabelle ohne Schema finden will, sondern eine explizite Schemaangabe der Form Schema.Objekt habe und die eigentliche Tabelle aber in einem anderem Schema liegt.

Gruss Jürgen Spatz

Nein, das setzt du pro Verbindung, nicht pro Schema.
Jede Verbindung zur Datenbank kann einen anderen Inhalt in search_path haben.

Hallo Jürgen

Bei Gupta-SQLBase sieht es doch so aus:

  • mittels grant vergibst Du die (wie bei allen anderen
    DBs) Benutzerrechte auf die Anwendungstabellen,
    die in der Regel vom Benutzer sysadm created wurden.

  • dann erfolgt das Anlegen des Synonyms via
    “create public synonym tab_app001 for tab_app001;”
    Theoretisch könntest Du der Tabelle dabei einen neuen
    Namen vergeben aber wirst das vermutlich garnicht machen.

Der Sinn des Synonyms besteht darin die Tabelle tab_app01
für die anderen Benutzer sichtbar zumachen.
Ohne das Synonyms gibt es die spezielle
Gupta-Tabellen-Eigenschaft, das ein Benutzer (oder public=alle anderen)
Rechte über eine Tabelle besitzen kann die er nicht sehen kann.
((Jenes Feature ergibt Sinn, wenn in einer Datenbank eine Tabelle
mehrmals mit unterschiedlichem Creator vorkommt.
Ansonsten sehe ich darin keinen Sinn.))
Ein Benutzer unter SQLBase bekommt eine Fehlermeldung
wenn er zwar das select-Recht auf tab_app01 besitzt
aber das Synonym für ihn bzw. das public-Synonym fehlt.

Ich würde sagen, lass das mit dem Synonym einfach unter den Tisch
fallen. Ich schätze mal unter PostgreSQL können andere
Benutzer grundsätzlich Tabellen sehen, zu den Ihnen
Rechte select, insert, update, delete… zugewiesen wurden.(Oder?)

Ansonsten denke ich:

Wenn Du ein allgemeines Programm zum Konvertieren von
SQLBase nach PostgreSQL schreibst, wird hier eine Stelle der
Einschränkung sein, d.h.:
Eine Konvertierung von Synonymen wird nicht möglich sein, wenn
wirklich deren Segen benötigt wird.

Per google hatte ich vor ein paar Tagen danach geschaut
und irgendwo ein statement gelesen, dass die Realisierung
von Synonymen als mögliche Fehlerquelle von den
postgres-Entwicklern verworfen wurde.
Oder vielleicht mal im englisch-sprachigen Hauptforum fragen?




Freundliche Grüße
Geert Schröder (Hamburg)

HI zusammen,

vielen Dank erst einmal für die vielen Anregungen, nur leider führen die alle nicht zum gewünschten Ziel (sämtliche Kombinationen mit SearchPath usw.).

Ich würde sagen, lass das mit dem Synonym einfach unter den Tisch
fallen. Ich schätze mal unter PostgreSQL können andere
Benutzer grundsätzlich Tabellen sehen, zu den Ihnen
Rechte select, insert, update, delete… zugewiesen wurden.(Oder?)

Das Problem sind nicht Rechtezuweisungen oder so etwas, sondern das Problem ist, dass in den bestehenden Programmen mit dem Ausdruck “Schema.Tabelle” auf die Tabelle zugegriffen wird und ich nicht alle 10.000 SQL-Statements ändern will, oder sogar teilweise gar nicht an den Code herankomme.
Wie gesagt, wenn ich keine User-Referenz angebe (sprich nur “select … from Table” angebe) funktioniert das alles, aber wenn die Referenz eben dasteht (“Select * from Schema**.Table**”), dann wird auch explizit in diesem Schema gesucht (ist ja auch ok so.) und dann natürlich nicht gefunden.

Nun ja, trotzdem vielen Dank

Jürgen Spatz