sql >> Databasteknik >  >> RDS >> PostgreSQL

Modellera PostgreSQL:s stora objekt i Rails

Om du använder ActiveRecord som följer med Rails med en av dess adaptrar, är den enda formella mappningen av databastyp till Rails eller Ruby typ som sker vanligtvis definierad i NATIVE_DATABASE_TYPES konstant i adaptern som returneras via dess native_database_types metod. För PostgreSQL i Rails 3.2.x, det vill säga i ActiveRecord::ConnectionAdapters::PostgreSQLAdapter som finns här . Så för den adaptern mappas den "binära" typen i Rails till typen "bytea" i PG. För vissa typer kan du åsidosätta den databastypen som den mappar till med en pärla som heter activerecord-native_db_types_override a> . Men vi vill använda stora föremål, så...

Migreringar

Som Jim Deville noterade i kommentarerna kan du ange den anpassade kolumnen i tabellen som:

t.column :some_oid, 'blob_oid', :null => false

Om du behöver göra ännu mer som inte är standard, kan du också använda en execute("SQL GOES HERE;") för att skapa tabellen med rak SQL. Och om du har ett befintligt äldre schema eller SQL-ändringar som har gjorts utanför migreringarna, överväg att använda structure.sql (config.active_record.schema_format = :sql alternativet i config/application.rb och gör sedan:rake db:structure:dump ).

Stora objekt Läs/Skriv/Kontrollera längd/Ta bort

Kopierat med några ändringar för att förtydliga, etc. från:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :

Uppdaterad :vi kan men behöver inte sätta en början före lo_read/lo_write/lo_lseek och gör lo_close i säkerställ blockering eftersom PG-dokumentation "Alla stora objektbeskrivningar som förblir öppna i slutet av en transaktion kommer att stängas automatiskt." (tack till Diogo för den informationen)

    require 'pg'

    ...

    def read
      (...).transaction do
        lo = connection.lo_open(identifier)
        content = connection.lo_read(lo, file_length)
        connection.lo_close(lo)
        content
      end
    end

    def write(file)
      (...).transaction do
        lo = connection.lo_open(identifier, ::PG::INV_WRITE)
        size = connection.lo_write(lo, file.read)
        connection.lo_close(lo)
        size
      end
    end

    def delete
      connection.lo_unlink(identifier)
    end

    def file_length
      (...).transaction do
        lo = connection.lo_open(identifier)
        size = connection.lo_lseek(lo, 0, 2)
        connection.lo_close(lo)
        size
      end
    end

Istället för connection , använd den råa anslutningen från modellen eller basen, t.ex. ActiveRecord::Base.connection.raw_connection (se detta ).

(...).transaction ringer transaktion på modell eller bas, t.ex. ActiveRecord::Base.transaction (se detta ).

identifier är den oid som du antingen behöver skicka in/ställa in eller få genom att bara göra en connection.lo_creat .

Andra exempel/info:

Det senare och några svar här föreslår att du kanske vill överväga lagring av stora filer separat från DB, t.ex. så att du kan använda molnlagring. Men om bara lagra sökvägarna/ID:n till externa filer som inte är hanteras av DB förlorar du ACID-konsistens (en eller flera DB-poster kan peka på en eller flera filer som inte finns där eller en eller flera filer som inte har en eller flera associerade poster i databasen). Ett annat argument för att lagra filer på filsystemet är att du kan streama filer, men PG large object lagrar filer på filsystemet på ett sätt som hanteras av postgres för att både säkerställa ACID-konsistens och tillåta streaming (vilket du inte kan göra med en vanlig BLOB) /Rails binär typ). Så, det beror bara på; vissa tycker att lagring i separat lagring med hjälp av sökvägsreferenser är ett bättre alternativ, och vissa föredrar ACID-konsistens via stora objekt.

Det enkla sättet

Använd bara CarrierWave och carrierwave-postgresql .




  1. Räknar rader från en underfråga

  2. SQL Server En utlösare för att fungera på infogning av flera rader

  3. Databasschema för ACL

  4. Ansluter till SSL-aktiverat Oracle DB via Java (JDBC)