sql >> Databasteknik >  >> RDS >> PostgreSQL

Förstå cast från bytea till oid

Skådespelarna är inte en riktig skådespelare. Det är bara (missbruk) att använda den bekväma syntaxen. Ett stort objekt (LO) skapas i bakgrunden som lagras separat och OID som refererar till det returneras.

Per dokumentation:

Det returnerade OID:t är i princip en FK till PK i systemtabellen pg_largeobject .

SKAPA TABELL är helt oberoende av funktionen och pseudo-cast.

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

Det är bara ett typiskt användningsfall för uppdragsgruppen som skapats ovan, vilket framgår av följande rad som du glömde att citera:

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

Vad händer här?

Datatypen lo är en domän över bastypen oid , skapad av tilläggsmodulen lo (felaktigt refererat till som "lo_manage package" i bloggenhet för Grace Batumbya ). Per dokumentation:

Funktionen decode() returnerar bytea . INSERT -satsen tilldelar bytea värde till kolumnen largeObj , vilket utlöser en tilldelning av typen lo , och det är där ovanstående skådespelare kommer in.

Varning / Korrigerande / Uppdatering

Blogginlägget är slarvigt och föråldrat vid det här laget.

  • Bryr sig inte om att nämna det (per dokumentation ):

    Du måste faktiskt vara superanvändare.

  • Skrivfel i SKAPA TABELL :kolumnnamn och typ omvända.

  • Funktionsdefinitionen är utförlig och ineffektiv. Detta skulle vara bättre (för Postgres 9.3 eller äldre):

    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-fiol.

Det finns en inbyggd funktion för detta i Postgres 9.4 . Använd det istället:

lo_from_bytea(loid oid, string bytea)

Från releasekommentarer :

För CREATE CAST (per dokumentation ):

Jag föreslår en överbelastad variant med bara en byte 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;

Eftersom pseudocasten har en ganska stor bieffekt är jag inte övertygad om att göra det till en UPPDRAGNING kasta. Jag skulle förmodligen börja med explicit-only:




  1. Hur man effektivt UPPDATERA en kolumn i en stor PostgreSQL-tabell med Python / psycopg2?

  2. Konvertera decimaltid till timmar och minuter

  3. Hur kan jag få värden från en tabell till en annan via liknande värden?

  4. Kan jag vara säker på Last Insert Id för Mysql?