PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comprendre le cast de bytea à oid

Le casting n'est pas un vrai casting. C'est juste (ab) en utilisant la syntaxe pratique. Un grand objet (LO) est créé en arrière-plan qui est stocké séparément et l'OID qui y fait référence est renvoyé.

Par documentation :

L'OID renvoyé est essentiellement un FK au PK de la table système pg_largeobject .

CREATE TABLE est complètement indépendant de la fonction et du pseudo-cast.

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

Il s'agit simplement d'un cas d'utilisation typique du casting d'affectation créé ci-dessus, qui ressort de la ligne suivante que vous avez oublié de citer :

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

Que se passe-t-il ici ?

Le type de données lo est un domaine sur le type de base oid , créé par le module supplémentaire lo (incorrectement référencé comme "paquet lo_manage" dans le blog de Grace Batumbya ). Par documentation :

La fonction decode() renvoie bytea . Le INSERT l'instruction attribue le bytea valeur à la colonne largeObj , qui déclenche une affectation convertie en son type lo , et c'est là que le casting ci-dessus entre en jeu.

Avertissement / Correctif / Mise à jour

L'entrée de blog est bâclée et obsolète à présent.

  • Ne prend pas la peine de le mentionner (par documentation ):

    En effet, vous devez être superutilisateur.

  • Faute de frappe dans CREATE TABLE :nom et type de colonne inversés.

  • La définition de la fonction est verbeuse et inefficace. Ce serait mieux (pour Postgres 9.3 ou plus ancien) :

    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.

Il y a un intégré fonction pour cela dans Postgres 9.4 . Utilisez-le à la place :

lo_from_bytea(loid oid, string bytea)

À partir des notes de version :

Pour CREATE CAST (par documentation ):

Je suggère une variante surchargée avec seulement un bytea paramètre :

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;

Étant donné que le pseudo-cast a un effet secondaire assez important, je ne suis pas convaincu d'en faire une ASSIGNMENT moulage. Je commencerais probablement par explicite uniquement :