PageRenderTime 51ms CodeModel.GetById 3ms app.highlight 35ms RepoModel.GetById 2ms app.codeStats 0ms

/gespac/config/PEAR/MDB2/Driver/Datatype/Common.php

http://gespac.googlecode.com/
PHP | 1837 lines | 780 code | 155 blank | 902 comment | 126 complexity | 0c87967f991c8dd76240735e4244d0c9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2// +----------------------------------------------------------------------+
   3// | PHP versions 4 and 5                                                 |
   4// +----------------------------------------------------------------------+
   5// | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 |
   6// | Stig. S. Bakken, Lukas Smith                                         |
   7// | All rights reserved.                                                 |
   8// +----------------------------------------------------------------------+
   9// | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  10// | API as well as database abstraction for PHP applications.            |
  11// | This LICENSE is in the BSD license style.                            |
  12// |                                                                      |
  13// | Redistribution and use in source and binary forms, with or without   |
  14// | modification, are permitted provided that the following conditions   |
  15// | are met:                                                             |
  16// |                                                                      |
  17// | Redistributions of source code must retain the above copyright       |
  18// | notice, this list of conditions and the following disclaimer.        |
  19// |                                                                      |
  20// | Redistributions in binary form must reproduce the above copyright    |
  21// | notice, this list of conditions and the following disclaimer in the  |
  22// | documentation and/or other materials provided with the distribution. |
  23// |                                                                      |
  24// | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25// | Lukas Smith nor the names of his contributors may be used to endorse |
  26// | or promote products derived from this software without specific prior|
  27// | written permission.                                                  |
  28// |                                                                      |
  29// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33// | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36// |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37// | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39// | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40// | POSSIBILITY OF SUCH DAMAGE.                                          |
  41// +----------------------------------------------------------------------+
  42// | Author: Lukas Smith <smith@pooteeweet.org>                           |
  43// +----------------------------------------------------------------------+
  44//
  45// $Id: Common.php,v 1.126 2007/03/28 16:49:43 quipo Exp $
  46
  47require_once 'MDB2/LOB.php';
  48
  49/**
  50 * @package  MDB2
  51 * @category Database
  52 * @author   Lukas Smith <smith@pooteeweet.org>
  53 */
  54
  55/**
  56 * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
  57 *
  58 * @package MDB2
  59 * @category Database
  60 * @author Lukas Smith <smith@pooteeweet.org>
  61 */
  62class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
  63{
  64    var $valid_default_values = array(
  65        'text'      => '',
  66        'boolean'   => true,
  67        'integer'   => 0,
  68        'decimal'   => 0.0,
  69        'float'     => 0.0,
  70        'timestamp' => '1970-01-01 00:00:00',
  71        'time'      => '00:00:00',
  72        'date'      => '1970-01-01',
  73        'clob'      => '',
  74        'blob'      => '',
  75    );
  76
  77    /**
  78     * contains all LOB objects created with this MDB2 instance
  79     * @var array
  80     * @access protected
  81     */
  82    var $lobs = array();
  83
  84    // }}}
  85    // {{{ getValidTypes()
  86
  87    /**
  88     * Get the list of valid types
  89     *
  90     * This function returns an array of valid types as keys with the values
  91     * being possible default values for all native datatypes and mapped types
  92     * for custom datatypes.
  93     *
  94     * @return mixed array on success, a MDB2 error on failure
  95     * @access public
  96     */
  97    function getValidTypes()
  98    {
  99        $types = $this->valid_default_values;
 100        $db =& $this->getDBInstance();
 101        if (PEAR::isError($db)) {
 102            return $db;
 103        }
 104        if (!empty($db->options['datatype_map'])) {
 105            foreach ($db->options['datatype_map'] as $type => $mapped_type) {
 106                if (array_key_exists($mapped_type, $types)) {
 107                    $types[$type] = $types[$mapped_type];
 108                } elseif (!empty($db->options['datatype_map_callback'][$type])) {
 109                    $parameter = array('type' => $type, 'mapped_type' => $mapped_type);
 110                    $default =  call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
 111                    $types[$type] = $default;
 112                }
 113            }
 114        }
 115        return $types;
 116    }
 117
 118    // }}}
 119    // {{{ checkResultTypes()
 120
 121    /**
 122     * Define the list of types to be associated with the columns of a given
 123     * result set.
 124     *
 125     * This function may be called before invoking fetchRow(), fetchOne()
 126     * fetchCole() and fetchAll() so that the necessary data type
 127     * conversions are performed on the data to be retrieved by them. If this
 128     * function is not called, the type of all result set columns is assumed
 129     * to be text, thus leading to not perform any conversions.
 130     *
 131     * @param array $types array variable that lists the
 132     *       data types to be expected in the result set columns. If this array
 133     *       contains less types than the number of columns that are returned
 134     *       in the result set, the remaining columns are assumed to be of the
 135     *       type text. Currently, the types clob and blob are not fully
 136     *       supported.
 137     * @return mixed MDB2_OK on success, a MDB2 error on failure
 138     * @access public
 139     */
 140    function checkResultTypes($types)
 141    {
 142        $types = is_array($types) ? $types : array($types);
 143        foreach ($types as $key => $type) {
 144            if (!isset($this->valid_default_values[$type])) {
 145                $db =& $this->getDBInstance();
 146                if (PEAR::isError($db)) {
 147                    return $db;
 148                }
 149                if (empty($db->options['datatype_map'][$type])) {
 150                    return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
 151                        $type.' for '.$key.' is not a supported column type', __FUNCTION__);
 152                }
 153            }
 154        }
 155        return $types;
 156    }
 157
 158    // }}}
 159    // {{{ _baseConvertResult()
 160
 161    /**
 162     * General type conversion method
 163     *
 164     * @param mixed   $value reference to a value to be converted
 165     * @param string  $type  specifies which type to convert to
 166     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
 167     * @return object an MDB2 error on failure
 168     * @access protected
 169     */
 170    function _baseConvertResult($value, $type, $rtrim = true)
 171    {
 172        switch ($type) {
 173        case 'text':
 174            if ($rtrim) {
 175                $value = rtrim($value);
 176            }
 177            return $value;
 178        case 'integer':
 179            return intval($value);
 180        case 'boolean':
 181            return !empty($value);
 182        case 'decimal':
 183            return $value;
 184        case 'float':
 185            return doubleval($value);
 186        case 'date':
 187            return $value;
 188        case 'time':
 189            return $value;
 190        case 'timestamp':
 191            return $value;
 192        case 'clob':
 193        case 'blob':
 194            $this->lobs[] = array(
 195                'buffer' => null,
 196                'position' => 0,
 197                'lob_index' => null,
 198                'endOfLOB' => false,
 199                'resource' => $value,
 200                'value' => null,
 201                'loaded' => false,
 202            );
 203            end($this->lobs);
 204            $lob_index = key($this->lobs);
 205            $this->lobs[$lob_index]['lob_index'] = $lob_index;
 206            return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index, 'r+');
 207        }
 208
 209        $db =& $this->getDBInstance();
 210        if (PEAR::isError($db)) {
 211            return $db;
 212        }
 213
 214        return $db->raiseError(MDB2_ERROR_INVALID, null, null,
 215            'attempt to convert result value to an unknown type :' . $type, __FUNCTION__);
 216    }
 217
 218    // }}}
 219    // {{{ convertResult()
 220
 221    /**
 222     * Convert a value to a RDBMS indipendent MDB2 type
 223     *
 224     * @param mixed   $value value to be converted
 225     * @param string  $type  specifies which type to convert to
 226     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
 227     * @return mixed converted value
 228     * @access public
 229     */
 230    function convertResult($value, $type, $rtrim = true)
 231    {
 232        if (is_null($value)) {
 233            return null;
 234        }
 235        $db =& $this->getDBInstance();
 236        if (PEAR::isError($db)) {
 237            return $db;
 238        }
 239        if (!empty($db->options['datatype_map'][$type])) {
 240            $type = $db->options['datatype_map'][$type];
 241            if (!empty($db->options['datatype_map_callback'][$type])) {
 242                $parameter = array('type' => $type, 'value' => $value, 'rtrim' => $rtrim);
 243                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
 244            }
 245        }
 246        return $this->_baseConvertResult($value, $type, $rtrim);
 247    }
 248
 249    // }}}
 250    // {{{ convertResultRow()
 251
 252    /**
 253     * Convert a result row
 254     *
 255     * @param array   $types
 256     * @param array   $row   specifies the types to convert to
 257     * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
 258     * @return mixed MDB2_OK on success, an MDB2 error on failure
 259     * @access public
 260     */
 261    function convertResultRow($types, $row, $rtrim = true)
 262    {
 263        $types = $this->_sortResultFieldTypes(array_keys($row), $types);
 264        foreach ($row as $key => $value) {
 265            if (empty($types[$key])) {
 266                continue;
 267            }
 268            $value = $this->convertResult($row[$key], $types[$key], $rtrim);
 269            if (PEAR::isError($value)) {
 270                return $value;
 271            }
 272            $row[$key] = $value;
 273        }
 274        return $row;
 275    }
 276
 277    // }}}
 278    // {{{ _sortResultFieldTypes()
 279
 280    /**
 281     * convert a result row
 282     *
 283     * @param array $types
 284     * @param array $row specifies the types to convert to
 285     * @param bool   $rtrim   if to rtrim text values or not
 286     * @return mixed MDB2_OK on success,  a MDB2 error on failure
 287     * @access public
 288     */
 289    function _sortResultFieldTypes($columns, $types)
 290    {
 291        $n_cols = count($columns);
 292        $n_types = count($types);
 293        if ($n_cols > $n_types) {
 294            for ($i= $n_cols - $n_types; $i >= 0; $i--) {
 295                $types[] = null;
 296            }
 297        }
 298        $sorted_types = array();
 299        foreach ($columns as $col) {
 300            $sorted_types[$col] = null;
 301        }
 302        foreach ($types as $name => $type) {
 303            if (array_key_exists($name, $sorted_types)) {
 304                $sorted_types[$name] = $type;
 305                unset($types[$name]);
 306            }
 307        }
 308        // if there are left types in the array, fill the null values of the
 309        // sorted array with them, in order.
 310        if (count($types)) {
 311            reset($types);
 312            foreach (array_keys($sorted_types) as $k) {
 313                if (is_null($sorted_types[$k])) {
 314                    $sorted_types[$k] = current($types);
 315                    next($types);
 316                }
 317            }
 318        }
 319        return $sorted_types;
 320    }
 321
 322    // }}}
 323    // {{{ getDeclaration()
 324
 325    /**
 326     * Obtain DBMS specific SQL code portion needed to declare
 327     * of the given type
 328     *
 329     * @param string $type type to which the value should be converted to
 330     * @param string  $name   name the field to be declared.
 331     * @param string  $field  definition of the field
 332     * @return string  DBMS specific SQL code portion that should be used to
 333     *                 declare the specified field.
 334     * @access public
 335     */
 336    function getDeclaration($type, $name, $field)
 337    {
 338        $db =& $this->getDBInstance();
 339        if (PEAR::isError($db)) {
 340            return $db;
 341        }
 342
 343        if (!empty($db->options['datatype_map'][$type])) {
 344            $type = $db->options['datatype_map'][$type];
 345            if (!empty($db->options['datatype_map_callback'][$type])) {
 346                $parameter = array('type' => $type, 'name' => $name, 'field' => $field);
 347                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
 348            }
 349            $field['type'] = $type;
 350        }
 351
 352        if (!method_exists($this, "_get{$type}Declaration")) {
 353            return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
 354                'type not defined: '.$type, __FUNCTION__);
 355        }
 356        return $this->{"_get{$type}Declaration"}($name, $field);
 357    }
 358
 359    // }}}
 360    // {{{ getTypeDeclaration()
 361
 362    /**
 363     * Obtain DBMS specific SQL code portion needed to declare an text type
 364     * field to be used in statements like CREATE TABLE.
 365     *
 366     * @param array $field  associative array with the name of the properties
 367     *      of the field being declared as array indexes. Currently, the types
 368     *      of supported field properties are as follows:
 369     *
 370     *      length
 371     *          Integer value that determines the maximum length of the text
 372     *          field. If this argument is missing the field should be
 373     *          declared to have the longest length allowed by the DBMS.
 374     *
 375     *      default
 376     *          Text value to be used as default for this field.
 377     *
 378     *      notnull
 379     *          Boolean flag that indicates whether this field is constrained
 380     *          to not be set to null.
 381     * @return string  DBMS specific SQL code portion that should be used to
 382     *      declare the specified field.
 383     * @access public
 384     */
 385    function getTypeDeclaration($field)
 386    {
 387        $db =& $this->getDBInstance();
 388        if (PEAR::isError($db)) {
 389            return $db;
 390        }
 391
 392        switch ($field['type']) {
 393        case 'text':
 394            $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length'];
 395            $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
 396            return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
 397                : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
 398        case 'clob':
 399            return 'TEXT';
 400        case 'blob':
 401            return 'TEXT';
 402        case 'integer':
 403            return 'INT';
 404        case 'boolean':
 405            return 'INT';
 406        case 'date':
 407            return 'CHAR ('.strlen('YYYY-MM-DD').')';
 408        case 'time':
 409            return 'CHAR ('.strlen('HH:MM:SS').')';
 410        case 'timestamp':
 411            return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
 412        case 'float':
 413            return 'TEXT';
 414        case 'decimal':
 415            return 'TEXT';
 416        }
 417        return '';
 418    }
 419
 420    // }}}
 421    // {{{ _getDeclaration()
 422
 423    /**
 424     * Obtain DBMS specific SQL code portion needed to declare a generic type
 425     * field to be used in statements like CREATE TABLE.
 426     *
 427     * @param string $name   name the field to be declared.
 428     * @param array  $field  associative array with the name of the properties
 429     *      of the field being declared as array indexes. Currently, the types
 430     *      of supported field properties are as follows:
 431     *
 432     *      length
 433     *          Integer value that determines the maximum length of the text
 434     *          field. If this argument is missing the field should be
 435     *          declared to have the longest length allowed by the DBMS.
 436     *
 437     *      default
 438     *          Text value to be used as default for this field.
 439     *
 440     *      notnull
 441     *          Boolean flag that indicates whether this field is constrained
 442     *          to not be set to null.
 443     *      charset
 444     *          Text value with the default CHARACTER SET for this field.
 445     *      collation
 446     *          Text value with the default COLLATION for this field.
 447     * @return string  DBMS specific SQL code portion that should be used to
 448     *      declare the specified field, or a MDB2_Error on failure
 449     * @access protected
 450     */
 451    function _getDeclaration($name, $field)
 452    {
 453        $db =& $this->getDBInstance();
 454        if (PEAR::isError($db)) {
 455            return $db;
 456        }
 457
 458        $name = $db->quoteIdentifier($name, true);
 459        $declaration_options = $db->datatype->_getDeclarationOptions($field);
 460        if (PEAR::isError($declaration_options)) {
 461            return $declaration_options;
 462        }
 463        return $name.' '.$this->getTypeDeclaration($field).$declaration_options;
 464    }
 465
 466    // }}}
 467    // {{{ _getDeclarationOptions()
 468
 469    /**
 470     * Obtain DBMS specific SQL code portion needed to declare a generic type
 471     * field to be used in statement like CREATE TABLE, without the field name
 472     * and type values (ie. just the character set, default value, if the
 473     * field is permitted to be NULL or not, and the collation options).
 474     *
 475     * @param array  $field  associative array with the name of the properties
 476     *      of the field being declared as array indexes. Currently, the types
 477     *      of supported field properties are as follows:
 478     *
 479     *      default
 480     *          Text value to be used as default for this field.
 481     *      notnull
 482     *          Boolean flag that indicates whether this field is constrained
 483     *          to not be set to null.
 484     *      charset
 485     *          Text value with the default CHARACTER SET for this field.
 486     *      collation
 487     *          Text value with the default COLLATION for this field.
 488     * @return string  DBMS specific SQL code portion that should be used to
 489     *      declare the specified field's options.
 490     * @access protected
 491     */
 492    function _getDeclarationOptions($field)
 493    {
 494        $charset = empty($field['charset']) ? '' :
 495            ' '.$this->_getCharsetFieldDeclaration($field['charset']);
 496
 497        $default = '';
 498        if (array_key_exists('default', $field)) {
 499            if ($field['default'] === '') {
 500                $db =& $this->getDBInstance();
 501                if (PEAR::isError($db)) {
 502                    return $db;
 503                }
 504                if (empty($field['notnull'])) {
 505                    $field['default'] = null;
 506                } else {
 507                    $valid_default_values = $this->getValidTypes();
 508                    $field['default'] = $valid_default_values[$field['type']];
 509                }
 510                if ($field['default'] === ''
 511                    && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
 512                ) {
 513                    $field['default'] = ' ';
 514                }
 515            }
 516            $default = ' DEFAULT '.$this->quote($field['default'], $field['type']);
 517        } elseif (empty($field['notnull'])) {
 518            $default = ' DEFAULT NULL';
 519        }
 520
 521        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
 522        
 523        $collation = empty($field['collation']) ? '' :
 524            ' '.$this->_getCollationFieldDeclaration($field['collation']);
 525        return $charset.$default.$notnull.$collation;
 526    }
 527
 528    // }}}
 529    // {{{ _getCharsetFieldDeclaration()
 530    
 531    /**
 532     * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
 533     * of a field declaration to be used in statements like CREATE TABLE.
 534     *
 535     * @param string $charset   name of the charset
 536     * @return string  DBMS specific SQL code portion needed to set the CHARACTER SET
 537     *                 of a field declaration.
 538     */
 539    function _getCharsetFieldDeclaration($charset)
 540    {
 541        return '';
 542    }
 543
 544    // }}}
 545    // {{{ _getCollationFieldDeclaration()
 546
 547    /**
 548     * Obtain DBMS specific SQL code portion needed to set the COLLATION
 549     * of a field declaration to be used in statements like CREATE TABLE.
 550     *
 551     * @param string $collation   name of the collation
 552     * @return string  DBMS specific SQL code portion needed to set the COLLATION
 553     *                 of a field declaration.
 554     */
 555    function _getCollationFieldDeclaration($collation)
 556    {
 557        return '';
 558    }
 559
 560    // }}}
 561    // {{{ _getIntegerDeclaration()
 562
 563    /**
 564     * Obtain DBMS specific SQL code portion needed to declare an integer type
 565     * field to be used in statements like CREATE TABLE.
 566     *
 567     * @param string $name name the field to be declared.
 568     * @param array $field associative array with the name of the properties
 569     *       of the field being declared as array indexes. Currently, the types
 570     *       of supported field properties are as follows:
 571     *
 572     *       unsigned
 573     *           Boolean flag that indicates whether the field should be
 574     *           declared as unsigned integer if possible.
 575     *
 576     *       default
 577     *           Integer value to be used as default for this field.
 578     *
 579     *       notnull
 580     *           Boolean flag that indicates whether this field is constrained
 581     *           to not be set to null.
 582     * @return string DBMS specific SQL code portion that should be used to
 583     *       declare the specified field.
 584     * @access protected
 585     */
 586    function _getIntegerDeclaration($name, $field)
 587    {
 588        if (!empty($field['unsigned'])) {
 589            $db =& $this->getDBInstance();
 590            if (PEAR::isError($db)) {
 591                return $db;
 592            }
 593
 594            $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
 595        }
 596        return $this->_getDeclaration($name, $field);
 597    }
 598
 599    // }}}
 600    // {{{ _getTextDeclaration()
 601
 602    /**
 603     * Obtain DBMS specific SQL code portion needed to declare an text type
 604     * field to be used in statements like CREATE TABLE.
 605     *
 606     * @param string $name name the field to be declared.
 607     * @param array $field associative array with the name of the properties
 608     *       of the field being declared as array indexes. Currently, the types
 609     *       of supported field properties are as follows:
 610     *
 611     *       length
 612     *           Integer value that determines the maximum length of the text
 613     *           field. If this argument is missing the field should be
 614     *           declared to have the longest length allowed by the DBMS.
 615     *
 616     *       default
 617     *           Text value to be used as default for this field.
 618     *
 619     *       notnull
 620     *           Boolean flag that indicates whether this field is constrained
 621     *           to not be set to null.
 622     * @return string DBMS specific SQL code portion that should be used to
 623     *       declare the specified field.
 624     * @access protected
 625     */
 626    function _getTextDeclaration($name, $field)
 627    {
 628        return $this->_getDeclaration($name, $field);
 629    }
 630
 631    // }}}
 632    // {{{ _getCLOBDeclaration()
 633
 634    /**
 635     * Obtain DBMS specific SQL code portion needed to declare an character
 636     * large object type field to be used in statements like CREATE TABLE.
 637     *
 638     * @param string $name name the field to be declared.
 639     * @param array $field associative array with the name of the properties
 640     *        of the field being declared as array indexes. Currently, the types
 641     *        of supported field properties are as follows:
 642     *
 643     *        length
 644     *            Integer value that determines the maximum length of the large
 645     *            object field. If this argument is missing the field should be
 646     *            declared to have the longest length allowed by the DBMS.
 647     *
 648     *        notnull
 649     *            Boolean flag that indicates whether this field is constrained
 650     *            to not be set to null.
 651     * @return string DBMS specific SQL code portion that should be used to
 652     *        declare the specified field.
 653     * @access public
 654     */
 655    function _getCLOBDeclaration($name, $field)
 656    {
 657        $db =& $this->getDBInstance();
 658        if (PEAR::isError($db)) {
 659            return $db;
 660        }
 661
 662        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
 663        $name = $db->quoteIdentifier($name, true);
 664        return $name.' '.$this->getTypeDeclaration($field).$notnull;
 665    }
 666
 667    // }}}
 668    // {{{ _getBLOBDeclaration()
 669
 670    /**
 671     * Obtain DBMS specific SQL code portion needed to declare an binary large
 672     * object type field to be used in statements like CREATE TABLE.
 673     *
 674     * @param string $name name the field to be declared.
 675     * @param array $field associative array with the name of the properties
 676     *        of the field being declared as array indexes. Currently, the types
 677     *        of supported field properties are as follows:
 678     *
 679     *        length
 680     *            Integer value that determines the maximum length of the large
 681     *            object field. If this argument is missing the field should be
 682     *            declared to have the longest length allowed by the DBMS.
 683     *
 684     *        notnull
 685     *            Boolean flag that indicates whether this field is constrained
 686     *            to not be set to null.
 687     * @return string DBMS specific SQL code portion that should be used to
 688     *        declare the specified field.
 689     * @access protected
 690     */
 691    function _getBLOBDeclaration($name, $field)
 692    {
 693        $db =& $this->getDBInstance();
 694        if (PEAR::isError($db)) {
 695            return $db;
 696        }
 697
 698        $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
 699        $name = $db->quoteIdentifier($name, true);
 700        return $name.' '.$this->getTypeDeclaration($field).$notnull;
 701    }
 702
 703    // }}}
 704    // {{{ _getBooleanDeclaration()
 705
 706    /**
 707     * Obtain DBMS specific SQL code portion needed to declare a boolean type
 708     * field to be used in statements like CREATE TABLE.
 709     *
 710     * @param string $name name the field to be declared.
 711     * @param array $field associative array with the name of the properties
 712     *       of the field being declared as array indexes. Currently, the types
 713     *       of supported field properties are as follows:
 714     *
 715     *       default
 716     *           Boolean value to be used as default for this field.
 717     *
 718     *       notnullL
 719     *           Boolean flag that indicates whether this field is constrained
 720     *           to not be set to null.
 721     * @return string DBMS specific SQL code portion that should be used to
 722     *       declare the specified field.
 723     * @access protected
 724     */
 725    function _getBooleanDeclaration($name, $field)
 726    {
 727        return $this->_getDeclaration($name, $field);
 728    }
 729
 730    // }}}
 731    // {{{ _getDateDeclaration()
 732
 733    /**
 734     * Obtain DBMS specific SQL code portion needed to declare a date type
 735     * field to be used in statements like CREATE TABLE.
 736     *
 737     * @param string $name name the field to be declared.
 738     * @param array $field associative array with the name of the properties
 739     *       of the field being declared as array indexes. Currently, the types
 740     *       of supported field properties are as follows:
 741     *
 742     *       default
 743     *           Date value to be used as default for this field.
 744     *
 745     *       notnull
 746     *           Boolean flag that indicates whether this field is constrained
 747     *           to not be set to null.
 748     * @return string DBMS specific SQL code portion that should be used to
 749     *       declare the specified field.
 750     * @access protected
 751     */
 752    function _getDateDeclaration($name, $field)
 753    {
 754        return $this->_getDeclaration($name, $field);
 755    }
 756
 757    // }}}
 758    // {{{ _getTimestampDeclaration()
 759
 760    /**
 761     * Obtain DBMS specific SQL code portion needed to declare a timestamp
 762     * field to be used in statements like CREATE TABLE.
 763     *
 764     * @param string $name name the field to be declared.
 765     * @param array $field associative array with the name of the properties
 766     *       of the field being declared as array indexes. Currently, the types
 767     *       of supported field properties are as follows:
 768     *
 769     *       default
 770     *           Timestamp value to be used as default for this field.
 771     *
 772     *       notnull
 773     *           Boolean flag that indicates whether this field is constrained
 774     *           to not be set to null.
 775     * @return string DBMS specific SQL code portion that should be used to
 776     *       declare the specified field.
 777     * @access protected
 778     */
 779    function _getTimestampDeclaration($name, $field)
 780    {
 781        return $this->_getDeclaration($name, $field);
 782    }
 783
 784    // }}}
 785    // {{{ _getTimeDeclaration()
 786
 787    /**
 788     * Obtain DBMS specific SQL code portion needed to declare a time
 789     * field to be used in statements like CREATE TABLE.
 790     *
 791     * @param string $name name the field to be declared.
 792     * @param array $field associative array with the name of the properties
 793     *       of the field being declared as array indexes. Currently, the types
 794     *       of supported field properties are as follows:
 795     *
 796     *       default
 797     *           Time value to be used as default for this field.
 798     *
 799     *       notnull
 800     *           Boolean flag that indicates whether this field is constrained
 801     *           to not be set to null.
 802     * @return string DBMS specific SQL code portion that should be used to
 803     *       declare the specified field.
 804     * @access protected
 805     */
 806    function _getTimeDeclaration($name, $field)
 807    {
 808        return $this->_getDeclaration($name, $field);
 809    }
 810
 811    // }}}
 812    // {{{ _getFloatDeclaration()
 813
 814    /**
 815     * Obtain DBMS specific SQL code portion needed to declare a float type
 816     * field to be used in statements like CREATE TABLE.
 817     *
 818     * @param string $name name the field to be declared.
 819     * @param array $field associative array with the name of the properties
 820     *       of the field being declared as array indexes. Currently, the types
 821     *       of supported field properties are as follows:
 822     *
 823     *       default
 824     *           Float value to be used as default for this field.
 825     *
 826     *       notnull
 827     *           Boolean flag that indicates whether this field is constrained
 828     *           to not be set to null.
 829     * @return string DBMS specific SQL code portion that should be used to
 830     *       declare the specified field.
 831     * @access protected
 832     */
 833    function _getFloatDeclaration($name, $field)
 834    {
 835        return $this->_getDeclaration($name, $field);
 836    }
 837
 838    // }}}
 839    // {{{ _getDecimalDeclaration()
 840
 841    /**
 842     * Obtain DBMS specific SQL code portion needed to declare a decimal type
 843     * field to be used in statements like CREATE TABLE.
 844     *
 845     * @param string $name name the field to be declared.
 846     * @param array $field associative array with the name of the properties
 847     *       of the field being declared as array indexes. Currently, the types
 848     *       of supported field properties are as follows:
 849     *
 850     *       default
 851     *           Decimal value to be used as default for this field.
 852     *
 853     *       notnull
 854     *           Boolean flag that indicates whether this field is constrained
 855     *           to not be set to null.
 856     * @return string DBMS specific SQL code portion that should be used to
 857     *       declare the specified field.
 858     * @access protected
 859     */
 860    function _getDecimalDeclaration($name, $field)
 861    {
 862        return $this->_getDeclaration($name, $field);
 863    }
 864
 865    // }}}
 866    // {{{ compareDefinition()
 867
 868    /**
 869     * Obtain an array of changes that may need to applied
 870     *
 871     * @param array $current new definition
 872     * @param array  $previous old definition
 873     * @return array  containing all changes that will need to be applied
 874     * @access public
 875     */
 876    function compareDefinition($current, $previous)
 877    {
 878        $type = !empty($current['type']) ? $current['type'] : null;
 879
 880        if (!method_exists($this, "_compare{$type}Definition")) {
 881            $db =& $this->getDBInstance();
 882            if (PEAR::isError($db)) {
 883                return $db;
 884            }
 885            if (!empty($db->options['datatype_map_callback'][$type])) {
 886                $parameter = array('current' => $current, 'previous' => $previous);
 887                $change =  call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
 888                return $change;
 889            }
 890            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
 891                'type "'.$current['type'].'" is not yet supported', __FUNCTION__);
 892        }
 893
 894        if (empty($previous['type']) || $previous['type'] != $type) {
 895            return $current;
 896        }
 897
 898        $change = $this->{"_compare{$type}Definition"}($current, $previous);
 899
 900        if ($previous['type'] != $type) {
 901            $change['type'] = true;
 902        }
 903
 904        $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
 905        $notnull = !empty($current['notnull']) ? $current['notnull'] : false;
 906        if ($previous_notnull != $notnull) {
 907            $change['notnull'] = true;
 908        }
 909
 910        $previous_default = array_key_exists('default', $previous) ? $previous['default'] :
 911            ($previous_notnull ? '' : null);
 912        $default = array_key_exists('default', $current) ? $current['default'] :
 913            ($notnull ? '' : null);
 914        if ($previous_default !== $default) {
 915            $change['default'] = true;
 916        }
 917
 918        return $change;
 919    }
 920
 921    // }}}
 922    // {{{ _compareIntegerDefinition()
 923
 924    /**
 925     * Obtain an array of changes that may need to applied to an integer field
 926     *
 927     * @param array $current new definition
 928     * @param array  $previous old definition
 929     * @return array  containing all changes that will need to be applied
 930     * @access protected
 931     */
 932    function _compareIntegerDefinition($current, $previous)
 933    {
 934        $change = array();
 935        $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false;
 936        $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false;
 937        if ($previous_unsigned != $unsigned) {
 938            $change['unsigned'] = true;
 939        }
 940        $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false;
 941        $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false;
 942        if ($previous_autoincrement != $autoincrement) {
 943            $change['autoincrement'] = true;
 944        }
 945        return $change;
 946    }
 947
 948    // }}}
 949    // {{{ _compareTextDefinition()
 950
 951    /**
 952     * Obtain an array of changes that may need to applied to an text field
 953     *
 954     * @param array $current new definition
 955     * @param array  $previous old definition
 956     * @return array  containing all changes that will need to be applied
 957     * @access protected
 958     */
 959    function _compareTextDefinition($current, $previous)
 960    {
 961        $change = array();
 962        $previous_length = !empty($previous['length']) ? $previous['length'] : 0;
 963        $length = !empty($current['length']) ? $current['length'] : 0;
 964        if ($previous_length != $length) {
 965            $change['length'] = true;
 966        }
 967        $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0;
 968        $fixed = !empty($current['fixed']) ? $current['fixed'] : 0;
 969        if ($previous_fixed != $fixed) {
 970            $change['fixed'] = true;
 971        }
 972        return $change;
 973    }
 974
 975    // }}}
 976    // {{{ _compareCLOBDefinition()
 977
 978    /**
 979     * Obtain an array of changes that may need to applied to an CLOB field
 980     *
 981     * @param array $current new definition
 982     * @param array  $previous old definition
 983     * @return array  containing all changes that will need to be applied
 984     * @access protected
 985     */
 986    function _compareCLOBDefinition($current, $previous)
 987    {
 988        return $this->_compareTextDefinition($current, $previous);
 989    }
 990
 991    // }}}
 992    // {{{ _compareBLOBDefinition()
 993
 994    /**
 995     * Obtain an array of changes that may need to applied to an BLOB field
 996     *
 997     * @param array $current new definition
 998     * @param array  $previous old definition
 999     * @return array  containing all changes that will need to be applied
1000     * @access protected
1001     */
1002    function _compareBLOBDefinition($current, $previous)
1003    {
1004        return $this->_compareTextDefinition($current, $previous);
1005    }
1006
1007    // }}}
1008    // {{{ _compareDateDefinition()
1009
1010    /**
1011     * Obtain an array of changes that may need to applied to an date field
1012     *
1013     * @param array $current new definition
1014     * @param array  $previous old definition
1015     * @return array  containing all changes that will need to be applied
1016     * @access protected
1017     */
1018    function _compareDateDefinition($current, $previous)
1019    {
1020        return array();
1021    }
1022
1023    // }}}
1024    // {{{ _compareTimeDefinition()
1025
1026    /**
1027     * Obtain an array of changes that may need to applied to an time field
1028     *
1029     * @param array $current new definition
1030     * @param array  $previous old definition
1031     * @return array  containing all changes that will need to be applied
1032     * @access protected
1033     */
1034    function _compareTimeDefinition($current, $previous)
1035    {
1036        return array();
1037    }
1038
1039    // }}}
1040    // {{{ _compareTimestampDefinition()
1041
1042    /**
1043     * Obtain an array of changes that may need to applied to an timestamp field
1044     *
1045     * @param array $current new definition
1046     * @param array  $previous old definition
1047     * @return array  containing all changes that will need to be applied
1048     * @access protected
1049     */
1050    function _compareTimestampDefinition($current, $previous)
1051    {
1052        return array();
1053    }
1054
1055    // }}}
1056    // {{{ _compareBooleanDefinition()
1057
1058    /**
1059     * Obtain an array of changes that may need to applied to an boolean field
1060     *
1061     * @param array $current new definition
1062     * @param array  $previous old definition
1063     * @return array  containing all changes that will need to be applied
1064     * @access protected
1065     */
1066    function _compareBooleanDefinition($current, $previous)
1067    {
1068        return array();
1069    }
1070
1071    // }}}
1072    // {{{ _compareFloatDefinition()
1073
1074    /**
1075     * Obtain an array of changes that may need to applied to an float field
1076     *
1077     * @param array $current new definition
1078     * @param array  $previous old definition
1079     * @return array  containing all changes that will need to be applied
1080     * @access protected
1081     */
1082    function _compareFloatDefinition($current, $previous)
1083    {
1084        return array();
1085    }
1086
1087    // }}}
1088    // {{{ _compareDecimalDefinition()
1089
1090    /**
1091     * Obtain an array of changes that may need to applied to an decimal field
1092     *
1093     * @param array $current new definition
1094     * @param array  $previous old definition
1095     * @return array  containing all changes that will need to be applied
1096     * @access protected
1097     */
1098    function _compareDecimalDefinition($current, $previous)
1099    {
1100        return array();
1101    }
1102
1103    // }}}
1104    // {{{ quote()
1105
1106    /**
1107     * Convert a text value into a DBMS specific format that is suitable to
1108     * compose query statements.
1109     *
1110     * @param string $value text string value that is intended to be converted.
1111     * @param string $type type to which the value should be converted to
1112     * @param bool $quote determines if the value should be quoted and escaped
1113     * @param bool $escape_wildcards if to escape escape wildcards
1114     * @return string text string that represents the given argument value in
1115     *       a DBMS specific format.
1116     * @access public
1117     */
1118    function quote($value, $type = null, $quote = true, $escape_wildcards = false)
1119    {
1120        $db =& $this->getDBInstance();
1121        if (PEAR::isError($db)) {
1122            return $db;
1123        }
1124
1125        if (is_null($value)
1126            || ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
1127        ) {
1128            if (!$quote) {
1129                return null;
1130            }
1131            return 'NULL';
1132        }
1133
1134        if (is_null($type)) {
1135            switch (gettype($value)) {
1136            case 'integer':
1137                $type = 'integer';
1138                break;
1139            case 'double':
1140                // todo: default to decimal as float is quite unusual
1141                // $type = 'float';
1142                $type = 'decimal';
1143                break;
1144            case 'boolean':
1145                $type = 'boolean';
1146                break;
1147            case 'array':
1148                 $value = serialize($value);
1149            case 'object':
1150                 $type = 'text';
1151                break;
1152            default:
1153                if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) {
1154                    $type = 'timestamp';
1155                } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) {
1156                    $type = 'time';
1157                } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
1158                    $type = 'date';
1159                } else {
1160                    $type = 'text';
1161                }
1162                break;
1163            }
1164        } elseif (!empty($db->options['datatype_map'][$type])) {
1165            $type = $db->options['datatype_map'][$type];
1166            if (!empty($db->options['datatype_map_callback'][$type])) {
1167                $parameter = array('type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards);
1168                return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
1169            }
1170        }
1171
1172        if (!method_exists($this, "_quote{$type}")) {
1173            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
1174                'type not defined: '.$type, __FUNCTION__);
1175        }
1176        $value = $this->{"_quote{$type}"}($value, $quote, $escape_wildcards);
1177        if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
1178            && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern']
1179        ) {
1180            $value.= $this->patternEscapeString();
1181        }
1182        return $value;
1183    }
1184
1185    // }}}
1186    // {{{ _quoteInteger()
1187
1188    /**
1189     * Convert a text value into a DBMS specific format that is suitable to
1190     * compose query statements.
1191     *
1192     * @param string $value text string value that is intended to be converted.
1193     * @param bool $quote determines if the value should be quoted and escaped
1194     * @param bool $escape_wildcards if to escape escape wildcards
1195     * @return string text string that represents the given argument value in
1196     *       a DBMS specific format.
1197     * @access protected
1198     */
1199    function _quoteInteger($value, $quote, $escape_wildcards)
1200    {
1201        return (int)$value;
1202    }
1203
1204    // }}}
1205    // {{{ _quoteText()
1206
1207    /**
1208     * Convert a text value into a DBMS specific format that is suitable to
1209     * compose query statements.
1210     *
1211     * @param string $value text string value that is intended to be converted.
1212     * @param bool $quote determines if the value should be quoted and escaped
1213     * @param bool $escape_wildcards if to escape escape wildcards
1214     * @return string text string that already contains any DBMS specific
1215     *       escaped character sequences.
1216     * @access protected
1217     */
1218    function _quoteText($value, $quote, $escape_wildcards)
1219    {
1220        if (!$quote) {
1221            return $value;
1222        }
1223
1224        $db =& $this->getDBInstance();
1225        if (PEAR::isError($db)) {
1226            return $db;
1227        }
1228
1229        $value = $db->escape($value, $escape_wildcards);
1230        if (PEAR::isError($value)) {
1231            return $value;
1232        }
1233        return "'".$value."'";
1234    }
1235
1236    // }}}
1237    // {{{ _readFile()
1238
1239    /**
1240     * Convert a text value into a DBMS specific format that is suitable to
1241     * compose query statements.
1242     *
1243     * @param string $value text string value that is intended to be converted.
1244     * @return string text string that represents the given argument value in
1245     *       a DBMS specific format.
1246     * @access protected
1247     */
1248    function _readFile($value)
1249    {
1250        $close = false;
1251        if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
1252            $close = true;
1253            if ($match[1] == 'file://') {
1254                $value = $match[2];
1255            }
1256            $value = @fopen($value, 'r');
1257        }
1258
1259        if (is_resource($value)) {
1260            $db =& $this->getDBInstance();
1261            if (PEAR::isError($db)) {
1262                return $db;
1263            }
1264
1265            $fp = $value;
1266            $value = '';
1267            while (!@feof($fp)) {
1268                $value.= @fread($fp, $db->options['lob_buffer_length']);
1269            }
1270            if ($close) {
1271                @fclose($fp);
1272            }
1273        }
1274
1275        return $value;
1276    }
1277
1278    // }}}
1279    // {{{ _quoteLOB()
1280
1281    /**
1282     * Convert a text value into a DBMS specific format that is suitable to
1283     * compose query statements.
1284     *
1285     * @param string $value text string value that is intended to be converted.
1286     * @param bool $quote determines if the value should be quoted and escaped
1287     * @param bool $escape_wildcards if to escape escape wildcards
1288     * @return string text string that represents the given argument value in
1289     *       a DBMS specific format.
1290     * @access protected
1291     */
1292    function _quoteLOB($value, $quote, $escape_wildcards)
1293    {
1294        $value = $this->_readFile($value);
1295        if (PEAR::isError($value)) {
1296            return $value;
1297        }
1298        return $this->_quoteText($value, $quote, $escape_wildcards);
1299    }
1300
1301    // }}}
1302    // {{{ _quoteCLOB()
1303
1304    /**
1305     * Convert a text value into a DBMS specific format that is suitable to
1306     * compose query statements.
1307     *
1308     * @param string $value text string value that is intended to be converted.
1309     * @param bool $quote determines if the value should be quoted and escaped
1310     * @param bool $escape_wildcards if to escape escape wildcards
1311     * @return string text string that represents the given argument value in
1312     *       a DBMS specific format.
1313     * @access protected
1314     */
1315    function _quoteCLOB($value, $quote, $escape_wildcards)
1316    {
1317        return $this->_quoteLOB($value, $quote, $escape_wildcards);
1318    }
1319
1320    // }}}
1321    // {{{ _quoteBLOB()
1322
1323    /**
1324     * Convert a text value into a DBMS specific format that is suitable to
1325     * compose query statements.
1326     *
1327     * @param string $value text string value that is intended to be converted.
1328     * @param bool $quote determines if the value should be quoted and escaped
1329     * @param bool $escape_wildcards if to escape escape wildcards
1330     * @return string text string that represents the given argument value in
1331     *       a DBMS specific format.
1332     * @access protected
1333     */
1334    function _quoteBLOB($value, $quote, $escape_wildcards)
1335    {
1336        return $this->_quoteLOB($value, $quote, $escape_wildcards);
1337    }
1338
1339    // }}}
1340    // {{{ _quoteBoolean()
1341
1342    /**
1343     * Convert a text value into a DBMS specific format that is suitable to
1344     * compose query statements.
1345     *
1346     * @param string $value text string value that is intended to be converted.
1347     * @param bool $quote determines if the value should be quoted and escaped
1348     * @param bool $escape_wildcards if to escape escape wildcards
1349     * @return string text string that represents the given argument value in
1350     *       a DBMS specific format.
1351     * @access protected
1352     */
1353    function _quoteBoolean($value, $quote, $escape_wildcards)
1354    {
1355        return ($value ? 1 : 0);
1356    }
1357
1358    // }}}
1359    // {{{ _quoteDate()
1360
1361    /**
1362     * Convert a text value into a DBMS specific format that is suitable to
1363     * compose query statements.
1364     *
1365     * @param string $value text string value that is intended to be converted.
1366     * @param bool $quote determines if the value should be quoted and escaped
1367     * @param bool $escape_wildcards if to escape escape wildcards
1368     * @return string text string that represents the given argument value in
1369     *       a DBMS specific format.
1370     * @access protected
1371     */
1372    function _quoteDate($value, $quote, $escape_wildcards)
1373    {
1374        if ($value === 'CURRENT_DATE') {
1375            $db =& $this->getDBInstance();
1376            if (PEAR::isError($db)) {
1377                return $db;
1378            }
1379            if (isset($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
1380                return $db->function->now('date');
1381            }
1382            return 'CURRENT_DATE';
1383        }
1384        return $this->_quoteText($value, $quote, $escape_wildcards);
1385    }
1386
1387    // }}}
1388    // {{{ _quoteTimestamp()
1389
1390    /**
1391     * Convert a text value into a DBMS specific format that is suitable to
1392     * compose query statements.
1393     *
1394     * @param string $value text string value that is intended to be converted.
1395     * @param bool $quote determines if the value should be qu…

Large files files are truncated, but you can click here to view the full file