sql >> Database >  >> RDS >> PostgreSQL

Begrip casten van bytea naar oid

De cast is geen echte cast. Het is gewoon (ab)gebruiken van de handige syntaxis. Een groot object (LO) wordt op de achtergrond gemaakt die afzonderlijk wordt opgeslagen en de OID die ernaar verwijst, wordt geretourneerd.

Per documentatie:

De geretourneerde OID is in feite een FK voor de PK van de systeemtabel pg_largeobject .

CREATE TABLE is volledig onafhankelijk van de functie en pseudo-cast.

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

Het is gewoon een typische use-case voor de hierboven gemaakte opdrachtcast, wat blijkt uit de volgende regel die u bent vergeten te citeren:

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

Wat gebeurt hier?

Het gegevenstype lo is een domein boven het basistype oid , gemaakt door de aanvullende module lo (ten onrechte naar "lo_manage-pakket" verwezen in de blog van Grace Batumbya ). Per documentatie:

De functie decode() retourneert bytea . De INSERT statement wijst de bytea . toe waarde naar de kolom largeObj , die een toewijzing activeert naar het type lo , en dat is waar de bovenstaande cast van pas komt.

Waarschuwing / Corrigerende / Update

Het blogbericht is inmiddels slordig en verouderd.

  • Neemt niet de moeite om dat te vermelden (per documentatie ):

    In feite moet u een supergebruiker zijn.

  • Typfout in CREATE TABLE :kolomnaam en type omgekeerd.

  • De functiedefinitie is uitgebreid en inefficiënt. Dit zou beter zijn (voor Postgres 9.3 of ouder):

    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.

Er is een ingebouwd functie hiervoor in Postgres 9.4 . Gebruik dat in plaats daarvan:

lo_from_bytea(loid oid, string bytea)

Uit de release-opmerkingen :

Voor CREATE CAST (per documentatie ):

Ik stel een overbelaste variant voor met alleen een bytea 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;

Aangezien de pseudo-cast nogal een groot neveneffect heeft, ben ik er niet van overtuigd om daar een ASSIGNMENT van te maken. vorm. Ik zou waarschijnlijk beginnen met alleen expliciet:




  1. Postgres:index op cosinus-overeenkomst van float-arrays voor een-op-veel-zoekopdracht

  2. MySQL gebruikt filesort op geïndexeerde TIMESTAMP-kolom

  3. Gebeurtenissen in javascript met volledige kalender uit de database invullen

  4. Hoe een testdatabase klonen van een productie-één in één enkele actie?