Frage

Zu Testzwecken stelle ich meine eigene Implementierung des zur Verfügung now() funktion, die ist public.now().Wobei search_path so überschreiben Sie die Standardeinstellung pg_catalog.now() mit meiner eigenen Version funktioniert meistens, aber ich habe eine Tabelle mit einer Tabelle mit einem Standardausdruck von now().Das Anzeigen der Tabelle ergibt etwas Ähnliches wie das Folgende:

 start_date   | date    | not null default now()

Nach dem Speichern und Wiederherstellen eines Schemas (in einer Testdatenbank) wird jedoch dieselbe Show-Tabelle erstellt

 start_date   | date    | not null default pg_catalog.now()

Ich gehe davon aus, dass die Funktion im Standardausdruck zunächst an kein Schema gebunden ist und der Suchpfad verwendet wird, um das richtige zu finden.Der Speicherauszugs- oder Wiederherstellungsvorgang scheint die Funktion jedoch an die aktuelle zu "binden".

Ist mein Verständnis des "Bindungszustands" der Funktion korrekt?Gibt es eine Möglichkeit, die Ungebundenheit der Funktion über Dump- / Wiederherstellungsgrenzen hinweg beizubehalten?

War es hilfreich?

Lösung

Standardwerte werden zum Zeitpunkt der Erstellung analysiert (frühe Bindung!).Was Sie in psql, pgAdmin oder anderen Clients sehen, ist eine Textdarstellung, aber tatsächlich ist die OID der Funktion now() zum Zeitpunkt der Erstellung wird die Spalte Default im Systemkatalog gespeichert pg_attrdef.Ich zitiere:

adbin   pg_node_tree  The internal representation of the column default value
adsrc   text          A human-readable representation of the default value

Wenn Sie das ändern search_path, was dazu führt, dass Postgres den Namen der schemaqualifizierten Funktion anzeigt, da sie mit der aktuellen nicht mehr korrekt aufgelöst würde search_path.

Dump und Wiederherstellung betreffen nicht Ihre Gewohnheit search_path Einstellung.Sie legen es explizit fest.Was Sie also sehen, hängt nicht mit dem Speicherauszugs- / Wiederherstellungszyklus zusammen.

Integrierte Funktionen überschreiben

Inverkehrbringen public vor pg_catalog in der search_path ist ein spiel der Gefahr.Unterprivilegierte Benutzer (einschließlich Sie selbst) dürfen oft dort schreiben und Funktionen erstellen, die versehentlich Systemfunktionen außer Kraft setzen können - mit willkürlichem (oder böswilligem) Ergebnis.

Du willst ein dediziertes Schema mit eingeschränktem Zugriff um eingebaute Funktionen außer Kraft zu setzen.Verwenden Sie stattdessen so etwas:

SET search_path = überschreiben, pg_catalog, public;

Details in diesem verwandte Antwort auf dba.SE.

Andere Tipps

Die Standardfunktion ist zum Zeitpunkt der Erstellung der Standardeinschränkung "gebunden".Die Ansicht, die den nicht qualifizierten Namen zeigt, kürzt ihn einfach ab.

Dies kann durch Einfügen von Zeilen vor und nach dem Schattieren der Funktion demonstriert werden:

Set search_path to public,pg_catalog;

Create Temp Table foo (
    test date not null default now()
);

Insert Into foo default values;

Create Function public.now() Returns timestamp with time zone Language SQL As $$ 
     -- No idea why I chose this date.
     Select '1942-05-09'::timestamp with time zone;
$$;

Insert Into foo default values;

Select * from foo;

Beachten Sie, dass beide Zeilen (vor und nach der Funktionserstellung eingefügt) das heutige Datum enthalten, nicht das falsche Datum.

Darüber hinaus führt das Erstellen einer Tabelle mit der obigen Funktion, die bereits im Gültigkeitsbereich ist, und der anschließende Versuch, die Funktion zu löschen, zu einem Abhängigkeitsfehler:

Set search_path to public,pg_catalog;

Create Function public.now() Returns timestamp with time zone Language SQL As $$ 
    Select '1942-05-09'::timestamp with time zone;
$$;

Create Temp Table bar (
    test date not null default now()
);

Insert Into bar default values;

Select * from bar;
-- Single row containing the dummy date rather than today

Drop Function public.now();
-- ERROR:  cannot drop function now() because other objects depend on it

Wenn die Bindung nur beim Einfügen erfolgen würde, gäbe es keine solche Abhängigkeit.

Kümmere dich nicht darum.Postgres schreibt manchmal seltsame Sachen, nachdem die Dinge kompiliert wurden.Gerade Ansichten werden oft bis zur Unkenntlichkeit verändert.

Und:now() und pg_catalog.now() ist normalerweise genau das gleiche.Sehen:

CREATE OR REPLACE FUNCTION now()
    RETURNS timestamp with time zone AS
'now'
    LANGUAGE internal STABLE STRICT
 COST 1;
 ALTER FUNCTION now()
    OWNER TO postgres;
 COMMENT ON FUNCTION now() IS 'current transaction time';

Keine Sorge.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top