[Checkins] SVN: relstorage/branches/postgres_blob_oid/relstorage/adapters/schema.py Delete OID blobs only when it's the last reference.

Martijn Pieters mj at zopatista.com
Tue Jun 14 14:07:35 EDT 2011


Log message for revision 121933:
  Delete OID blobs only when it's the last reference.
  
  When using undo, we copy the oid 'forward', creating an additional reference to the blob (but not duplicating the data). Only unlink if this is the last reference. We need to make this a BEFORE trigger, otherwise we cannot reliably count on a full DELETE FROM TABLE (cnt would be 0 at all times). This removes the need to catch the exception (caused by multiple refs). Also, clean out oid refs on drop_all().

Changed:
  U   relstorage/branches/postgres_blob_oid/relstorage/adapters/schema.py

-=-
Modified: relstorage/branches/postgres_blob_oid/relstorage/adapters/schema.py
===================================================================
--- relstorage/branches/postgres_blob_oid/relstorage/adapters/schema.py	2011-06-14 16:56:00 UTC (rev 121932)
+++ relstorage/branches/postgres_blob_oid/relstorage/adapters/schema.py	2011-06-14 18:07:35 UTC (rev 121933)
@@ -107,6 +107,7 @@
             chunk       OID NOT NULL
         );
         CREATE INDEX blob_chunk_lookup ON blob_chunk (zoid, tid);
+        CREATE INDEX blob_chunk_loid ON blob_chunk (chunk);
         ALTER TABLE blob_chunk ADD CONSTRAINT blob_chunk_fk
             FOREIGN KEY (zoid, tid)
             REFERENCES object_state (zoid, tid)
@@ -396,15 +397,18 @@
 
 postgresql_history_preserving_plpgsql = """
 CREATE OR REPLACE FUNCTION blob_chunk_delete_trigger() RETURNS TRIGGER 
-AS $blob_chunk_ delete_trigger$
+AS $blob_chunk_delete_trigger$
     -- Version: %s
     -- Unlink large object data file after blob_chunck row deletion
+    DECLARE
+        cnt integer;
     BEGIN
-        PERFORM lo_unlink(OLD.chunk);
-        RETURN NULL;
-    EXCEPTION
-        WHEN undefined_object THEN
-            RETURN NULL;
+        SELECT count(*) into cnt FROM blob_chunk WHERE chunk=OLD.chunk;
+        IF (cnt = 1) THEN
+            -- Last reference to this oid, unlink
+            PERFORM lo_unlink(OLD.chunk);
+        END IF;
+        RETURN OLD;
     END;
 $blob_chunk_delete_trigger$ LANGUAGE plpgsql;
 /
@@ -412,7 +416,7 @@
 DROP TRIGGER IF EXISTS blob_chunk_delete ON blob_chunk;
 /
 CREATE TRIGGER blob_chunk_delete 
-    AFTER DELETE ON blob_chunk
+    BEFORE DELETE ON blob_chunk
     FOR EACH ROW
     EXECUTE PROCEDURE blob_chunk_delete_trigger();
 /
@@ -979,7 +983,15 @@
             res[name.lower()] = version
         return res
 
+    def drop_all(self):
+        def callback(conn, cursor):
+            # make sure we clean up our blob oids first
+            if 'blob_chunk' in self.list_tables(cursor):
+                cursor.execute("DELETE FROM blob_chunk")
+        self.connmanager.open_and_call(callback)
+        super(PostgreSQLSchemaInstaller, self).drop_all()
 
+
 class MySQLSchemaInstaller(AbstractSchemaInstaller):
     implements(ISchemaInstaller)
 



More information about the checkins mailing list