MDB2
[ class tree: MDB2 ] [ index: MDB2 ] [ all elements ]

Source for file Common.php

Documentation is available at Common.php

  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.  
  47. require_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.  */
  62. {
  63.     var $valid_default_values = array(
  64.         'text'      => '',
  65.         'boolean'   => true,
  66.         'integer'   => 0,
  67.         'decimal'   => 0.0,
  68.         'float'     => 0.0,
  69.         'timestamp' => '1970-01-01 00:00:00',
  70.         'time'      => '00:00:00',
  71.         'date'      => '1970-01-01',
  72.         'clob'      => '',
  73.         'blob'      => '',
  74.     );
  75.  
  76.     /**
  77.      * contains all LOB objects created with this MDB2 instance
  78.      * @var array 
  79.      * @access protected
  80.      */
  81.     var $lobs = array();
  82.  
  83.     // }}}
  84.     // {{{ getValidTypes()
  85.  
  86.     /**
  87.      * Get the list of valid types
  88.      *
  89.      * This function returns an array of valid types as keys with the values
  90.      * being possible default values for all native datatypes and mapped types
  91.      * for custom datatypes.
  92.      *
  93.      * @return mixed array on success, a MDB2 error on failure
  94.      * @access public
  95.      */
  96.     function getValidTypes()
  97.     {
  98.         $types $this->valid_default_values;
  99.         $db =$this->getDBInstance();
  100.         if (PEAR::isError($db)) {
  101.             return $db;
  102.         }
  103.         if (!empty($db->options['datatype_map'])) {
  104.             foreach ($db->options['datatype_map'as $type => $mapped_type{
  105.                 if (array_key_exists($mapped_type$types)) {
  106.                     $types[$type$types[$mapped_type];
  107.                 elseif (!empty($db->options['datatype_map_callback'][$type])) {
  108.                     $parameter = array('type' => $type'mapped_type' => $mapped_type);
  109.                     $default =  call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  110.                     $types[$type$default;
  111.                 }
  112.             }
  113.         }
  114.         return $types;
  115.     }
  116.  
  117.     // }}}
  118.     // {{{ checkResultTypes()
  119.  
  120.     /**
  121.      * Define the list of types to be associated with the columns of a given
  122.      * result set.
  123.      *
  124.      * This function may be called before invoking fetchRow(), fetchOne()
  125.      * fetchCole() and fetchAll() so that the necessary data type
  126.      * conversions are performed on the data to be retrieved by them. If this
  127.      * function is not called, the type of all result set columns is assumed
  128.      * to be text, thus leading to not perform any conversions.
  129.      *
  130.      * @param array $types array variable that lists the
  131.      *        data types to be expected in the result set columns. If this array
  132.      *        contains less types than the number of columns that are returned
  133.      *        in the result set, the remaining columns are assumed to be of the
  134.      *        type text. Currently, the types clob and blob are not fully
  135.      *        supported.
  136.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  137.      * @access public
  138.      */
  139.     function checkResultTypes($types)
  140.     {
  141.         $types is_array($types$types : array($types);
  142.         foreach ($types as $key => $type{
  143.             if (!isset($this->valid_default_values[$type])) {
  144.                 $db =$this->getDBInstance();
  145.                 if (PEAR::isError($db)) {
  146.                     return $db;
  147.                 }
  148.                 if (empty($db->options['datatype_map'][$type])) {
  149.                     return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  150.                         $type.' for '.$key.' is not a supported column type'__FUNCTION__);
  151.                 }
  152.             }
  153.         }
  154.         return $types;
  155.     }
  156.  
  157.     // }}}
  158.     // {{{ _baseConvertResult()
  159.  
  160.     /**
  161.      * General type conversion method
  162.      *
  163.      * @param mixed   $value reference to a value to be converted
  164.      * @param string  $type  specifies which type to convert to
  165.      * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
  166.      * @return object an MDB2 error on failure
  167.      * @access protected
  168.      */
  169.     function _baseConvertResult($value$type$rtrim = true)
  170.     {
  171.         switch ($type{
  172.         case 'text':
  173.             if ($rtrim{
  174.                 $value rtrim($value);
  175.             }
  176.             return $value;
  177.         case 'integer':
  178.             return intval($value);
  179.         case 'boolean':
  180.             return !empty($value);
  181.         case 'decimal':
  182.             return $value;
  183.         case 'float':
  184.             return doubleval($value);
  185.         case 'date':
  186.             return $value;
  187.         case 'time':
  188.             return $value;
  189.         case 'timestamp':
  190.             return $value;
  191.         case 'clob':
  192.         case 'blob':
  193.             $this->lobs[= array(
  194.                 'buffer' => null,
  195.                 'position' => 0,
  196.                 'lob_index' => null,
  197.                 'endOfLOB' => false,
  198.                 'resource' => $value,
  199.                 'value' => null,
  200.                 'loaded' => false,
  201.             );
  202.             end($this->lobs);
  203.             $lob_index key($this->lobs);
  204.             $this->lobs[$lob_index]['lob_index'$lob_index;
  205.             return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index'r+');
  206.         }
  207.  
  208.         $db =$this->getDBInstance();
  209.         if (PEAR::isError($db)) {
  210.             return $db;
  211.         }
  212.  
  213.         return $db->raiseError(MDB2_ERROR_INVALIDnullnull,
  214.             'attempt to convert result value to an unknown type :' $type__FUNCTION__);
  215.     }
  216.  
  217.     // }}}
  218.     // {{{ convertResult()
  219.  
  220.     /**
  221.      * Convert a value to a RDBMS indipendent MDB2 type
  222.      *
  223.      * @param mixed   $value value to be converted
  224.      * @param string  $type  specifies which type to convert to
  225.      * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
  226.      * @return mixed converted value
  227.      * @access public
  228.      */
  229.     function convertResult($value$type$rtrim = true)
  230.     {
  231.         if (is_null($value)) {
  232.             return null;
  233.         }
  234.         $db =$this->getDBInstance();
  235.         if (PEAR::isError($db)) {
  236.             return $db;
  237.         }
  238.         if (!empty($db->options['datatype_map'][$type])) {
  239.             $type $db->options['datatype_map'][$type];
  240.             if (!empty($db->options['datatype_map_callback'][$type])) {
  241.                 $parameter = array('type' => $type'value' => $value'rtrim' => $rtrim);
  242.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  243.             }
  244.         }
  245.         return $this->_baseConvertResult($value$type$rtrim);
  246.     }
  247.  
  248.     // }}}
  249.     // {{{ convertResultRow()
  250.  
  251.     /**
  252.      * Convert a result row
  253.      *
  254.      * @param array   $types 
  255.      * @param array   $row   specifies the types to convert to
  256.      * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
  257.      * @return mixed MDB2_OK on success, an MDB2 error on failure
  258.      * @access public
  259.      */
  260.     function convertResultRow($types$row$rtrim = true)
  261.     {
  262.         $types $this->_sortResultFieldTypes(array_keys($row)$types);
  263.         foreach ($row as $key => $value{
  264.             if (empty($types[$key])) {
  265.                 continue;
  266.             }
  267.             $value $this->convertResult($row[$key]$types[$key]$rtrim);
  268.             if (PEAR::isError($value)) {
  269.                 return $value;
  270.             }
  271.             $row[$key$value;
  272.         }
  273.         return $row;
  274.     }
  275.  
  276.     // }}}
  277.     // {{{ _sortResultFieldTypes()
  278.  
  279.     /**
  280.      * convert a result row
  281.      *
  282.      * @param array $types 
  283.      * @param array $row specifies the types to convert to
  284.      * @param bool   $rtrim   if to rtrim text values or not
  285.      * @return mixed MDB2_OK on success,  a MDB2 error on failure
  286.      * @access public
  287.      */
  288.     function _sortResultFieldTypes($columns$types)
  289.     {
  290.         $n_cols count($columns);
  291.         $n_types count($types);
  292.         if ($n_cols $n_types{
  293.             for ($i$n_cols $n_types$i >= 0; $i--{
  294.                 $types[= null;
  295.             }
  296.         }
  297.         $sorted_types = array();
  298.         foreach ($columns as $col{
  299.             $sorted_types[$col= null;
  300.         }
  301.         foreach ($types as $name => $type{
  302.             if (array_key_exists($name$sorted_types)) {
  303.                 $sorted_types[$name$type;
  304.                 unset($types[$name]);
  305.             }
  306.         }
  307.         // if there are left types in the array, fill the null values of the
  308.         // sorted array with them, in order.
  309.         if (count($types)) {
  310.             reset($types);
  311.             foreach (array_keys($sorted_typesas $k{
  312.                 if (is_null($sorted_types[$k])) {
  313.                     $sorted_types[$kcurrent($types);
  314.                     next($types);
  315.                 }
  316.             }
  317.         }
  318.         return $sorted_types;
  319.     }
  320.  
  321.     // }}}
  322.     // {{{ getDeclaration()
  323.  
  324.     /**
  325.      * Obtain DBMS specific SQL code portion needed to declare
  326.      * of the given type
  327.      *
  328.      * @param string $type type to which the value should be converted to
  329.      * @param string  $name   name the field to be declared.
  330.      * @param string  $field  definition of the field
  331.      * @return string  DBMS specific SQL code portion that should be used to
  332.      *                  declare the specified field.
  333.      * @access public
  334.      */
  335.     function getDeclaration($type$name$field)
  336.     {
  337.         $db =$this->getDBInstance();
  338.         if (PEAR::isError($db)) {
  339.             return $db;
  340.         }
  341.  
  342.         if (!empty($db->options['datatype_map'][$type])) {
  343.             $type $db->options['datatype_map'][$type];
  344.             if (!empty($db->options['datatype_map_callback'][$type])) {
  345.                 $parameter = array('type' => $type'name' => $name'field' => $field);
  346.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  347.             }
  348.             $field['type'$type;
  349.         }
  350.  
  351.         if (!method_exists($this"_get{$type}Declaration")) {
  352.             return $db->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  353.                 'type not defined: '.$type__FUNCTION__);
  354.         }
  355.         return $this->{"_get{$type}Declaration"}($name$field);
  356.     }
  357.  
  358.     // }}}
  359.     // {{{ getTypeDeclaration()
  360.  
  361.     /**
  362.      * Obtain DBMS specific SQL code portion needed to declare an text type
  363.      * field to be used in statements like CREATE TABLE.
  364.      *
  365.      * @param array $field  associative array with the name of the properties
  366.      *       of the field being declared as array indexes. Currently, the types
  367.      *       of supported field properties are as follows:
  368.      *
  369.      *       length
  370.      *           Integer value that determines the maximum length of the text
  371.      *           field. If this argument is missing the field should be
  372.      *           declared to have the longest length allowed by the DBMS.
  373.      *
  374.      *       default
  375.      *           Text value to be used as default for this field.
  376.      *
  377.      *       notnull
  378.      *           Boolean flag that indicates whether this field is constrained
  379.      *           to not be set to null.
  380.      * @return string  DBMS specific SQL code portion that should be used to
  381.      *       declare the specified field.
  382.      * @access public
  383.      */
  384.     function getTypeDeclaration($field)
  385.     {
  386.         $db =$this->getDBInstance();
  387.         if (PEAR::isError($db)) {
  388.             return $db;
  389.         }
  390.  
  391.         switch ($field['type']{
  392.         case 'text':
  393.             $length !empty($field['length']$field['length'$db->options['default_text_field_length'];
  394.             $fixed !empty($field['fixed']$field['fixed': false;
  395.             return $fixed ($length 'CHAR('.$length.')' 'CHAR('.$db->options['default_text_field_length'].')')
  396.                 : ($length 'VARCHAR('.$length.')' 'TEXT');
  397.         case 'clob':
  398.             return 'TEXT';
  399.         case 'blob':
  400.             return 'TEXT';
  401.         case 'integer':
  402.             return 'INT';
  403.         case 'boolean':
  404.             return 'INT';
  405.         case 'date':
  406.             return 'CHAR ('.strlen('YYYY-MM-DD').')';
  407.         case 'time':
  408.             return 'CHAR ('.strlen('HH:MM:SS').')';
  409.         case 'timestamp':
  410.             return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
  411.         case 'float':
  412.             return 'TEXT';
  413.         case 'decimal':
  414.             return 'TEXT';
  415.         }
  416.         return '';
  417.     }
  418.  
  419.     // }}}
  420.     // {{{ _getDeclaration()
  421.  
  422.     /**
  423.      * Obtain DBMS specific SQL code portion needed to declare a generic type
  424.      * field to be used in statements like CREATE TABLE.
  425.      *
  426.      * @param string $name   name the field to be declared.
  427.      * @param array  $field  associative array with the name of the properties
  428.      *       of the field being declared as array indexes. Currently, the types
  429.      *       of supported field properties are as follows:
  430.      *
  431.      *       length
  432.      *           Integer value that determines the maximum length of the text
  433.      *           field. If this argument is missing the field should be
  434.      *           declared to have the longest length allowed by the DBMS.
  435.      *
  436.      *       default
  437.      *           Text value to be used as default for this field.
  438.      *
  439.      *       notnull
  440.      *           Boolean flag that indicates whether this field is constrained
  441.      *           to not be set to null.
  442.      *       charset
  443.      *           Text value with the default CHARACTER SET for this field.
  444.      *       collation
  445.      *           Text value with the default COLLATION for this field.
  446.      * @return string  DBMS specific SQL code portion that should be used to
  447.      *       declare the specified field, or a MDB2_Error on failure
  448.      * @access protected
  449.      */
  450.     function _getDeclaration($name$field)
  451.     {
  452.         $db =$this->getDBInstance();
  453.         if (PEAR::isError($db)) {
  454.             return $db;
  455.         }
  456.  
  457.         $name $db->quoteIdentifier($nametrue);
  458.         $declaration_options $db->datatype->_getDeclarationOptions($field);
  459.         if (PEAR::isError($declaration_options)) {
  460.             return $declaration_options;
  461.         }
  462.         return $name.' '.$this->getTypeDeclaration($field).$declaration_options;
  463.     }
  464.  
  465.     // }}}
  466.     // {{{ _getDeclarationOptions()
  467.  
  468.     /**
  469.      * Obtain DBMS specific SQL code portion needed to declare a generic type
  470.      * field to be used in statement like CREATE TABLE, without the field name
  471.      * and type values (ie. just the character set, default value, if the
  472.      * field is permitted to be NULL or not, and the collation options).
  473.      *
  474.      * @param array  $field  associative array with the name of the properties
  475.      *       of the field being declared as array indexes. Currently, the types
  476.      *       of supported field properties are as follows:
  477.      *
  478.      *       default
  479.      *           Text value to be used as default for this field.
  480.      *       notnull
  481.      *           Boolean flag that indicates whether this field is constrained
  482.      *           to not be set to null.
  483.      *       charset
  484.      *           Text value with the default CHARACTER SET for this field.
  485.      *       collation
  486.      *           Text value with the default COLLATION for this field.
  487.      * @return string  DBMS specific SQL code portion that should be used to
  488.      *       declare the specified field's options.
  489.      * @access protected
  490.      */
  491.     function _getDeclarationOptions($field)
  492.     {
  493.         $charset = empty($field['charset']'' :
  494.             ' '.$this->_getCharsetFieldDeclaration($field['charset']);
  495.  
  496.         $default '';
  497.         if (array_key_exists('default'$field)) {
  498.             if ($field['default'=== ''{
  499.                 $db =$this->getDBInstance();
  500.                 if (PEAR::isError($db)) {
  501.                     return $db;
  502.                 }
  503.                 if (empty($field['notnull'])) {
  504.                     $field['default'= null;
  505.                 else {
  506.                     $valid_default_values $this->getValidTypes();
  507.                     $field['default'$valid_default_values[$field['type']];
  508.                 }
  509.                 if ($field['default'=== ''
  510.                     && ($db->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL)
  511.                 {
  512.                     $field['default'' ';
  513.                 }
  514.             }
  515.             $default ' DEFAULT '.$this->quote($field['default']$field['type']);
  516.         elseif (empty($field['notnull'])) {
  517.             $default ' DEFAULT NULL';
  518.         }
  519.  
  520.         $notnull = empty($field['notnull']'' ' NOT NULL';
  521.         
  522.         $collation = empty($field['collation']'' :
  523.             ' '.$this->_getCollationFieldDeclaration($field['collation']);
  524.         return $charset.$default.$notnull.$collation;
  525.     }
  526.  
  527.     // }}}
  528.     // {{{ _getCharsetFieldDeclaration()
  529.     
  530.     /**
  531.      * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
  532.      * of a field declaration to be used in statements like CREATE TABLE.
  533.      *
  534.      * @param string $charset   name of the charset
  535.      * @return string  DBMS specific SQL code portion needed to set the CHARACTER SET
  536.      *                  of a field declaration.
  537.      */
  538.     function _getCharsetFieldDeclaration($charset)
  539.     {
  540.         return '';
  541.     }
  542.  
  543.     // }}}
  544.     // {{{ _getCollationFieldDeclaration()
  545.  
  546.     /**
  547.      * Obtain DBMS specific SQL code portion needed to set the COLLATION
  548.      * of a field declaration to be used in statements like CREATE TABLE.
  549.      *
  550.      * @param string $collation   name of the collation
  551.      * @return string  DBMS specific SQL code portion needed to set the COLLATION
  552.      *                  of a field declaration.
  553.      */
  554.     function _getCollationFieldDeclaration($collation)
  555.     {
  556.         return '';
  557.     }
  558.  
  559.     // }}}
  560.     // {{{ _getIntegerDeclaration()
  561.  
  562.     /**
  563.      * Obtain DBMS specific SQL code portion needed to declare an integer type
  564.      * field to be used in statements like CREATE TABLE.
  565.      *
  566.      * @param string $name name the field to be declared.
  567.      * @param array $field associative array with the name of the properties
  568.      *        of the field being declared as array indexes. Currently, the types
  569.      *        of supported field properties are as follows:
  570.      *
  571.      *        unsigned
  572.      *            Boolean flag that indicates whether the field should be
  573.      *            declared as unsigned integer if possible.
  574.      *
  575.      *        default
  576.      *            Integer value to be used as default for this field.
  577.      *
  578.      *        notnull
  579.      *            Boolean flag that indicates whether this field is constrained
  580.      *            to not be set to null.
  581.      * @return string DBMS specific SQL code portion that should be used to
  582.      *        declare the specified field.
  583.      * @access protected
  584.      */
  585.     function _getIntegerDeclaration($name$field)
  586.     {
  587.         if (!empty($field['unsigned'])) {
  588.             $db =$this->getDBInstance();
  589.             if (PEAR::isError($db)) {
  590.                 return $db;
  591.             }
  592.  
  593.             $db->warnings[= "unsigned integer field \"$name\" is being declared as signed integer";
  594.         }
  595.         return $this->_getDeclaration($name$field);
  596.     }
  597.  
  598.     // }}}
  599.     // {{{ _getTextDeclaration()
  600.  
  601.     /**
  602.      * Obtain DBMS specific SQL code portion needed to declare an text type
  603.      * field to be used in statements like CREATE TABLE.
  604.      *
  605.      * @param string $name name the field to be declared.
  606.      * @param array $field associative array with the name of the properties
  607.      *        of the field being declared as array indexes. Currently, the types
  608.      *        of supported field properties are as follows:
  609.      *
  610.      *        length
  611.      *            Integer value that determines the maximum length of the text
  612.      *            field. If this argument is missing the field should be
  613.      *            declared to have the longest length allowed by the DBMS.
  614.      *
  615.      *        default
  616.      *            Text value to be used as default for this field.
  617.      *
  618.      *        notnull
  619.      *            Boolean flag that indicates whether this field is constrained
  620.      *            to not be set to null.
  621.      * @return string DBMS specific SQL code portion that should be used to
  622.      *        declare the specified field.
  623.      * @access protected
  624.      */
  625.     function _getTextDeclaration($name$field)
  626.     {
  627.         return $this->_getDeclaration($name$field);
  628.     }
  629.  
  630.     // }}}
  631.     // {{{ _getCLOBDeclaration()
  632.  
  633.     /**
  634.      * Obtain DBMS specific SQL code portion needed to declare an character
  635.      * large object type field to be used in statements like CREATE TABLE.
  636.      *
  637.      * @param string $name name the field to be declared.
  638.      * @param array $field associative array with the name of the properties
  639.      *         of the field being declared as array indexes. Currently, the types
  640.      *         of supported field properties are as follows:
  641.      *
  642.      *         length
  643.      *             Integer value that determines the maximum length of the large
  644.      *             object field. If this argument is missing the field should be
  645.      *             declared to have the longest length allowed by the DBMS.
  646.      *
  647.      *         notnull
  648.      *             Boolean flag that indicates whether this field is constrained
  649.      *             to not be set to null.
  650.      * @return string DBMS specific SQL code portion that should be used to
  651.      *         declare the specified field.
  652.      * @access public
  653.      */
  654.     function _getCLOBDeclaration($name$field)
  655.     {
  656.         $db =$this->getDBInstance();
  657.         if (PEAR::isError($db)) {
  658.             return $db;
  659.         }
  660.  
  661.         $notnull = empty($field['notnull']'' ' NOT NULL';
  662.         $name $db->quoteIdentifier($nametrue);
  663.         return $name.' '.$this->getTypeDeclaration($field).$notnull;
  664.     }
  665.  
  666.     // }}}
  667.     // {{{ _getBLOBDeclaration()
  668.  
  669.     /**
  670.      * Obtain DBMS specific SQL code portion needed to declare an binary large
  671.      * object type field to be used in statements like CREATE TABLE.
  672.      *
  673.      * @param string $name name the field to be declared.
  674.      * @param array $field associative array with the name of the properties
  675.      *         of the field being declared as array indexes. Currently, the types
  676.      *         of supported field properties are as follows:
  677.      *
  678.      *         length
  679.      *             Integer value that determines the maximum length of the large
  680.      *             object field. If this argument is missing the field should be
  681.      *             declared to have the longest length allowed by the DBMS.
  682.      *
  683.      *         notnull
  684.      *             Boolean flag that indicates whether this field is constrained
  685.      *             to not be set to null.
  686.      * @return string DBMS specific SQL code portion that should be used to
  687.      *         declare the specified field.
  688.      * @access protected
  689.      */
  690.     function _getBLOBDeclaration($name$field)
  691.     {
  692.         $db =$this->getDBInstance();
  693.         if (PEAR::isError($db)) {
  694.             return $db;
  695.         }
  696.  
  697.         $notnull = empty($field['notnull']'' ' NOT NULL';
  698.         $name $db->quoteIdentifier($nametrue);
  699.         return $name.' '.$this->getTypeDeclaration($field).$notnull;
  700.     }
  701.  
  702.     // }}}
  703.     // {{{ _getBooleanDeclaration()
  704.  
  705.     /**
  706.      * Obtain DBMS specific SQL code portion needed to declare a boolean type
  707.      * field to be used in statements like CREATE TABLE.
  708.      *
  709.      * @param string $name name the field to be declared.
  710.      * @param array $field associative array with the name of the properties
  711.      *        of the field being declared as array indexes. Currently, the types
  712.      *        of supported field properties are as follows:
  713.      *
  714.      *        default
  715.      *            Boolean value to be used as default for this field.
  716.      *
  717.      *        notnullL
  718.      *            Boolean flag that indicates whether this field is constrained
  719.      *            to not be set to null.
  720.      * @return string DBMS specific SQL code portion that should be used to
  721.      *        declare the specified field.
  722.      * @access protected
  723.      */
  724.     function _getBooleanDeclaration($name$field)
  725.     {
  726.         return $this->_getDeclaration($name$field);
  727.     }
  728.  
  729.     // }}}
  730.     // {{{ _getDateDeclaration()
  731.  
  732.     /**
  733.      * Obtain DBMS specific SQL code portion needed to declare a date type
  734.      * field to be used in statements like CREATE TABLE.
  735.      *
  736.      * @param string $name name the field to be declared.
  737.      * @param array $field associative array with the name of the properties
  738.      *        of the field being declared as array indexes. Currently, the types
  739.      *        of supported field properties are as follows:
  740.      *
  741.      *        default
  742.      *            Date value to be used as default for this field.
  743.      *
  744.      *        notnull
  745.      *            Boolean flag that indicates whether this field is constrained
  746.      *            to not be set to null.
  747.      * @return string DBMS specific SQL code portion that should be used to
  748.      *        declare the specified field.
  749.      * @access protected
  750.      */
  751.     function _getDateDeclaration($name$field)
  752.     {
  753.         return $this->_getDeclaration($name$field);
  754.     }
  755.  
  756.     // }}}
  757.     // {{{ _getTimestampDeclaration()
  758.  
  759.     /**
  760.      * Obtain DBMS specific SQL code portion needed to declare a timestamp
  761.      * field to be used in statements like CREATE TABLE.
  762.      *
  763.      * @param string $name name the field to be declared.
  764.      * @param array $field associative array with the name of the properties
  765.      *        of the field being declared as array indexes. Currently, the types
  766.      *        of supported field properties are as follows:
  767.      *
  768.      *        default
  769.      *            Timestamp value to be used as default for this field.
  770.      *
  771.      *        notnull
  772.      *            Boolean flag that indicates whether this field is constrained
  773.      *            to not be set to null.
  774.      * @return string DBMS specific SQL code portion that should be used to
  775.      *        declare the specified field.
  776.      * @access protected
  777.      */
  778.     function _getTimestampDeclaration($name$field)
  779.     {
  780.         return $this->_getDeclaration($name$field);
  781.     }
  782.  
  783.     // }}}
  784.     // {{{ _getTimeDeclaration()
  785.  
  786.     /**
  787.      * Obtain DBMS specific SQL code portion needed to declare a time
  788.      * field to be used in statements like CREATE TABLE.
  789.      *
  790.      * @param string $name name the field to be declared.
  791.      * @param array $field associative array with the name of the properties
  792.      *        of the field being declared as array indexes. Currently, the types
  793.      *        of supported field properties are as follows:
  794.      *
  795.      *        default
  796.      *            Time value to be used as default for this field.
  797.      *
  798.      *        notnull
  799.      *            Boolean flag that indicates whether this field is constrained
  800.      *            to not be set to null.
  801.      * @return string DBMS specific SQL code portion that should be used to
  802.      *        declare the specified field.
  803.      * @access protected
  804.      */
  805.     function _getTimeDeclaration($name$field)
  806.     {
  807.         return $this->_getDeclaration($name$field);
  808.     }
  809.  
  810.     // }}}
  811.     // {{{ _getFloatDeclaration()
  812.  
  813.     /**
  814.      * Obtain DBMS specific SQL code portion needed to declare a float type
  815.      * field to be used in statements like CREATE TABLE.
  816.      *
  817.      * @param string $name name the field to be declared.
  818.      * @param array $field associative array with the name of the properties
  819.      *        of the field being declared as array indexes. Currently, the types
  820.      *        of supported field properties are as follows:
  821.      *
  822.      *        default
  823.      *            Float value to be used as default for this field.
  824.      *
  825.      *        notnull
  826.      *            Boolean flag that indicates whether this field is constrained
  827.      *            to not be set to null.
  828.      * @return string DBMS specific SQL code portion that should be used to
  829.      *        declare the specified field.
  830.      * @access protected
  831.      */
  832.     function _getFloatDeclaration($name$field)
  833.     {
  834.         return $this->_getDeclaration($name$field);
  835.     }
  836.  
  837.     // }}}
  838.     // {{{ _getDecimalDeclaration()
  839.  
  840.     /**
  841.      * Obtain DBMS specific SQL code portion needed to declare a decimal type
  842.      * field to be used in statements like CREATE TABLE.
  843.      *
  844.      * @param string $name name the field to be declared.
  845.      * @param array $field associative array with the name of the properties
  846.      *        of the field being declared as array indexes. Currently, the types
  847.      *        of supported field properties are as follows:
  848.      *
  849.      *        default
  850.      *            Decimal value to be used as default for this field.
  851.      *
  852.      *        notnull
  853.      *            Boolean flag that indicates whether this field is constrained
  854.      *            to not be set to null.
  855.      * @return string DBMS specific SQL code portion that should be used to
  856.      *        declare the specified field.
  857.      * @access protected
  858.      */
  859.     function _getDecimalDeclaration($name$field)
  860.     {
  861.         return $this->_getDeclaration($name$field);
  862.     }
  863.  
  864.     // }}}
  865.     // {{{ compareDefinition()
  866.  
  867.     /**
  868.      * Obtain an array of changes that may need to applied
  869.      *
  870.      * @param array $current new definition
  871.      * @param array  $previous old definition
  872.      * @return array  containing all changes that will need to be applied
  873.      * @access public
  874.      */
  875.     function compareDefinition($current$previous)
  876.     {
  877.         $type !empty($current['type']$current['type': null;
  878.  
  879.         if (!method_exists($this"_compare{$type}Definition")) {
  880.             $db =$this->getDBInstance();
  881.             if (PEAR::isError($db)) {
  882.                 return $db;
  883.             }
  884.             if (!empty($db->options['datatype_map_callback'][$type])) {
  885.                 $parameter = array('current' => $current'previous' => $previous);
  886.                 $change =  call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  887.                 return $change;
  888.             }
  889.             return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  890.                 'type "'.$current['type'].'" is not yet supported'__FUNCTION__);
  891.         }
  892.  
  893.         if (empty($previous['type']|| $previous['type'!= $type{
  894.             return $current;
  895.         }
  896.  
  897.         $change $this->{"_compare{$type}Definition"}($current$previous);
  898.  
  899.         if ($previous['type'!= $type{
  900.             $change['type'= true;
  901.         }
  902.  
  903.         $previous_notnull !empty($previous['notnull']$previous['notnull': false;
  904.         $notnull !empty($current['notnull']$current['notnull': false;
  905.         if ($previous_notnull != $notnull{
  906.             $change['notnull'= true;
  907.         }
  908.  
  909.         $previous_default array_key_exists('default'$previous$previous['default':
  910.             ($previous_notnull '' : null);
  911.         $default array_key_exists('default'$current$current['default':
  912.             ($notnull '' : null);
  913.         if ($previous_default !== $default{
  914.             $change['default'= true;
  915.         }
  916.  
  917.         return $change;
  918.     }
  919.  
  920.     // }}}
  921.     // {{{ _compareIntegerDefinition()
  922.  
  923.     /**
  924.      * Obtain an array of changes that may need to applied to an integer field
  925.      *
  926.      * @param array $current new definition
  927.      * @param array  $previous old definition
  928.      * @return array  containing all changes that will need to be applied
  929.      * @access protected
  930.      */
  931.     function _compareIntegerDefinition($current$previous)
  932.     {
  933.         $change = array();
  934.         $previous_unsigned !empty($previous['unsigned']$previous['unsigned': false;
  935.         $unsigned !empty($current['unsigned']$current['unsigned': false;
  936.         if ($previous_unsigned != $unsigned{
  937.             $change['unsigned'= true;
  938.         }
  939.         $previous_autoincrement !empty($previous['autoincrement']$previous['autoincrement': false;
  940.         $autoincrement !empty($current['autoincrement']$current['autoincrement': false;
  941.         if ($previous_autoincrement != $autoincrement{
  942.             $change['autoincrement'= true;
  943.         }
  944.         return $change;
  945.     }
  946.  
  947.     // }}}
  948.     // {{{ _compareTextDefinition()
  949.  
  950.     /**
  951.      * Obtain an array of changes that may need to applied to an text field
  952.      *
  953.      * @param array $current new definition
  954.      * @param array  $previous old definition
  955.      * @return array  containing all changes that will need to be applied
  956.      * @access protected
  957.      */
  958.     function _compareTextDefinition($current$previous)
  959.     {
  960.         $change = array();
  961.         $previous_length !empty($previous['length']$previous['length': 0;
  962.         $length !empty($current['length']$current['length': 0;
  963.         if ($previous_length != $length{
  964.             $change['length'= true;
  965.         }
  966.         $previous_fixed !empty($previous['fixed']$previous['fixed': 0;
  967.         $fixed !empty($current['fixed']$current['fixed': 0;
  968.         if ($previous_fixed != $fixed{
  969.             $change['fixed'= true;
  970.         }
  971.         return $change;
  972.     }
  973.  
  974.     // }}}
  975.     // {{{ _compareCLOBDefinition()
  976.  
  977.     /**
  978.      * Obtain an array of changes that may need to applied to an CLOB field
  979.      *
  980.      * @param array $current new definition
  981.      * @param array  $previous old definition
  982.      * @return array  containing all changes that will need to be applied
  983.      * @access protected
  984.      */
  985.     function _compareCLOBDefinition($current$previous)
  986.     {
  987.         return $this->_compareTextDefinition($current$previous);
  988.     }
  989.  
  990.     // }}}
  991.     // {{{ _compareBLOBDefinition()
  992.  
  993.     /**
  994.      * Obtain an array of changes that may need to applied to an BLOB field
  995.      *
  996.      * @param array $current new definition
  997.      * @param array  $previous old definition
  998.      * @return array  containing all changes that will need to be applied
  999.      * @access protected
  1000.      */
  1001.     function _compareBLOBDefinition($current$previous)
  1002.     {
  1003.         return $this->_compareTextDefinition($current$previous);
  1004.     }
  1005.  
  1006.     // }}}
  1007.     // {{{ _compareDateDefinition()
  1008.  
  1009.     /**
  1010.      * Obtain an array of changes that may need to applied to an date field
  1011.      *
  1012.      * @param array $current new definition
  1013.      * @param array  $previous old definition
  1014.      * @return array  containing all changes that will need to be applied
  1015.      * @access protected
  1016.      */
  1017.     function _compareDateDefinition($current$previous)
  1018.     {
  1019.         return array();
  1020.     }
  1021.  
  1022.     // }}}
  1023.     // {{{ _compareTimeDefinition()
  1024.  
  1025.     /**
  1026.      * Obtain an array of changes that may need to applied to an time field
  1027.      *
  1028.      * @param array $current new definition
  1029.      * @param array  $previous old definition
  1030.      * @return array  containing all changes that will need to be applied
  1031.      * @access protected
  1032.      */
  1033.     function _compareTimeDefinition($current$previous)
  1034.     {
  1035.         return array();
  1036.     }
  1037.  
  1038.     // }}}
  1039.     // {{{ _compareTimestampDefinition()
  1040.  
  1041.     /**
  1042.      * Obtain an array of changes that may need to applied to an timestamp field
  1043.      *
  1044.      * @param array $current new definition
  1045.      * @param array  $previous old definition
  1046.      * @return array  containing all changes that will need to be applied
  1047.      * @access protected
  1048.      */
  1049.     function _compareTimestampDefinition($current$previous)
  1050.     {
  1051.         return array();
  1052.     }
  1053.  
  1054.     // }}}
  1055.     // {{{ _compareBooleanDefinition()
  1056.  
  1057.     /**
  1058.      * Obtain an array of changes that may need to applied to an boolean field
  1059.      *
  1060.      * @param array $current new definition
  1061.      * @param array  $previous old definition
  1062.      * @return array  containing all changes that will need to be applied
  1063.      * @access protected
  1064.      */
  1065.     function _compareBooleanDefinition($current$previous)
  1066.     {
  1067.         return array();
  1068.     }
  1069.  
  1070.     // }}}
  1071.     // {{{ _compareFloatDefinition()
  1072.  
  1073.     /**
  1074.      * Obtain an array of changes that may need to applied to an float field
  1075.      *
  1076.      * @param array $current new definition
  1077.      * @param array  $previous old definition
  1078.      * @return array  containing all changes that will need to be applied
  1079.      * @access protected
  1080.      */
  1081.     function _compareFloatDefinition($current$previous)
  1082.     {
  1083.         return array();
  1084.     }
  1085.  
  1086.     // }}}
  1087.     // {{{ _compareDecimalDefinition()
  1088.  
  1089.     /**
  1090.      * Obtain an array of changes that may need to applied to an decimal field
  1091.      *
  1092.      * @param array $current new definition
  1093.      * @param array  $previous old definition
  1094.      * @return array  containing all changes that will need to be applied
  1095.      * @access protected
  1096.      */
  1097.     function _compareDecimalDefinition($current$previous)
  1098.     {
  1099.         return array();
  1100.     }
  1101.  
  1102.     // }}}
  1103.     // {{{ quote()
  1104.  
  1105.     /**
  1106.      * Convert a text value into a DBMS specific format that is suitable to
  1107.      * compose query statements.
  1108.      *
  1109.      * @param string $value text string value that is intended to be converted.
  1110.      * @param string $type type to which the value should be converted to
  1111.      * @param bool $quote determines if the value should be quoted and escaped
  1112.      * @param bool $escape_wildcards if to escape escape wildcards
  1113.      * @return string text string that represents the given argument value in
  1114.      *        a DBMS specific format.
  1115.      * @access public
  1116.      */
  1117.     function quote($value$type = null$quote = true$escape_wildcards = false)
  1118.     {
  1119.         $db =$this->getDBInstance();
  1120.         if (PEAR::isError($db)) {
  1121.             return $db;
  1122.         }
  1123.  
  1124.         if (is_null($value)
  1125.             || ($value === '' && $db->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL)
  1126.         {
  1127.             if (!$quote{
  1128.                 return null;
  1129.             }
  1130.             return 'NULL';
  1131.         }
  1132.  
  1133.         if (is_null($type)) {
  1134.             switch (gettype($value)) {
  1135.             case 'integer':
  1136.                 $type 'integer';
  1137.                 break;
  1138.             case 'double':
  1139.                 // todo: default to decimal as float is quite unusual
  1140.                 // $type = 'float';
  1141.                 $type 'decimal';
  1142.                 break;
  1143.             case 'boolean':
  1144.                 $type 'boolean';
  1145.                 break;
  1146.             case 'array':
  1147.                  $value serialize($value);
  1148.             case 'object':
  1149.                  $type 'text';
  1150.                 break;
  1151.             default:
  1152.                 if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/'$value)) {
  1153.                     $type 'timestamp';
  1154.                 elseif (preg_match('/^\d{2}:\d{2}$/'$value)) {
  1155.                     $type 'time';
  1156.                 elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/'$value)) {
  1157.                     $type 'date';
  1158.                 else {
  1159.                     $type 'text';
  1160.                 }
  1161.                 break;
  1162.             }
  1163.         elseif (!empty($db->options['datatype_map'][$type])) {
  1164.             $type $db->options['datatype_map'][$type];
  1165.             if (!empty($db->options['datatype_map_callback'][$type])) {
  1166.                 $parameter = array('type' => $type'value' => $value'quote' => $quote'escape_wildcards' => $escape_wildcards);
  1167.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  1168.             }
  1169.         }
  1170.  
  1171.         if (!method_exists($this"_quote{$type}")) {
  1172.             return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1173.                 'type not defined: '.$type__FUNCTION__);
  1174.         }
  1175.         $value $this->{"_quote{$type}"}($value$quote$escape_wildcards);
  1176.         if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
  1177.             && $db->string_quoting['escape'!== $db->string_quoting['escape_pattern']
  1178.         {
  1179.             $value.= $this->patternEscapeString();
  1180.         }
  1181.         return $value;
  1182.     }
  1183.  
  1184.     // }}}
  1185.     // {{{ _quoteInteger()
  1186.  
  1187.     /**
  1188.      * Convert a text value into a DBMS specific format that is suitable to
  1189.      * compose query statements.
  1190.      *
  1191.      * @param string $value text string value that is intended to be converted.
  1192.      * @param bool $quote determines if the value should be quoted and escaped
  1193.      * @param bool $escape_wildcards if to escape escape wildcards
  1194.      * @return string text string that represents the given argument value in
  1195.      *        a DBMS specific format.
  1196.      * @access protected
  1197.      */
  1198.     function _quoteInteger($value$quote$escape_wildcards)
  1199.     {
  1200.         return (int)$value;
  1201.     }
  1202.  
  1203.     // }}}
  1204.     // {{{ _quoteText()
  1205.  
  1206.     /**
  1207.      * Convert a text value into a DBMS specific format that is suitable to
  1208.      * compose query statements.
  1209.      *
  1210.      * @param string $value text string value that is intended to be converted.
  1211.      * @param bool $quote determines if the value should be quoted and escaped
  1212.      * @param bool $escape_wildcards if to escape escape wildcards
  1213.      * @return string text string that already contains any DBMS specific
  1214.      *        escaped character sequences.
  1215.      * @access protected
  1216.      */
  1217.     function _quoteText($value$quote$escape_wildcards)
  1218.     {
  1219.         if (!$quote{
  1220.             return $value;
  1221.         }
  1222.  
  1223.         $db =$this->getDBInstance();
  1224.         if (PEAR::isError($db)) {
  1225.             return $db;
  1226.         }
  1227.  
  1228.         $value $db->escape($value$escape_wildcards);
  1229.         if (PEAR::isError($value)) {
  1230.             return $value;
  1231.         }
  1232.         return "'".$value."'";
  1233.     }
  1234.  
  1235.     // }}}
  1236.     // {{{ _readFile()
  1237.  
  1238.     /**
  1239.      * Convert a text value into a DBMS specific format that is suitable to
  1240.      * compose query statements.
  1241.      *
  1242.      * @param string $value text string value that is intended to be converted.
  1243.      * @return string text string that represents the given argument value in
  1244.      *        a DBMS specific format.
  1245.      * @access protected
  1246.      */
  1247.     function _readFile($value)
  1248.     {
  1249.         $close = false;
  1250.         if (preg_match('/^(\w+:\/\/)(.*)$/'$value$match)) {
  1251.             $close = true;
  1252.             if ($match[1== 'file://'{
  1253.                 $value $match[2];
  1254.             }
  1255.             $value @fopen($value'r');
  1256.         }
  1257.  
  1258.         if (is_resource($value)) {
  1259.             $db =$this->getDBInstance();
  1260.             if (PEAR::isError($db)) {
  1261.                 return $db;
  1262.             }
  1263.  
  1264.             $fp $value;
  1265.             $value '';
  1266.             while (!@feof($fp)) {
  1267.                 $value.= @fread($fp$db->options['lob_buffer_length']);
  1268.             }
  1269.             if ($close{
  1270.                 @fclose($fp);
  1271.             }
  1272.         }
  1273.  
  1274.         return $value;
  1275.     }
  1276.  
  1277.     // }}}
  1278.     // {{{ _quoteLOB()
  1279.  
  1280.     /**
  1281.      * Convert a text value into a DBMS specific format that is suitable to
  1282.      * compose query statements.
  1283.      *
  1284.      * @param string $value text string value that is intended to be converted.
  1285.      * @param bool $quote determines if the value should be quoted and escaped
  1286.      * @param bool $escape_wildcards if to escape escape wildcards
  1287.      * @return string text string that represents the given argument value in
  1288.      *        a DBMS specific format.
  1289.      * @access protected
  1290.      */
  1291.     function _quoteLOB($value$quote$escape_wildcards)
  1292.     {
  1293.         $value $this->_readFile($value);
  1294.         if (PEAR::isError($value)) {
  1295.             return $value;
  1296.         }
  1297.         return $this->_quoteText($value$quote$escape_wildcards);
  1298.     }
  1299.  
  1300.     // }}}
  1301.     // {{{ _quoteCLOB()
  1302.  
  1303.     /**
  1304.      * Convert a text value into a DBMS specific format that is suitable to
  1305.      * compose query statements.
  1306.      *
  1307.      * @param string $value text string value that is intended to be converted.
  1308.      * @param bool $quote determines if the value should be quoted and escaped
  1309.      * @param bool $escape_wildcards if to escape escape wildcards
  1310.      * @return string text string that represents the given argument value in
  1311.      *        a DBMS specific format.
  1312.      * @access protected
  1313.      */
  1314.     function _quoteCLOB($value$quote$escape_wildcards)
  1315.     {
  1316.         return $this->_quoteLOB($value$quote$escape_wildcards);
  1317.     }
  1318.  
  1319.     // }}}
  1320.     // {{{ _quoteBLOB()
  1321.  
  1322.     /**
  1323.      * Convert a text value into a DBMS specific format that is suitable to
  1324.      * compose query statements.
  1325.      *
  1326.      * @param string $value text string value that is intended to be converted.
  1327.      * @param bool $quote determines if the value should be quoted and escaped
  1328.      * @param bool $escape_wildcards if to escape escape wildcards
  1329.      * @return string text string that represents the given argument value in
  1330.      *        a DBMS specific format.
  1331.      * @access protected
  1332.      */
  1333.     function _quoteBLOB($value$quote$escape_wildcards)
  1334.     {
  1335.         return $this->_quoteLOB($value$quote$escape_wildcards);
  1336.     }
  1337.  
  1338.     // }}}
  1339.     // {{{ _quoteBoolean()
  1340.  
  1341.     /**
  1342.      * Convert a text value into a DBMS specific format that is suitable to
  1343.      * compose query statements.
  1344.      *
  1345.      * @param string $value text string value that is intended to be converted.
  1346.      * @param bool $quote determines if the value should be quoted and escaped
  1347.      * @param bool $escape_wildcards if to escape escape wildcards
  1348.      * @return string text string that represents the given argument value in
  1349.      *        a DBMS specific format.
  1350.      * @access protected
  1351.      */
  1352.     function _quoteBoolean($value$quote$escape_wildcards)
  1353.     {
  1354.         return ($value ? 1 : 0);
  1355.     }
  1356.  
  1357.     // }}}
  1358.     // {{{ _quoteDate()
  1359.  
  1360.     /**
  1361.      * Convert a text value into a DBMS specific format that is suitable to
  1362.      * compose query statements.
  1363.      *
  1364.      * @param string $value text string value that is intended to be converted.
  1365.      * @param bool $quote determines if the value should be quoted and escaped
  1366.      * @param bool $escape_wildcards if to escape escape wildcards
  1367.      * @return string text string that represents the given argument value in
  1368.      *        a DBMS specific format.
  1369.      * @access protected
  1370.      */
  1371.     function _quoteDate($value$quote$escape_wildcards)
  1372.     {
  1373.         if ($value === 'CURRENT_DATE'{
  1374.             $db =$this->getDBInstance();
  1375.             if (PEAR::isError($db)) {
  1376.                 return $db;
  1377.             }
  1378.             if (isset($db->function&& is_a($db->function'MDB2_Driver_Function_Common')) {
  1379.                 return $db->function->now('date');
  1380.             }
  1381.             return 'CURRENT_DATE';
  1382.         }
  1383.         return $this->_quoteText($value$quote$escape_wildcards);
  1384.     }
  1385.  
  1386.     // }}}
  1387.     // {{{ _quoteTimestamp()
  1388.  
  1389.     /**
  1390.      * Convert a text value into a DBMS specific format that is suitable to
  1391.      * compose query statements.
  1392.      *
  1393.      * @param string $value text string value that is intended to be converted.
  1394.      * @param bool $quote determines if the value should be quoted and escaped
  1395.      * @param bool $escape_wildcards if to escape escape wildcards
  1396.      * @return string text string that represents the given argument value in
  1397.      *        a DBMS specific format.
  1398.      * @access protected
  1399.      */
  1400.     function _quoteTimestamp($value$quote$escape_wildcards)
  1401.     {
  1402.         if ($value === 'CURRENT_TIMESTAMP'{
  1403.             $db =$this->getDBInstance();
  1404.             if (PEAR::isError($db)) {
  1405.                 return $db;
  1406.             }
  1407.             if (isset($db->function&& is_a($db->function'MDB2_Driver_Function_Common')) {
  1408.                 return $db->function->now('timestamp');
  1409.             }
  1410.             return 'CURRENT_TIMESTAMP';
  1411.         }
  1412.         return $this->_quoteText($value$quote$escape_wildcards);
  1413.     }
  1414.  
  1415.     // }}}
  1416.     // {{{ _quoteTime()
  1417.  
  1418.     /**
  1419.      * Convert a text value into a DBMS specific format that is suitable to
  1420.      *       compose query statements.
  1421.      *
  1422.      * @param string $value text string value that is intended to be converted.
  1423.      * @param bool $quote determines if the value should be quoted and escaped
  1424.      * @param bool $escape_wildcards if to escape escape wildcards
  1425.      * @return string text string that represents the given argument value in
  1426.      *        a DBMS specific format.
  1427.      * @access protected
  1428.      */
  1429.     function _quoteTime($value$quote$escape_wildcards)
  1430.     {
  1431.         if ($value === 'CURRENT_TIME'{
  1432.             $db =$this->getDBInstance();
  1433.             if (PEAR::isError($db)) {
  1434.                 return $db;
  1435.             }
  1436.             if (isset($db->function&& is_a($db->function'MDB2_Driver_Function_Common')) {
  1437.                 return $db->function->now('time');
  1438.             }
  1439.             return 'CURRENT_TIME';
  1440.         }
  1441.         return $this->_quoteText($value$quote$escape_wildcards);
  1442.     }
  1443.  
  1444.     // }}}
  1445.     // {{{ _quoteFloat()
  1446.  
  1447.     /**
  1448.      * Convert a text value into a DBMS specific format that is suitable to
  1449.      * compose query statements.
  1450.      *
  1451.      * @param string $value text string value that is intended to be converted.
  1452.      * @param bool $quote determines if the value should be quoted and escaped
  1453.      * @param bool $escape_wildcards if to escape escape wildcards
  1454.      * @return string text string that represents the given argument value in
  1455.      *        a DBMS specific format.
  1456.      * @access protected
  1457.      */
  1458.     function _quoteFloat($value$quote$escape_wildcards)
  1459.     {
  1460.         if (preg_match('/^(.*)e([-+])(\d+)$/i'$value$matches)) {
  1461.             $decimal $this->_quoteDecimal($matches[1]$quote$escape_wildcards);
  1462.             $sign $matches[2];
  1463.             $exponent str_pad($matches[3]2'0'STR_PAD_LEFT);
  1464.             $value $decimal.'E'.$sign.$exponent;
  1465.         else {
  1466.             $value $this->_quoteDecimal($value$quote$escape_wildcards);
  1467.         }
  1468.         return $value;
  1469.     }
  1470.  
  1471.     // }}}
  1472.     // {{{ _quoteDecimal()
  1473.  
  1474.     /**
  1475.      * Convert a text value into a DBMS specific format that is suitable to
  1476.      * compose query statements.
  1477.      *
  1478.      * @param string $value text string value that is intended to be converted.
  1479.      * @param bool $quote determines if the value should be quoted and escaped
  1480.      * @param bool $escape_wildcards if to escape escape wildcards
  1481.      * @return string text string that represents the given argument value in
  1482.      *        a DBMS specific format.
  1483.      * @access protected
  1484.      */
  1485.     function _quoteDecimal($value$quote$escape_wildcards)
  1486.     {
  1487.         $value = (string)$value;
  1488.         $value preg_replace('/[^\d\.,\-+eE]/'''$value);
  1489.         if (preg_match('/[^.0-9]/'$value)) {
  1490.             if (strpos($value',')) {
  1491.                 // 1000,00
  1492.                 if (!strpos($value'.')) {
  1493.                     // convert the last "," to a "."
  1494.                     $value strrev(str_replace(',''.'strrev($value)));
  1495.                 // 1.000,00
  1496.                 elseif (strpos($value'.'&& strpos($value'.'strpos($value',')) {
  1497.                     $value str_replace('.'''$value);
  1498.                     // convert the last "," to a "."
  1499.                     $value strrev(str_replace(',''.'strrev($value)));
  1500.                 // 1,000.00
  1501.                 else {
  1502.                     $value str_replace(','''$value);
  1503.                 }
  1504.             }
  1505.         }
  1506.         return $value;
  1507.     }
  1508.  
  1509.     // }}}
  1510.     // {{{ writeLOBToFile()
  1511.  
  1512.     /**
  1513.      * retrieve LOB from the database
  1514.      *
  1515.      * @param resource $lob stream handle
  1516.      * @param string $file name of the file into which the LOb should be fetched
  1517.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  1518.      * @access protected
  1519.      */
  1520.     function writeLOBToFile($lob$file)
  1521.     {
  1522.         $db =$this->getDBInstance();
  1523.         if (PEAR::isError($db)) {
  1524.             return $db;
  1525.         }
  1526.  
  1527.         if (preg_match('/^(\w+:\/\/)(.*)$/'$file$match)) {
  1528.             if ($match[1== 'file://'{
  1529.                 $file $match[2];
  1530.             }
  1531.         }
  1532.  
  1533.         $fp @fopen($file'wb');
  1534.         while (!@feof($lob)) {
  1535.             $result @fread($lob$db->options['lob_buffer_length']);
  1536.             $read strlen($result);
  1537.             if (@fwrite($fp$result$read!= $read{
  1538.                 @fclose($fp);
  1539.                 return $db->raiseError(MDB2_ERRORnullnull,
  1540.                     'could not write to the output file'__FUNCTION__);
  1541.             }
  1542.         }
  1543.         @fclose($fp);
  1544.         return MDB2_OK;
  1545.     }
  1546.  
  1547.     // }}}
  1548.     // {{{ _retrieveLOB()
  1549.  
  1550.     /**
  1551.      * retrieve LOB from the database
  1552.      *
  1553.      * @param array $lob array
  1554.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  1555.      * @access protected
  1556.      */
  1557.     function _retrieveLOB(&$lob)
  1558.     {
  1559.         if (is_null($lob['value'])) {
  1560.             $lob['value'$lob['resource'];
  1561.         }
  1562.         $lob['loaded'= true;
  1563.         return MDB2_OK;
  1564.     }
  1565.  
  1566.     // }}}
  1567.     // {{{ readLOB()
  1568.  
  1569.     /**
  1570.      * Read data from large object input stream.
  1571.      *
  1572.      * @param resource $lob stream handle
  1573.      * @param string $data reference to a variable that will hold data
  1574.      *                           to be read from the large object input stream
  1575.      * @param integer $length    value that indicates the largest ammount ofdata
  1576.      *                           to be read from the large object input stream.
  1577.      * @return mixed the effective number of bytes read from the large object
  1578.      *                       input stream on sucess or an MDB2 error object.
  1579.      * @access public
  1580.      * @see endOfLOB()
  1581.      */
  1582.     function _readLOB($lob$length)
  1583.     {
  1584.         return substr($lob['value']$lob['position']$length);
  1585.     }
  1586.  
  1587.     // }}}
  1588.     // {{{ _endOfLOB()
  1589.  
  1590.     /**
  1591.      * Determine whether it was reached the end of the large object and
  1592.      * therefore there is no more data to be read for the its input stream.
  1593.      *
  1594.      * @param array $lob array
  1595.      * @return mixed true or false on success, a MDB2 error on failure
  1596.      * @access protected
  1597.      */
  1598.     function _endOfLOB($lob)
  1599.     {
  1600.         return $lob['endOfLOB'];
  1601.     }
  1602.  
  1603.     // }}}
  1604.     // {{{ destroyLOB()
  1605.  
  1606.     /**
  1607.      * Free any resources allocated during the lifetime of the large object
  1608.      * handler object.
  1609.      *
  1610.      * @param resource $lob stream handle
  1611.      * @access public
  1612.      */
  1613.     function destroyLOB($lob)
  1614.     {
  1615.         $lob_data stream_get_meta_data($lob);
  1616.         $lob_index $lob_data['wrapper_data']->lob_index;
  1617.         fclose($lob);
  1618.         if (isset($this->lobs[$lob_index])) {
  1619.             $this->_destroyLOB($this->lobs[$lob_index]);
  1620.             unset($this->lobs[$lob_index]);
  1621.         }
  1622.         return MDB2_OK;
  1623.     }
  1624.  
  1625.     // }}}
  1626.     // {{{ _destroyLOB()
  1627.  
  1628.     /**
  1629.      * Free any resources allocated during the lifetime of the large object
  1630.      * handler object.
  1631.      *
  1632.      * @param array $lob array
  1633.      * @access private
  1634.      */
  1635.     function _destroyLOB(&$lob)
  1636.     {
  1637.         return MDB2_OK;
  1638.     }
  1639.  
  1640.     // }}}
  1641.     // {{{ implodeArray()
  1642.  
  1643.     /**
  1644.      * apply a type to all values of an array and return as a comma seperated string
  1645.      * useful for generating IN statements
  1646.      *
  1647.      * @access public
  1648.      *
  1649.      * @param array $array data array
  1650.      * @param string $type determines type of the field
  1651.      *
  1652.      * @return string comma seperated values
  1653.      */
  1654.     function implodeArray($array$type = false)
  1655.     {
  1656.         if (!is_array($array|| empty($array)) {
  1657.             return 'NULL';
  1658.         }
  1659.         if ($type{
  1660.             foreach ($array as $value{
  1661.                 $return[$this->quote($value$type);
  1662.             }
  1663.         else {
  1664.             $return $array;
  1665.         }
  1666.         return implode(', '$return);
  1667.     }
  1668.  
  1669.     // }}}
  1670.     // {{{ matchPattern()
  1671.  
  1672.     /**
  1673.      * build a pattern matching string
  1674.      *
  1675.      * EXPERIMENTAL
  1676.      *
  1677.      * WARNING: this function is experimental and may change signature at
  1678.      * any time until labelled as non-experimental
  1679.      *
  1680.      * @access public
  1681.      *
  1682.      * @param array $pattern even keys are strings, odd are patterns (% and _)
  1683.      * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
  1684.      * @param string $field optional field name that is being matched against
  1685.      *                   (might be required when emulating ILIKE)
  1686.      *
  1687.      * @return string SQL pattern
  1688.      */
  1689.     function matchPattern($pattern$operator = null$field = null)
  1690.     {
  1691.         $db =$this->getDBInstance();
  1692.         if (PEAR::isError($db)) {
  1693.             return $db;
  1694.         }
  1695.  
  1696.         $match '';
  1697.         if (!is_null($operator)) {
  1698.             $operator strtoupper($operator);
  1699.             switch ($operator{
  1700.             // case insensitive
  1701.             case 'ILIKE':
  1702.                 if (is_null($field)) {
  1703.                     return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1704.                         'case insensitive LIKE matching requires passing the field name'__FUNCTION__);
  1705.                 }
  1706.                 $db->loadModule('Function'nulltrue);
  1707.                 $match $db->function->lower($field).' LIKE ';
  1708.                 break;
  1709.             // case sensitive
  1710.             case 'LIKE':
  1711.                 $match is_null($field'LIKE ' $field.' LIKE ';
  1712.                 break;
  1713.             default:
  1714.                 return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1715.                     'not a supported operator type:'$operator__FUNCTION__);
  1716.             }
  1717.         }
  1718.         $match.= "'";
  1719.         foreach ($pattern as $key => $value{
  1720.             if ($key % 2{
  1721.                 $match.= $value;
  1722.             else {
  1723.                 if ($operator === 'ILIKE'{
  1724.                     $value strtolower($value);
  1725.                 }
  1726.                 $escaped $db->escape($value);
  1727.                 if (PEAR::isError($escaped)) {
  1728.                     return $escaped;
  1729.                 }
  1730.                 $match.= $db->escapePattern($escaped);
  1731.             }
  1732.         }
  1733.         $match.= "'";
  1734.         $match.= $this->patternEscapeString();
  1735.         return $match;
  1736.     }
  1737.  
  1738.     // }}}
  1739.     // {{{ patternEscapeString()
  1740.  
  1741.     /**
  1742.      * build string to define pattern escape character
  1743.      *
  1744.      * EXPERIMENTAL
  1745.      *
  1746.      * WARNING: this function is experimental and may change signature at
  1747.      * any time until labelled as non-experimental
  1748.      *
  1749.      * @access public
  1750.      *
  1751.      * @return string define pattern escape character
  1752.      */
  1753.     function patternEscapeString()
  1754.     {
  1755.         return '';
  1756.     }
  1757.  
  1758.     // }}}
  1759.     // {{{ mapNativeDatatype()
  1760.  
  1761.     /**
  1762.      * Maps a native array description of a field to a MDB2 datatype and length
  1763.      *
  1764.      * @param array  $field native field description
  1765.      * @return array containing the various possible types, length, sign, fixed
  1766.      * @access public
  1767.      */
  1768.     function mapNativeDatatype($field)
  1769.     {
  1770.         $db =$this->getDBInstance();
  1771.         if (PEAR::isError($db)) {
  1772.             return $db;
  1773.         }
  1774.  
  1775.         // If the user has specified an option to map the native field
  1776.         // type to a custom MDB2 datatype...
  1777.         $db_type strtok($field['type']'(), ');
  1778.         if (!empty($db->options['nativetype_map_callback'][$db_type])) {
  1779.             return call_user_func_array($db->options['nativetype_map_callback'][$db_type]array($db$field));
  1780.         }
  1781.  
  1782.         // Otherwise perform the built-in (i.e. normal) MDB2 native type to
  1783.         // MDB2 datatype conversion
  1784.         return $this->_mapNativeDatatype($field);
  1785.     }
  1786.  
  1787.     // }}}
  1788.     // {{{ _mapNativeDatatype()
  1789.  
  1790.     /**
  1791.      * Maps a native array description of a field to a MDB2 datatype and length
  1792.      *
  1793.      * @param array  $field native field description
  1794.      * @return array containing the various possible types, length, sign, fixed
  1795.      * @access public
  1796.      */
  1797.     function _mapNativeDatatype($field)
  1798.     {
  1799.         $db =$this->getDBInstance();
  1800.         if (PEAR::isError($db)) {
  1801.             return $db;
  1802.         }
  1803.  
  1804.         return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1805.             'method not implemented'__FUNCTION__);
  1806.     }
  1807.  
  1808.     // }}}
  1809.     // {{{ mapPrepareDatatype()
  1810.  
  1811.     /**
  1812.      * Maps an mdb2 datatype to mysqli prepare type
  1813.      *
  1814.      * @param string $type 
  1815.      * @return string 
  1816.      * @access public
  1817.      */
  1818.     function mapPrepareDatatype($type)
  1819.     {
  1820.         $db =$this->getDBInstance();
  1821.         if (PEAR::isError($db)) {
  1822.             return $db;
  1823.         }
  1824.  
  1825.         if (!empty($db->options['datatype_map'][$type])) {
  1826.             $type $db->options['datatype_map'][$type];
  1827.             if (!empty($db->options['datatype_map_callback'][$type])) {
  1828.                 $parameter = array('type' => $type);
  1829.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  1830.             }
  1831.         }
  1832.  
  1833.         return $type;
  1834.     }
  1835. }
  1836. ?>

Documentation generated on Mon, 11 Mar 2019 15:01:21 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.