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 328137 2012-10-25 02:26:35Z danielc $
  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.  * To load this module in the MDB2 object:
  59.  * $mdb->loadModule('Datatype');
  60.  *
  61.  * @package MDB2
  62.  * @category Database
  63.  * @author Lukas Smith <smith@pooteeweet.org>
  64.  */
  65. {
  66.     var $valid_default_values = array(
  67.         'text'      => '',
  68.         'boolean'   => true,
  69.         'integer'   => 0,
  70.         'decimal'   => 0.0,
  71.         'float'     => 0.0,
  72.         'timestamp' => '1970-01-01 00:00:00',
  73.         'time'      => '00:00:00',
  74.         'date'      => '1970-01-01',
  75.         'clob'      => '',
  76.         'blob'      => '',
  77.     );
  78.  
  79.     /**
  80.      * contains all LOB objects created with this MDB2 instance
  81.      * @var array 
  82.      * @access protected
  83.      */
  84.     var $lobs = array();
  85.  
  86.     // }}}
  87.     // {{{ getValidTypes()
  88.  
  89.     /**
  90.      * Get the list of valid types
  91.      *
  92.      * This function returns an array of valid types as keys with the values
  93.      * being possible default values for all native datatypes and mapped types
  94.      * for custom datatypes.
  95.      *
  96.      * @return mixed array on success, a MDB2 error on failure
  97.      * @access public
  98.      */
  99.     function getValidTypes()
  100.     {
  101.         $types $this->valid_default_values;
  102.         $db $this->getDBInstance();
  103.         if (MDB2::isError($db)) {
  104.             return $db;
  105.         }
  106.         if (!empty($db->options['datatype_map'])) {
  107.             foreach ($db->options['datatype_map'as $type => $mapped_type{
  108.                 if (array_key_exists($mapped_type$types)) {
  109.                     $types[$type$types[$mapped_type];
  110.                 elseif (!empty($db->options['datatype_map_callback'][$type])) {
  111.                     $parameter = array('type' => $type'mapped_type' => $mapped_type);
  112.                     $default =  call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  113.                     $types[$type$default;
  114.                 }
  115.             }
  116.         }
  117.         return $types;
  118.     }
  119.  
  120.     // }}}
  121.     // {{{ checkResultTypes()
  122.  
  123.     /**
  124.      * Define the list of types to be associated with the columns of a given
  125.      * result set.
  126.      *
  127.      * This function may be called before invoking fetchRow(), fetchOne()
  128.      * fetchCole() and fetchAll() so that the necessary data type
  129.      * conversions are performed on the data to be retrieved by them. If this
  130.      * function is not called, the type of all result set columns is assumed
  131.      * to be text, thus leading to not perform any conversions.
  132.      *
  133.      * @param array $types array variable that lists the
  134.      *        data types to be expected in the result set columns. If this array
  135.      *        contains less types than the number of columns that are returned
  136.      *        in the result set, the remaining columns are assumed to be of the
  137.      *        type text. Currently, the types clob and blob are not fully
  138.      *        supported.
  139.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  140.      * @access public
  141.      */
  142.     function checkResultTypes($types)
  143.     {
  144.         $types is_array($types$types : array($types);
  145.         foreach ($types as $key => $type{
  146.             if (!isset($this->valid_default_values[$type])) {
  147.                 $db $this->getDBInstance();
  148.                 if (MDB2::isError($db)) {
  149.                     return $db;
  150.                 }
  151.                 if (empty($db->options['datatype_map'][$type])) {
  152.                     return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  153.                         $type.' for '.$key.' is not a supported column type'__FUNCTION__);
  154.                 }
  155.             }
  156.         }
  157.         return $types;
  158.     }
  159.  
  160.     // }}}
  161.     // {{{ _baseConvertResult()
  162.  
  163.     /**
  164.      * General type conversion method
  165.      *
  166.      * @param mixed   $value reference to a value to be converted
  167.      * @param string  $type  specifies which type to convert to
  168.      * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
  169.      * @return object an MDB2 error on failure
  170.      * @access protected
  171.      */
  172.     function _baseConvertResult($value$type$rtrim = true)
  173.     {
  174.         switch ($type{
  175.         case 'text':
  176.             if ($rtrim{
  177.                 $value rtrim($value);
  178.             }
  179.             return $value;
  180.         case 'integer':
  181.             return intval($value);
  182.         case 'boolean':
  183.             return !empty($value);
  184.         case 'decimal':
  185.             return $value;
  186.         case 'float':
  187.             return doubleval($value);
  188.         case 'date':
  189.             return $value;
  190.         case 'time':
  191.             return $value;
  192.         case 'timestamp':
  193.             return $value;
  194.         case 'clob':
  195.         case 'blob':
  196.             $this->lobs[= array(
  197.                 'buffer' => null,
  198.                 'position' => 0,
  199.                 'lob_index' => null,
  200.                 'endOfLOB' => false,
  201.                 'resource' => $value,
  202.                 'value' => null,
  203.                 'loaded' => false,
  204.             );
  205.             end($this->lobs);
  206.             $lob_index key($this->lobs);
  207.             $this->lobs[$lob_index]['lob_index'$lob_index;
  208.             return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index'r+');
  209.         }
  210.  
  211.         $db $this->getDBInstance();
  212.         if (MDB2::isError($db)) {
  213.             return $db;
  214.         }
  215.  
  216.         return $db->raiseError(MDB2_ERROR_INVALIDnullnull,
  217.             'attempt to convert result value to an unknown type :' $type__FUNCTION__);
  218.     }
  219.  
  220.     // }}}
  221.     // {{{ convertResult()
  222.  
  223.     /**
  224.      * Convert a value to a RDBMS indipendent MDB2 type
  225.      *
  226.      * @param mixed   $value value to be converted
  227.      * @param string  $type  specifies which type to convert to
  228.      * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
  229.      * @return mixed converted value
  230.      * @access public
  231.      */
  232.     function convertResult($value$type$rtrim = true)
  233.     {
  234.         if (null === $value{
  235.             return null;
  236.         }
  237.         $db $this->getDBInstance();
  238.         if (MDB2::isError($db)) {
  239.             return $db;
  240.         }
  241.         if (!empty($db->options['datatype_map'][$type])) {
  242.             $type $db->options['datatype_map'][$type];
  243.             if (!empty($db->options['datatype_map_callback'][$type])) {
  244.                 $parameter = array('type' => $type'value' => $value'rtrim' => $rtrim);
  245.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  246.             }
  247.         }
  248.         return $this->_baseConvertResult($value$type$rtrim);
  249.     }
  250.  
  251.     // }}}
  252.     // {{{ convertResultRow()
  253.  
  254.     /**
  255.      * Convert a result row
  256.      *
  257.      * @param array   $types 
  258.      * @param array   $row   specifies the types to convert to
  259.      * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
  260.      * @return mixed MDB2_OK on success, an MDB2 error on failure
  261.      * @access public
  262.      */
  263.     function convertResultRow($types$row$rtrim = true)
  264.     {
  265.         //$types = $this->_sortResultFieldTypes(array_keys($row), $types);
  266.         $keys array_keys($row);
  267.         if (is_int($keys[0])) {
  268.             $types $this->_sortResultFieldTypes($keys$types);
  269.         }
  270.         foreach ($row as $key => $value{
  271.             if (empty($types[$key])) {
  272.                 continue;
  273.             }
  274.             $value $this->convertResult($row[$key]$types[$key]$rtrim);
  275.             if (MDB2::isError($value)) {
  276.                 return $value;
  277.             }
  278.             $row[$key$value;
  279.         }
  280.         return $row;
  281.     }
  282.  
  283.     // }}}
  284.     // {{{ _sortResultFieldTypes()
  285.  
  286.     /**
  287.      * convert a result row
  288.      *
  289.      * @param array $types 
  290.      * @param array $row specifies the types to convert to
  291.      * @param bool   $rtrim   if to rtrim text values or not
  292.      * @return mixed MDB2_OK on success,  a MDB2 error on failure
  293.      * @access public
  294.      */
  295.     function _sortResultFieldTypes($columns$types)
  296.     {
  297.         $n_cols count($columns);
  298.         $n_types count($types);
  299.         if ($n_cols $n_types{
  300.             for ($i$n_cols $n_types$i >= 0; $i--{
  301.                 $types[= null;
  302.             }
  303.         }
  304.         $sorted_types = array();
  305.         foreach ($columns as $col{
  306.             $sorted_types[$col= null;
  307.         }
  308.         foreach ($types as $name => $type{
  309.             if (array_key_exists($name$sorted_types)) {
  310.                 $sorted_types[$name$type;
  311.                 unset($types[$name]);
  312.             }
  313.         }
  314.         // if there are left types in the array, fill the null values of the
  315.         // sorted array with them, in order.
  316.         if (count($types)) {
  317.             reset($types);
  318.             foreach (array_keys($sorted_typesas $k{
  319.                 if (null === $sorted_types[$k]{
  320.                     $sorted_types[$kcurrent($types);
  321.                     next($types);
  322.                 }
  323.             }
  324.         }
  325.         return $sorted_types;
  326.     }
  327.  
  328.     // }}}
  329.     // {{{ getDeclaration()
  330.  
  331.     /**
  332.      * Obtain DBMS specific SQL code portion needed to declare
  333.      * of the given type
  334.      *
  335.      * @param string $type type to which the value should be converted to
  336.      * @param string  $name   name the field to be declared.
  337.      * @param string  $field  definition of the field
  338.      * @return string  DBMS specific SQL code portion that should be used to
  339.      *                  declare the specified field.
  340.      * @access public
  341.      */
  342.     function getDeclaration($type$name$field)
  343.     {
  344.         $db $this->getDBInstance();
  345.         if (MDB2::isError($db)) {
  346.             return $db;
  347.         }
  348.  
  349.         if (!empty($db->options['datatype_map'][$type])) {
  350.             $type $db->options['datatype_map'][$type];
  351.             if (!empty($db->options['datatype_map_callback'][$type])) {
  352.                 $parameter = array('type' => $type'name' => $name'field' => $field);
  353.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  354.             }
  355.             $field['type'$type;
  356.         }
  357.  
  358.         if (!method_exists($this"_get{$type}Declaration")) {
  359.             return $db->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  360.                 'type not defined: '.$type__FUNCTION__);
  361.         }
  362.         return $this->{"_get{$type}Declaration"}($name$field);
  363.     }
  364.  
  365.     // }}}
  366.     // {{{ getTypeDeclaration()
  367.  
  368.     /**
  369.      * Obtain DBMS specific SQL code portion needed to declare an text type
  370.      * field to be used in statements like CREATE TABLE.
  371.      *
  372.      * @param array $field  associative array with the name of the properties
  373.      *       of the field being declared as array indexes. Currently, the types
  374.      *       of supported field properties are as follows:
  375.      *
  376.      *       length
  377.      *           Integer value that determines the maximum length of the text
  378.      *           field. If this argument is missing the field should be
  379.      *           declared to have the longest length allowed by the DBMS.
  380.      *
  381.      *       default
  382.      *           Text value to be used as default for this field.
  383.      *
  384.      *       notnull
  385.      *           Boolean flag that indicates whether this field is constrained
  386.      *           to not be set to null.
  387.      * @return string  DBMS specific SQL code portion that should be used to
  388.      *       declare the specified field.
  389.      * @access public
  390.      */
  391.     function getTypeDeclaration($field)
  392.     {
  393.         $db $this->getDBInstance();
  394.         if (MDB2::isError($db)) {
  395.             return $db;
  396.         }
  397.  
  398.         switch ($field['type']{
  399.         case 'text':
  400.             $length !empty($field['length']$field['length'$db->options['default_text_field_length'];
  401.             $fixed !empty($field['fixed']$field['fixed': false;
  402.             return $fixed ($length 'CHAR('.$length.')' 'CHAR('.$db->options['default_text_field_length'].')')
  403.                 : ($length 'VARCHAR('.$length.')' 'TEXT');
  404.         case 'clob':
  405.             return 'TEXT';
  406.         case 'blob':
  407.             return 'TEXT';
  408.         case 'integer':
  409.             return 'INT';
  410.         case 'boolean':
  411.             return 'INT';
  412.         case 'date':
  413.             return 'CHAR ('.strlen('YYYY-MM-DD').')';
  414.         case 'time':
  415.             return 'CHAR ('.strlen('HH:MM:SS').')';
  416.         case 'timestamp':
  417.             return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
  418.         case 'float':
  419.             return 'TEXT';
  420.         case 'decimal':
  421.             return 'TEXT';
  422.         }
  423.         return '';
  424.     }
  425.  
  426.     // }}}
  427.     // {{{ _getDeclaration()
  428.  
  429.     /**
  430.      * Obtain DBMS specific SQL code portion needed to declare a generic type
  431.      * field to be used in statements like CREATE TABLE.
  432.      *
  433.      * @param string $name   name the field to be declared.
  434.      * @param array  $field  associative array with the name of the properties
  435.      *       of the field being declared as array indexes. Currently, the types
  436.      *       of supported field properties are as follows:
  437.      *
  438.      *       length
  439.      *           Integer value that determines the maximum length of the text
  440.      *           field. If this argument is missing the field should be
  441.      *           declared to have the longest length allowed by the DBMS.
  442.      *
  443.      *       default
  444.      *           Text value to be used as default for this field.
  445.      *
  446.      *       notnull
  447.      *           Boolean flag that indicates whether this field is constrained
  448.      *           to not be set to null.
  449.      *       charset
  450.      *           Text value with the default CHARACTER SET for this field.
  451.      *       collation
  452.      *           Text value with the default COLLATION for this field.
  453.      * @return string  DBMS specific SQL code portion that should be used to
  454.      *       declare the specified field, or a MDB2_Error on failure
  455.      * @access protected
  456.      */
  457.     function _getDeclaration($name$field)
  458.     {
  459.         $db $this->getDBInstance();
  460.         if (MDB2::isError($db)) {
  461.             return $db;
  462.         }
  463.  
  464.         $name $db->quoteIdentifier($nametrue);
  465.         $declaration_options $db->datatype->_getDeclarationOptions($field);
  466.         if (MDB2::isError($declaration_options)) {
  467.             return $declaration_options;
  468.         }
  469.         return $name.' '.$this->getTypeDeclaration($field).$declaration_options;
  470.     }
  471.  
  472.     // }}}
  473.     // {{{ _getDeclarationOptions()
  474.  
  475.     /**
  476.      * Obtain DBMS specific SQL code portion needed to declare a generic type
  477.      * field to be used in statement like CREATE TABLE, without the field name
  478.      * and type values (ie. just the character set, default value, if the
  479.      * field is permitted to be NULL or not, and the collation options).
  480.      *
  481.      * @param array  $field  associative array with the name of the properties
  482.      *       of the field being declared as array indexes. Currently, the types
  483.      *       of supported field properties are as follows:
  484.      *
  485.      *       default
  486.      *           Text value to be used as default for this field.
  487.      *       notnull
  488.      *           Boolean flag that indicates whether this field is constrained
  489.      *           to not be set to null.
  490.      *       charset
  491.      *           Text value with the default CHARACTER SET for this field.
  492.      *       collation
  493.      *           Text value with the default COLLATION for this field.
  494.      * @return string  DBMS specific SQL code portion that should be used to
  495.      *       declare the specified field's options.
  496.      * @access protected
  497.      */
  498.     function _getDeclarationOptions($field)
  499.     {
  500.         $charset = empty($field['charset']'' :
  501.             ' '.$this->_getCharsetFieldDeclaration($field['charset']);
  502.  
  503.         $notnull = empty($field['notnull']'' ' NOT NULL';
  504.         $default '';
  505.         if (array_key_exists('default'$field)) {
  506.             if ($field['default'=== ''{
  507.                 $db $this->getDBInstance();
  508.                 if (MDB2::isError($db)) {
  509.                     return $db;
  510.                 }
  511.                 $valid_default_values $this->getValidTypes();
  512.                 $field['default'$valid_default_values[$field['type']];
  513.                 if ($field['default'=== '' && ($db->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL)) {
  514.                     $field['default'' ';
  515.                 }
  516.             }
  517.             if (null !== $field['default']{
  518.                 $default ' DEFAULT ' $this->quote($field['default']$field['type']);
  519.             }
  520.         }
  521.  
  522.         $collation = empty($field['collation']'' :
  523.             ' '.$this->_getCollationFieldDeclaration($field['collation']);
  524.  
  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 (MDB2::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 (MDB2::isError($db)) {
  659.             return $db;
  660.         }
  661.  
  662.         $notnull = empty($field['notnull']'' ' NOT NULL';
  663.         $name $db->quoteIdentifier($nametrue);
  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 (MDB2::isError($db)) {
  695.             return $db;
  696.         }
  697.  
  698.         $notnull = empty($field['notnull']'' ' NOT NULL';
  699.         $name $db->quoteIdentifier($nametrue);
  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 (MDB2::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_UNSUPPORTEDnullnull,
  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.             null;
  912.         $default array_key_exists('default'$current$current['default':
  913.             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_length !empty($previous['length']$previous['length': 4;
  936.         $length !empty($current['length']$current['length': 4;
  937.         if ($previous_length != $length{
  938.             $change['length'$length;
  939.         }
  940.         $previous_unsigned !empty($previous['unsigned']$previous['unsigned': false;
  941.         $unsigned !empty($current['unsigned']$current['unsigned': false;
  942.         if ($previous_unsigned != $unsigned{
  943.             $change['unsigned'= true;
  944.         }
  945.         $previous_autoincrement !empty($previous['autoincrement']$previous['autoincrement': false;
  946.         $autoincrement !empty($current['autoincrement']$current['autoincrement': false;
  947.         if ($previous_autoincrement != $autoincrement{
  948.             $change['autoincrement'= true;
  949.         }
  950.         return $change;
  951.     }
  952.  
  953.     // }}}
  954.     // {{{ _compareTextDefinition()
  955.  
  956.     /**
  957.      * Obtain an array of changes that may need to applied to an text field
  958.      *
  959.      * @param array $current new definition
  960.      * @param array  $previous old definition
  961.      * @return array  containing all changes that will need to be applied
  962.      * @access protected
  963.      */
  964.     function _compareTextDefinition($current$previous)
  965.     {
  966.         $change = array();
  967.         $previous_length !empty($previous['length']$previous['length': 0;
  968.         $length !empty($current['length']$current['length': 0;
  969.         if ($previous_length != $length{
  970.             $change['length'= true;
  971.         }
  972.         $previous_fixed !empty($previous['fixed']$previous['fixed': 0;
  973.         $fixed !empty($current['fixed']$current['fixed': 0;
  974.         if ($previous_fixed != $fixed{
  975.             $change['fixed'= true;
  976.         }
  977.         return $change;
  978.     }
  979.  
  980.     // }}}
  981.     // {{{ _compareCLOBDefinition()
  982.  
  983.     /**
  984.      * Obtain an array of changes that may need to applied to an CLOB field
  985.      *
  986.      * @param array $current new definition
  987.      * @param array  $previous old definition
  988.      * @return array  containing all changes that will need to be applied
  989.      * @access protected
  990.      */
  991.     function _compareCLOBDefinition($current$previous)
  992.     {
  993.         return $this->_compareTextDefinition($current$previous);
  994.     }
  995.  
  996.     // }}}
  997.     // {{{ _compareBLOBDefinition()
  998.  
  999.     /**
  1000.      * Obtain an array of changes that may need to applied to an BLOB field
  1001.      *
  1002.      * @param array $current new definition
  1003.      * @param array  $previous old definition
  1004.      * @return array  containing all changes that will need to be applied
  1005.      * @access protected
  1006.      */
  1007.     function _compareBLOBDefinition($current$previous)
  1008.     {
  1009.         return $this->_compareTextDefinition($current$previous);
  1010.     }
  1011.  
  1012.     // }}}
  1013.     // {{{ _compareDateDefinition()
  1014.  
  1015.     /**
  1016.      * Obtain an array of changes that may need to applied to an date field
  1017.      *
  1018.      * @param array $current new definition
  1019.      * @param array  $previous old definition
  1020.      * @return array  containing all changes that will need to be applied
  1021.      * @access protected
  1022.      */
  1023.     function _compareDateDefinition($current$previous)
  1024.     {
  1025.         return array();
  1026.     }
  1027.  
  1028.     // }}}
  1029.     // {{{ _compareTimeDefinition()
  1030.  
  1031.     /**
  1032.      * Obtain an array of changes that may need to applied to an time field
  1033.      *
  1034.      * @param array $current new definition
  1035.      * @param array  $previous old definition
  1036.      * @return array  containing all changes that will need to be applied
  1037.      * @access protected
  1038.      */
  1039.     function _compareTimeDefinition($current$previous)
  1040.     {
  1041.         return array();
  1042.     }
  1043.  
  1044.     // }}}
  1045.     // {{{ _compareTimestampDefinition()
  1046.  
  1047.     /**
  1048.      * Obtain an array of changes that may need to applied to an timestamp field
  1049.      *
  1050.      * @param array $current new definition
  1051.      * @param array  $previous old definition
  1052.      * @return array  containing all changes that will need to be applied
  1053.      * @access protected
  1054.      */
  1055.     function _compareTimestampDefinition($current$previous)
  1056.     {
  1057.         return array();
  1058.     }
  1059.  
  1060.     // }}}
  1061.     // {{{ _compareBooleanDefinition()
  1062.  
  1063.     /**
  1064.      * Obtain an array of changes that may need to applied to an boolean field
  1065.      *
  1066.      * @param array $current new definition
  1067.      * @param array  $previous old definition
  1068.      * @return array  containing all changes that will need to be applied
  1069.      * @access protected
  1070.      */
  1071.     function _compareBooleanDefinition($current$previous)
  1072.     {
  1073.         return array();
  1074.     }
  1075.  
  1076.     // }}}
  1077.     // {{{ _compareFloatDefinition()
  1078.  
  1079.     /**
  1080.      * Obtain an array of changes that may need to applied to an float field
  1081.      *
  1082.      * @param array $current new definition
  1083.      * @param array  $previous old definition
  1084.      * @return array  containing all changes that will need to be applied
  1085.      * @access protected
  1086.      */
  1087.     function _compareFloatDefinition($current$previous)
  1088.     {
  1089.         return array();
  1090.     }
  1091.  
  1092.     // }}}
  1093.     // {{{ _compareDecimalDefinition()
  1094.  
  1095.     /**
  1096.      * Obtain an array of changes that may need to applied to an decimal field
  1097.      *
  1098.      * @param array $current new definition
  1099.      * @param array  $previous old definition
  1100.      * @return array  containing all changes that will need to be applied
  1101.      * @access protected
  1102.      */
  1103.     function _compareDecimalDefinition($current$previous)
  1104.     {
  1105.         return array();
  1106.     }
  1107.  
  1108.     // }}}
  1109.     // {{{ quote()
  1110.  
  1111.     /**
  1112.      * Convert a text value into a DBMS specific format that is suitable to
  1113.      * compose query statements.
  1114.      *
  1115.      * @param string $value text string value that is intended to be converted.
  1116.      * @param string $type type to which the value should be converted to
  1117.      * @param bool $quote determines if the value should be quoted and escaped
  1118.      * @param bool $escape_wildcards if to escape escape wildcards
  1119.      * @return string text string that represents the given argument value in
  1120.      *        a DBMS specific format.
  1121.      * @access public
  1122.      */
  1123.     function quote($value$type = null$quote = true$escape_wildcards = false)
  1124.     {
  1125.         $db $this->getDBInstance();
  1126.         if (MDB2::isError($db)) {
  1127.             return $db;
  1128.         }
  1129.  
  1130.         if ((null === $value)
  1131.             || ($value === '' && $db->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL)
  1132.         {
  1133.             if (!$quote{
  1134.                 return null;
  1135.             }
  1136.             return 'NULL';
  1137.         }
  1138.  
  1139.         if (null === $type{
  1140.             switch (gettype($value)) {
  1141.             case 'integer':
  1142.                 $type 'integer';
  1143.                 break;
  1144.             case 'double':
  1145.                 // todo: default to decimal as float is quite unusual
  1146.                 // $type = 'float';
  1147.                 $type 'decimal';
  1148.                 break;
  1149.             case 'boolean':
  1150.                 $type 'boolean';
  1151.                 break;
  1152.             case 'array':
  1153.                  $value serialize($value);
  1154.             case 'object':
  1155.                  $type 'text';
  1156.                 break;
  1157.             default:
  1158.                 if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/'$value)) {
  1159.                     $type 'timestamp';
  1160.                 elseif (preg_match('/^\d{2}:\d{2}$/'$value)) {
  1161.                     $type 'time';
  1162.                 elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/'$value)) {
  1163.                     $type 'date';
  1164.                 else {
  1165.                     $type 'text';
  1166.                 }
  1167.                 break;
  1168.             }
  1169.         elseif (!empty($db->options['datatype_map'][$type])) {
  1170.             $type $db->options['datatype_map'][$type];
  1171.             if (!empty($db->options['datatype_map_callback'][$type])) {
  1172.                 $parameter = array('type' => $type'value' => $value'quote' => $quote'escape_wildcards' => $escape_wildcards);
  1173.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  1174.             }
  1175.         }
  1176.  
  1177.         if (!method_exists($this"_quote{$type}")) {
  1178.             return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1179.                 'type not defined: '.$type__FUNCTION__);
  1180.         }
  1181.         $value $this->{"_quote{$type}"}($value$quote$escape_wildcards);
  1182.         if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
  1183.             && $db->string_quoting['escape'!== $db->string_quoting['escape_pattern']
  1184.         {
  1185.             $value.= $this->patternEscapeString();
  1186.         }
  1187.         return $value;
  1188.     }
  1189.  
  1190.     // }}}
  1191.     // {{{ _quoteInteger()
  1192.  
  1193.     /**
  1194.      * Convert a text value into a DBMS specific format that is suitable to
  1195.      * compose query statements.
  1196.      *
  1197.      * @param string $value text string value that is intended to be converted.
  1198.      * @param bool $quote determines if the value should be quoted and escaped
  1199.      * @param bool $escape_wildcards if to escape escape wildcards
  1200.      * @return string text string that represents the given argument value in
  1201.      *        a DBMS specific format.
  1202.      * @access protected
  1203.      */
  1204.     function _quoteInteger($value$quote$escape_wildcards)
  1205.     {
  1206.         return (int)$value;
  1207.     }
  1208.  
  1209.     // }}}
  1210.     // {{{ _quoteText()
  1211.  
  1212.     /**
  1213.      * Convert a text value into a DBMS specific format that is suitable to
  1214.      * compose query statements.
  1215.      *
  1216.      * @param string $value text string value that is intended to be converted.
  1217.      * @param bool $quote determines if the value should be quoted and escaped
  1218.      * @param bool $escape_wildcards if to escape escape wildcards
  1219.      * @return string text string that already contains any DBMS specific
  1220.      *        escaped character sequences.
  1221.      * @access protected
  1222.      */
  1223.     function _quoteText($value$quote$escape_wildcards)
  1224.     {
  1225.         if (!$quote{
  1226.             return $value;
  1227.         }
  1228.  
  1229.         $db $this->getDBInstance();
  1230.         if (MDB2::isError($db)) {
  1231.             return $db;
  1232.         }
  1233.  
  1234.         $value $db->escape($value$escape_wildcards);
  1235.         if (MDB2::isError($value)) {
  1236.             return $value;
  1237.         }
  1238.         return "'".$value."'";
  1239.     }
  1240.  
  1241.     // }}}
  1242.     // {{{ _readFile()
  1243.  
  1244.     /**
  1245.      * Convert a text value into a DBMS specific format that is suitable to
  1246.      * compose query statements.
  1247.      *
  1248.      * @param string $value text string value that is intended to be converted.
  1249.      * @return string text string that represents the given argument value in
  1250.      *        a DBMS specific format.
  1251.      * @access protected
  1252.      */
  1253.     function _readFile($value)
  1254.     {
  1255.         $close = false;
  1256.         if (preg_match('/^(\w+:\/\/)(.*)$/'$value$match)) {
  1257.             $close = true;
  1258.             if (strtolower($match[1]== 'file://'{
  1259.                 $value $match[2];
  1260.             }
  1261.             $value @fopen($value'r');
  1262.         }
  1263.  
  1264.         if (is_resource($value)) {
  1265.             $db $this->getDBInstance();
  1266.             if (MDB2::isError($db)) {
  1267.                 return $db;
  1268.             }
  1269.  
  1270.             $fp $value;
  1271.             $value '';
  1272.             while (!@feof($fp)) {
  1273.                 $value.= @fread($fp$db->options['lob_buffer_length']);
  1274.             }
  1275.             if ($close{
  1276.                 @fclose($fp);
  1277.             }
  1278.         }
  1279.  
  1280.         return $value;
  1281.     }
  1282.  
  1283.     // }}}
  1284.     // {{{ _quoteLOB()
  1285.  
  1286.     /**
  1287.      * Convert a text value into a DBMS specific format that is suitable to
  1288.      * compose query statements.
  1289.      *
  1290.      * @param string $value text string value that is intended to be converted.
  1291.      * @param bool $quote determines if the value should be quoted and escaped
  1292.      * @param bool $escape_wildcards if to escape escape wildcards
  1293.      * @return string text string that represents the given argument value in
  1294.      *        a DBMS specific format.
  1295.      * @access protected
  1296.      */
  1297.     function _quoteLOB($value$quote$escape_wildcards)
  1298.     {
  1299.         $db $this->getDBInstance();
  1300.         if (MDB2::isError($db)) {
  1301.             return $db;
  1302.         }
  1303.         if ($db->options['lob_allow_url_include']{
  1304.             $value $this->_readFile($value);
  1305.             if (MDB2::isError($value)) {
  1306.                 return $value;
  1307.             }
  1308.         }
  1309.         return $this->_quoteText($value$quote$escape_wildcards);
  1310.     }
  1311.  
  1312.     // }}}
  1313.     // {{{ _quoteCLOB()
  1314.  
  1315.     /**
  1316.      * Convert a text value into a DBMS specific format that is suitable to
  1317.      * compose query statements.
  1318.      *
  1319.      * @param string $value text string value that is intended to be converted.
  1320.      * @param bool $quote determines if the value should be quoted and escaped
  1321.      * @param bool $escape_wildcards if to escape escape wildcards
  1322.      * @return string text string that represents the given argument value in
  1323.      *        a DBMS specific format.
  1324.      * @access protected
  1325.      */
  1326.     function _quoteCLOB($value$quote$escape_wildcards)
  1327.     {
  1328.         return $this->_quoteLOB($value$quote$escape_wildcards);
  1329.     }
  1330.  
  1331.     // }}}
  1332.     // {{{ _quoteBLOB()
  1333.  
  1334.     /**
  1335.      * Convert a text value into a DBMS specific format that is suitable to
  1336.      * compose query statements.
  1337.      *
  1338.      * @param string $value text string value that is intended to be converted.
  1339.      * @param bool $quote determines if the value should be quoted and escaped
  1340.      * @param bool $escape_wildcards if to escape escape wildcards
  1341.      * @return string text string that represents the given argument value in
  1342.      *        a DBMS specific format.
  1343.      * @access protected
  1344.      */
  1345.     function _quoteBLOB($value$quote$escape_wildcards)
  1346.     {
  1347.         return $this->_quoteLOB($value$quote$escape_wildcards);
  1348.     }
  1349.  
  1350.     // }}}
  1351.     // {{{ _quoteBoolean()
  1352.  
  1353.     /**
  1354.      * Convert a text value into a DBMS specific format that is suitable to
  1355.      * compose query statements.
  1356.      *
  1357.      * @param string $value text string value that is intended to be converted.
  1358.      * @param bool $quote determines if the value should be quoted and escaped
  1359.      * @param bool $escape_wildcards if to escape escape wildcards
  1360.      * @return string text string that represents the given argument value in
  1361.      *        a DBMS specific format.
  1362.      * @access protected
  1363.      */
  1364.     function _quoteBoolean($value$quote$escape_wildcards)
  1365.     {
  1366.         return ($value ? 1 : 0);
  1367.     }
  1368.  
  1369.     // }}}
  1370.     // {{{ _quoteDate()
  1371.  
  1372.     /**
  1373.      * Convert a text value into a DBMS specific format that is suitable to
  1374.      * compose query statements.
  1375.      *
  1376.      * @param string $value text string value that is intended to be converted.
  1377.      * @param bool $quote determines if the value should be quoted and escaped
  1378.      * @param bool $escape_wildcards if to escape escape wildcards
  1379.      * @return string text string that represents the given argument value in
  1380.      *        a DBMS specific format.
  1381.      * @access protected
  1382.      */
  1383.     function _quoteDate($value$quote$escape_wildcards)
  1384.     {
  1385.         if ($value === 'CURRENT_DATE'{
  1386.             $db $this->getDBInstance();
  1387.             if (MDB2::isError($db)) {
  1388.                 return $db;
  1389.             }
  1390.             if (isset($db->function&& is_object($this->function&& is_a($db->function'MDB2_Driver_Function_Common')) {
  1391.                 return $db->function->now('date');
  1392.             }
  1393.             return 'CURRENT_DATE';
  1394.         }
  1395.         return $this->_quoteText($value$quote$escape_wildcards);
  1396.     }
  1397.  
  1398.     // }}}
  1399.     // {{{ _quoteTimestamp()
  1400.  
  1401.     /**
  1402.      * Convert a text value into a DBMS specific format that is suitable to
  1403.      * compose query statements.
  1404.      *
  1405.      * @param string $value text string value that is intended to be converted.
  1406.      * @param bool $quote determines if the value should be quoted and escaped
  1407.      * @param bool $escape_wildcards if to escape escape wildcards
  1408.      * @return string text string that represents the given argument value in
  1409.      *        a DBMS specific format.
  1410.      * @access protected
  1411.      */
  1412.     function _quoteTimestamp($value$quote$escape_wildcards)
  1413.     {
  1414.         if ($value === 'CURRENT_TIMESTAMP'{
  1415.             $db $this->getDBInstance();
  1416.             if (MDB2::isError($db)) {
  1417.                 return $db;
  1418.             }
  1419.             if (isset($db->function&& is_object($db->function&& is_a($db->function'MDB2_Driver_Function_Common')) {
  1420.                 return $db->function->now('timestamp');
  1421.             }
  1422.             return 'CURRENT_TIMESTAMP';
  1423.         }
  1424.         return $this->_quoteText($value$quote$escape_wildcards);
  1425.     }
  1426.  
  1427.     // }}}
  1428.     // {{{ _quoteTime()
  1429.  
  1430.     /**
  1431.      * Convert a text value into a DBMS specific format that is suitable to
  1432.      *       compose query statements.
  1433.      *
  1434.      * @param string $value text string value that is intended to be converted.
  1435.      * @param bool $quote determines if the value should be quoted and escaped
  1436.      * @param bool $escape_wildcards if to escape escape wildcards
  1437.      * @return string text string that represents the given argument value in
  1438.      *        a DBMS specific format.
  1439.      * @access protected
  1440.      */
  1441.     function _quoteTime($value$quote$escape_wildcards)
  1442.     {
  1443.         if ($value === 'CURRENT_TIME'{
  1444.             $db $this->getDBInstance();
  1445.             if (MDB2::isError($db)) {
  1446.                 return $db;
  1447.             }
  1448.             if (isset($db->function&& is_object($this->function&& is_a($db->function'MDB2_Driver_Function_Common')) {
  1449.                 return $db->function->now('time');
  1450.             }
  1451.             return 'CURRENT_TIME';
  1452.         }
  1453.         return $this->_quoteText($value$quote$escape_wildcards);
  1454.     }
  1455.  
  1456.     // }}}
  1457.     // {{{ _quoteFloat()
  1458.  
  1459.     /**
  1460.      * Convert a text value into a DBMS specific format that is suitable to
  1461.      * compose query statements.
  1462.      *
  1463.      * @param string $value text string value that is intended to be converted.
  1464.      * @param bool $quote determines if the value should be quoted and escaped
  1465.      * @param bool $escape_wildcards if to escape escape wildcards
  1466.      * @return string text string that represents the given argument value in
  1467.      *        a DBMS specific format.
  1468.      * @access protected
  1469.      */
  1470.     function _quoteFloat($value$quote$escape_wildcards)
  1471.     {
  1472.         if (preg_match('/^(.*)e([-+])(\d+)$/i'$value$matches)) {
  1473.             $decimal $this->_quoteDecimal($matches[1]$quote$escape_wildcards);
  1474.             $sign $matches[2];
  1475.             $exponent str_pad($matches[3]2'0'STR_PAD_LEFT);
  1476.             $value $decimal.'E'.$sign.$exponent;
  1477.         else {
  1478.             $value $this->_quoteDecimal($value$quote$escape_wildcards);
  1479.         }
  1480.         return $value;
  1481.     }
  1482.  
  1483.     // }}}
  1484.     // {{{ _quoteDecimal()
  1485.  
  1486.     /**
  1487.      * Convert a text value into a DBMS specific format that is suitable to
  1488.      * compose query statements.
  1489.      *
  1490.      * @param string $value text string value that is intended to be converted.
  1491.      * @param bool $quote determines if the value should be quoted and escaped
  1492.      * @param bool $escape_wildcards if to escape escape wildcards
  1493.      * @return string text string that represents the given argument value in
  1494.      *        a DBMS specific format.
  1495.      * @access protected
  1496.      */
  1497.     function _quoteDecimal($value$quote$escape_wildcards)
  1498.     {
  1499.         $value = (string)$value;
  1500.         $value preg_replace('/[^\d\.,\-+eE]/'''$value);
  1501.         if (preg_match('/[^\.\d]/'$value)) {
  1502.             if (strpos($value',')) {
  1503.                 // 1000,00
  1504.                 if (!strpos($value'.')) {
  1505.                     // convert the last "," to a "."
  1506.                     $value strrev(str_replace(',''.'strrev($value)));
  1507.                 // 1.000,00
  1508.                 elseif (strpos($value'.'&& strpos($value'.'strpos($value',')) {
  1509.                     $value str_replace('.'''$value);
  1510.                     // convert the last "," to a "."
  1511.                     $value strrev(str_replace(',''.'strrev($value)));
  1512.                 // 1,000.00
  1513.                 else {
  1514.                     $value str_replace(','''$value);
  1515.                 }
  1516.             }
  1517.         }
  1518.         return $value;
  1519.     }
  1520.  
  1521.     // }}}
  1522.     // {{{ writeLOBToFile()
  1523.  
  1524.     /**
  1525.      * retrieve LOB from the database
  1526.      *
  1527.      * @param resource $lob stream handle
  1528.      * @param string $file name of the file into which the LOb should be fetched
  1529.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  1530.      * @access protected
  1531.      */
  1532.     function writeLOBToFile($lob$file)
  1533.     {
  1534.         $db $this->getDBInstance();
  1535.         if (MDB2::isError($db)) {
  1536.             return $db;
  1537.         }
  1538.  
  1539.         if (preg_match('/^(\w+:\/\/)(.*)$/'$file$match)) {
  1540.             if ($match[1== 'file://'{
  1541.                 $file $match[2];
  1542.             }
  1543.         }
  1544.  
  1545.         $fp @fopen($file'wb');
  1546.         while (!@feof($lob)) {
  1547.             $result @fread($lob$db->options['lob_buffer_length']);
  1548.             $read strlen($result);
  1549.             if (@fwrite($fp$result$read!= $read{
  1550.                 @fclose($fp);
  1551.                 return $db->raiseError(MDB2_ERRORnullnull,
  1552.                     'could not write to the output file'__FUNCTION__);
  1553.             }
  1554.         }
  1555.         @fclose($fp);
  1556.         return MDB2_OK;
  1557.     }
  1558.  
  1559.     // }}}
  1560.     // {{{ _retrieveLOB()
  1561.  
  1562.     /**
  1563.      * retrieve LOB from the database
  1564.      *
  1565.      * @param array $lob array
  1566.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  1567.      * @access protected
  1568.      */
  1569.     function _retrieveLOB(&$lob)
  1570.     {
  1571.         if (null === $lob['value']{
  1572.             $lob['value'$lob['resource'];
  1573.         }
  1574.         $lob['loaded'= true;
  1575.         return MDB2_OK;
  1576.     }
  1577.  
  1578.     // }}}
  1579.     // {{{ readLOB()
  1580.  
  1581.     /**
  1582.      * Read data from large object input stream.
  1583.      *
  1584.      * @param resource $lob stream handle
  1585.      * @param string $data reference to a variable that will hold data
  1586.      *                           to be read from the large object input stream
  1587.      * @param integer $length    value that indicates the largest ammount ofdata
  1588.      *                           to be read from the large object input stream.
  1589.      * @return mixed the effective number of bytes read from the large object
  1590.      *                       input stream on sucess or an MDB2 error object.
  1591.      * @access public
  1592.      * @see endOfLOB()
  1593.      */
  1594.     function _readLOB($lob$length)
  1595.     {
  1596.         return substr($lob['value']$lob['position']$length);
  1597.     }
  1598.  
  1599.     // }}}
  1600.     // {{{ _endOfLOB()
  1601.  
  1602.     /**
  1603.      * Determine whether it was reached the end of the large object and
  1604.      * therefore there is no more data to be read for the its input stream.
  1605.      *
  1606.      * @param array $lob array
  1607.      * @return mixed true or false on success, a MDB2 error on failure
  1608.      * @access protected
  1609.      */
  1610.     function _endOfLOB($lob)
  1611.     {
  1612.         return $lob['endOfLOB'];
  1613.     }
  1614.  
  1615.     // }}}
  1616.     // {{{ destroyLOB()
  1617.  
  1618.     /**
  1619.      * Free any resources allocated during the lifetime of the large object
  1620.      * handler object.
  1621.      *
  1622.      * @param resource $lob stream handle
  1623.      * @access public
  1624.      */
  1625.     function destroyLOB($lob)
  1626.     {
  1627.         $lob_data stream_get_meta_data($lob);
  1628.         $lob_index $lob_data['wrapper_data']->lob_index;
  1629.         fclose($lob);
  1630.         if (isset($this->lobs[$lob_index])) {
  1631.             $this->_destroyLOB($this->lobs[$lob_index]);
  1632.             unset($this->lobs[$lob_index]);
  1633.         }
  1634.         return MDB2_OK;
  1635.     }
  1636.  
  1637.     // }}}
  1638.     // {{{ _destroyLOB()
  1639.  
  1640.     /**
  1641.      * Free any resources allocated during the lifetime of the large object
  1642.      * handler object.
  1643.      *
  1644.      * @param array $lob array
  1645.      * @access private
  1646.      */
  1647.     function _destroyLOB(&$lob)
  1648.     {
  1649.         return MDB2_OK;
  1650.     }
  1651.  
  1652.     // }}}
  1653.     // {{{ implodeArray()
  1654.  
  1655.     /**
  1656.      * apply a type to all values of an array and return as a comma seperated string
  1657.      * useful for generating IN statements
  1658.      *
  1659.      * @access public
  1660.      *
  1661.      * @param array $array data array
  1662.      * @param string $type determines type of the field
  1663.      *
  1664.      * @return string comma seperated values
  1665.      */
  1666.     function implodeArray($array$type = false)
  1667.     {
  1668.         if (!is_array($array|| empty($array)) {
  1669.             return 'NULL';
  1670.         }
  1671.         if ($type{
  1672.             foreach ($array as $value{
  1673.                 $return[$this->quote($value$type);
  1674.             }
  1675.         else {
  1676.             $return $array;
  1677.         }
  1678.         return implode(', '$return);
  1679.     }
  1680.  
  1681.     // }}}
  1682.     // {{{ matchPattern()
  1683.  
  1684.     /**
  1685.      * build a pattern matching string
  1686.      *
  1687.      * @access public
  1688.      *
  1689.      * @param array $pattern even keys are strings, odd are patterns (% and _)
  1690.      * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
  1691.      * @param string $field optional field name that is being matched against
  1692.      *                   (might be required when emulating ILIKE)
  1693.      *
  1694.      * @return string SQL pattern
  1695.      */
  1696.     function matchPattern($pattern$operator = null$field = null)
  1697.     {
  1698.         $db $this->getDBInstance();
  1699.         if (MDB2::isError($db)) {
  1700.             return $db;
  1701.         }
  1702.  
  1703.         $match '';
  1704.         if (null !== $operator{
  1705.             $operator strtoupper($operator);
  1706.             switch ($operator{
  1707.             // case insensitive
  1708.             case 'ILIKE':
  1709.                 if (null === $field{
  1710.                     return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1711.                         'case insensitive LIKE matching requires passing the field name'__FUNCTION__);
  1712.                 }
  1713.                 $db->loadModule('Function'nulltrue);
  1714.                 $match $db->function->lower($field).' LIKE ';
  1715.                 break;
  1716.             case 'NOT ILIKE':
  1717.                 if (null === $field{
  1718.                     return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1719.                         'case insensitive NOT ILIKE matching requires passing the field name'__FUNCTION__);
  1720.                 }
  1721.                 $db->loadModule('Function'nulltrue);
  1722.                 $match $db->function->lower($field).' NOT LIKE ';
  1723.                 break;
  1724.             // case sensitive
  1725.             case 'LIKE':
  1726.                 $match (null === $field'LIKE ' ($field.' LIKE ');
  1727.                 break;
  1728.             case 'NOT LIKE':
  1729.                 $match (null === $field'NOT LIKE ' ($field.' NOT LIKE ');
  1730.                 break;
  1731.             default:
  1732.                 return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1733.                     'not a supported operator type:'$operator__FUNCTION__);
  1734.             }
  1735.         }
  1736.         $match.= "'";
  1737.         foreach ($pattern as $key => $value{
  1738.             if ($key % 2{
  1739.                 $match.= $value;
  1740.             else {
  1741.                 $escaped $db->escape($value);
  1742.                 if (MDB2::isError($escaped)) {
  1743.                     return $escaped;
  1744.                 }
  1745.                 $match.= $db->escapePattern($escaped);
  1746.             }
  1747.         }
  1748.         $match.= "'";
  1749.         $match.= $this->patternEscapeString();
  1750.         return $match;
  1751.     }
  1752.  
  1753.     // }}}
  1754.     // {{{ patternEscapeString()
  1755.  
  1756.     /**
  1757.      * build string to define pattern escape character
  1758.      *
  1759.      * @access public
  1760.      *
  1761.      * @return string define pattern escape character
  1762.      */
  1763.     function patternEscapeString()
  1764.     {
  1765.         return '';
  1766.     }
  1767.  
  1768.     // }}}
  1769.     // {{{ mapNativeDatatype()
  1770.  
  1771.     /**
  1772.      * Maps a native array description of a field to a MDB2 datatype and length
  1773.      *
  1774.      * @param array  $field native field description
  1775.      * @return array containing the various possible types, length, sign, fixed
  1776.      * @access public
  1777.      */
  1778.     function mapNativeDatatype($field)
  1779.     {
  1780.         $db $this->getDBInstance();
  1781.         if (MDB2::isError($db)) {
  1782.             return $db;
  1783.         }
  1784.  
  1785.         // If the user has specified an option to map the native field
  1786.         // type to a custom MDB2 datatype...
  1787.         $db_type strtok($field['type']'(), ');
  1788.         if (!empty($db->options['nativetype_map_callback'][$db_type])) {
  1789.             return call_user_func_array($db->options['nativetype_map_callback'][$db_type]array($db$field));
  1790.         }
  1791.  
  1792.         // Otherwise perform the built-in (i.e. normal) MDB2 native type to
  1793.         // MDB2 datatype conversion
  1794.         return $this->_mapNativeDatatype($field);
  1795.     }
  1796.  
  1797.     // }}}
  1798.     // {{{ _mapNativeDatatype()
  1799.  
  1800.     /**
  1801.      * Maps a native array description of a field to a MDB2 datatype and length
  1802.      *
  1803.      * @param array  $field native field description
  1804.      * @return array containing the various possible types, length, sign, fixed
  1805.      * @access public
  1806.      */
  1807.     function _mapNativeDatatype($field)
  1808.     {
  1809.         $db $this->getDBInstance();
  1810.         if (MDB2::isError($db)) {
  1811.             return $db;
  1812.         }
  1813.  
  1814.         return $db->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  1815.             'method not implemented'__FUNCTION__);
  1816.     }
  1817.  
  1818.     // }}}
  1819.     // {{{ mapPrepareDatatype()
  1820.  
  1821.     /**
  1822.      * Maps an mdb2 datatype to mysqli prepare type
  1823.      *
  1824.      * @param string $type 
  1825.      * @return string 
  1826.      * @access public
  1827.      */
  1828.     function mapPrepareDatatype($type)
  1829.     {
  1830.         $db $this->getDBInstance();
  1831.         if (MDB2::isError($db)) {
  1832.             return $db;
  1833.         }
  1834.  
  1835.         if (!empty($db->options['datatype_map'][$type])) {
  1836.             $type $db->options['datatype_map'][$type];
  1837.             if (!empty($db->options['datatype_map_callback'][$type])) {
  1838.                 $parameter = array('type' => $type);
  1839.                 return call_user_func_array($db->options['datatype_map_callback'][$type]array(&$db__FUNCTION__$parameter));
  1840.             }
  1841.         }
  1842.  
  1843.         return $type;
  1844.     }
  1845. }
  1846. ?>

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