PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Cast von Bytea zu Oid verstehen

Die Besetzung ist keine echte Besetzung. Es wird nur die bequeme Syntax (ab)verwendet. Ein großes Objekt (LO) wird im Hintergrund erstellt, separat gespeichert und die darauf referenzierende OID zurückgegeben.

Pro Dokumentation:

Die zurückgegebene OID ist im Grunde ein FK zum PK der Systemtabelle pg_largeobject .

CREATE TABLE ist völlig unabhängig von Funktion und Pseudocast.

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

Es ist nur ein typischer Anwendungsfall für den oben erstellten Assignment Cast, was aus der folgenden Zeile hervorgeht, die Sie vergessen haben zu zitieren:

INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex'));

Was passiert hier?

Der Datentyp lo ist eine Domäne über den Basistyp oid , erstellt durch das Zusatzmodul lo (fälschlicherweise als "lo_manage package" im Blog-Eintrag von Grace Batumbya ). Pro Dokumentation:

Die Funktion decode() gibt bytea zurück . Das INSERT -Anweisung weist das bytea zu Wert in die Spalte largeObj , was eine Zuweisungsumwandlung in seinen Typ lo auslöst , und hier kommt die obige Besetzung ins Spiel.

Warnung/Korrektur/Aktualisierung

Der Blogeintrag ist schlampig und mittlerweile veraltet.

  • Macht sich nicht die Mühe, das zu erwähnen (pro Dokumentation ). ):

    Tatsächlich müssen Sie Superuser sein.

  • Tippfehler in CREATE TABLE :Spaltenname und Typ umgekehrt.

  • Die Funktionsdefinition ist ausführlich und ineffizient. Dies wäre besser (für Postgres 9.3 oder älter):

    CREATE OR REPLACE FUNCTION blob_write(bytea)
      RETURNS oid AS
    $func$
    DECLARE
       loid oid := lo_create(0);
       lfd  int := lo_open(loid,131072);  -- = 2^17 = x2000
       -- symbolic constant defined in the header file libpq/libpq-fs.h
       -- #define   INV_WRITE   0x00020000
    BEGIN
       PERFORM lowrite(lfd, $1);
       PERFORM lo_close(lfd);
       RETURN loid;
    END
    $func$  LANGUAGE plpgsql VOLATILE STRICT;
    

    SQL-Fiddle.

Es ist ein eingebaut Funktion dafür in Postgres 9.4 . Verwenden Sie stattdessen:

lo_from_bytea(loid oid, string bytea)

Aus den Versionshinweisen :

Für CREATE CAST (pro Dokumentation ). ):

Ich schlage eine überladene Variante mit nur einem bytea vor Parameter:

CREATE OR REPLACE FUNCTION lo_from_bytea(bytea)
   RETURNS oid LANGUAGE sql AS
'SELECT lo_from_bytea(0, $1)';

CREATE CAST (bytea AS oid) WITH FUNCTION lo_from_bytea(bytea) AS ASSIGNMENT;

Da der Pseudo-Cast einen ziemlich großen Nebeneffekt hat, bin ich nicht davon überzeugt, daraus eine ASSIGNMENT zu machen gießen. Ich würde wahrscheinlich mit Explicit-only beginnen: