From e4e38e02cfe626ffeda26b1d4a08df7a6cd3997d Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Wed, 02 Feb 2011 14:41:41 -0500
Subject: [PATCH] Fix inconsistency in de_DE localization (#1487749)

---
 program/lib/MDB2/Driver/Datatype/pgsql.php |  818 +++++++++++++++++++---------------------------------------
 1 files changed, 267 insertions(+), 551 deletions(-)

diff --git a/program/lib/MDB2/Driver/Datatype/pgsql.php b/program/lib/MDB2/Driver/Datatype/pgsql.php
old mode 100755
new mode 100644
index 8308ba6..f036886
--- a/program/lib/MDB2/Driver/Datatype/pgsql.php
+++ b/program/lib/MDB2/Driver/Datatype/pgsql.php
@@ -2,7 +2,7 @@
 // +----------------------------------------------------------------------+
 // | PHP versions 4 and 5                                                 |
 // +----------------------------------------------------------------------+
-// | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
+// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
 // | Stig. S. Bakken, Lukas Smith                                         |
 // | All rights reserved.                                                 |
 // +----------------------------------------------------------------------+
@@ -42,7 +42,7 @@
 // | Author: Paul Cooper <pgc@ucecom.com>                                 |
 // +----------------------------------------------------------------------+
 //
-// $Id$
+// $Id: pgsql.php 295587 2010-02-28 17:16:38Z quipo $
 
 require_once 'MDB2/Driver/Datatype/Common.php';
 
@@ -55,19 +55,20 @@
  */
 class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
 {
-    // {{{ convertResult()
+    // {{{ _baseConvertResult()
 
     /**
-     * convert a value to a RDBMS independent MDB2 type
+     * General type conversion method
      *
-     * @param mixed $value value to be converted
-     * @param int $type constant that specifies which type to convert to
-     * @return mixed converted value or a MDB2 error on failure
-     * @access public
+     * @param mixed   $value refernce to a value to be converted
+     * @param string  $type  specifies which type to convert to
+     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
+     * @return object a MDB2 error on failure
+     * @access protected
      */
-    function convertResult($value, $type)
+    function _baseConvertResult($value, $type, $rtrim = true)
     {
-        if (is_null($value)) {
+        if (null === $value) {
             return null;
         }
         switch ($type) {
@@ -78,12 +79,14 @@
         case 'date':
             return $value;
         case 'time':
-            return $value;
+            return substr($value, 0, strlen('HH:MM:SS'));
         case 'timestamp':
             return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
-        default:
-            return $this->_baseConvertResult($value, $type);
+        case 'blob':
+            $value = pg_unescape_bytea($value);
+            return parent::_baseConvertResult($value, $type, $rtrim);
         }
+        return parent::_baseConvertResult($value, $type, $rtrim);
     }
 
     // }}}
@@ -114,21 +117,40 @@
      */
     function getTypeDeclaration($field)
     {
-        $db =& $this->getDBInstance();
+        $db = $this->getDBInstance();
         if (PEAR::isError($db)) {
             return $db;
         }
 
         switch ($field['type']) {
         case 'text':
-            return array_key_exists('length', $field) ? 'VARCHAR ('.$field['length'].')' : 'TEXT';
+            $length = !empty($field['length']) ? $field['length'] : false;
+            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
+            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
+                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
         case 'clob':
-            return 'OID';
+            return 'TEXT';
         case 'blob':
-            return 'OID';
+            return 'BYTEA';
         case 'integer':
-            if (array_key_exists('autoincrement', $field) && $field['autoincrement']) {
+            if (!empty($field['autoincrement'])) {
+                if (!empty($field['length'])) {
+                    $length = $field['length'];
+                    if ($length > 4) {
+                        return 'BIGSERIAL PRIMARY KEY';
+                    }
+                }
                 return 'SERIAL PRIMARY KEY';
+            }
+            if (!empty($field['length'])) {
+                $length = $field['length'];
+                if ($length <= 2) {
+                    return 'SMALLINT';
+                } elseif ($length == 3 || $length == 4) {
+                    return 'INT';
+                } elseif ($length > 4) {
+                    return 'BIGINT';
+                }
             }
             return 'INT';
         case 'boolean':
@@ -142,7 +164,9 @@
         case 'float':
             return 'FLOAT8';
         case 'decimal':
-            return 'NUMERIC(18, '.$db->options['decimal_places'].')';
+            $length = !empty($field['length']) ? $field['length'] : 18;
+            $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
+            return 'NUMERIC('.$length.','.$scale.')';
         }
     }
 
@@ -174,385 +198,32 @@
      */
     function _getIntegerDeclaration($name, $field)
     {
-        if (array_key_exists('unsigned', $field) && $field['unsigned']) {
-            $db =& $this->getDBInstance();
-            if (PEAR::isError($db)) {
-                return $db;
-            }
+        $db = $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
 
+        if (!empty($field['unsigned'])) {
             $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
         }
-        if (array_key_exists('autoincrement', $field) && $field['autoincrement']) {
+        if (!empty($field['autoincrement'])) {
+            $name = $db->quoteIdentifier($name, true);
             return $name.' '.$this->getTypeDeclaration($field);
         }
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'integer') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getTextDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a text type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      length
-     *          Integer value that determines the maximum length of the text
-     *          field. If this argument is missing the field should be
-     *          declared to have the longest length allowed by the DBMS.
-     *
-     *      default
-     *          Text value to be used as default for this field.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getTextDeclaration($name, $field)
-    {
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'text') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getCLOBDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a character
-     * large object type field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      length
-     *          Integer value that determines the maximum length of the large
-     *          object field. If this argument is missing the field should be
-     *          declared to have the longest length allowed by the DBMS.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getCLOBDeclaration($name, $field)
-    {
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$notnull;
-    }
-
-    // }}}
-    // {{{ _getBLOBDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a binary large
-     * object type field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      length
-     *          Integer value that determines the maximum length of the large
-     *          object field. If this argument is missing the field should be
-     *          declared to have the longest length allowed by the DBMS.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getBLOBDeclaration($name, $field)
-    {
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$notnull;
-    }
-
-    // }}}
-    // {{{ _getBooleanDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a boolean type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name name the field to be declared.
-     * @param array $field associative array with the name of the properties
-     *       of the field being declared as array indexes. Currently, the types
-     *       of supported field properties are as follows:
-     *
-     *       default
-     *           Boolean value to be used as default for this field.
-     *
-     *       notnullL
-     *           Boolean flag that indicates whether this field is constrained
-     *           to not be set to null.
-     * @return string DBMS specific SQL code portion that should be used to
-     *       declare the specified field.
-     * @access protected
-     */
-    function _getBooleanDeclaration($name, $field)
-    {
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'boolean') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getDateDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a date type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      default
-     *          Date value to be used as default for this field.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getDateDeclaration($name, $field)
-    {
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'date') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getTimeDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a time
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      default
-     *          Time value to be used as default for this field.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getTimeDeclaration($name, $field)
-    {
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'time') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getTimestampDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a timestamp
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name name the field to be declared.
-     * @param array $field associative array with the name of the properties
-     *       of the field being declared as array indexes. Currently, the types
-     *       of supported field properties are as follows:
-     *
-     *       default
-     *           Timestamp value to be used as default for this field.
-     *
-     *       notnull
-     *           Boolean flag that indicates whether this field is constrained
-     *           to not be set to null.
-     * @return string DBMS specific SQL code portion that should be used to
-     *       declare the specified field.
-     * @access protected
-     */
-    function _getTimestampDeclaration($name, $field)
-    {
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'timestamp') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getFloatDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a float type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      default
-     *          Float value to be used as default for this field.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getFloatDeclaration($name, $field)
-    {
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'float') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _getDecimalDeclaration()
-
-    /**
-     * Obtain DBMS specific SQL code portion needed to declare a decimal type
-     * field to be used in statements like CREATE TABLE.
-     *
-     * @param string $name   name the field to be declared.
-     * @param array $field  associative array with the name of the properties
-     *      of the field being declared as array indexes. Currently, the types
-     *      of supported field properties are as follows:
-     *
-     *      default
-     *          Decimal value to be used as default for this field.
-     *
-     *      notnull
-     *          Boolean flag that indicates whether this field is constrained
-     *          to not be set to null.
-     * @return string  DBMS specific SQL code portion that should be used to
-     *      declare the specified field.
-     * @access protected
-     */
-    function _getDecimalDeclaration($name, $field)
-    {
-        $db =& $this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $default = array_key_exists('default', $field) ? ' DEFAULT '.
-            $this->quote($field['default'], 'float') : '';
-        $notnull = (array_key_exists('notnull', $field) && $field['notnull']) ? ' NOT NULL' : '';
-        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
-    }
-
-    // }}}
-    // {{{ _quoteLOB()
-
-    /**
-     * Convert a text value into a DBMS specific format that is suitable to
-     * compose query statements.
-     *
-     * @param           $value
-     * @return string text string that represents the given argument value in
-     *      a DBMS specific format.
-     * @access protected
-     */
-    function _quoteLOB($value)
-    {
-        $db =& $this->getDBInstance();
-        if (PEAR::isError($db)) {
-            return $db;
-        }
-
-        $connect = $db->connect();
-        if (PEAR::isError($connect)) {
-            return $connect;
-        }
-        if (!$db->in_transaction && !@pg_query($db->connection, 'BEGIN')) {
-            return $db->raiseError(MDB2_ERROR, null, null,
-                'error starting transaction');
-        }
-        if (is_resource($value)) {
-            $close = false;
-        } elseif (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
-            $close = true;
-            if ($match[1] == 'file://') {
-                $value = $match[2];
+        $default = '';
+        if (array_key_exists('default', $field)) {
+            if ($field['default'] === '') {
+                $field['default'] = empty($field['notnull']) ? null : 0;
             }
-            // disabled use of pg_lo_import() for now with the following line
-            $value = @fopen($value, 'r');
-        } else {
-            $close = true;
-            $fp = @tmpfile();
-            @fwrite($fp, $value);
-            @rewind($fp);
-            $value = $fp;
+            $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
         }
-        $result = false;
-        if (is_resource($value)) {
-            if (($lo = @pg_lo_create($db->connection))) {
-                if (($handle = @pg_lo_open($db->connection, $lo, 'w'))) {
-                    while (!@feof($value)) {
-                        $data = @fread($value, $db->options['lob_buffer_length']);
-                        if ($data === '') {
-                            break;
-                        }
-                        if (!@pg_lo_write($handle, $data)) {
-                            $result = $db->raiseError();
-                            break;
-                        }
-                    }
-                    if (!PEAR::isError($result)) {
-                        $result = strval($lo);
-                    }
-                    @pg_lo_close($handle);
-                } else {
-                    $result = $db->raiseError();
-                    @pg_lo_unlink($db->connection, $lo);
-                }
-            }
-            if ($close) {
-                @fclose($value);
-            }
-        } else {
-            if (!@pg_lo_import($db->connection, $value)) {
-                $result = $db->raiseError();
-            }
+
+        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
+        if (empty($default) && empty($notnull)) {
+            $default = ' DEFAULT NULL';
         }
-        if (!$db->in_transaction) {
-            if (PEAR::isError($result)) {
-                @pg_query($db->connection, 'ROLLBACK');
-            } else {
-                @pg_query($db->connection, 'COMMIT');
-            }
-        }
-        return $result;
+        $name = $db->quoteIdentifier($name, true);
+        return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
     }
 
     // }}}
@@ -562,14 +233,26 @@
      * Convert a text value into a DBMS specific format that is suitable to
      * compose query statements.
      *
-     * @param           $value
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
      * @return string text string that represents the given argument value in
      *      a DBMS specific format.
      * @access protected
      */
-    function _quoteCLOB($value)
+    function _quoteCLOB($value, $quote, $escape_wildcards)
     {
-        return $this->_quoteLOB($value);
+        $db = $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        if ($db->options['lob_allow_url_include']) {
+            $value = $this->_readFile($value);
+            if (PEAR::isError($value)) {
+                return $value;
+            }
+        }
+        return $this->_quoteText($value, $quote, $escape_wildcards);
     }
 
     // }}}
@@ -579,14 +262,38 @@
      * Convert a text value into a DBMS specific format that is suitable to
      * compose query statements.
      *
-     * @param           $value
+     * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
      * @return string text string that represents the given argument value in
      *      a DBMS specific format.
      * @access protected
      */
-    function _quoteBLOB($value)
+    function _quoteBLOB($value, $quote, $escape_wildcards)
     {
-        return $this->_quoteLOB($value);
+        if (!$quote) {
+            return $value;
+        }
+        $db = $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+        if ($db->options['lob_allow_url_include']) {
+            $value = $this->_readFile($value);
+            if (PEAR::isError($value)) {
+                return $value;
+            }
+        }
+        if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
+            $connection = $db->getConnection();
+            if (PEAR::isError($connection)) {
+                return $connection;
+            }
+            $value = @pg_escape_bytea($connection, $value);
+        } else {
+            $value = @pg_escape_bytea($value);
+        }
+        return "'".$value."'";
     }
 
     // }}}
@@ -597,213 +304,170 @@
      * compose query statements.
      *
      * @param string $value text string value that is intended to be converted.
+     * @param bool $quote determines if the value should be quoted and escaped
+     * @param bool $escape_wildcards if to escape escape wildcards
      * @return string text string that represents the given argument value in
      *       a DBMS specific format.
      * @access protected
      */
-    function _quoteBoolean($value)
+    function _quoteBoolean($value, $quote, $escape_wildcards)
     {
-        return ($value ? "'t'" : "'f'");
+        $value = $value ? 't' : 'f';
+        if (!$quote) {
+            return $value;
+        }
+        return "'".$value."'";
     }
 
     // }}}
-    // {{{ _quoteFloat()
+    // {{{ matchPattern()
 
     /**
-     * Convert a text value into a DBMS specific format that is suitable to
-     * compose query statements.
+     * build a pattern matching string
      *
-     * @param string $value text string value that is intended to be converted.
-     * @return string text string that represents the given argument value in
-     *      a DBMS specific format.
-     * @access protected
-     */
-    function _quoteFloat($value)
-    {
-        return (float)$value;
-    }
-
-    // }}}
-    // {{{ _quoteDecimal()
-
-    /**
-     * Convert a text value into a DBMS specific format that is suitable to
-     * compose query statements.
+     * @access public
      *
-     * @param string $value text string value that is intended to be converted.
-     * @return string text string that represents the given argument value in
-     *      a DBMS specific format.
-     * @access protected
+     * @param array $pattern even keys are strings, odd are patterns (% and _)
+     * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
+     * @param string $field optional field name that is being matched against
+     *                  (might be required when emulating ILIKE)
+     *
+     * @return string SQL pattern
      */
-    function _quoteDecimal($value)
+    function matchPattern($pattern, $operator = null, $field = null)
     {
-        $db =& $this->getDBInstance();
+        $db = $this->getDBInstance();
         if (PEAR::isError($db)) {
             return $db;
         }
 
-        return $db->escape($value);
+        $match = '';
+        if (null !== $operator) {
+            $field = (null === $field) ? '' : $field.' ';
+            $operator = strtoupper($operator);
+            switch ($operator) {
+            // case insensitive
+            case 'ILIKE':
+                $match = $field.'ILIKE ';
+                break;
+            case 'NOT ILIKE':
+                $match = $field.'NOT ILIKE ';
+                break;
+            // case sensitive
+            case 'LIKE':
+                $match = $field.'LIKE ';
+                break;
+            case 'NOT LIKE':
+                $match = $field.'NOT LIKE ';
+                break;
+            default:
+                return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                    'not a supported operator type:'. $operator, __FUNCTION__);
+            }
+        }
+        $match.= "'";
+        foreach ($pattern as $key => $value) {
+            if ($key % 2) {
+                $match.= $value;
+            } else {
+                $match.= $db->escapePattern($db->escape($value));
+            }
+        }
+        $match.= "'";
+        $match.= $this->patternEscapeString();
+        return $match;
     }
 
     // }}}
-    // {{{ writeLOBToFile()
+    // {{{ patternEscapeString()
 
     /**
-     * retrieve LOB from the database
+     * build string to define escape pattern string
      *
-     * @param resource $lob stream handle
-     * @param string $file name of the file into which the LOb should be fetched
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access protected
+     * @access public
+     *
+     *
+     * @return string define escape pattern
      */
-    function writeLOBToFile($lob, $file)
+    function patternEscapeString()
     {
-        $db =& $this->getDBInstance();
+        $db = $this->getDBInstance();
         if (PEAR::isError($db)) {
             return $db;
         }
-
-        $lob_data = stream_get_meta_data($lob);
-        $lob_index = $lob_data['wrapper_data']->lob_index;
-        if (!pg_lo_export($db->connection, $this->lobs[$lob_index]['ressource'], $file)) {
-            return $db->raiseError();
-        }
-        return MDB2_OK;
+        return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
     }
 
     // }}}
-    // {{{ _retrieveLOB()
-
-    /**
-     * retrieve LOB from the database
-     *
-     * @param resource $lob stream handle
-     * @return mixed MDB2_OK on success, a MDB2 error on failure
-     * @access protected
-     */
-    function _retrieveLOB(&$lob)
-    {
-        if (!array_key_exists('handle', $lob)) {
-            $db =& $this->getDBInstance();
-            if (PEAR::isError($db)) {
-                return $db;
-            }
-            if (!$db->in_transaction) {
-                if (!@pg_query($db->connection, 'BEGIN')) {
-                    return $db->raiseError();
-                }
-                $lob['in_transaction'] = true;
-            }
-            $lob['handle'] = @pg_lo_open($db->connection, $lob['ressource'], 'r');
-            if (!$lob['handle']) {
-                if (array_key_exists('in_transaction', $lob)) {
-                    @pg_query($db->connection, 'END');
-                    unset($lob['in_transaction']);
-                }
-                return $db->raiseError();
-            }
-        }
-        return MDB2_OK;
-    }
-
-    // }}}
-    // {{{ _readLOB()
-
-    /**
-     * Read data from large object input stream.
-     *
-     * @param resource $lob stream handle
-     * @param blob $data reference to a variable that will hold data to be
-     *      read from the large object input stream
-     * @param int $length integer value that indicates the largest ammount of
-     *      data to be read from the large object input stream.
-     * @return mixed length on success, a MDB2 error on failure
-     * @access protected
-     */
-    function _readLOB($lob, $length)
-    {
-        $data = @pg_lo_read($lob['handle'], $length);
-        if (!is_string($data)) {
-            $db =& $this->getDBInstance();
-            if (PEAR::isError($db)) {
-                return $db;
-            }
-
-            return $db->raiseError();
-        }
-        return $data;
-    }
-
-    // }}}
-    // {{{ _destroyLOB()
-
-    /**
-     * Free any resources allocated during the lifetime of the large object
-     * handler object.
-     *
-     * @param int $lob_index from the lob array
-     * @access protected
-     */
-    function _destroyLOB($lob_index)
-    {
-        if (isset($this->lobs[$lob_index]['handle'])) {
-            @pg_lo_close($this->lobs[$lob_index]['handle']);
-            unset($this->lobs[$lob_index]['handle']);
-            if (isset($this->lobs[$lob_index]['in_transaction'])) {
-/*
-for some reason this piece of code causes an apache crash
-                $db =& $this->getDBInstance();
-                if (PEAR::isError($db)) {
-                    return $db;
-                }
-
-                @pg_query($db->connection, 'END');
-*/
-            }
-        }
-    }
-
-    // }}}
-    // {{{ mapNativeDatatype()
+    // {{{ _mapNativeDatatype()
 
     /**
      * Maps a native array description of a field to a MDB2 datatype and length
      *
      * @param array  $field native field description
-     * @return array containing the various possible types and the length
+     * @return array containing the various possible types, length, sign, fixed
      * @access public
      */
-    function mapNativeDatatype($field)
+    function _mapNativeDatatype($field)
     {
-        $db_type = preg_replace('/\d/','', strtolower($field['typname']) );
-        $length = $field['attlen'];
-        if ($length == '-1') {
-            $length = $field['atttypmod']-4;
-        }
-        if ((int)$length <= 0) {
-            $length = null;
-        }
+        $db_type = strtolower($field['type']);
+        $length = $field['length'];
         $type = array();
+        $unsigned = $fixed = null;
         switch ($db_type) {
-        case 'int':
+        case 'smallint':
+        case 'int2':
             $type[] = 'integer';
-            if ($length == '1') {
+            $unsigned = false;
+            $length = 2;
+            if ($length == '2') {
                 $type[] = 'boolean';
+                if (preg_match('/^(is|has)/', $field['name'])) {
+                    $type = array_reverse($type);
+                }
             }
             break;
+        case 'int':
+        case 'int4':
+        case 'integer':
+        case 'serial':
+        case 'serial4':
+            $type[] = 'integer';
+            $unsigned = false;
+            $length = 4;
+            break;
+        case 'bigint':
+        case 'int8':
+        case 'bigserial':
+        case 'serial8':
+            $type[] = 'integer';
+            $unsigned = false;
+            $length = 8;
+            break;
         case 'bool':
+        case 'boolean':
             $type[] = 'boolean';
             $length = null;
             break;
         case 'text':
-        case 'char':
         case 'varchar':
+            $fixed = false;
+        case 'unknown':
+        case 'char':
         case 'bpchar':
             $type[] = 'text';
             if ($length == '1') {
                 $type[] = 'boolean';
-            } elseif (strstr($db_type, 'text'))
+                if (preg_match('/^(is|has)/', $field['name'])) {
+                    $type = array_reverse($type);
+                }
+            } elseif (strstr($db_type, 'text')) {
                 $type[] = 'clob';
+                $type = array_reverse($type);
+            }
+            if ($fixed !== false) {
+                $fixed = true;
+            }
             break;
         case 'date':
             $type[] = 'date';
@@ -811,6 +475,7 @@
             break;
         case 'datetime':
         case 'timestamp':
+        case 'timestamptz':
             $type[] = 'timestamp';
             $length = null;
             break;
@@ -819,6 +484,8 @@
             $length = null;
             break;
         case 'float':
+        case 'float4':
+        case 'float8':
         case 'double':
         case 'real':
             $type[] = 'float';
@@ -827,11 +494,15 @@
         case 'money':
         case 'numeric':
             $type[] = 'decimal';
+            if (isset($field['scale'])) {
+                $length = $length.','.$field['scale'];
+            }
             break;
         case 'tinyblob':
         case 'mediumblob':
         case 'longblob':
         case 'blob':
+        case 'bytea':
             $type[] = 'blob';
             $length = null;
             break;
@@ -846,18 +517,63 @@
             $length = null;
             break;
         default:
-            $db =& $this->getDBInstance();
+            $db = $this->getDBInstance();
             if (PEAR::isError($db)) {
                 return $db;
             }
-
-            return $db->raiseError(MDB2_ERROR, null, null,
-                'getTableFieldDefinition: unknown database attribute type');
+            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
+                'unknown database attribute type: '.$db_type, __FUNCTION__);
         }
 
-        return array($type, $length);
+        if ((int)$length <= 0) {
+            $length = null;
+        }
+
+        return array($type, $length, $unsigned, $fixed);
     }
 
     // }}}
+    // {{{ mapPrepareDatatype()
+
+    /**
+     * Maps an mdb2 datatype to native prepare type
+     *
+     * @param string $type
+     * @return string
+     * @access public
+     */
+    function mapPrepareDatatype($type)
+    {
+        $db = $this->getDBInstance();
+        if (PEAR::isError($db)) {
+            return $db;
+        }
+
+        if (!empty($db->options['datatype_map'][$type])) {
+            $type = $db->options['datatype_map'][$type];
+            if (!empty($db->options['datatype_map_callback'][$type])) {
+                $parameter = array('type' => $type);
+                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
+            }
+        }
+
+        switch ($type) {
+            case 'integer':
+                return 'int';
+            case 'boolean':
+                return 'bool';
+            case 'decimal':
+            case 'float':
+                return 'numeric';
+            case 'clob':
+                return 'text';
+            case 'blob':
+                return 'bytea';
+            default:
+                break;
+        }
+        return $type;
+    }
+    // }}}
 }
 ?>
\ No newline at end of file

--
Gitblit v1.9.1