? sites/default/modules
? sites/default/settings.php
Index: includes/database/pgsql/query.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/pgsql/query.inc,v
retrieving revision 1.2
diff -u -p -r1.2 query.inc
--- includes/database/pgsql/query.inc	15 Sep 2008 20:48:07 -0000	1.2
+++ includes/database/pgsql/query.inc	14 Oct 2008 12:57:00 -0000
@@ -28,23 +28,31 @@ class InsertQuery_pgsql extends InsertQu
 
     $max_placeholder = 0;
     $blobs = array();
-    $blob_cnt = 0;
+    $blob_count = 0;
     foreach ($this->insertValues as &$insert_values) {
       foreach ($this->insertFields as $idx => $field) {
-        switch ($schema['fields'][$field]['type']) {
-          case 'blob':
-            $blobs[$blob_cnt] = fopen('php://memory', 'a');
-            fwrite($blobs[$blob_cnt], $insert_values[$idx]);
-            rewind($blobs[$blob_cnt]);
-
-            $stmt->bindParam(':db_insert_placeholder_' . $max_placeholder++, $blobs[$blob_cnt], PDO::PARAM_LOB);
-
-            ++$blob_cnt;
-
-            break;
-          default:
-            $stmt->bindParam(':db_insert_placeholder_'. $max_placeholder++, $insert_values[$idx]);
-            break;
+        $placeholder = ':db_insert_placeholder_' . ($max_placeholder++);
+
+        if ($schema['fields'][$field]['type'] == 'blob') {
+          if (is_null($insert_values[$idx])) {
+            // BLOB NULL is a bit different from normal case: we can't use
+            // StreamAPI, but bind NULL to target field direcly.
+            $stmt->bindParam($placeholder, $insert_values[$idx], PDO::PARAM_LOB);
+          }
+          else {
+            // Writing NULL into file handler means write nothing. The file
+            // handler will contain an empty string but not NULL. Therefore
+            // NULL will be translated as empty string when save into
+            // database, and so buggy.
+            $blobs[$blob_count] = fopen('php://memory', 'a');
+            fwrite($blobs[$blob_count], $insert_values[$idx]);
+            rewind($blobs[$blob_count]);
+            $stmt->bindParam($placeholder, $blobs[$blob_count], PDO::PARAM_LOB);
+            ++$blob_count;
+          }
+        }
+        else {
+          $stmt->bindParam($placeholder, $insert_values[$idx]);
         }
       }
     }
@@ -105,10 +113,6 @@ class InsertQuery_pgsql extends InsertQu
 
 class UpdateQuery_pgsql extends UpdateQuery {
   public function execute() {
-    $max_placeholder = 0;
-    $blobs = array();
-    $blob_count = 0;
-
     $schema = drupal_get_schema($this->table);
 
     // Because we filter $fields the same way here and in __toString(), the
@@ -131,20 +135,32 @@ class UpdateQuery_pgsql extends UpdateQu
       unset($fields[$field]);
     }
 
+    $max_placeholder = 0;
+    $blobs = array();
+    $blob_count = 0;
     foreach ($fields as $field => &$value) {
       $placeholder = ':db_update_placeholder_' . ($max_placeholder++);
 
-      switch ($schema['fields'][$field]['type']) {
-        case 'blob':
+      if ($schema['fields'][$field]['type'] == 'blob') {
+        if (is_null($value)) {
+          // BLOB NULL is a bit different from normal case: we can't use
+          // StreamAPI, but bind NULL to target field direcly.
+          $stmt->bindParam($placeholder, $value, PDO::PARAM_LOB);
+        }
+        else {
+          // Writing NULL into file handler means write nothing. The file
+          // handler will contain an empty string but not NULL. Therefore
+          // NULL will be translated as empty string when save into
+          // database, and so buggy.
           $blobs[$blob_count] = fopen('php://memory', 'a');
           fwrite($blobs[$blob_count], $value);
           rewind($blobs[$blob_count]);
           $stmt->bindParam($placeholder, $blobs[$blob_count], PDO::PARAM_LOB);
           ++$blob_count;
-          break;
-        default:
-          $stmt->bindParam($placeholder, $value);
-          break;
+        }
+      }
+      else {
+        $stmt->bindParam($placeholder, $value);
       }
     }
 
