Changeset d1403fd in github


Ignore:
Timestamp:
May 2, 2008 3:35:00 AM (5 years ago)
Author:
alecpl <alec@…>
Branches:
master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
Children:
c5cc386
Parents:
bbf15d8
Message:
  • fixed #1485032 and updated MDB2 package+drivers
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    r7ec922f rd1403fd  
    11CHANGELOG RoundCube Webmail 
    22--------------------------- 
     3 
     42008/05/02 (alec) 
     5---------- 
     6- Updated MDB2 package to version 2.5.0b1 
     7- Updated MDB2 pgsql, mysql, mysqli, sqlite drivers to version 1.5.0b1 
     8- Updated MDB2 mssql driver to version 1.3.0b1 
     9- Fixed identities saving when using MDB2 pgsql driver (#1485032) 
    310 
    4112008/05/01 (alec) 
  • program/lib/MDB2.php

    r95ebbc98 rd1403fd  
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: MDB2.php,v 1.307 2007/11/10 13:29:05 quipo Exp $ 
     46// $Id: MDB2.php,v 1.318 2008/03/08 14:18:38 quipo Exp $ 
    4747// 
    4848 
     
    101101define('MDB2_ERROR_LOADMODULE',         -34); 
    102102define('MDB2_ERROR_INSUFFICIENT_DATA',  -35); 
     103define('MDB2_ERROR_NO_PERMISSION',      -36); 
     104 
    103105// }}} 
    104106// {{{ Verbose constants 
     
    565567    function apiVersion() 
    566568    { 
    567         return '2.5.0a2'; 
     569        return '2.5.0b1'; 
    568570    } 
    569571 
     
    765767                MDB2_ERROR_TRUNCATED          => 'truncated', 
    766768                MDB2_ERROR_DEADLOCK           => 'deadlock detected', 
     769                MDB2_ERROR_NO_PERMISSION      => 'no permission', 
    767770            ); 
    768771        } 
     
    889892                //e.g. "scott/tiger@//mymachine:1521/oracle" 
    890893                $proto_opts = $dsn; 
    891                 $dsn = null; 
     894                $dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1); 
    892895            } elseif (strpos($dsn, '/') !== false) { 
    893896                list($proto_opts, $dsn) = explode('/', $dsn, 2); 
     
    10961099        'replace' => false, 
    10971100        'sub_selects' => false, 
     1101        'triggers' => false, 
    10981102        'auto_increment' => false, 
    10991103        'primary_key' => false, 
     
    11431147     *  <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li> 
    11441148     *  <li>$options['bindname_format'] -> string: regular expression pattern for named parameters 
     1149     *  <li>$options['max_identifiers_length'] -> integer: max identifier length</li> 
    11451150     * </ul> 
    11461151     * 
     
    11911196        'lob_allow_url_include' => false, 
    11921197        'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)', 
     1198        'max_identifiers_length' => 30, 
    11931199    ); 
    11941200 
     
    22202226 
    22212227    // }}} 
     2228    // {{{ databaseExists() 
     2229 
     2230    /** 
     2231     * check if given database name is exists? 
     2232     * 
     2233     * @param string $name    name of the database that should be checked 
     2234     * 
     2235     * @return mixed true/false on success, a MDB2 error on failure 
     2236     * @access public 
     2237     */ 
     2238    function databaseExists($name) 
     2239    { 
     2240        return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 
     2241            'method not implemented', __FUNCTION__); 
     2242    } 
     2243 
     2244    // }}} 
    22222245    // {{{ setCharset($charset, $connection = null) 
    22232246 
     
    22782301        $previous_database_name = (isset($this->database_name)) ? $this->database_name : ''; 
    22792302        $this->database_name = $name; 
    2280         $this->disconnect(false); 
     2303        if (!empty($this->connected_database_name) && ($this->connected_database_name != $this->database_name)) { 
     2304            $this->disconnect(false); 
     2305        } 
    22812306        return $previous_database_name; 
    22822307    } 
     
    27962821                        'key value '.$name.' may not be NULL', __FUNCTION__); 
    27972822                } 
    2798                 $condition[] = $name . '=' . $value; 
     2823                $condition[] = $this->quoteIdentifier($name, true) . '=' . $value; 
    27992824            } 
    28002825        } 
     
    28162841 
    28172842        $condition = ' WHERE '.implode(' AND ', $condition); 
    2818         $query = "DELETE FROM $table$condition"; 
     2843        $query = 'DELETE FROM ' . $this->quoteIdentifier($table, true) . $condition; 
    28192844        $result =& $this->_doQuery($query, true, $connection); 
    28202845        if (!PEAR::isError($result)) { 
    28212846            $affected_rows = $this->_affectedRows($connection, $result); 
    2822             $insert = implode(', ', array_keys($values)); 
     2847            $insert = ''; 
     2848            foreach ($values as $key => $value) { 
     2849                $insert .= ($insert?', ':'') . $this->quoteIdentifier($key, true); 
     2850            } 
    28232851            $values = implode(', ', $values); 
    2824             $query = "INSERT INTO $table ($insert) VALUES ($values)"; 
     2852            $query = 'INSERT INTO '. $this->quoteIdentifier($table, true) . "($insert) VALUES ($values)"; 
    28252853            $result =& $this->_doQuery($query, true, $connection); 
    28262854            if (!PEAR::isError($result)) { 
     
    29993027                            } 
    30003028                        } 
    3001                     } while ($ignore['escape'] && $query[($end_quote - 1)] == $ignore['escape']); 
     3029                    } while ($ignore['escape'] && $query[($end_quote - 1)] == $ignore['escape'] && $end_quote-1 != $start_quote); 
    30023030                    $position = $end_quote + 1; 
    30033031                    return $position; 
     
    39814009        $parameters = array_keys($values); 
    39824010        foreach ($parameters as $key => $parameter) { 
     4011            $this->db->pushErrorHandling(PEAR_ERROR_RETURN); 
    39834012            $this->db->expectError(MDB2_ERROR_NOT_FOUND); 
    39844013            $err = $this->bindValue($parameter, $values[$parameter], $types[$key]); 
    39854014            $this->db->popExpect(); 
     4015            $this->db->popErrorHandling(); 
    39864016            if (PEAR::isError($err)) { 
    39874017                if ($err->getCode() == MDB2_ERROR_NOT_FOUND) { 
  • program/lib/MDB2/Driver/Datatype/Common.php

    r95ebbc98 rd1403fd  
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: Common.php,v 1.128 2007/11/09 20:54:58 quipo Exp $ 
     45// $Id: Common.php,v 1.137 2008/02/17 18:53:40 afz Exp $ 
    4646 
    4747require_once 'MDB2/LOB.php'; 
     
    498498            ' '.$this->_getCharsetFieldDeclaration($field['charset']); 
    499499 
     500        $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; 
    500501        $default = ''; 
    501502        if (array_key_exists('default', $field)) { 
     
    505506                    return $db; 
    506507                } 
    507                 if (empty($field['notnull'])) { 
    508                     $field['default'] = null; 
    509                 } else { 
    510                     $valid_default_values = $this->getValidTypes(); 
    511                     $field['default'] = $valid_default_values[$field['type']]; 
    512                 } 
    513                 if ($field['default'] === '' 
    514                     && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL) 
    515                 ) { 
     508                $valid_default_values = $this->getValidTypes(); 
     509                $field['default'] = $valid_default_values[$field['type']]; 
     510                if ($field['default'] === ''&& ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)) { 
    516511                    $field['default'] = ' '; 
    517512                } 
    518513            } 
    519             $default = ' DEFAULT '.$this->quote($field['default'], $field['type']); 
    520         } elseif (empty($field['notnull'])) { 
    521             $default = ' DEFAULT NULL'; 
    522         } 
    523  
    524         $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; 
    525          
     514            if (!is_null($field['default'])) { 
     515                $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']); 
     516            } 
     517        } 
     518 
    526519        $collation = empty($field['collation']) ? '' : 
    527520            ' '.$this->_getCollationFieldDeclaration($field['collation']); 
     521 
    528522        return $charset.$default.$notnull.$collation; 
    529523    } 
     
    14911485        $value = (string)$value; 
    14921486        $value = preg_replace('/[^\d\.,\-+eE]/', '', $value); 
    1493         if (preg_match('/[^.0-9]/', $value)) { 
     1487        if (preg_match('/[^\.\d]/', $value)) { 
    14941488            if (strpos($value, ',')) { 
    14951489                // 1000,00 
  • program/lib/MDB2/Driver/Datatype/mssql.php

    r95ebbc98 rd1403fd  
    4545// +----------------------------------------------------------------------+ 
    4646// 
    47 // $Id: mssql.php,v 1.59 2007/12/03 20:59:50 quipo Exp $ 
     47// $Id: mssql.php,v 1.65 2008/02/19 14:54:17 afz Exp $ 
    4848// 
    4949 
     
    186186 
    187187    // }}} 
    188     // {{{ _getDeclaration() 
    189  
    190     /** 
    191      * Obtain DBMS specific SQL code portion needed to declare a generic type 
    192      * field to be used in statements like CREATE TABLE. 
    193      * 
    194      * @param string $name   name the field to be declared. 
    195      * @param array  $field  associative array with the name of the properties 
    196      *      of the field being declared as array indexes. Currently, the types 
    197      *      of supported field properties are as follows: 
    198      * 
    199      *      length 
    200      *          Integer value that determines the maximum length of the text 
    201      *          field. If this argument is missing the field should be 
    202      *          declared to have the longest length allowed by the DBMS. 
    203      * 
    204      *      default 
    205      *          Text value to be used as default for this field. 
    206      * 
    207      *      notnull 
    208      *          Boolean flag that indicates whether this field is constrained 
    209      *          to not be set to null. 
    210      * @return string  DBMS specific SQL code portion that should be used to 
    211      *      declare the specified field. 
    212      * @access protected 
    213      */ 
    214     function _getDeclarationOptions($field) 
    215     { 
    216         $charset = empty($field['charset']) ? '' : 
    217             ' '.$this->_getCharsetFieldDeclaration($field['charset']); 
    218  
    219         $default = ''; 
    220         if (array_key_exists('default', $field)) { 
    221             if ($field['default'] === '') { 
    222                 $db =& $this->getDBInstance(); 
    223                 if (PEAR::isError($db)) { 
    224                     return $db; 
    225                 } 
    226                 $field['default'] = empty($field['notnull']) 
    227                     ? null : $this->valid_default_values[$field['type']]; 
    228                 if ($field['default'] === '' 
    229                     && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL) 
    230                 ) { 
    231                     $field['default'] = ' '; 
    232                 } 
    233             } 
    234             $default = ' DEFAULT '.$this->quote($field['default'], $field['type']); 
    235         } elseif (empty($field['notnull'])) { 
    236             $default = ' DEFAULT NULL'; 
    237         } 
    238  
    239         $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; 
    240         if ($default == ' DEFAULT NULL' && $notnull == ' NULL') { 
    241             $notnull = ''; 
    242         } 
    243  
    244         $collation = empty($field['collation']) ? '' : 
    245             ' '.$this->_getCollationFieldDeclaration($field['collation']); 
    246         return $charset.$default.$notnull.$collation; 
    247     } 
    248  
    249     // }}} 
    250188    // {{{ _getIntegerDeclaration() 
    251189 
     
    283221        } 
    284222 
    285         $default = $autoinc = '';; 
     223        $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; 
     224        $default = $autoinc = ''; 
    286225        if (!empty($field['autoincrement'])) { 
    287226            $autoinc = ' IDENTITY PRIMARY KEY'; 
    288227        } elseif (array_key_exists('default', $field)) { 
    289228            if ($field['default'] === '') { 
    290                 $field['default'] = empty($field['notnull']) ? null : 0; 
    291             } 
    292             $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
    293         } elseif (empty($field['notnull'])) { 
    294             $default = ' DEFAULT NULL'; 
    295         } 
    296  
    297         $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; 
    298         if ($default == ' DEFAULT NULL' && $notnull == ' NULL') { 
    299             $notnull = ''; 
    300         } 
     229                $field['default'] = 0; 
     230            } 
     231            if (is_null($field['default'])) { 
     232                $default = ' DEFAULT (null)'; 
     233            } else { 
     234                $default = ' DEFAULT (' . $this->quote($field['default'], 'integer') . ')'; 
     235            } 
     236        } 
     237 
    301238        if (!empty($field['unsigned'])) { 
    302239            $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; 
    303240        } 
     241 
    304242        $name = $db->quoteIdentifier($name, true); 
    305         return $name.' '.$this->getTypeDeclaration($field).$default.$notnull.$autoinc; 
     243        return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc; 
    306244    } 
    307245 
     
    397335            return $value; 
    398336        } 
    399         $value = bin2hex("0x".$this->_readFile($value)); 
     337        $value = '0x'.bin2hex($this->_readFile($value)); 
    400338        return $value; 
    401339    } 
  • program/lib/MDB2/Driver/Datatype/mysql.php

    r95ebbc98 rd1403fd  
    44// | PHP versions 4 and 5                                                 | 
    55// +----------------------------------------------------------------------+ 
    6 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     6// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    77// | Stig. S. Bakken, Lukas Smith                                         | 
    88// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: mysql.php,v 1.62 2007/11/09 20:54:58 quipo Exp $ 
     46// $Id: mysql.php,v 1.65 2008/02/22 19:23:49 quipo Exp $ 
    4747// 
    4848 
     
    233233            } 
    234234            $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
    235         } elseif (empty($field['notnull'])) { 
    236             $default = ' DEFAULT NULL'; 
    237235        } 
    238236 
     
    241239        $name = $db->quoteIdentifier($name, true); 
    242240        return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; 
     241    } 
     242 
     243    // }}} 
     244    // {{{ _getFloatDeclaration() 
     245 
     246    /** 
     247     * Obtain DBMS specific SQL code portion needed to declare an float type 
     248     * field to be used in statements like CREATE TABLE. 
     249     * 
     250     * @param string  $name   name the field to be declared. 
     251     * @param string  $field  associative array with the name of the properties 
     252     *                        of the field being declared as array indexes. 
     253     *                        Currently, the types of supported field 
     254     *                        properties are as follows: 
     255     * 
     256     *                       unsigned 
     257     *                        Boolean flag that indicates whether the field 
     258     *                        should be declared as unsigned float if 
     259     *                        possible. 
     260     * 
     261     *                       default 
     262     *                        float value to be used as default for this 
     263     *                        field. 
     264     * 
     265     *                       notnull 
     266     *                        Boolean flag that indicates whether this field is 
     267     *                        constrained to not be set to null. 
     268     * @return string  DBMS specific SQL code portion that should be used to 
     269     *                 declare the specified field. 
     270     * @access protected 
     271     */ 
     272    function _getFloatDeclaration($name, $field) 
     273    { 
     274        // Since AUTO_INCREMENT can be used for integer or floating-point types, 
     275        // reuse the INTEGER declaration 
     276        // @see http://bugs.mysql.com/bug.php?id=31032 
     277        return $this->_getIntegerDeclaration($name, $field); 
     278    } 
     279 
     280    // }}} 
     281    // {{{ _getDecimalDeclaration() 
     282 
     283    /** 
     284     * Obtain DBMS specific SQL code portion needed to declare an decimal type 
     285     * field to be used in statements like CREATE TABLE. 
     286     * 
     287     * @param string  $name   name the field to be declared. 
     288     * @param string  $field  associative array with the name of the properties 
     289     *                        of the field being declared as array indexes. 
     290     *                        Currently, the types of supported field 
     291     *                        properties are as follows: 
     292     * 
     293     *                       unsigned 
     294     *                        Boolean flag that indicates whether the field 
     295     *                        should be declared as unsigned integer if 
     296     *                        possible. 
     297     * 
     298     *                       default 
     299     *                        Decimal value to be used as default for this 
     300     *                        field. 
     301     * 
     302     *                       notnull 
     303     *                        Boolean flag that indicates whether this field is 
     304     *                        constrained to not be set to null. 
     305     * @return string  DBMS specific SQL code portion that should be used to 
     306     *                 declare the specified field. 
     307     * @access protected 
     308     */ 
     309    function _getDecimalDeclaration($name, $field) 
     310    { 
     311        $db =& $this->getDBInstance(); 
     312        if (PEAR::isError($db)) { 
     313            return $db; 
     314        } 
     315 
     316        $default = ''; 
     317        if (array_key_exists('default', $field)) { 
     318            if ($field['default'] === '') { 
     319                $field['default'] = empty($field['notnull']) ? null : 0; 
     320            } 
     321            $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
     322        } elseif (empty($field['notnull'])) { 
     323            $default = ' DEFAULT NULL'; 
     324        } 
     325 
     326        $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; 
     327        $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; 
     328        $name = $db->quoteIdentifier($name, true); 
     329        return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull; 
    243330    } 
    244331 
  • program/lib/MDB2/Driver/Datatype/mysqli.php

    r95ebbc98 rd1403fd  
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: mysqli.php,v 1.61 2007/11/09 20:54:58 quipo Exp $ 
     46// $Id: mysqli.php,v 1.63 2008/02/22 19:23:49 quipo Exp $ 
    4747// 
    4848 
     
    233233            } 
    234234            $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
    235         } elseif (empty($field['notnull'])) { 
    236             $default = ' DEFAULT NULL'; 
    237235        } 
    238236 
     
    241239        $name = $db->quoteIdentifier($name, true); 
    242240        return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc; 
     241    } 
     242 
     243    // }}} 
     244    // {{{ _getFloatDeclaration() 
     245 
     246    /** 
     247     * Obtain DBMS specific SQL code portion needed to declare an float type 
     248     * field to be used in statements like CREATE TABLE. 
     249     * 
     250     * @param string  $name   name the field to be declared. 
     251     * @param string  $field  associative array with the name of the properties 
     252     *                        of the field being declared as array indexes. 
     253     *                        Currently, the types of supported field 
     254     *                        properties are as follows: 
     255     * 
     256     *                       unsigned 
     257     *                        Boolean flag that indicates whether the field 
     258     *                        should be declared as unsigned float if 
     259     *                        possible. 
     260     * 
     261     *                       default 
     262     *                        float value to be used as default for this 
     263     *                        field. 
     264     * 
     265     *                       notnull 
     266     *                        Boolean flag that indicates whether this field is 
     267     *                        constrained to not be set to null. 
     268     * @return string  DBMS specific SQL code portion that should be used to 
     269     *                 declare the specified field. 
     270     * @access protected 
     271     */ 
     272    function _getFloatDeclaration($name, $field) 
     273    { 
     274        // Since AUTO_INCREMENT can be used for integer or floating-point types, 
     275        // reuse the INTEGER declaration 
     276        // @see http://bugs.mysql.com/bug.php?id=31032 
     277        return $this->_getIntegerDeclaration($name, $field); 
     278    } 
     279 
     280    // }}} 
     281    // {{{ _getDecimalDeclaration() 
     282 
     283    /** 
     284     * Obtain DBMS specific SQL code portion needed to declare an decimal type 
     285     * field to be used in statements like CREATE TABLE. 
     286     * 
     287     * @param string  $name   name the field to be declared. 
     288     * @param string  $field  associative array with the name of the properties 
     289     *                        of the field being declared as array indexes. 
     290     *                        Currently, the types of supported field 
     291     *                        properties are as follows: 
     292     * 
     293     *                       unsigned 
     294     *                        Boolean flag that indicates whether the field 
     295     *                        should be declared as unsigned integer if 
     296     *                        possible. 
     297     * 
     298     *                       default 
     299     *                        Decimal value to be used as default for this 
     300     *                        field. 
     301     * 
     302     *                       notnull 
     303     *                        Boolean flag that indicates whether this field is 
     304     *                        constrained to not be set to null. 
     305     * @return string  DBMS specific SQL code portion that should be used to 
     306     *                 declare the specified field. 
     307     * @access protected 
     308     */ 
     309    function _getDecimalDeclaration($name, $field) 
     310    { 
     311        $db =& $this->getDBInstance(); 
     312        if (PEAR::isError($db)) { 
     313            return $db; 
     314        } 
     315 
     316        $default = ''; 
     317        if (array_key_exists('default', $field)) { 
     318            if ($field['default'] === '') { 
     319                $field['default'] = empty($field['notnull']) ? null : 0; 
     320            } 
     321            $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
     322        } elseif (empty($field['notnull'])) { 
     323            $default = ' DEFAULT NULL'; 
     324        } 
     325 
     326        $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; 
     327        $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED'; 
     328        $name = $db->quoteIdentifier($name, true); 
     329        return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull; 
    243330    } 
    244331 
     
    357444        case 'longtext': 
    358445        case 'text': 
    359         case 'text': 
    360446        case 'varchar': 
    361447            $fixed = false; 
  • program/lib/MDB2/Driver/Datatype/pgsql.php

    r95ebbc98 rd1403fd  
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: pgsql.php,v 1.88 2007/11/09 20:54:58 quipo Exp $ 
     45// $Id: pgsql.php,v 1.91 2008/03/09 12:28:08 quipo Exp $ 
    4646 
    4747require_once 'MDB2/Driver/Datatype/Common.php'; 
     
    218218            } 
    219219            $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
    220         } elseif (empty($field['notnull'])) { 
    221             $default = ' DEFAULT NULL'; 
    222220        } 
    223221 
     
    454452        case 'datetime': 
    455453        case 'timestamp': 
     454        case 'timestamptz': 
    456455            $type[] = 'timestamp'; 
    457456            $length = null; 
     
    462461            break; 
    463462        case 'float': 
     463        case 'float4': 
    464464        case 'float8': 
    465465        case 'double': 
  • program/lib/MDB2/Driver/Datatype/sqlite.php

    r95ebbc98 rd1403fd  
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: sqlite.php,v 1.65 2007/12/03 20:59:51 quipo Exp $ 
     46// $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $ 
    4747// 
    4848 
     
    213213            } 
    214214            $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 
    215         } elseif (empty($field['notnull'])) { 
    216             $default = ' DEFAULT NULL'; 
    217215        } 
    218216 
     
    395393                return $db; 
    396394            } 
    397  
    398395            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 
    399396                'unknown database attribute type: '.$db_type, __FUNCTION__); 
  • program/lib/MDB2/Driver/Function/Common.php

    r95ebbc98 rd1403fd  
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: Common.php,v 1.19 2007/09/09 13:47:36 quipo Exp $ 
     45// $Id: Common.php,v 1.21 2008/02/17 18:51:39 quipo Exp $ 
    4646// 
    4747 
     
    5858 * $mdb->loadModule('Function'); 
    5959 * 
    60  * @package MDB2 
     60 * @package  MDB2 
    6161 * @category Database 
    62  * @author  Lukas Smith <smith@pooteeweet.org> 
     62 * @author   Lukas Smith <smith@pooteeweet.org> 
    6363 */ 
    6464class MDB2_Driver_Function_Common extends MDB2_Module_Common 
     
    7575     * @param mixed $result_class string which specifies which result class to use 
    7676     * @param mixed $result_wrap_class string which specifies which class to wrap results in 
     77     * 
    7778     * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure 
    7879     * @access public 
     
    113114     * - CURRENT_DATE (date, DATE type) 
    114115     * - CURRENT_TIME (time, TIME type) 
     116     * 
     117     * @param string $type 'timestamp' | 'time' | 'date' 
    115118     * 
    116119     * @return string to call a variable with the current timestamp 
     
    131134 
    132135    // }}} 
     136    // {{{ unixtimestamp() 
     137 
     138    /** 
     139     * return string to call a function to get the unix timestamp from a iso timestamp 
     140     * 
     141     * @param string $expression 
     142     * 
     143     * @return string to call a variable with the timestamp 
     144     * @access public 
     145     */ 
     146    function unixtimestamp($expression) 
     147    { 
     148        $db =& $this->getDBInstance(); 
     149        if (PEAR::isError($db)) { 
     150            return $db; 
     151        } 
     152 
     153        $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 
     154            'method not implemented', __FUNCTION__); 
     155        return $error; 
     156    } 
     157 
     158    // }}} 
    133159    // {{{ substring() 
    134160 
     
    145171        } 
    146172        return "SUBSTRING($value FROM $position)"; 
     173    } 
     174 
     175    // }}} 
     176    // {{{ replace() 
     177 
     178    /** 
     179     * return string to call a function to get replace inside an SQL statement. 
     180     * 
     181     * @return string to call a function to get a replace 
     182     * @access public 
     183     */ 
     184    function replace($str, $from_str, $to_str) 
     185    { 
     186        return "REPLACE($str, $from_str , $to_str)"; 
    147187    } 
    148188 
     
    156196     * @param string $value2 
    157197     * @param string $values... 
     198     * 
    158199     * @return string to concatenate two strings 
    159200     * @access public 
     
    186227     * 
    187228     * @param string $expression 
     229     * 
    188230     * @return return string to lower case of an expression 
    189231     * @access public 
     
    201243     * 
    202244     * @param string $expression 
     245     * 
    203246     * @return return string to upper case of an expression 
    204247     * @access public 
     
    216259     * 
    217260     * @param string $expression 
     261     * 
    218262     * @return return string to get the string expression length 
    219263     * @access public 
  • program/lib/MDB2/Driver/Function/mssql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: mssql.php,v 1.15 2007/08/11 16:02:22 quipo Exp $ 
     45// $Id: mssql.php,v 1.16 2008/02/17 18:54:08 quipo Exp $ 
    4646// 
    4747 
     
    5858class MDB2_Driver_Function_mssql extends MDB2_Driver_Function_Common 
    5959{ 
    60      // }}} 
    6160    // {{{ executeStoredProc() 
    6261 
     
    107106            return 'GETDATE()'; 
    108107        } 
     108    } 
     109 
     110    // }}} 
     111    // {{{ unixtimestamp() 
     112 
     113    /** 
     114     * return string to call a function to get the unix timestamp from a iso timestamp 
     115     * 
     116     * @param string $expression 
     117     * 
     118     * @return string to call a variable with the timestamp 
     119     * @access public 
     120     */ 
     121    function unixtimestamp($expression) 
     122    { 
     123        return 'DATEDIFF(second, \'19700101\', '. $expression.') + DATEDIFF(second, GETDATE(), GETUTCDATE())'; 
    109124    } 
    110125 
  • program/lib/MDB2/Driver/Function/mysql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: mysql.php,v 1.11 2007/01/12 11:29:12 quipo Exp $ 
     45// $Id: mysql.php,v 1.12 2008/02/17 18:54:08 quipo Exp $ 
    4646// 
    4747 
     
    8585 
    8686    // }}} 
     87    // {{{ unixtimestamp() 
     88 
     89    /** 
     90     * return string to call a function to get the unix timestamp from a iso timestamp 
     91     * 
     92     * @param string $expression 
     93     * 
     94     * @return string to call a variable with the timestamp 
     95     * @access public 
     96     */ 
     97    function unixtimestamp($expression) 
     98    { 
     99        return 'UNIX_TIMESTAMP('. $expression.')'; 
     100    } 
     101 
     102    // }}} 
    87103    // {{{ concat() 
    88104 
  • program/lib/MDB2/Driver/Function/mysqli.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: mysqli.php,v 1.13 2007/01/12 11:29:12 quipo Exp $ 
     45// $Id: mysqli.php,v 1.14 2008/02/17 18:54:08 quipo Exp $ 
    4646// 
    4747 
     
    9393 
    9494    // }}} 
     95    // {{{ unixtimestamp() 
     96 
     97    /** 
     98     * return string to call a function to get the unix timestamp from a iso timestamp 
     99     * 
     100     * @param string $expression 
     101     * 
     102     * @return string to call a variable with the timestamp 
     103     * @access public 
     104     */ 
     105    function unixtimestamp($expression) 
     106    { 
     107        return 'UNIX_TIMESTAMP('. $expression.')'; 
     108    } 
     109 
     110    // }}} 
    95111    // {{{ concat() 
    96112 
  • program/lib/MDB2/Driver/Function/pgsql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: pgsql.php,v 1.9 2006/06/12 21:48:43 lsmith Exp $ 
     45// $Id: pgsql.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ 
    4646 
    4747require_once 'MDB2/Driver/Function/Common.php'; 
     
    8282    } 
    8383    // }}} 
     84    // {{{ unixtimestamp() 
     85 
     86    /** 
     87     * return string to call a function to get the unix timestamp from a iso timestamp 
     88     * 
     89     * @param string $expression 
     90     * 
     91     * @return string to call a variable with the timestamp 
     92     * @access public 
     93     */ 
     94    function unixtimestamp($expression) 
     95    { 
     96        return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', TIMESTAMP '. $expression.'))'; 
     97    } 
     98 
     99    // }}} 
    84100    // {{{ random() 
    85101 
  • program/lib/MDB2/Driver/Function/sqlite.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: sqlite.php,v 1.8 2006/06/13 22:55:55 lsmith Exp $ 
     45// $Id: sqlite.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ 
    4646// 
    4747 
     
    9191 
    9292    // }}} 
     93    // {{{ unixtimestamp() 
     94 
     95    /** 
     96     * return string to call a function to get the unix timestamp from a iso timestamp 
     97     * 
     98     * @param string $expression 
     99     * 
     100     * @return string to call a variable with the timestamp 
     101     * @access public 
     102     */ 
     103    function unixtimestamp($expression) 
     104    { 
     105        return 'strftime("%s",'. $expression.', "utc")'; 
     106    } 
     107 
     108    // }}} 
    93109    // {{{ substring() 
    94110 
     
    122138 
    123139    // }}} 
     140    // {{{ replace() 
     141 
     142    /** 
     143     * return string to call a function to get a replacement inside an SQL statement. 
     144     * 
     145     * @return string to call a function to get a replace 
     146     * @access public 
     147     */ 
     148    function replace($str, $from_str, $to_str) 
     149    { 
     150        $db =& $this->getDBInstance(); 
     151        if (PEAR::isError($db)) { 
     152            return $db; 
     153        } 
     154 
     155        $error =& $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 
     156            'method not implemented', __FUNCTION__); 
     157        return $error; 
     158    } 
     159 
     160    // }}} 
    124161} 
    125162?> 
  • program/lib/MDB2/Driver/Manager/Common.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4040// | POSSIBILITY OF SUCH DAMAGE.                                          | 
    4141// +----------------------------------------------------------------------+ 
    42 // | Author: Lukas Smith <smith@pooteeweet.org>                           | 
     42// | Authors: Lukas Smith <smith@pooteeweet.org>                          | 
     43// |          Lorenzo Alberton <l.alberton@quipo.it>                      | 
    4344// +----------------------------------------------------------------------+ 
    4445// 
    45 // $Id: Common.php,v 1.68 2007/12/03 20:59:15 quipo Exp $ 
     46// $Id: Common.php,v 1.71 2008/02/12 23:12:27 quipo Exp $ 
    4647// 
    4748 
     
    5051 * @category Database 
    5152 * @author   Lukas Smith <smith@pooteeweet.org> 
     53 * @author   Lorenzo Alberton <l.alberton@quipo.it> 
    5254 */ 
    5355 
     
    189191     */ 
    190192    function createDatabase($database, $options = array()) 
     193    { 
     194        $db =& $this->getDBInstance(); 
     195        if (PEAR::isError($db)) { 
     196            return $db; 
     197        } 
     198 
     199        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 
     200            'method not implemented', __FUNCTION__); 
     201    } 
     202 
     203    // }}} 
     204    // {{{ alterDatabase() 
     205 
     206    /** 
     207     * alter an existing database 
     208     * 
     209     * @param string $name    name of the database that should be created 
     210     * @param array  $options array with charset, collation info 
     211     * 
     212     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     213     * @access public 
     214     */ 
     215    function alterDatabase($database, $options = array()) 
    191216    { 
    192217        $db =& $this->getDBInstance(); 
     
    358383        $name = $db->quoteIdentifier($name, true); 
    359384        return $db->exec("DROP TABLE $name"); 
     385    } 
     386 
     387    // }}} 
     388    // {{{ truncateTable() 
     389 
     390    /** 
     391     * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, 
     392     * it falls back to a DELETE FROM TABLE query) 
     393     * 
     394     * @param string $name name of the table that should be truncated 
     395     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     396     * @access public 
     397     */ 
     398    function truncateTable($name) 
     399    { 
     400        $db =& $this->getDBInstance(); 
     401        if (PEAR::isError($db)) { 
     402            return $db; 
     403        } 
     404 
     405        $name = $db->quoteIdentifier($name, true); 
     406        return $db->exec("DELETE FROM $name"); 
     407    } 
     408 
     409    // }}} 
     410    // {{{ vacuum() 
     411 
     412    /** 
     413     * Optimize (vacuum) all the tables in the db (or only the specified table) 
     414     * and optionally run ANALYZE. 
     415     * 
     416     * @param string $table table name (all the tables if empty) 
     417     * @param array  $options an array with driver-specific options: 
     418     *               - timeout [int] (in seconds) [mssql-only] 
     419     *               - analyze [boolean] [pgsql and mysql] 
     420     *               - full [boolean] [pgsql-only] 
     421     *               - freeze [boolean] [pgsql-only] 
     422     * 
     423     * @return mixed MDB2_OK success, a MDB2 error on failure 
     424     * @access public 
     425     */ 
     426    function vacuum($table = null, $options = array()) 
     427    { 
     428        $db =& $this->getDBInstance(); 
     429        if (PEAR::isError($db)) { 
     430            return $db; 
     431        } 
     432 
     433        return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 
     434            'method not implemented', __FUNCTION__); 
    360435    } 
    361436 
  • program/lib/MDB2/Driver/Manager/mssql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4545// +----------------------------------------------------------------------+ 
    4646// 
    47 // $Id: mssql.php,v 1.93 2007/12/03 20:59:15 quipo Exp $ 
     47// $Id: mssql.php,v 1.109 2008/03/05 12:55:57 afz Exp $ 
    4848// 
    4949 
     
    9191        } 
    9292        return $db->standaloneQuery($query, null, true); 
     93    } 
     94 
     95    // }}} 
     96    // {{{ alterDatabase() 
     97 
     98    /** 
     99     * alter an existing database 
     100     * 
     101     * @param string $name    name of the database that is intended to be changed 
     102     * @param array  $options array with name, collation info 
     103     * 
     104     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     105     * @access public 
     106     */ 
     107    function alterDatabase($name, $options = array()) 
     108    { 
     109        $db =& $this->getDBInstance(); 
     110        if (PEAR::isError($db)) { 
     111            return $db; 
     112        } 
     113 
     114        $query = ''; 
     115        if (!empty($options['name'])) { 
     116            $query .= ' MODIFY NAME = ' .$db->quoteIdentifier($options['name'], true); 
     117        } 
     118        if (!empty($options['collation'])) { 
     119            $query .= ' COLLATE ' . $options['collation']; 
     120        } 
     121        if (!empty($query)) { 
     122            $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true) . $query; 
     123            return $db->standaloneQuery($query, null, true); 
     124        } 
     125        return MDB2_OK; 
    93126    } 
    94127 
     
    198231        } 
    199232        return parent::createTable($name, $fields, $options); 
     233    } 
     234 
     235    // }}} 
     236    // {{{ truncateTable() 
     237 
     238    /** 
     239     * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, 
     240     * it falls back to a DELETE FROM TABLE query) 
     241     * 
     242     * @param string $name name of the table that should be truncated 
     243     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     244     * @access public 
     245     */ 
     246    function truncateTable($name) 
     247    { 
     248        $db =& $this->getDBInstance(); 
     249        if (PEAR::isError($db)) { 
     250            return $db; 
     251        } 
     252 
     253        $name = $db->quoteIdentifier($name, true); 
     254        return $db->exec("TRUNCATE TABLE $name"); 
     255    } 
     256 
     257    // }}} 
     258    // {{{ vacuum() 
     259 
     260    /** 
     261     * Optimize (vacuum) all the tables in the db (or only the specified table) 
     262     * and optionally run ANALYZE. 
     263     * 
     264     * @param string $table table name (all the tables if empty) 
     265     * @param array  $options an array with driver-specific options: 
     266     *               - timeout [int] (in seconds) [mssql-only] 
     267     *               - analyze [boolean] [pgsql and mysql] 
     268     *               - full [boolean] [pgsql-only] 
     269     *               - freeze [boolean] [pgsql-only] 
     270     * 
     271     * NB: you have to run the NSControl Create utility to enable VACUUM 
     272     * 
     273     * @return mixed MDB2_OK success, a MDB2 error on failure 
     274     * @access public 
     275     */ 
     276    function vacuum($table = null, $options = array()) 
     277    { 
     278        $db =& $this->getDBInstance(); 
     279        if (PEAR::isError($db)) { 
     280            return $db; 
     281        } 
     282        $timeout = isset($options['timeout']) ? (int)$options['timeout'] : 300; 
     283 
     284        $query = 'NSControl Create'; 
     285        $result = $db->exec($query); 
     286        if (PEAR::isError($result)) { 
     287            return $result; 
     288        } 
     289 
     290        return $db->exec('EXEC NSVacuum '.$timeout); 
    200291    } 
    201292 
     
    299390            return $db; 
    300391        } 
     392        $name_quoted = $db->quoteIdentifier($name, true); 
    301393 
    302394        foreach ($changes as $change_name => $change) { 
    303395            switch ($change_name) { 
     396            case 'remove': 
     397            case 'rename': 
    304398            case 'add': 
     399            case 'change': 
     400            case 'name': 
    305401                break; 
    306             case 'remove': 
    307                 break; 
    308             case 'name': 
    309             case 'rename': 
    310             case 'change': 
    311402            default: 
    312403                return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, 
     
    319410        } 
    320411 
    321         $query = ''; 
    322         if (!empty($changes['add']) && is_array($changes['add'])) { 
    323             foreach ($changes['add'] as $field_name => $field) { 
    324                 if ($query) { 
    325                     $query.= ', '; 
    326                 } else { 
    327                     $query.= 'ADD COLUMN '; 
    328                 } 
    329                 $query.= $db->getDeclaration($field['type'], $field_name, $field); 
    330             } 
    331         } 
     412        $idxname_format = $db->getOption('idxname_format'); 
     413        $db->setOption('idxname_format', '%s'); 
    332414 
    333415        if (!empty($changes['remove']) && is_array($changes['remove'])) { 
     416            $result = $this->_dropConflictingIndices($name, array_keys($changes['remove'])); 
     417            if (PEAR::isError($result)) { 
     418                $db->setOption('idxname_format', $idxname_format); 
     419                return $result; 
     420            } 
     421            $result = $this->_dropConflictingConstraints($name, array_keys($changes['remove'])); 
     422            if (PEAR::isError($result)) { 
     423                $db->setOption('idxname_format', $idxname_format); 
     424                return $result; 
     425            } 
     426 
     427            $query = ''; 
    334428            foreach ($changes['remove'] as $field_name => $field) { 
    335429                if ($query) { 
     
    337431                } 
    338432                $field_name = $db->quoteIdentifier($field_name, true); 
    339                 $query.= 'DROP COLUMN ' . $field_name; 
    340             } 
    341         } 
    342  
    343         if (!$query) { 
    344             return MDB2_OK; 
    345         } 
    346  
    347         $name = $db->quoteIdentifier($name, true); 
    348         return $db->exec("ALTER TABLE $name $query"); 
     433                $query.= 'COLUMN ' . $field_name; 
     434            } 
     435 
     436            $result = $db->exec("ALTER TABLE $name_quoted DROP $query"); 
     437            if (PEAR::isError($result)) { 
     438                $db->setOption('idxname_format', $idxname_format); 
     439                return $result; 
     440            } 
     441        } 
     442 
     443        if (!empty($changes['rename']) && is_array($changes['rename'])) { 
     444            foreach ($changes['rename'] as $field_name => $field) { 
     445                $field_name = $db->quoteIdentifier($field_name, true); 
     446                $result = $db->exec("sp_rename '$name_quoted.$field_name', '".$field['name']."', 'COLUMN'"); 
     447                if (PEAR::isError($result)) { 
     448                    $db->setOption('idxname_format', $idxname_format); 
     449                    return $result; 
     450                } 
     451            } 
     452        } 
     453 
     454        if (!empty($changes['add']) && is_array($changes['add'])) { 
     455            $query = ''; 
     456            foreach ($changes['add'] as $field_name => $field) { 
     457                if ($query) { 
     458                    $query.= ', '; 
     459                } else { 
     460                    $query.= 'ADD '; 
     461                } 
     462                $query.= $db->getDeclaration($field['type'], $field_name, $field); 
     463            } 
     464 
     465            $result = $db->exec("ALTER TABLE $name_quoted $query"); 
     466            if (PEAR::isError($result)) { 
     467                $db->setOption('idxname_format', $idxname_format); 
     468                return $result; 
     469            } 
     470        } 
     471 
     472        $dropped_indices     = array(); 
     473        $dropped_constraints = array(); 
     474 
     475        if (!empty($changes['change']) && is_array($changes['change'])) { 
     476            $dropped = $this->_dropConflictingIndices($name, array_keys($changes['change'])); 
     477            if (PEAR::isError($dropped)) { 
     478                $db->setOption('idxname_format', $idxname_format); 
     479                return $dropped; 
     480            } 
     481            $dropped_indices = array_merge($dropped_indices, $dropped); 
     482            $dropped = $this->_dropConflictingConstraints($name, array_keys($changes['change'])); 
     483            if (PEAR::isError($dropped)) { 
     484                $db->setOption('idxname_format', $idxname_format); 
     485                return $dropped; 
     486            } 
     487            $dropped_constraints = array_merge($dropped_constraints, $dropped); 
     488 
     489            foreach ($changes['change'] as $field_name => $field) { 
     490                //MSSQL doesn't allow multiple ALTER COLUMNs in one query 
     491                $query = 'ALTER COLUMN '; 
     492 
     493                //MSSQL doesn't allow changing the DEFAULT value of a field in altering mode 
     494                if (array_key_exists('default', $field['definition'])) { 
     495                    unset($field['definition']['default']); 
     496                } 
     497 
     498                $query .= $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']); 
     499                $result = $db->exec("ALTER TABLE $name_quoted $query"); 
     500                if (PEAR::isError($result)) { 
     501                    $db->setOption('idxname_format', $idxname_format); 
     502                    return $result; 
     503                } 
     504            } 
     505        } 
     506 
     507        // restore the dropped conflicting indices and constraints 
     508        foreach ($dropped_indices as $index_name => $index) { 
     509            $result = $this->createIndex($name, $index_name, $index); 
     510            if (PEAR::isError($result)) { 
     511                $db->setOption('idxname_format', $idxname_format); 
     512                return $result; 
     513            } 
     514        } 
     515        foreach ($dropped_constraints as $constraint_name => $constraint) { 
     516            $result = $this->createConstraint($name, $constraint_name, $constraint); 
     517            if (PEAR::isError($result)) { 
     518                $db->setOption('idxname_format', $idxname_format); 
     519                return $result; 
     520            } 
     521        } 
     522 
     523        $db->setOption('idxname_format', $idxname_format); 
     524 
     525        if (!empty($changes['name'])) { 
     526            $new_name = $db->quoteIdentifier($changes['name'], true); 
     527            $result = $db->exec("sp_rename '$name_quoted', '$new_name'"); 
     528            if (PEAR::isError($result)) { 
     529                return $result; 
     530            } 
     531        } 
     532 
     533        return MDB2_OK; 
     534    } 
     535 
     536    // }}} 
     537    // {{{ _dropConflictingIndices() 
     538 
     539    /** 
     540     * Drop the indices that prevent a successful ALTER TABLE action 
     541     * 
     542     * @param string $table  table name 
     543     * @param array  $fields array of names of the fields affected by the change 
     544     * 
     545     * @return array dropped indices definitions 
     546     */ 
     547    function _dropConflictingIndices($table, $fields) 
     548    { 
     549        $db =& $this->getDBInstance(); 
     550        if (PEAR::isError($db)) { 
     551            return $db; 
     552        } 
     553 
     554        $dropped = array(); 
     555        $index_names = $this->listTableIndexes($table); 
     556        if (PEAR::isError($index_names)) { 
     557            return $index_names; 
     558        } 
     559        $db->loadModule('Reverse'); 
     560        $indexes = array(); 
     561        foreach ($index_names as $index_name) { 
     562                $idx_def = $db->reverse->getTableIndexDefinition($table, $index_name); 
     563            if (!PEAR::isError($idx_def)) { 
     564                $indexes[$index_name] = $idx_def; 
     565            } 
     566        } 
     567        foreach ($fields as $field_name) { 
     568            foreach ($indexes as $index_name => $index) { 
     569                if (!isset($dropped[$index_name]) && array_key_exists($field_name, $index['fields'])) { 
     570                    $dropped[$index_name] = $index; 
     571                    $result = $this->dropIndex($table, $index_name); 
     572                    if (PEAR::isError($result)) { 
     573                        return $result; 
     574                    } 
     575                } 
     576            } 
     577        } 
     578 
     579        return $dropped; 
     580    } 
     581 
     582    // }}} 
     583    // {{{ _dropConflictingConstraints() 
     584 
     585    /** 
     586     * Drop the constraints that prevent a successful ALTER TABLE action 
     587     * 
     588     * @param string $table  table name 
     589     * @param array  $fields array of names of the fields affected by the change 
     590     * 
     591     * @return array dropped constraints definitions 
     592     */ 
     593    function _dropConflictingConstraints($table, $fields) 
     594    { 
     595        $db =& $this->getDBInstance(); 
     596        if (PEAR::isError($db)) { 
     597            return $db; 
     598        } 
     599 
     600        $dropped = array(); 
     601        $constraint_names = $this->listTableConstraints($table); 
     602        if (PEAR::isError($constraint_names)) { 
     603            return $constraint_names; 
     604        } 
     605        $db->loadModule('Reverse'); 
     606        $constraints = array(); 
     607        foreach ($constraint_names as $constraint_name) { 
     608                $cons_def = $db->reverse->getTableConstraintDefinition($table, $constraint_name); 
     609            if (!PEAR::isError($cons_def)) { 
     610                $constraints[$constraint_name] = $cons_def; 
     611            } 
     612        } 
     613        foreach ($fields as $field_name) { 
     614            foreach ($constraints as $constraint_name => $constraint) { 
     615                if (!isset($dropped[$constraint_name]) && array_key_exists($field_name, $constraint['fields'])) { 
     616                    $dropped[$constraint_name] = $constraint; 
     617                    $result = $this->dropConstraint($table, $constraint_name); 
     618                    if (PEAR::isError($result)) { 
     619                        return $result; 
     620                    } 
     621                } 
     622            } 
     623            // also drop implicit DEFAULT constraints 
     624            $default = $this->_getTableFieldDefaultConstraint($table, $field_name); 
     625            if (!PEAR::isError($default) && !empty($default)) { 
     626                $result = $this->dropConstraint($table, $default); 
     627                if (PEAR::isError($result)) { 
     628                    return $result; 
     629                } 
     630            } 
     631        } 
     632 
     633        return $dropped; 
     634    } 
     635 
     636    // }}} 
     637    // {{{ _getTableFieldDefaultConstraint() 
     638 
     639    /** 
     640     * Get the default constraint for a table field 
     641     * 
     642     * @param string $table name of table that should be used in method 
     643     * @param string $field name of field that should be used in method 
     644     * 
     645     * @return mixed name of default constraint on success, a MDB2 error on failure 
     646     * @access private 
     647     */ 
     648    function _getTableFieldDefaultConstraint($table, $field) 
     649    { 
     650        $db =& $this->getDBInstance(); 
     651        if (PEAR::isError($db)) { 
     652            return $db; 
     653        } 
     654 
     655        $table = $db->quoteIdentifier($table, true); 
     656        $field = $db->quote($field, 'text'); 
     657        $query = "SELECT OBJECT_NAME(syscolumns.cdefault) 
     658                    FROM syscolumns 
     659                   WHERE syscolumns.id = object_id('$table') 
     660                     AND syscolumns.name = $field 
     661                     AND syscolumns.cdefault <> 0"; 
     662        return $db->queryOne($query); 
    349663    } 
    350664 
     
    401715            return $db; 
    402716        } 
    403          
     717 
    404718        $table = $db->quoteIdentifier($table, true); 
    405719        $columns = $db->queryCol("SELECT c.name 
     
    682996        } 
    683997        $table = $db->quoteIdentifier($table, true); 
    684          
     998 
    685999        $query = "SELECT c.constraint_name 
    6861000                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c 
     
    7121026     * create sequence 
    7131027     * 
    714      * @param string $seq_name  name of the sequence to be created 
    715      * @param string $start     start value of the sequence; default is 1 
     1028     * @param string $seq_name name of the sequence to be created 
     1029     * @param string $start    start value of the sequence; default is 1 
    7161030     * 
    7171031     * @return mixed MDB2_OK on success, a MDB2 error on failure 
  • program/lib/MDB2/Driver/Manager/mysql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: mysql.php,v 1.100 2007/12/03 20:59:15 quipo Exp $ 
     45// $Id: mysql.php,v 1.108 2008/03/11 19:58:12 quipo Exp $ 
    4646// 
    4747 
     
    8080        $query = 'CREATE DATABASE ' . $name; 
    8181        if (!empty($options['charset'])) { 
    82             $query .= ' DEFAULT CHARACTER SET ' . $options['charset']; 
     82            $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); 
    8383        } 
    8484        if (!empty($options['collation'])) { 
    85             $query .= ' COLLATE ' . $options['collation']; 
    86         } 
    87         $result = $db->exec($query); 
    88         if (PEAR::isError($result)) { 
    89             return $result; 
    90         } 
    91         return MDB2_OK; 
     85            $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); 
     86        } 
     87        return $db->standaloneQuery($query, null, true); 
     88    } 
     89 
     90    // }}} 
     91    // {{{ alterDatabase() 
     92 
     93    /** 
     94     * alter an existing database 
     95     * 
     96     * @param string $name    name of the database that is intended to be changed 
     97     * @param array  $options array with charset, collation info 
     98     * 
     99     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     100     * @access public 
     101     */ 
     102    function alterDatabase($name, $options = array()) 
     103    { 
     104        $db =& $this->getDBInstance(); 
     105        if (PEAR::isError($db)) { 
     106            return $db; 
     107        } 
     108 
     109        $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); 
     110        if (!empty($options['charset'])) { 
     111            $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); 
     112        } 
     113        if (!empty($options['collation'])) { 
     114            $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); 
     115        } 
     116        return $db->standaloneQuery($query, null, true); 
    92117    } 
    93118 
     
    111136        $name = $db->quoteIdentifier($name, true); 
    112137        $query = "DROP DATABASE $name"; 
    113         $result = $db->exec($query); 
    114         if (PEAR::isError($result)) { 
    115             return $result; 
    116         } 
    117         return MDB2_OK; 
     138        return $db->standaloneQuery($query, null, true); 
    118139    } 
    119140 
     
    189210        } 
    190211 
     212        // if we have an AUTO_INCREMENT column and a PK on more than one field, 
     213        // we have to handle it differently... 
     214        $autoincrement = null; 
     215        if (empty($options['primary'])) { 
     216            $pk_fields = array(); 
     217            foreach ($fields as $fieldname => $def) { 
     218                if (!empty($def['primary'])) { 
     219                    $pk_fields[$fieldname] = true; 
     220                } 
     221                if (!empty($def['autoincrement'])) { 
     222                    $autoincrement = $fieldname; 
     223                } 
     224            } 
     225            if (!is_null($autoincrement) && count($pk_fields) > 1) { 
     226                $options['primary'] = $pk_fields; 
     227            } else { 
     228                // the PK constraint is on max one field => OK 
     229                $autoincrement = null; 
     230            } 
     231        } 
     232 
    191233        $query = $this->_getCreateTableQuery($name, $fields, $options); 
    192234        if (PEAR::isError($query)) { 
    193235            return $query; 
     236        } 
     237 
     238        if (!is_null($autoincrement)) { 
     239            // we have to remove the PK clause added by _getIntegerDeclaration() 
     240            $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query); 
    194241        } 
    195242 
     
    223270        if (PEAR::isError($result)) { 
    224271            return $result; 
     272        } 
     273        return MDB2_OK; 
     274    } 
     275 
     276    // }}} 
     277    // {{{ dropTable() 
     278 
     279    /** 
     280     * drop an existing table 
     281     * 
     282     * @param string $name name of the table that should be dropped 
     283     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     284     * @access public 
     285     */ 
     286    function dropTable($name) 
     287    { 
     288        $db =& $this->getDBInstance(); 
     289        if (PEAR::isError($db)) { 
     290            return $db; 
     291        } 
     292 
     293        //delete the triggers associated to existing FK constraints 
     294        $constraints = $this->listTableConstraints($name); 
     295        if (!PEAR::isError($constraints) && !empty($constraints)) { 
     296            $db->loadModule('Reverse', null, true); 
     297            foreach ($constraints as $constraint) { 
     298                $definition = $db->reverse->getTableConstraintDefinition($name, $constraint); 
     299                if (!PEAR::isError($definition) && !empty($definition['foreign'])) { 
     300                    $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']); 
     301                    if (PEAR::isError($result)) { 
     302                        return $result; 
     303                    } 
     304                } 
     305            } 
     306        } 
     307 
     308        return parent::dropTable($name); 
     309    } 
     310 
     311    // }}} 
     312    // {{{ truncateTable() 
     313 
     314    /** 
     315     * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, 
     316     * it falls back to a DELETE FROM TABLE query) 
     317     * 
     318     * @param string $name name of the table that should be truncated 
     319     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     320     * @access public 
     321     */ 
     322    function truncateTable($name) 
     323    { 
     324        $db =& $this->getDBInstance(); 
     325        if (PEAR::isError($db)) { 
     326            return $db; 
     327        } 
     328 
     329        $name = $db->quoteIdentifier($name, true); 
     330        return $db->exec("TRUNCATE TABLE $name"); 
     331    } 
     332 
     333    // }}} 
     334    // {{{ vacuum() 
     335 
     336    /** 
     337     * Optimize (vacuum) all the tables in the db (or only the specified table) 
     338     * and optionally run ANALYZE. 
     339     * 
     340     * @param string $table table name (all the tables if empty) 
     341     * @param array  $options an array with driver-specific options: 
     342     *               - timeout [int] (in seconds) [mssql-only] 
     343     *               - analyze [boolean] [pgsql and mysql] 
     344     *               - full [boolean] [pgsql-only] 
     345     *               - freeze [boolean] [pgsql-only] 
     346     * 
     347     * @return mixed MDB2_OK success, a MDB2 error on failure 
     348     * @access public 
     349     */ 
     350    function vacuum($table = null, $options = array()) 
     351    { 
     352        $db =& $this->getDBInstance(); 
     353        if (PEAR::isError($db)) { 
     354            return $db; 
     355        } 
     356 
     357        if (empty($table)) { 
     358            $table = $this->listTables(); 
     359            if (PEAR::isError($table)) { 
     360                return $table; 
     361            } 
     362        } 
     363        if (is_array($table)) { 
     364            foreach (array_keys($table) as $k) { 
     365                $table[$k] = $db->quoteIdentifier($table[$k], true); 
     366            } 
     367            $table = implode(', ', $table); 
     368        } else { 
     369            $table = $db->quoteIdentifier($table, true); 
     370        } 
     371         
     372        $result = $db->exec('OPTIMIZE TABLE '.$table); 
     373        if (PEAR::isError($result)) { 
     374            return $result; 
     375        } 
     376        if (!empty($options['analyze'])) { 
     377            return $db->exec('ANALYZE TABLE '.$table); 
    225378        } 
    226379        return MDB2_OK; 
     
    630783     * 
    631784     * @author Leoncx 
    632      * @param string    $table         name of the table on which the index is to be created 
    633      * @param string    $name         name of the index to be created 
    634      * @param array     $definition        associative array that defines properties of the index to be created. 
    635      *                                 Currently, only one property named FIELDS is supported. This property 
    636      *                                 is also an associative with the names of the index fields as array 
    637      *                                 indexes. Each entry of this array is set to another type of associative 
    638      *                                 array that specifies properties of the index that are specific to 
    639      *                                 each field. 
    640      * 
    641      *                                Currently, only the sorting property is supported. It should be used 
    642      *                                 to define the sorting direction of the index. It may be set to either 
    643      *                                 ascending or descending. 
    644      * 
    645      *                                Not all DBMS support index sorting direction configuration. The DBMS 
    646      *                                 drivers of those that do not support it ignore this property. Use the 
    647      *                                 function supports() to determine whether the DBMS driver can manage indexes. 
    648      * 
    649      *                                 Example 
    650      *                                    array( 
    651      *                                        'fields' => array( 
    652      *                                            'user_name' => array( 
    653      *                                                'sorting' => 'ascending' 
    654      *                                                'length' => 10 
    655      *                                            ), 
    656      *                                            'last_login' => array() 
    657      *                                        ) 
     785     * @param string $table      name of the table on which the index is to be created 
     786     * @param string $name       name of the index to be created 
     787     * @param array  $definition associative array that defines properties of the index to be created. 
     788     *                           Currently, only one property named FIELDS is supported. This property 
     789     *                           is also an associative with the names of the index fields as array 
     790     *                           indexes. Each entry of this array is set to another type of associative 
     791     *                           array that specifies properties of the index that are specific to 
     792     *                           each field. 
     793     * 
     794     *                           Currently, only the sorting property is supported. It should be used 
     795     *                           to define the sorting direction of the index. It may be set to either 
     796     *                           ascending or descending. 
     797     * 
     798     *                           Not all DBMS support index sorting direction configuration. The DBMS 
     799     *                           drivers of those that do not support it ignore this property. Use the 
     800     *                           function supports() to determine whether the DBMS driver can manage indexes. 
     801     * 
     802     *                           Example 
     803     *                               array( 
     804     *                                   'fields' => array( 
     805     *                                       'user_name' => array( 
     806     *                                           'sorting' => 'ascending' 
     807     *                                           'length' => 10 
     808     *                                       ), 
     809     *                                       'last_login' => array() 
    658810     *                                    ) 
     811     *                                ) 
     812     * 
    659813     * @return mixed MDB2_OK on success, a MDB2 error on failure 
    660814     * @access public 
     
    801955        } 
    802956 
    803         $table = $db->quoteIdentifier($table, true); 
    804         $query = "ALTER TABLE $table ADD $type $name"; 
     957        $table_quoted = $db->quoteIdentifier($table, true); 
     958        $query = "ALTER TABLE $table_quoted ADD $type $name"; 
    805959        if (!empty($definition['foreign'])) { 
    806             $query .= ' FOREIGN KEY '; 
     960            $query .= ' FOREIGN KEY'; 
    807961        } 
    808962        $fields = array(); 
     
    820974            $query .= $this->_getAdvancedFKOptions($definition); 
    821975        } 
    822         return $db->exec($query); 
     976        $res = $db->exec($query); 
     977        if (PEAR::isError($res)) { 
     978            return $res; 
     979        } 
     980        if (!empty($definition['foreign'])) { 
     981            return $this->_createFKTriggers($table, array($name => $definition)); 
     982        } 
     983        return MDB2_OK; 
    823984    } 
    824985 
     
    8421003        } 
    8431004 
     1005        if ($primary || strtolower($name) == 'primary') { 
     1006            $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY'; 
     1007            return $db->exec($query); 
     1008        } 
     1009 
     1010        //is it a FK constraint? If so, also delete the associated triggers 
     1011        $db->loadModule('Reverse', null, true); 
     1012        $definition = $db->reverse->getTableConstraintDefinition($table, $name); 
     1013        if (!PEAR::isError($definition) && !empty($definition['foreign'])) { 
     1014            //first drop the FK enforcing triggers 
     1015            $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']); 
     1016            if (PEAR::isError($result)) { 
     1017                return $result; 
     1018            } 
     1019            //then drop the constraint itself 
     1020            $table = $db->quoteIdentifier($table, true); 
     1021            $name = $db->quoteIdentifier($db->getIndexName($name), true); 
     1022            $query = "ALTER TABLE $table DROP FOREIGN KEY $name"; 
     1023            return $db->exec($query); 
     1024        } 
     1025 
    8441026        $table = $db->quoteIdentifier($table, true); 
    845         if ($primary || strtolower($name) == 'primary') { 
    846             $query = "ALTER TABLE $table DROP PRIMARY KEY"; 
    847         } else { 
    848             $name = $db->quoteIdentifier($db->getIndexName($name), true); 
    849             $query = "ALTER TABLE $table DROP INDEX $name"; 
    850         } 
     1027        $name = $db->quoteIdentifier($db->getIndexName($name), true); 
     1028        $query = "ALTER TABLE $table DROP INDEX $name"; 
    8511029        return $db->exec($query); 
     1030    } 
     1031 
     1032    // }}} 
     1033    // {{{ _createFKTriggers() 
     1034 
     1035    /** 
     1036     * Create triggers to enforce the FOREIGN KEY constraint on the table 
     1037     * 
     1038     * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql, 
     1039     * we call a non-existent procedure to raise the FK violation message. 
     1040     * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877 
     1041     * 
     1042     * @param string $table        table name 
     1043     * @param array  $foreign_keys FOREIGN KEY definitions 
     1044     * 
     1045     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     1046     * @access private 
     1047     */ 
     1048    function _createFKTriggers($table, $foreign_keys) 
     1049    { 
     1050        $db =& $this->getDBInstance(); 
     1051        if (PEAR::isError($db)) { 
     1052            return $db; 
     1053        } 
     1054        // create triggers to enforce FOREIGN KEY constraints 
     1055        if ($db->supports('triggers') && !empty($foreign_keys)) { 
     1056            $table = $db->quoteIdentifier($table, true); 
     1057            foreach ($foreign_keys as $fkname => $fkdef) { 
     1058                if (empty($fkdef)) { 
     1059                    continue; 
     1060                } 
     1061                //set actions to 'RESTRICT' if not set 
     1062                $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']); 
     1063                $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']); 
     1064 
     1065                $trigger_names = array( 
     1066                    'insert'    => $fkname.'_insert_trg', 
     1067                    'update'    => $fkname.'_update_trg', 
     1068                    'pk_update' => $fkname.'_pk_update_trg', 
     1069                    'pk_delete' => $fkname.'_pk_delete_trg', 
     1070                ); 
     1071                $table_fields = array_keys($fkdef['fields']); 
     1072                $referenced_fields = array_keys($fkdef['references']['fields']); 
     1073 
     1074                //create the ON [UPDATE|DELETE] triggers on the primary table 
     1075                $restrict_action = ' IF (SELECT '; 
     1076                $aliased_fields = array(); 
     1077                foreach ($table_fields as $field) { 
     1078                    $aliased_fields[] = $table .'.'.$field .' AS '.$field; 
     1079                } 
     1080                $restrict_action .= implode(',', $aliased_fields) 
     1081                       .' FROM '.$table 
     1082                       .' WHERE '; 
     1083                $conditions  = array(); 
     1084                $new_values  = array(); 
     1085                $null_values = array(); 
     1086                for ($i=0; $i<count($table_fields); $i++) { 
     1087                    $conditions[]  = $table_fields[$i] .' = OLD.'.$referenced_fields[$i]; 
     1088                    $new_values[]  = $table_fields[$i] .' = NEW.'.$referenced_fields[$i]; 
     1089                    $null_values[] = $table_fields[$i] .' = NULL'; 
     1090                } 
     1091                $restrict_action .= implode(' AND ', $conditions).') IS NOT NULL' 
     1092                                .' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();' 
     1093                                .' END IF;'; 
     1094 
     1095                $cascade_action_update = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';'; 
     1096                $cascade_action_delete = 'DELETE FROM '.$table.' WHERE '.implode(' AND ', $conditions). ';'; 
     1097                $setnull_action        = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';'; 
     1098 
     1099                if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) { 
     1100                    $db->loadModule('Reverse', null, true); 
     1101                    $default_values = array(); 
     1102                    foreach ($table_fields as $table_field) { 
     1103                        $field_definition = $db->reverse->getTableFieldDefinition($table, $field); 
     1104                        if (PEAR::isError($field_definition)) { 
     1105                            return $field_definition; 
     1106                        } 
     1107                        $default_values[] = $table_field .' = '. $field_definition[0]['default']; 
     1108                    } 
     1109                    $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';'; 
     1110                } 
     1111 
     1112                $query = 'CREATE TRIGGER %s' 
     1113                        .' %s ON '.$fkdef['references']['table'] 
     1114                        .' FOR EACH ROW BEGIN ' 
     1115                        .' SET FOREIGN_KEY_CHECKS = 0; ';  //only really needed for ON UPDATE CASCADE 
     1116 
     1117                if ('CASCADE' == $fkdef['onupdate']) { 
     1118                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE',  'update') . $cascade_action_update; 
     1119                } elseif ('SET NULL' == $fkdef['onupdate']) { 
     1120                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action; 
     1121                } elseif ('SET DEFAULT' == $fkdef['onupdate']) { 
     1122                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action; 
     1123                } elseif ('NO ACTION' == $fkdef['onupdate']) { 
     1124                    $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update'); 
     1125                } else { 
     1126                    //'RESTRICT' 
     1127                    $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update'); 
     1128                } 
     1129                if ('CASCADE' == $fkdef['ondelete']) { 
     1130                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE',  'delete') . $cascade_action_delete; 
     1131                } elseif ('SET NULL' == $fkdef['ondelete']) { 
     1132                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action; 
     1133                } elseif ('SET DEFAULT' == $fkdef['ondelete']) { 
     1134                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action; 
     1135                } elseif ('NO ACTION' == $fkdef['ondelete']) { 
     1136                    $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete'); 
     1137                } else { 
     1138                    //'RESTRICT' 
     1139                    $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete'); 
     1140                } 
     1141                $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; 
     1142                $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; 
     1143 
     1144                $db->pushErrorHandling(PEAR_ERROR_RETURN); 
     1145                $db->expectError(MDB2_ERROR_CANNOT_CREATE); 
     1146                $result = $db->exec($sql_delete); 
     1147                $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table'; 
     1148                $db->popExpect(); 
     1149                $db->popErrorHandling(); 
     1150                if (PEAR::isError($result)) { 
     1151                    if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { 
     1152                        return $result; 
     1153                    } 
     1154                    $db->warnings[] = $expected_errmsg; 
     1155                } 
     1156                $db->pushErrorHandling(PEAR_ERROR_RETURN); 
     1157                $db->expectError(MDB2_ERROR_CANNOT_CREATE); 
     1158                $result = $db->exec($sql_update); 
     1159                $db->popExpect(); 
     1160                $db->popErrorHandling(); 
     1161                if (PEAR::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) { 
     1162                    if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { 
     1163                        return $result; 
     1164                    } 
     1165                    $db->warnings[] = $expected_errmsg; 
     1166                } 
     1167            } 
     1168        } 
     1169        return MDB2_OK; 
     1170    } 
     1171 
     1172    // }}} 
     1173    // {{{ _dropFKTriggers() 
     1174 
     1175    /** 
     1176     * Drop the triggers created to enforce the FOREIGN KEY constraint on the table 
     1177     * 
     1178     * @param string $table            table name 
     1179     * @param string $fkname           FOREIGN KEY constraint name 
     1180     * @param string $referenced_table referenced table name 
     1181     * 
     1182     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     1183     * @access private 
     1184     */ 
     1185    function _dropFKTriggers($table, $fkname, $referenced_table) 
     1186    { 
     1187        $db =& $this->getDBInstance(); 
     1188        if (PEAR::isError($db)) { 
     1189            return $db; 
     1190        } 
     1191 
     1192        $triggers  = $this->listTableTriggers($table); 
     1193        $triggers2 = $this->listTableTriggers($referenced_table); 
     1194        if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) { 
     1195            $triggers = array_merge($triggers, $triggers2); 
     1196            $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i'; 
     1197            foreach ($triggers as $trigger) { 
     1198                if (preg_match($pattern, $trigger)) { 
     1199                    $result = $db->exec('DROP TRIGGER '.$trigger); 
     1200                    if (PEAR::isError($result)) { 
     1201                        return $result; 
     1202                    } 
     1203                } 
     1204            } 
     1205        } 
     1206        return MDB2_OK; 
    8521207    } 
    8531208 
     
    9051260        $definition = $db->queryOne($query, 'text', 1); 
    9061261        if (!PEAR::isError($definition) && !empty($definition)) { 
    907             $pattern = '/\bCONSTRAINT\s+([^\s]+)\s+FOREIGN KEY\b/i'; 
    908             if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 1) { 
     1262            $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims'; 
     1263            if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) { 
    9091264                foreach ($matches[1] as $constraint) { 
    9101265                    $result[$constraint] = true; 
     
    9751330        } 
    9761331        $res = $db->exec($query); 
    977  
    9781332        if (PEAR::isError($res)) { 
    9791333            return $res; 
  • program/lib/MDB2/Driver/Manager/mysqli.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: mysqli.php,v 1.87 2007/12/03 20:59:15 quipo Exp $ 
     45// $Id: mysqli.php,v 1.95 2008/03/11 19:58:12 quipo Exp $ 
    4646// 
    4747 
     
    8080        $query = 'CREATE DATABASE ' . $name; 
    8181        if (!empty($options['charset'])) { 
    82             $query .= ' DEFAULT CHARACTER SET ' . $options['charset']; 
     82            $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); 
    8383        } 
    8484        if (!empty($options['collation'])) { 
    85             $query .= ' COLLATE ' . $options['collation']; 
    86         } 
    87         $result = $db->exec($query); 
    88         if (PEAR::isError($result)) { 
    89             return $result; 
    90         } 
    91         return MDB2_OK; 
     85            $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); 
     86        } 
     87        return $db->standaloneQuery($query, null, true); 
     88    } 
     89 
     90    // }}} 
     91    // {{{ alterDatabase() 
     92 
     93    /** 
     94     * alter an existing database 
     95     * 
     96     * @param string $name    name of the database that is intended to be changed 
     97     * @param array  $options array with charset, collation info 
     98     * 
     99     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     100     * @access public 
     101     */ 
     102    function alterDatabase($name, $options = array()) 
     103    { 
     104        $db =& $this->getDBInstance(); 
     105        if (PEAR::isError($db)) { 
     106            return $db; 
     107        } 
     108 
     109        $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); 
     110        if (!empty($options['charset'])) { 
     111            $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); 
     112        } 
     113        if (!empty($options['collation'])) { 
     114            $query .= ' COLLATE ' . $db->quote($options['collation'], 'text'); 
     115        } 
     116        return $db->standaloneQuery($query, null, true); 
    92117    } 
    93118 
     
    111136        $name = $db->quoteIdentifier($name, true); 
    112137        $query = "DROP DATABASE $name"; 
    113         $result = $db->exec($query); 
    114         if (PEAR::isError($result)) { 
    115             return $result; 
    116         } 
    117         return MDB2_OK; 
     138        return $db->standaloneQuery($query, null, true); 
    118139    } 
    119140 
     
    189210        } 
    190211 
     212        // if we have an AUTO_INCREMENT column and a PK on more than one field, 
     213        // we have to handle it differently... 
     214        $autoincrement = null; 
     215        if (empty($options['primary'])) { 
     216            $pk_fields = array(); 
     217            foreach ($fields as $fieldname => $def) { 
     218                if (!empty($def['primary'])) { 
     219                    $pk_fields[$fieldname] = true; 
     220                } 
     221                if (!empty($def['autoincrement'])) { 
     222                    $autoincrement = $fieldname; 
     223                } 
     224            } 
     225            if (!is_null($autoincrement) && count($pk_fields) > 1) { 
     226                $options['primary'] = $pk_fields; 
     227            } else { 
     228                // the PK constraint is on max one field => OK 
     229                $autoincrement = null; 
     230            } 
     231        } 
     232 
    191233        $query = $this->_getCreateTableQuery($name, $fields, $options); 
    192234        if (PEAR::isError($query)) { 
    193235            return $query; 
     236        } 
     237 
     238        if (!is_null($autoincrement)) { 
     239            // we have to remove the PK clause added by _getIntegerDeclaration() 
     240            $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query); 
    194241        } 
    195242 
     
    223270        if (PEAR::isError($result)) { 
    224271            return $result; 
     272        } 
     273        return MDB2_OK; 
     274    } 
     275 
     276    // }}} 
     277    // {{{ dropTable() 
     278 
     279    /** 
     280     * drop an existing table 
     281     * 
     282     * @param string $name name of the table that should be dropped 
     283     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     284     * @access public 
     285     */ 
     286    function dropTable($name) 
     287    { 
     288        $db =& $this->getDBInstance(); 
     289        if (PEAR::isError($db)) { 
     290            return $db; 
     291        } 
     292 
     293        //delete the triggers associated to existing FK constraints 
     294        $constraints = $this->listTableConstraints($name); 
     295        if (!PEAR::isError($constraints) && !empty($constraints)) { 
     296            $db->loadModule('Reverse', null, true); 
     297            foreach ($constraints as $constraint) { 
     298                $definition = $db->reverse->getTableConstraintDefinition($name, $constraint); 
     299                if (!PEAR::isError($definition) && !empty($definition['foreign'])) { 
     300                    $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']); 
     301                    if (PEAR::isError($result)) { 
     302                        return $result; 
     303                    } 
     304                } 
     305            } 
     306        } 
     307 
     308        return parent::dropTable($name); 
     309    } 
     310 
     311    // }}} 
     312    // {{{ truncateTable() 
     313 
     314    /** 
     315     * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, 
     316     * it falls back to a DELETE FROM TABLE query) 
     317     * 
     318     * @param string $name name of the table that should be truncated 
     319     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     320     * @access public 
     321     */ 
     322    function truncateTable($name) 
     323    { 
     324        $db =& $this->getDBInstance(); 
     325        if (PEAR::isError($db)) { 
     326            return $db; 
     327        } 
     328 
     329        $name = $db->quoteIdentifier($name, true); 
     330        return $db->exec("TRUNCATE TABLE $name"); 
     331    } 
     332 
     333    // }}} 
     334    // {{{ vacuum() 
     335 
     336    /** 
     337     * Optimize (vacuum) all the tables in the db (or only the specified table) 
     338     * and optionally run ANALYZE. 
     339     * 
     340     * @param string $table table name (all the tables if empty) 
     341     * @param array  $options an array with driver-specific options: 
     342     *               - timeout [int] (in seconds) [mssql-only] 
     343     *               - analyze [boolean] [pgsql and mysql] 
     344     *               - full [boolean] [pgsql-only] 
     345     *               - freeze [boolean] [pgsql-only] 
     346     * 
     347     * @return mixed MDB2_OK success, a MDB2 error on failure 
     348     * @access public 
     349     */ 
     350    function vacuum($table = null, $options = array()) 
     351    { 
     352        $db =& $this->getDBInstance(); 
     353        if (PEAR::isError($db)) { 
     354            return $db; 
     355        } 
     356 
     357        if (empty($table)) { 
     358            $table = $this->listTables(); 
     359            if (PEAR::isError($table)) { 
     360                return $table; 
     361            } 
     362        } 
     363        if (is_array($table)) { 
     364            foreach (array_keys($table) as $k) { 
     365                $table[$k] = $db->quoteIdentifier($table[$k], true); 
     366            } 
     367            $table = implode(', ', $table); 
     368        } else { 
     369            $table = $db->quoteIdentifier($table, true); 
     370        } 
     371 
     372        $result = $db->exec('OPTIMIZE TABLE '.$table); 
     373        if (PEAR::isError($result)) { 
     374            return $result; 
     375        } 
     376        if (!empty($options['analyze'])) { 
     377            return $db->exec('ANALYZE TABLE '.$table); 
    225378        } 
    226379        return MDB2_OK; 
     
    657810     *                                        ) 
    658811     *                                    ) 
     812     * 
    659813     * @return mixed MDB2_OK on success, a MDB2 error on failure 
    660814     * @access public 
     
    801955        } 
    802956 
    803         $table = $db->quoteIdentifier($table, true); 
    804         $query = "ALTER TABLE $table ADD $type $name"; 
     957        $table_quoted = $db->quoteIdentifier($table, true); 
     958        $query = "ALTER TABLE $table_quoted ADD $type $name"; 
    805959        if (!empty($definition['foreign'])) { 
    806             $query .= ' FOREIGN KEY '; 
     960            $query .= ' FOREIGN KEY'; 
    807961        } 
    808962        $fields = array(); 
     
    820974            $query .= $this->_getAdvancedFKOptions($definition); 
    821975        } 
    822         return $db->exec($query); 
     976        $res = $db->exec($query); 
     977        if (PEAR::isError($res)) { 
     978            return $res; 
     979        } 
     980        if (!empty($definition['foreign'])) { 
     981            return $this->_createFKTriggers($table, array($name => $definition)); 
     982        } 
     983        return MDB2_OK; 
    823984    } 
    824985 
     
    8411002            return $db; 
    8421003        } 
     1004         
     1005        if ($primary || strtolower($name) == 'primary') { 
     1006            $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY'; 
     1007            return $db->exec($query); 
     1008        } 
     1009         
     1010        //is it a FK constraint? If so, also delete the associated triggers 
     1011        $db->loadModule('Reverse', null, true); 
     1012        $definition = $db->reverse->getTableConstraintDefinition($table, $name); 
     1013        if (!PEAR::isError($definition) && !empty($definition['foreign'])) { 
     1014            //first drop the FK enforcing triggers 
     1015            $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']); 
     1016            if (PEAR::isError($result)) { 
     1017                return $result; 
     1018            } 
     1019            //then drop the constraint itself 
     1020            $table = $db->quoteIdentifier($table, true); 
     1021            $name = $db->quoteIdentifier($db->getIndexName($name), true); 
     1022            $query = "ALTER TABLE $table DROP FOREIGN KEY $name"; 
     1023            return $db->exec($query); 
     1024        } 
    8431025 
    8441026        $table = $db->quoteIdentifier($table, true); 
    845         if ($primary || strtolower($name) == 'primary') { 
    846             $query = "ALTER TABLE $table DROP PRIMARY KEY"; 
    847         } else { 
    848             $name = $db->quoteIdentifier($db->getIndexName($name), true); 
    849             $query = "ALTER TABLE $table DROP INDEX $name"; 
    850         } 
     1027        $name = $db->quoteIdentifier($db->getIndexName($name), true); 
     1028        $query = "ALTER TABLE $table DROP INDEX $name"; 
    8511029        return $db->exec($query); 
     1030    } 
     1031 
     1032    // }}} 
     1033    // {{{ _createFKTriggers() 
     1034 
     1035    /** 
     1036     * Create triggers to enforce the FOREIGN KEY constraint on the table 
     1037     * 
     1038     * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql, 
     1039     * we call a non-existent procedure to raise the FK violation message. 
     1040     * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877 
     1041     * 
     1042     * @param string $table        table name 
     1043     * @param array  $foreign_keys FOREIGN KEY definitions 
     1044     * 
     1045     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     1046     * @access private 
     1047     */ 
     1048    function _createFKTriggers($table, $foreign_keys) 
     1049    { 
     1050        $db =& $this->getDBInstance(); 
     1051        if (PEAR::isError($db)) { 
     1052            return $db; 
     1053        } 
     1054        // create triggers to enforce FOREIGN KEY constraints 
     1055        if ($db->supports('triggers') && !empty($foreign_keys)) { 
     1056            $table = $db->quoteIdentifier($table, true); 
     1057            foreach ($foreign_keys as $fkname => $fkdef) { 
     1058                if (empty($fkdef)) { 
     1059                    continue; 
     1060                } 
     1061                //set actions to 'RESTRICT' if not set 
     1062                $fkdef['onupdate'] = empty($fkdef['onupdate']) ? 'RESTRICT' : strtoupper($fkdef['onupdate']); 
     1063                $fkdef['ondelete'] = empty($fkdef['ondelete']) ? 'RESTRICT' : strtoupper($fkdef['ondelete']); 
     1064 
     1065                $trigger_names = array( 
     1066                    'insert'    => $fkname.'_insert_trg', 
     1067                    'update'    => $fkname.'_update_trg', 
     1068                    'pk_update' => $fkname.'_pk_update_trg', 
     1069                    'pk_delete' => $fkname.'_pk_delete_trg', 
     1070                ); 
     1071                $table_fields = array_keys($fkdef['fields']); 
     1072                $referenced_fields = array_keys($fkdef['references']['fields']); 
     1073 
     1074                //create the ON [UPDATE|DELETE] triggers on the primary table 
     1075                $restrict_action = ' IF (SELECT '; 
     1076                $aliased_fields = array(); 
     1077                foreach ($table_fields as $field) { 
     1078                    $aliased_fields[] = $table .'.'.$field .' AS '.$field; 
     1079                } 
     1080                $restrict_action .= implode(',', $aliased_fields) 
     1081                       .' FROM '.$table 
     1082                       .' WHERE '; 
     1083                $conditions  = array(); 
     1084                $new_values  = array(); 
     1085                $null_values = array(); 
     1086                for ($i=0; $i<count($table_fields); $i++) { 
     1087                    $conditions[]  = $table_fields[$i] .' = OLD.'.$referenced_fields[$i]; 
     1088                    $new_values[]  = $table_fields[$i] .' = NEW.'.$referenced_fields[$i]; 
     1089                    $null_values[] = $table_fields[$i] .' = NULL'; 
     1090                } 
     1091                $restrict_action .= implode(' AND ', $conditions).') IS NOT NULL' 
     1092                                .' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();' 
     1093                                .' END IF;'; 
     1094 
     1095                $cascade_action_update = 'UPDATE '.$table.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';'; 
     1096                $cascade_action_delete = 'DELETE FROM '.$table.' WHERE '.implode(' AND ', $conditions). ';'; 
     1097                $setnull_action        = 'UPDATE '.$table.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';'; 
     1098 
     1099                if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) { 
     1100                    $db->loadModule('Reverse', null, true); 
     1101                    $default_values = array(); 
     1102                    foreach ($table_fields as $table_field) { 
     1103                        $field_definition = $db->reverse->getTableFieldDefinition($table, $field); 
     1104                        if (PEAR::isError($field_definition)) { 
     1105                            return $field_definition; 
     1106                        } 
     1107                        $default_values[] = $table_field .' = '. $field_definition[0]['default']; 
     1108                    } 
     1109                    $setdefault_action = 'UPDATE '.$table.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';'; 
     1110                } 
     1111 
     1112                $query = 'CREATE TRIGGER %s' 
     1113                        .' %s ON '.$fkdef['references']['table'] 
     1114                        .' FOR EACH ROW BEGIN ' 
     1115                        .' SET FOREIGN_KEY_CHECKS = 0; ';  //only really needed for ON UPDATE CASCADE 
     1116 
     1117                if ('CASCADE' == $fkdef['onupdate']) { 
     1118                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE',  'update') . $cascade_action_update; 
     1119                } elseif ('SET NULL' == $fkdef['onupdate']) { 
     1120                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action; 
     1121                } elseif ('SET DEFAULT' == $fkdef['onupdate']) { 
     1122                    $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action; 
     1123                } elseif ('NO ACTION' == $fkdef['onupdate']) { 
     1124                    $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'AFTER UPDATE', 'update'); 
     1125                } else { 
     1126                    //'RESTRICT' 
     1127                    $sql_update = sprintf($query.$restrict_action, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update'); 
     1128                } 
     1129                if ('CASCADE' == $fkdef['ondelete']) { 
     1130                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE',  'delete') . $cascade_action_delete; 
     1131                } elseif ('SET NULL' == $fkdef['ondelete']) { 
     1132                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action; 
     1133                } elseif ('SET DEFAULT' == $fkdef['ondelete']) { 
     1134                    $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action; 
     1135                } elseif ('NO ACTION' == $fkdef['ondelete']) { 
     1136                    $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete'); 
     1137                } else { 
     1138                    //'RESTRICT' 
     1139                    $sql_delete = sprintf($query.$restrict_action, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete'); 
     1140                } 
     1141                $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; 
     1142                $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;'; 
     1143 
     1144                $db->pushErrorHandling(PEAR_ERROR_RETURN); 
     1145                $db->expectError(MDB2_ERROR_CANNOT_CREATE);  
     1146                $result = $db->exec($sql_delete); 
     1147                $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table'; 
     1148                $db->popExpect(); 
     1149                $db->popErrorHandling(); 
     1150                if (PEAR::isError($result)) { 
     1151                    if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { 
     1152                        return $result; 
     1153                    } 
     1154                    $db->warnings[] = $expected_errmsg; 
     1155                } 
     1156                $db->pushErrorHandling(PEAR_ERROR_RETURN); 
     1157                $db->expectError(MDB2_ERROR_CANNOT_CREATE); 
     1158                $result = $db->exec($sql_update); 
     1159                $db->popExpect(); 
     1160                $db->popErrorHandling(); 
     1161                if (PEAR::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) { 
     1162                    if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) { 
     1163                        return $result; 
     1164                    } 
     1165                    $db->warnings[] = $expected_errmsg; 
     1166                } 
     1167            } 
     1168        } 
     1169        return MDB2_OK; 
     1170    } 
     1171 
     1172    // }}} 
     1173    // {{{ _dropFKTriggers() 
     1174 
     1175    /** 
     1176     * Drop the triggers created to enforce the FOREIGN KEY constraint on the table 
     1177     * 
     1178     * @param string $table            table name 
     1179     * @param string $fkname           FOREIGN KEY constraint name 
     1180     * @param string $referenced_table referenced table name 
     1181     * 
     1182     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     1183     * @access private 
     1184     */ 
     1185    function _dropFKTriggers($table, $fkname, $referenced_table) 
     1186    { 
     1187        $db =& $this->getDBInstance(); 
     1188        if (PEAR::isError($db)) { 
     1189            return $db; 
     1190        } 
     1191 
     1192        $triggers  = $this->listTableTriggers($table); 
     1193        $triggers2 = $this->listTableTriggers($referenced_table); 
     1194        if (!PEAR::isError($triggers2) && !PEAR::isError($triggers)) { 
     1195            $triggers = array_merge($triggers, $triggers2); 
     1196            $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i'; 
     1197            foreach ($triggers as $trigger) { 
     1198                if (preg_match($pattern, $trigger)) { 
     1199                    $result = $db->exec('DROP TRIGGER '.$trigger); 
     1200                    if (PEAR::isError($result)) { 
     1201                        return $result; 
     1202                    } 
     1203                } 
     1204            } 
     1205        } 
     1206        return MDB2_OK; 
    8521207    } 
    8531208 
     
    9051260        $definition = $db->queryOne($query, 'text', 1); 
    9061261        if (!PEAR::isError($definition) && !empty($definition)) { 
    907             $pattern = '/\bCONSTRAINT\s+([^\s]+)\s+FOREIGN KEY\b/i'; 
    908             if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 1) { 
     1262            $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims'; 
     1263            if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) { 
    9091264                foreach ($matches[1] as $constraint) { 
    9101265                    $result[$constraint] = true; 
     
    9701325        } 
    9711326 
    972         if (!empty($options_strings)) { 
    973             $query.= ' '.implode(' ', $options_strings); 
    974         } 
    975  
    9761327        $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))"; 
    9771328        if (!empty($options_strings)) { 
  • program/lib/MDB2/Driver/Manager/pgsql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: pgsql.php,v 1.74 2007/12/03 20:59:15 quipo Exp $ 
     45// $Id: pgsql.php,v 1.82 2008/03/05 12:55:57 afz Exp $ 
    4646 
    4747require_once 'MDB2/Driver/Manager/Common.php'; 
     
    8383 
    8484    // }}} 
     85    // {{{ alterDatabase() 
     86 
     87    /** 
     88     * alter an existing database 
     89     * 
     90     * @param string $name    name of the database that is intended to be changed 
     91     * @param array  $options array with name, owner info 
     92     * 
     93     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     94     * @access public 
     95     */ 
     96    function alterDatabase($name, $options = array()) 
     97    { 
     98        $db =& $this->getDBInstance(); 
     99        if (PEAR::isError($db)) { 
     100            return $db; 
     101        } 
     102 
     103        $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true); 
     104        if (!empty($options['name'])) { 
     105            $query .= ' RENAME TO ' . $options['name']; 
     106        } 
     107        if (!empty($options['owner'])) { 
     108            $query .= ' OWNER TO ' . $options['owner']; 
     109        } 
     110        return $db->standaloneQuery($query, null, true); 
     111    } 
     112 
     113    // }}} 
    85114    // {{{ dropDatabase() 
    86115 
     
    100129 
    101130        $name = $db->quoteIdentifier($name, true); 
    102         return $db->standaloneQuery("DROP DATABASE $name", null, true); 
     131        $query = "DROP DATABASE $name"; 
     132        return $db->standaloneQuery($query, null, true); 
    103133    } 
    104134 
     
    137167        } 
    138168        return $query; 
     169    } 
     170 
     171    // }}} 
     172    // {{{ truncateTable() 
     173 
     174    /** 
     175     * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported, 
     176     * it falls back to a DELETE FROM TABLE query) 
     177     * 
     178     * @param string $name name of the table that should be truncated 
     179     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     180     * @access public 
     181     */ 
     182    function truncateTable($name) 
     183    { 
     184        $db =& $this->getDBInstance(); 
     185        if (PEAR::isError($db)) { 
     186            return $db; 
     187        } 
     188 
     189        $name = $db->quoteIdentifier($name, true); 
     190        return $db->exec("TRUNCATE TABLE $name"); 
     191    } 
     192 
     193    // }}} 
     194    // {{{ vacuum() 
     195 
     196    /** 
     197     * Optimize (vacuum) all the tables in the db (or only the specified table) 
     198     * and optionally run ANALYZE. 
     199     * 
     200     * @param string $table table name (all the tables if empty) 
     201     * @param array  $options an array with driver-specific options: 
     202     *               - timeout [int] (in seconds) [mssql-only] 
     203     *               - analyze [boolean] [pgsql and mysql] 
     204     *               - full [boolean] [pgsql-only] 
     205     *               - freeze [boolean] [pgsql-only] 
     206     * 
     207     * @return mixed MDB2_OK success, a MDB2 error on failure 
     208     * @access public 
     209     */ 
     210    function vacuum($table = null, $options = array()) 
     211    { 
     212        $db =& $this->getDBInstance(); 
     213        if (PEAR::isError($db)) { 
     214            return $db; 
     215        } 
     216        $query = 'VACUUM'; 
     217 
     218        if (!empty($options['full'])) { 
     219            $query .= ' FULL'; 
     220        } 
     221        if (!empty($options['freeze'])) { 
     222            $query .= ' FREEZE'; 
     223        } 
     224        if (!empty($options['analyze'])) { 
     225            $query .= ' ANALYZE'; 
     226        } 
     227 
     228        if (!empty($table)) { 
     229            $query .= ' '.$db->quoteIdentifier($table, true); 
     230        } 
     231        return $db->exec($query); 
    139232    } 
    140233 
     
    257350        } 
    258351 
    259         if (!empty($changes['add']) && is_array($changes['add'])) { 
    260             foreach ($changes['add'] as $field_name => $field) { 
    261                 $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); 
     352        if (!empty($changes['remove']) && is_array($changes['remove'])) { 
     353            foreach ($changes['remove'] as $field_name => $field) { 
     354                $field_name = $db->quoteIdentifier($field_name, true); 
     355                $query = 'DROP ' . $field_name; 
    262356                $result = $db->exec("ALTER TABLE $name $query"); 
    263357                if (PEAR::isError($result)) { 
     
    267361        } 
    268362 
    269         if (!empty($changes['remove']) && is_array($changes['remove'])) { 
    270             foreach ($changes['remove'] as $field_name => $field) { 
     363        if (!empty($changes['rename']) && is_array($changes['rename'])) { 
     364            foreach ($changes['rename'] as $field_name => $field) { 
    271365                $field_name = $db->quoteIdentifier($field_name, true); 
    272                 $query = 'DROP ' . $field_name; 
     366                $result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true)); 
     367                if (PEAR::isError($result)) { 
     368                    return $result; 
     369                } 
     370            } 
     371        } 
     372 
     373        if (!empty($changes['add']) && is_array($changes['add'])) { 
     374            foreach ($changes['add'] as $field_name => $field) { 
     375                $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field); 
    273376                $result = $db->exec("ALTER TABLE $name $query"); 
    274377                if (PEAR::isError($result)) { 
     
    314417        } 
    315418 
    316         if (!empty($changes['rename']) && is_array($changes['rename'])) { 
    317             foreach ($changes['rename'] as $field_name => $field) { 
    318                 $field_name = $db->quoteIdentifier($field_name, true); 
    319                 $result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true)); 
    320                 if (PEAR::isError($result)) { 
    321                     return $result; 
    322                 } 
    323             } 
    324         } 
    325  
    326419        $name = $db->quoteIdentifier($name, true); 
    327420        if (!empty($changes['name'])) { 
     
    663756 
    664757        $table = $db->quote($table, 'text'); 
    665         $subquery = "SELECT indexrelid FROM pg_index, pg_class"; 
    666         $subquery.= " WHERE pg_class.relname=$table AND pg_class.oid=pg_index.indrelid AND (indisunique = 't' OR indisprimary = 't')"; 
    667         $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)"; 
     758        $query = 'SELECT conname 
     759                    FROM pg_constraint, pg_class 
     760                   WHERE pg_constraint.conrelid = pg_class.oid 
     761                     AND relname = ' .$table; 
    668762        $constraints = $db->queryCol($query); 
    669763        if (PEAR::isError($constraints)) { 
  • program/lib/MDB2/Driver/Manager/sqlite.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith, Lorenzo Alberton                       | 
    77// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: sqlite.php,v 1.72 2007/12/03 20:59:15 quipo Exp $ 
     46// $Id: sqlite.php,v 1.74 2008/03/05 11:08:53 quipo Exp $ 
    4747// 
    4848 
     
    402402        $name = $db->quoteIdentifier($name, true); 
    403403        return $db->exec("DROP TABLE $name"); 
     404    } 
     405 
     406    // }}} 
     407    // {{{ vacuum() 
     408 
     409    /** 
     410     * Optimize (vacuum) all the tables in the db (or only the specified table) 
     411     * and optionally run ANALYZE. 
     412     * 
     413     * @param string $table table name (all the tables if empty) 
     414     * @param array  $options an array with driver-specific options: 
     415     *               - timeout [int] (in seconds) [mssql-only] 
     416     *               - analyze [boolean] [pgsql and mysql] 
     417     *               - full [boolean] [pgsql-only] 
     418     *               - freeze [boolean] [pgsql-only] 
     419     * 
     420     * @return mixed MDB2_OK success, a MDB2 error on failure 
     421     * @access public 
     422     */ 
     423    function vacuum($table = null, $options = array()) 
     424    { 
     425        $db =& $this->getDBInstance(); 
     426        if (PEAR::isError($db)) { 
     427            return $db; 
     428        } 
     429 
     430        $query = 'VACUUM'; 
     431        if (!empty($table)) { 
     432            $query .= ' '.$db->quoteIdentifier($table, true); 
     433        } 
     434        return $db->exec($query); 
    404435    } 
    405436 
     
    12081239            return $table_def; 
    12091240        } 
    1210         if (preg_match("/\bPRIMARY\s+KEY\b\s*\(([^)]+)/i", $table_def, $tmp)) { 
     1241        if (preg_match("/\bPRIMARY\s+KEY\b/i", $table_def, $tmp)) { 
    12111242            $result['primary'] = true; 
    12121243        } 
  • program/lib/MDB2/Driver/Reverse/Common.php

    r95ebbc98 rd1403fd  
    4343// +----------------------------------------------------------------------+ 
    4444// 
    45 // $Id: Common.php,v 1.41 2007/09/09 13:47:36 quipo Exp $ 
     45// $Id: Common.php,v 1.42 2008/01/12 12:50:58 quipo Exp $ 
    4646// 
    4747 
     
    467467        } 
    468468 
     469        $res = array(); 
     470 
    469471        if ($mode) { 
    470472            $res['num_fields'] = count($fields); 
  • program/lib/MDB2/Driver/Reverse/mssql.php

    r95ebbc98 rd1403fd  
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: mssql.php,v 1.48 2007/11/25 13:38:29 quipo Exp $ 
     46// $Id: mssql.php,v 1.49 2008/02/17 15:30:57 quipo Exp $ 
    4747// 
    4848 
     
    455455        $trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text'); 
    456456        if (!PEAR::isError($trg_body)) { 
    457             $def['trigger_body'] = implode('', $trg_body); 
     457            $def['trigger_body'] = implode(' ', $trg_body); 
    458458        } 
    459459        return $def; 
  • program/lib/MDB2/Driver/Reverse/pgsql.php

    r95ebbc98 rd1403fd  
    33// | PHP versions 4 and 5                                                 | 
    44// +----------------------------------------------------------------------+ 
    5 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     5// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    66// | Stig. S. Bakken, Lukas Smith                                         | 
    77// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: pgsql.php,v 1.68 2007/11/25 13:38:29 quipo Exp $ 
     46// $Id: pgsql.php,v 1.70 2008/03/13 20:38:09 quipo Exp $ 
    4747 
    4848require_once 'MDB2/Driver/Reverse/Common.php'; 
     
    359359                        FROM pg_constraint c 
    360360                   LEFT JOIN pg_class t  ON c.confrelid  = t.oid 
    361                    LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey) 
     361                   LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey) 
    362362                       WHERE c.conname = %s 
    363363                         AND t.relname = ' . $db->quote($definition['references']['table'], 'text'); 
     
    425425                            WHEN 12 THEN 'INSERT, DELETE' 
    426426                         END AS trigger_event, 
    427                          trg.tgenabled AS trigger_enabled, 
     427                         CASE trg.tgenabled 
     428                            WHEN 'O' THEN 't' 
     429                            ELSE trg.tgenabled 
     430                         END AS trigger_enabled, 
    428431                         obj_description(trg.oid, 'pg_trigger') AS trigger_comment 
    429432                    FROM pg_trigger trg, 
  • program/lib/MDB2/Driver/Reverse/sqlite.php

    r95ebbc98 rd1403fd  
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: sqlite.php,v 1.78 2007/12/01 10:46:13 quipo Exp $ 
     46// $Id: sqlite.php,v 1.79 2008/03/05 11:08:53 quipo Exp $ 
    4747// 
    4848 
     
    394394                    return $definition; 
    395395                } 
     396                if (preg_match("/\"([^\"]+)\"[^\,\"]+\bPRIMARY\s+KEY\b[^\,\)]*/i", $sql, $tmp)) { 
     397                    $definition['primary'] = true; 
     398                    $definition['fields'] = array(); 
     399                    $column_names = split(',', $tmp[1]); 
     400                    $colpos = 1; 
     401                    foreach ($column_names as $column_name) { 
     402                        $definition['fields'][trim($column_name)] = array( 
     403                            'position' => $colpos++ 
     404                        ); 
     405                    } 
     406                    return $definition; 
     407                } 
    396408            } else { 
    397409                // search in table definition for FOREIGN KEYs 
  • program/lib/MDB2/Driver/mssql.php

    r95ebbc98 rd1403fd  
    44// | PHP versions 4 and 5                                                 | 
    55// +----------------------------------------------------------------------+ 
    6 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     6// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    77// | Stig. S. Bakken, Lukas Smith, Frank M. Kromann                       | 
    88// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: mssql.php,v 1.161 2007/11/18 17:52:00 quipo Exp $ 
     46// $Id: mssql.php,v 1.174 2008/03/08 14:18:39 quipo Exp $ 
    4747// 
    4848// {{{ Class MDB2_Driver_mssql 
     
    8787        $this->supported['replace'] = 'emulated'; 
    8888        $this->supported['sub_selects'] = true; 
     89        $this->supported['triggers'] = true; 
    8990        $this->supported['auto_increment'] = true; 
    9091        $this->supported['primary_key'] = true; 
     
    9495        $this->supported['new_link'] = true; 
    9596 
     97        $this->options['DBA_username'] = false; 
     98        $this->options['DBA_password'] = false; 
    9699        $this->options['database_device'] = false; 
    97100        $this->options['database_size'] = false; 
     101        $this->options['max_identifiers_length'] = 128; // MS Access: 64 
    98102    } 
    99103 
     
    108112     * @access public 
    109113     */ 
    110     function errorInfo($error = null) 
    111     { 
     114    function errorInfo($error = null, $connection = null) 
     115    { 
     116        if (is_null($connection)) { 
     117            $connection = $this->connection; 
     118        } 
     119 
    112120        $native_code = null; 
    113         if ($this->connection) { 
    114             $result = @mssql_query('select @@ERROR as ErrorCode', $this->connection); 
     121        if ($connection) { 
     122            $result = @mssql_query('select @@ERROR as ErrorCode', $connection); 
    115123            if ($result) { 
    116124                $native_code = @mssql_result($result, 0, 0); 
     
    137145                    515   => MDB2_ERROR_CONSTRAINT_NOT_NULL, 
    138146                    547   => MDB2_ERROR_CONSTRAINT, 
     147                    911   => MDB2_ERROR_NOT_FOUND, 
    139148                    1018  => MDB2_ERROR_SYNTAX, 
    140149                    1035  => MDB2_ERROR_SYNTAX, 
     150                    1801  => MDB2_ERROR_ALREADY_EXISTS, 
    141151                    1913  => MDB2_ERROR_ALREADY_EXISTS, 
    142152                    2209  => MDB2_ERROR_SYNTAX, 
     
    297307 
    298308    // }}} 
     309    // {{{ _doConnect() 
     310 
     311    /** 
     312     * do the grunt work of the connect 
     313     * 
     314     * @return connection on success or MDB2 Error Object on failure 
     315     * @access protected 
     316     */ 
     317    function _doConnect($username, $password, $persistent = false) 
     318    { 
     319        if (!PEAR::loadExtension($this->phptype) && !PEAR::loadExtension('sybase_ct')) { 
     320            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 
     321                'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); 
     322        } 
     323 
     324        $params = array( 
     325            $this->dsn['hostspec'] ? $this->dsn['hostspec'] : 'localhost', 
     326            $username ? $username : null, 
     327            $password ? $password : null, 
     328        ); 
     329        if ($this->dsn['port']) { 
     330            $params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port']; 
     331        } 
     332        if (!$persistent) { 
     333            if (isset($this->dsn['new_link']) 
     334                && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) 
     335            ) { 
     336                $params[] = true; 
     337            } else { 
     338                $params[] = false; 
     339            } 
     340        } 
     341 
     342        $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect'; 
     343 
     344        $connection = @call_user_func_array($connect_function, $params); 
     345        if ($connection <= 0) { 
     346            return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, 
     347                'unable to establish a connection', __FUNCTION__, __FUNCTION__); 
     348        } 
     349 
     350        @mssql_query('SET ANSI_NULL_DFLT_ON ON', $connection); 
     351 
     352        if (!empty($this->dsn['charset'])) { 
     353            $result = $this->setCharset($this->dsn['charset'], $connection); 
     354            if (PEAR::isError($result)) { 
     355                return $result; 
     356            } 
     357        } 
     358 
     359       if ((bool)ini_get('mssql.datetimeconvert')) { 
     360           @ini_set('mssql.datetimeconvert', '0'); 
     361       } 
     362 
     363       if (empty($this->dsn['disable_iso_date'])) { 
     364           @mssql_query('SET DATEFORMAT ymd', $connection); 
     365       } 
     366 
     367       return $connection; 
     368    } 
     369 
     370    // }}} 
    299371    // {{{ connect() 
    300372 
     
    316388        } 
    317389 
    318         if (!PEAR::loadExtension($this->phptype)) { 
    319             return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 
    320                 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); 
    321         } 
    322  
    323         $params = array( 
    324             $this->dsn['hostspec'] ? $this->dsn['hostspec'] : 'localhost', 
    325             $this->dsn['username'] ? $this->dsn['username'] : null, 
    326             $this->dsn['password'] ? $this->dsn['password'] : null, 
     390        $connection = $this->_doConnect( 
     391            $this->dsn['username'], 
     392            $this->dsn['password'], 
     393            $this->options['persistent'] 
    327394        ); 
    328         if ($this->dsn['port']) { 
    329             $params[0].= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':').$this->dsn['port']; 
    330         } 
    331         if (!$this->options['persistent']) { 
    332             if (isset($this->dsn['new_link']) 
    333                 && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) 
    334             ) { 
    335                 $params[] = true; 
    336             } else { 
    337                 $params[] = false; 
    338             } 
    339         } 
    340  
    341         $connect_function = $this->options['persistent'] ? 'mssql_pconnect' : 'mssql_connect'; 
    342  
    343         $connection = @call_user_func_array($connect_function, $params); 
    344         if ($connection <= 0) { 
    345             return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, 
    346                 'unable to establish a connection', __FUNCTION__, __FUNCTION__); 
    347         } 
    348  
    349         if (!empty($this->dsn['charset'])) { 
    350             $result = $this->setCharset($this->dsn['charset'], $connection); 
    351             if (PEAR::isError($result)) { 
    352                 return $result; 
    353             } 
    354         } 
    355  
    356        if ((bool)ini_get('mssql.datetimeconvert')) { 
    357            @ini_set('mssql.datetimeconvert', '0'); 
    358        } 
    359  
    360        if (empty($this->dsn['disable_iso_date'])) { 
    361            @mssql_query('SET DATEFORMAT ymd', $connection); 
    362        } 
     395        if (PEAR::isError($connection)) { 
     396            return $connection; 
     397        } 
    363398 
    364399        $this->connection = $connection; 
     
    380415 
    381416        return MDB2_OK; 
     417    } 
     418 
     419    // }}} 
     420    // {{{ databaseExists() 
     421 
     422    /** 
     423     * check if given database name is exists? 
     424     * 
     425     * @param string $name    name of the database that should be checked 
     426     * 
     427     * @return mixed true/false on success, a MDB2 error on failure 
     428     * @access public 
     429     */ 
     430    function databaseExists($name) 
     431    { 
     432        $connection = $this->_doConnect($this->dsn['username'], 
     433                                        $this->dsn['password'], 
     434                                        $this->options['persistent']); 
     435        if (PEAR::isError($connection)) { 
     436            return $connection; 
     437        } 
     438 
     439        $result = @mssql_select_db($name, $connection); 
     440        $errorInfo = $this->errorInfo(null, $connection); 
     441        @mssql_close($connection); 
     442        if (!$result) { 
     443            if ($errorInfo[0] != MDB2_ERROR_NOT_FOUND) { 
     444            exit; 
     445                $result = $this->raiseError($errorInfo[0], null, null, $errorInfo[2], __FUNCTION__); 
     446                return $result; 
     447            } 
     448            $result = false; 
     449        } 
     450 
     451        return $result; 
    382452    } 
    383453 
     
    418488 
    419489    // }}} 
     490    // {{{ standaloneQuery() 
     491 
     492   /** 
     493     * execute a query as DBA 
     494     * 
     495     * @param string $query the SQL query 
     496     * @param mixed   $types  array that contains the types of the columns in 
     497     *                        the result set 
     498     * @param boolean $is_manip  if the query is a manipulation query 
     499     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     500     * @access public 
     501     */ 
     502    function &standaloneQuery($query, $types = null, $is_manip = false) 
     503    { 
     504        $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; 
     505        $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; 
     506        $connection = $this->_doConnect($user, $pass, $this->options['persistent']); 
     507        if (PEAR::isError($connection)) { 
     508            return $connection; 
     509        } 
     510 
     511        $offset = $this->offset; 
     512        $limit = $this->limit; 
     513        $this->offset = $this->limit = 0; 
     514        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); 
     515         
     516        $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); 
     517        if (!PEAR::isError($result)) { 
     518            $result = $this->_affectedRows($connection, $result); 
     519        } 
     520 
     521        @mssql_close($connection); 
     522        return $result; 
     523    } 
     524 
     525    // }}} 
    420526    // {{{ _doQuery() 
    421527 
     
    547653        $this->connected_server_info = $server_info; 
    548654        if (!$native && !PEAR::isError($server_info)) { 
    549             if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $server_info, $tmp)) { 
     655            if (preg_match('/(\d+)\.(\d+)\.(\d+)/', $server_info, $tmp)) { 
    550656                $server_info = array( 
    551657                    'major' => $tmp[1], 
     
    610716        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); 
    611717        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); 
     718        $this->pushErrorHandling(PEAR_ERROR_RETURN); 
    612719        $this->expectError(MDB2_ERROR_NOSUCHTABLE); 
    613720         
     
    622729        $result =& $this->_doQuery($query, true); 
    623730        $this->popExpect(); 
     731        $this->popErrorHandling(); 
    624732        if (PEAR::isError($result)) { 
    625733            if ($ondemand && !$this->_checkSequence($sequence_name)) { 
     
    670778     * @param string $table name of the table into which a new row was inserted 
    671779     * @param string $field name of the field into which a new row was inserted 
     780     * 
    672781     * @return mixed MDB2 Error Object or id 
    673782     * @access public 
     
    679788           && $server_info['major'] >= 8 
    680789        ) { 
    681             $query = "SELECT SCOPE_IDENTITY()"; 
     790            $query = "SELECT IDENT_CURRENT('$table')"; 
    682791        } else { 
    683792            $query = "SELECT @@IDENTITY"; 
     793            if (!is_null($table)) { 
     794                $query .= ' FROM '.$this->quoteIdentifier($table, true); 
     795            } 
    684796        } 
    685797 
  • program/lib/MDB2/Driver/mysql.php

    r95ebbc98 rd1403fd  
    44// | PHP versions 4 and 5                                                 | 
    55// +----------------------------------------------------------------------+ 
    6 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     6// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    77// | Stig. S. Bakken, Lukas Smith                                         | 
    88// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: mysql.php,v 1.195 2007/11/10 13:27:03 quipo Exp $ 
     46// $Id: mysql.php,v 1.208 2008/03/13 03:31:55 afz Exp $ 
    4747// 
    4848 
     
    9999        $this->supported['replace'] = true; 
    100100        $this->supported['sub_selects'] = 'emulated'; 
     101        $this->supported['triggers'] = false; 
    101102        $this->supported['auto_increment'] = true; 
    102103        $this->supported['primary_key'] = true; 
     
    107108        $this->supported['new_link'] = true; 
    108109 
     110        $this->options['DBA_username'] = false; 
     111        $this->options['DBA_password'] = false; 
    109112        $this->options['default_table_type'] = ''; 
     113        $this->options['max_identifiers_length'] = 64; 
     114 
     115        $this->_reCheckSupportedOptions(); 
     116    } 
     117 
     118    // }}} 
     119    // {{{ _reCheckSupportedOptions() 
     120     
     121    /** 
     122     * If the user changes certain options, other capabilities may depend 
     123     * on the new settings, so we need to check them (again). 
     124     * 
     125     * @access private 
     126     */ 
     127    function _reCheckSupportedOptions() 
     128    { 
     129        $this->supported['transactions'] = $this->options['use_transactions']; 
     130        $this->supported['savepoints']   = $this->options['use_transactions']; 
     131        if ($this->options['default_table_type']) { 
     132            switch (strtoupper($this->options['default_table_type'])) { 
     133            case 'BLACKHOLE': 
     134            case 'MEMORY': 
     135            case 'ARCHIVE': 
     136            case 'CSV': 
     137            case 'HEAP': 
     138            case 'ISAM': 
     139            case 'MERGE': 
     140            case 'MRG_ISAM': 
     141            case 'ISAM': 
     142            case 'MRG_MYISAM': 
     143            case 'MYISAM': 
     144                $this->supported['savepoints']   = false; 
     145                $this->supported['transactions'] = false; 
     146                $this->warnings[] = $this->options['default_table_type'] . 
     147                    ' is not a supported default table type'; 
     148                break; 
     149            } 
     150        } 
     151    } 
     152 
     153    // }}} 
     154    // {{{ function setOption($option, $value) 
     155 
     156    /** 
     157     * set the option for the db class 
     158     * 
     159     * @param   string  option name 
     160     * @param   mixed   value for the option 
     161     * 
     162     * @return  mixed   MDB2_OK or MDB2 Error Object 
     163     * 
     164     * @access  public 
     165     */ 
     166    function setOption($option, $value) 
     167    { 
     168        $res = parent::setOption($option, $value); 
     169        $this->_reCheckSupportedOptions(); 
    110170    } 
    111171 
     
    178238                    1217 => MDB2_ERROR_CONSTRAINT, 
    179239                    1227 => MDB2_ERROR_ACCESS_VIOLATION, 
     240                    1235 => MDB2_ERROR_CANNOT_CREATE, 
    180241                    1299 => MDB2_ERROR_INVALID_DATE, 
    181242                    1300 => MDB2_ERROR_INVALID, 
     
    196257                    1546 => MDB2_ERROR_CONSTRAINT, 
    197258                    1582 => MDB2_ERROR_CONSTRAINT, 
     259                    2003 => MDB2_ERROR_CONNECT_FAILED, 
     260                    2019 => MDB2_ERROR_INVALID, 
    198261                ); 
    199262            } 
     
    423486 
    424487    // }}} 
    425     // {{{ connect() 
    426  
    427     /** 
    428      * Connect to the database 
    429      * 
    430      * @return true on success, MDB2 Error Object on failure 
    431      */ 
    432     function connect() 
    433     { 
    434         if (is_resource($this->connection)) { 
    435             //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 
    436             if (MDB2::areEquals($this->connected_dsn, $this->dsn) 
    437                 && $this->opened_persistent == $this->options['persistent'] 
    438                 && $this->connected_database_name == $this->database_name 
    439             ) { 
    440                 return MDB2_OK; 
    441             } 
    442             $this->disconnect(false); 
    443         } 
    444  
     488    // {{{ _doConnect() 
     489 
     490    /** 
     491     * do the grunt work of the connect 
     492     * 
     493     * @return connection on success or MDB2 Error Object on failure 
     494     * @access protected 
     495     */ 
     496    function _doConnect($username, $password, $persistent = false) 
     497    { 
    445498        if (!PEAR::loadExtension($this->phptype)) { 
    446499            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 
     
    458511            } 
    459512        } 
    460         $params[] = $this->dsn['username'] ? $this->dsn['username'] : null; 
    461         $params[] = $this->dsn['password'] ? $this->dsn['password'] : null; 
    462         if (!$this->options['persistent']) { 
     513        $params[] = $username ? $username : null; 
     514        $params[] = $password ? $password : null; 
     515        if (!$persistent) { 
    463516            if (isset($this->dsn['new_link']) 
    464517                && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) 
     
    473526                ? $this->dsn['client_flags'] : null; 
    474527        } 
    475         $connect_function = $this->options['persistent'] ? 'mysql_pconnect' : 'mysql_connect'; 
     528        $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; 
    476529 
    477530        $connection = @call_user_func_array($connect_function, $params); 
     
    489542            $result = $this->setCharset($this->dsn['charset'], $connection); 
    490543            if (PEAR::isError($result)) { 
     544                $this->disconnect(false); 
    491545                return $result; 
    492546            } 
     547        } 
     548 
     549        return $connection; 
     550    } 
     551 
     552    // }}} 
     553    // {{{ connect() 
     554 
     555    /** 
     556     * Connect to the database 
     557     * 
     558     * @return MDB2_OK on success, MDB2 Error Object on failure 
     559     * @access public 
     560     */ 
     561    function connect() 
     562    { 
     563        if (is_resource($this->connection)) { 
     564            //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0 
     565            if (MDB2::areEquals($this->connected_dsn, $this->dsn) 
     566                && $this->opened_persistent == $this->options['persistent'] 
     567            ) { 
     568                return MDB2_OK; 
     569            } 
     570            $this->disconnect(false); 
     571        } 
     572 
     573        $connection = $this->_doConnect( 
     574            $this->dsn['username'], 
     575            $this->dsn['password'], 
     576            $this->options['persistent'] 
     577        ); 
     578        if (PEAR::isError($connection)) { 
     579            return $connection; 
    493580        } 
    494581 
     
    510597        } 
    511598 
    512         $this->supported['transactions'] = $this->options['use_transactions']; 
    513         if ($this->options['default_table_type']) { 
    514             switch (strtoupper($this->options['default_table_type'])) { 
    515             case 'BLACKHOLE': 
    516             case 'MEMORY': 
    517             case 'ARCHIVE': 
    518             case 'CSV': 
    519             case 'HEAP': 
    520             case 'ISAM': 
    521             case 'MERGE': 
    522             case 'MRG_ISAM': 
    523             case 'ISAM': 
    524             case 'MRG_MYISAM': 
    525             case 'MYISAM': 
    526                 $this->supported['transactions'] = false; 
    527                 $this->warnings[] = $this->options['default_table_type'] . 
    528                     ' is not a supported default table type'; 
    529                 break; 
    530             } 
    531         } 
    532          
    533599        $this->_getServerCapabilities(); 
    534600 
     
    542608     * Set the charset on the current connection 
    543609     * 
    544      * @param string    charset 
     610     * @param string    charset (or array(charset, collation)) 
    545611     * @param resource  connection handle 
    546612     * 
     
    555621            } 
    556622        } 
     623        $collation = null; 
     624        if (is_array($charset) && 2 == count($charset)) { 
     625            $collation = array_pop($charset); 
     626            $charset   = array_pop($charset); 
     627        } 
    557628        $query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'"; 
     629        if (!is_null($collation)) { 
     630            $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; 
     631        } 
    558632        return $this->_doQuery($query, true, $connection); 
     633    } 
     634 
     635    // }}} 
     636    // {{{ databaseExists() 
     637 
     638    /** 
     639     * check if given database name is exists? 
     640     * 
     641     * @param string $name    name of the database that should be checked 
     642     * 
     643     * @return mixed true/false on success, a MDB2 error on failure 
     644     * @access public 
     645     */ 
     646    function databaseExists($name) 
     647    { 
     648        $connection = $this->_doConnect($this->dsn['username'], 
     649                                        $this->dsn['password'], 
     650                                        $this->options['persistent']); 
     651        if (PEAR::isError($connection)) { 
     652            return $connection; 
     653        } 
     654 
     655        $result = @mysql_select_db($name, $connection); 
     656        @mysql_close($connection); 
     657 
     658        return $result; 
    559659    } 
    560660 
     
    595695 
    596696    // }}} 
     697    // {{{ standaloneQuery() 
     698 
     699   /** 
     700     * execute a query as DBA 
     701     * 
     702     * @param string $query the SQL query 
     703     * @param mixed   $types  array that contains the types of the columns in 
     704     *                        the result set 
     705     * @param boolean $is_manip  if the query is a manipulation query 
     706     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     707     * @access public 
     708     */ 
     709    function &standaloneQuery($query, $types = null, $is_manip = false) 
     710    { 
     711        $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; 
     712        $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; 
     713        $connection = $this->_doConnect($user, $pass, $this->options['persistent']); 
     714        if (PEAR::isError($connection)) { 
     715            return $connection; 
     716        } 
     717 
     718        $offset = $this->offset; 
     719        $limit = $this->limit; 
     720        $this->offset = $this->limit = 0; 
     721        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); 
     722         
     723        $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); 
     724        if (!PEAR::isError($result)) { 
     725            $result = $this->_affectedRows($connection, $result); 
     726        } 
     727 
     728        @mysql_close($connection); 
     729        return $result; 
     730    } 
     731 
     732    // }}} 
    597733    // {{{ _doQuery() 
    598734 
     
    794930            $this->supported['sub_selects'] = 'emulated'; 
    795931            $this->supported['prepared_statements'] = 'emulated'; 
     932            $this->supported['triggers'] = false; 
    796933            $this->start_transaction = false; 
    797934            $this->varchar_max_length = 255; 
     
    799936            $server_info = $this->getServerVersion(); 
    800937            if (is_array($server_info)) { 
    801                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.0', '<')) { 
     938                $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch']; 
     939 
     940                if (!version_compare($server_version, '4.1.0', '<')) { 
    802941                    $this->supported['sub_selects'] = true; 
    803942                    $this->supported['prepared_statements'] = true; 
    804943                } 
    805944 
    806                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.14', '<') 
    807                     || !version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.1', '<') 
    808                 ) { 
    809                     $this->supported['savepoints'] = true; 
     945                // SAVEPOINTs were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB) 
     946                if (version_compare($server_version, '4.1.0', '>=')) { 
     947                    if (version_compare($server_version, '4.1.1', '<')) { 
     948                        $this->supported['savepoints'] = false; 
     949                    } 
     950                } elseif (version_compare($server_version, '4.0.14', '<')) { 
     951                    $this->supported['savepoints'] = false; 
    810952                } 
    811953 
    812                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.11', '<')) { 
     954                if (!version_compare($server_version, '4.0.11', '<')) { 
    813955                    $this->start_transaction = true; 
    814956                } 
    815957 
    816                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) { 
     958                if (!version_compare($server_version, '5.0.3', '<')) { 
    817959                    $this->varchar_max_length = 65532; 
     960                } 
     961 
     962                if (!version_compare($server_version, '5.0.2', '<')) { 
     963                    $this->supported['triggers'] = true; 
    818964                } 
    819965            } 
     
    9591105        } 
    9601106        static $prep_statement_counter = 1; 
    961         $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++; 
     1107        $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); 
     1108        $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); 
    9621109        $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text'); 
    9631110        $statement =& $this->_doQuery($query, true, $connection); 
     
    10501197                $values.= ','; 
    10511198            } 
    1052             $query.= $name; 
     1199            $query.= $this->quoteIdentifier($name, true); 
    10531200            if (isset($fields[$name]['null']) && $fields[$name]['null']) { 
    10541201                $value = 'NULL'; 
     
    10791226        } 
    10801227 
     1228        $table = $this->quoteIdentifier($table, true); 
    10811229        $query = "REPLACE INTO $table ($query) VALUES ($values)"; 
    10821230        $result =& $this->_doQuery($query, true, $connection); 
     
    11061254        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); 
    11071255        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; 
     1256        $this->pushErrorHandling(PEAR_ERROR_RETURN); 
    11081257        $this->expectError(MDB2_ERROR_NOSUCHTABLE); 
    11091258        $result =& $this->_doQuery($query, true); 
    11101259        $this->popExpect(); 
     1260        $this->popErrorHandling(); 
    11111261        if (PEAR::isError($result)) { 
    11121262            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { 
  • program/lib/MDB2/Driver/mysqli.php

    r95ebbc98 rd1403fd  
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: mysqli.php,v 1.176 2007/11/10 13:27:03 quipo Exp $ 
     46// $Id: mysqli.php,v 1.188 2008/03/13 03:31:55 afz Exp $ 
    4747// 
    4848 
     
    9999        $this->supported['replace'] = true; 
    100100        $this->supported['sub_selects'] = 'emulated'; 
     101        $this->supported['triggers'] = false; 
    101102        $this->supported['auto_increment'] = true; 
    102103        $this->supported['primary_key'] = true; 
     
    107108        $this->supported['new_link'] = true; 
    108109 
     110        $this->options['DBA_username'] = false; 
     111        $this->options['DBA_password'] = false; 
    109112        $this->options['default_table_type'] = ''; 
    110113        $this->options['multi_query'] = false; 
     114        $this->options['max_identifiers_length'] = 64; 
     115 
     116        $this->_reCheckSupportedOptions(); 
     117    } 
     118 
     119    // }}} 
     120    // {{{ _reCheckSupportedOptions() 
     121 
     122    /** 
     123     * If the user changes certain options, other capabilities may depend 
     124     * on the new settings, so we need to check them (again). 
     125     * 
     126     * @access private 
     127     */ 
     128    function _reCheckSupportedOptions() 
     129    { 
     130        $this->supported['transactions'] = $this->options['use_transactions']; 
     131        $this->supported['savepoints']   = $this->options['use_transactions']; 
     132        if ($this->options['default_table_type']) { 
     133            switch (strtoupper($this->options['default_table_type'])) { 
     134            case 'BLACKHOLE': 
     135            case 'MEMORY': 
     136            case 'ARCHIVE': 
     137            case 'CSV': 
     138            case 'HEAP': 
     139            case 'ISAM': 
     140            case 'MERGE': 
     141            case 'MRG_ISAM': 
     142            case 'ISAM': 
     143            case 'MRG_MYISAM': 
     144            case 'MYISAM': 
     145                $this->supported['savepoints']   = false; 
     146                $this->supported['transactions'] = false; 
     147                $this->warnings[] = $this->options['default_table_type'] . 
     148                    ' is not a supported default table type'; 
     149                break; 
     150            } 
     151        } 
     152    } 
     153 
     154    // }}} 
     155    // {{{ function setOption($option, $value) 
     156 
     157    /** 
     158     * set the option for the db class 
     159     * 
     160     * @param   string  option name 
     161     * @param   mixed   value for the option 
     162     * 
     163     * @return  mixed   MDB2_OK or MDB2 Error Object 
     164     * 
     165     * @access  public 
     166     */ 
     167    function setOption($option, $value) 
     168    { 
     169        $res = parent::setOption($option, $value); 
     170        $this->_reCheckSupportedOptions(); 
    111171    } 
    112172 
     
    179239                    1217 => MDB2_ERROR_CONSTRAINT, 
    180240                    1227 => MDB2_ERROR_ACCESS_VIOLATION, 
     241                    1235 => MDB2_ERROR_CANNOT_CREATE, 
    181242                    1299 => MDB2_ERROR_INVALID_DATE, 
    182243                    1300 => MDB2_ERROR_INVALID, 
     
    197258                    1546 => MDB2_ERROR_CONSTRAINT, 
    198259                    1582 => MDB2_ERROR_CONSTRAINT, 
     260                    2003 => MDB2_ERROR_CONNECT_FAILED, 
    199261                    2019 => MDB2_ERROR_INVALID, 
    200262                ); 
     
    421483 
    422484    // }}} 
    423     // {{{ connect() 
    424  
    425     /** 
    426      * Connect to the database 
    427      * 
    428      * @return true on success, MDB2 Error Object on failure 
    429      */ 
    430     function connect() 
    431     { 
    432         if (is_object($this->connection)) { 
    433             //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0) { 
    434             if (MDB2::areEquals($this->connected_dsn, $this->dsn)) { 
    435                 return MDB2_OK; 
    436             } 
    437             $this->connection = 0; 
    438         } 
    439  
     485    // {{{ _doConnect() 
     486 
     487    /** 
     488     * do the grunt work of the connect 
     489     * 
     490     * @return connection on success or MDB2 Error Object on failure 
     491     * @access protected 
     492     */ 
     493    function _doConnect($username, $password, $persistent = false) 
     494    { 
    440495        if (!PEAR::loadExtension($this->phptype)) { 
    441496            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 
     
    447502            @mysqli_options($connection, MYSQLI_SET_CHARSET_NAME, $this->dsn['charset']); 
    448503        } 
    449  
    450504 
    451505        if ($this->options['ssl']) { 
     
    463517            $connection, 
    464518            $this->dsn['hostspec'], 
    465             $this->dsn['username'], 
    466             $this->dsn['password'], 
     519            $username, 
     520            $password, 
    467521            $this->database_name, 
    468522            $this->dsn['port'], 
    469523            $this->dsn['socket'] 
    470524        )) { 
    471  
    472525            if (($err = @mysqli_connect_error()) != '') { 
    473526                return $this->raiseError(null, 
     
    486539        } 
    487540 
     541        return $connection; 
     542    } 
     543 
     544    // }}} 
     545    // {{{ connect() 
     546 
     547    /** 
     548     * Connect to the database 
     549     * 
     550     * @return true on success, MDB2 Error Object on failure 
     551     */ 
     552    function connect() 
     553    { 
     554        if (is_object($this->connection)) { 
     555            //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0) { 
     556            if (MDB2::areEquals($this->connected_dsn, $this->dsn)) { 
     557                return MDB2_OK; 
     558            } 
     559            $this->connection = 0; 
     560        } 
     561 
     562        $connection = $this->_doConnect( 
     563            $this->dsn['username'], 
     564            $this->dsn['password'] 
     565        ); 
     566        if (PEAR::isError($connection)) { 
     567            return $connection; 
     568        } 
     569 
    488570        $this->connection = $connection; 
    489571        $this->connected_dsn = $this->dsn; 
     
    491573        $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; 
    492574 
    493         $this->supported['transactions'] = $this->options['use_transactions']; 
    494         if ($this->options['default_table_type']) { 
    495             switch (strtoupper($this->options['default_table_type'])) { 
    496             case 'BLACKHOLE': 
    497             case 'MEMORY': 
    498             case 'ARCHIVE': 
    499             case 'CSV': 
    500             case 'HEAP': 
    501             case 'ISAM': 
    502             case 'MERGE': 
    503             case 'MRG_ISAM': 
    504             case 'ISAM': 
    505             case 'MRG_MYISAM': 
    506             case 'MYISAM': 
    507                 $this->supported['transactions'] = false; 
    508                 $this->warnings[] = $this->options['default_table_type'] . 
    509                     ' is not a supported default table type'; 
    510                 break; 
    511             } 
    512         } 
    513          
    514575        $this->_getServerCapabilities(); 
    515576 
     
    523584     * Set the charset on the current connection 
    524585     * 
    525      * @param string    charset 
     586     * @param string    charset (or array(charset, collation)) 
    526587     * @param resource  connection handle 
    527588     * 
     
    535596                return $connection; 
    536597            } 
     598        } 
     599        $collation = null; 
     600        if (is_array($charset) && 2 == count($charset)) { 
     601            $collation = array_pop($charset); 
     602            $charset   = array_pop($charset); 
    537603        } 
    538604        $client_info = mysqli_get_client_version(); 
     
    541607        ) { 
    542608            $query = "SET NAMES '".mysqli_real_escape_string($connection, $charset)."'"; 
     609            if (!is_null($collation)) { 
     610                $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; 
     611            } 
    543612            return $this->_doQuery($query, true, $connection); 
    544613        } 
     
    548617            return $err; 
    549618        } 
     619        return $result; 
     620    } 
     621 
     622    // }}} 
     623    // {{{ databaseExists() 
     624 
     625    /** 
     626     * check if given database name is exists? 
     627     * 
     628     * @param string $name    name of the database that should be checked 
     629     * 
     630     * @return mixed true/false on success, a MDB2 error on failure 
     631     * @access public 
     632     */ 
     633    function databaseExists($name) 
     634    { 
     635        $connection = $this->_doConnect($this->dsn['username'], 
     636                                        $this->dsn['password']); 
     637        if (PEAR::isError($connection)) { 
     638            return $connection; 
     639        } 
     640 
     641        $result = @mysqli_select_db($connection, $name); 
     642        @mysqli_close($connection); 
     643 
    550644        return $result; 
    551645    } 
     
    587681 
    588682    // }}} 
     683    // {{{ standaloneQuery() 
     684 
     685   /** 
     686     * execute a query as DBA 
     687     * 
     688     * @param string $query the SQL query 
     689     * @param mixed   $types  array that contains the types of the columns in 
     690     *                        the result set 
     691     * @param boolean $is_manip  if the query is a manipulation query 
     692     * @return mixed MDB2_OK on success, a MDB2 error on failure 
     693     * @access public 
     694     */ 
     695    function &standaloneQuery($query, $types = null, $is_manip = false) 
     696    { 
     697        $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; 
     698        $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; 
     699        $connection = $this->_doConnect($user, $pass); 
     700        if (PEAR::isError($connection)) { 
     701            return $connection; 
     702        } 
     703 
     704        $offset = $this->offset; 
     705        $limit = $this->limit; 
     706        $this->offset = $this->limit = 0; 
     707        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); 
     708         
     709        $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); 
     710        if (!PEAR::isError($result)) { 
     711            $result = $this->_affectedRows($connection, $result); 
     712        } 
     713 
     714        @mysqli_close($connection); 
     715        return $result; 
     716    } 
     717 
     718    // }}} 
    589719    // {{{ _doQuery() 
    590720 
     
    804934            $this->supported['sub_selects'] = 'emulated'; 
    805935            $this->supported['prepared_statements'] = 'emulated'; 
     936            $this->supported['triggers'] = false; 
    806937            $this->start_transaction = false; 
    807938            $this->varchar_max_length = 255; 
     
    809940            $server_info = $this->getServerVersion(); 
    810941            if (is_array($server_info)) { 
    811                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.0', '<')) { 
     942                $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch']; 
     943             
     944                if (!version_compare($server_version, '4.1.0', '<')) { 
    812945                    $this->supported['sub_selects'] = true; 
    813946                    $this->supported['prepared_statements'] = true; 
    814947                } 
    815948 
    816                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.14', '<') 
    817                     || !version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.1.1', '<') 
    818                 ) { 
    819                     $this->supported['savepoints'] = true; 
     949                // SAVEPOINTS were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB) 
     950                if (version_compare($server_version, '4.1.0', '>=')) { 
     951                    if (version_compare($server_version, '4.1.1', '<')) { 
     952                        $this->supported['savepoints'] = false; 
     953                    } 
     954                } elseif (version_compare($server_version, '4.0.14', '<')) { 
     955                    $this->supported['savepoints'] = false; 
    820956                } 
    821957 
    822                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '4.0.11', '<')) { 
     958                if (!version_compare($server_version, '4.0.11', '<')) { 
    823959                    $this->start_transaction = true; 
    824960                } 
    825961 
    826                 if (!version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) { 
     962                if (!version_compare($server_version, '5.0.3', '<')) { 
    827963                    $this->varchar_max_length = 65532; 
     964                } 
     965 
     966                if (!version_compare($server_version, '5.0.2', '<')) { 
     967                    $this->supported['triggers'] = true; 
    828968                } 
    829969            } 
     
    9711111        if (!$is_manip) { 
    9721112            static $prep_statement_counter = 1; 
    973             $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++; 
     1113            $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); 
     1114            $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); 
    9741115            $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text'); 
    9751116 
     
    10721213                $values.= ','; 
    10731214            } 
    1074             $query.= $name; 
     1215            $query.= $this->quoteIdentifier($name, true); 
    10751216            if (isset($fields[$name]['null']) && $fields[$name]['null']) { 
    10761217                $value = 'NULL'; 
     
    11011242        } 
    11021243 
     1244        $table = $this->quoteIdentifier($table, true); 
    11031245        $query = "REPLACE INTO $table ($query) VALUES ($values)"; 
    11041246        $result =& $this->_doQuery($query, true, $connection); 
     
    11281270        $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); 
    11291271        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; 
     1272        $this->pushErrorHandling(PEAR_ERROR_RETURN); 
    11301273        $this->expectError(MDB2_ERROR_NOSUCHTABLE); 
    11311274        $result =& $this->_doQuery($query, true); 
    11321275        $this->popExpect(); 
     1276        $this->popErrorHandling(); 
    11331277        if (PEAR::isError($result)) { 
    11341278            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { 
  • program/lib/MDB2/Driver/pgsql.php

    r95ebbc98 rd1403fd  
    44// | PHP versions 4 and 5                                                 | 
    55// +----------------------------------------------------------------------+ 
    6 // | Copyright (c) 1998-2006 Manuel Lemos, Tomas V.V.Cox,                 | 
     6// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    77// | Stig. S. Bakken, Lukas Smith                                         | 
    88// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: pgsql.php,v 1.186 2007/11/10 13:27:03 quipo Exp $ 
     46// $Id: pgsql.php,v 1.197 2008/03/08 14:18:39 quipo Exp $ 
    4747 
    4848/** 
     
    8484        $this->supported['replace'] = 'emulated'; 
    8585        $this->supported['sub_selects'] = true; 
     86        $this->supported['triggers'] = true; 
    8687        $this->supported['auto_increment'] = 'emulated'; 
    8788        $this->supported['primary_key'] = true; 
     
    9293        $this->supported['new_link'] = true; 
    9394 
     95        $this->options['DBA_username'] = false; 
     96        $this->options['DBA_password'] = false; 
    9497        $this->options['multi_query'] = false; 
    9598        $this->options['disable_smart_seqname'] = false; 
     99        $this->options['max_identifiers_length'] = 63; 
    96100    } 
    97101 
     
    120124                $error_code = MDB2_ERROR_CONNECT_FAILED; 
    121125            } 
     126        } else { 
     127            $native_msg = @pg_last_error(); 
    122128        } 
    123129 
     
    129135                '/(relation|sequence|table).*does not exist|class .* not found/i' 
    130136                    => MDB2_ERROR_NOSUCHTABLE, 
     137                '/database .* does not exist/' 
     138                    => MDB2_ERROR_NOT_FOUND, 
    131139                '/index .* does not exist/' 
    132140                    => MDB2_ERROR_NOT_FOUND, 
     141                '/database .* already exists/i' 
     142                    => MDB2_ERROR_ALREADY_EXISTS, 
    133143                '/relation .* already exists/i' 
    134144                    => MDB2_ERROR_ALREADY_EXISTS, 
     
    203213            return $connection; 
    204214        } 
    205         if (version_compare(PHP_VERSION, '5.2.0RC5', '>=')) { 
     215        if (is_resource($connection) && version_compare(PHP_VERSION, '5.2.0RC5', '>=')) { 
    206216            $text = @pg_escape_string($connection, $text); 
    207217        } else { 
     
    354364 
    355365    /** 
    356      * Does the grunt work of connecting to the database 
     366     * Do the grunt work of connecting to the database 
    357367     * 
    358368     * @return mixed connection resource on success, MDB2 Error Object on failure 
    359369     * @access protected 
    360      **/ 
    361     function _doConnect($database_name, $persistent = false) 
    362     { 
     370     */ 
     371    function _doConnect($username, $password, $database_name, $persistent = false) 
     372    { 
     373        if (!PEAR::loadExtension($this->phptype)) { 
     374            return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 
     375                'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); 
     376        } 
     377         
    363378        if ($database_name == '') { 
    364379            $database_name = 'template1'; 
     
    387402            $params[0].= ' dbname=\'' . addslashes($database_name) . '\''; 
    388403        } 
    389         if ($this->dsn['username']) { 
    390             $params[0].= ' user=\'' . addslashes($this->dsn['username']) . '\''; 
    391         } 
    392         if ($this->dsn['password']) { 
    393             $params[0].= ' password=\'' . addslashes($this->dsn['password']) . '\''; 
     404        if ($username) { 
     405            $params[0].= ' user=\'' . addslashes($username) . '\''; 
     406        } 
     407        if ($password) { 
     408            $params[0].= ' password=\'' . addslashes($password) . '\''; 
    394409        } 
    395410        if (!empty($this->dsn['options'])) { 
     
    418433 
    419434        $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; 
    420  
    421435        $connection = @call_user_func_array($connect_function, $params); 
    422436        if (!$connection) { 
     
    450464     * @return true on success, MDB2 Error Object on failure 
    451465     * @access public 
    452      **/ 
     466     */ 
    453467    function connect() 
    454468    { 
     
    464478        } 
    465479 
    466         if (!PEAR::loadExtension($this->phptype)) { 
    467             return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, 
    468                 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__); 
    469         } 
    470  
    471480        if ($this->database_name) { 
    472             $connection = $this->_doConnect($this->database_name, $this->options['persistent']); 
     481            $connection = $this->_doConnect($this->dsn['username'], 
     482                                            $this->dsn['password'], 
     483                                            $this->database_name, 
     484                                            $this->options['persistent']); 
    473485            if (PEAR::isError($connection)) { 
    474486                return $connection; 
    475487            } 
     488 
    476489            $this->connection = $connection; 
    477490            $this->connected_dsn = $this->dsn; 
     
    480493            $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; 
    481494        } 
     495 
    482496        return MDB2_OK; 
    483497    } 
     
    502516            } 
    503517        } 
    504  
     518        if (is_array($charset)) { 
     519            $charset   = array_shift($charset); 
     520            $this->warnings[] = 'postgresql does not support setting client collation'; 
     521        } 
    505522        $result = @pg_set_client_encoding($connection, $charset); 
    506523        if ($result == -1) { 
     
    509526        } 
    510527        return MDB2_OK; 
     528    } 
     529 
     530    // }}} 
     531    // {{{ databaseExists() 
     532 
     533    /** 
     534     * check if given database name is exists? 
     535     * 
     536     * @param string $name    name of the database that should be checked 
     537     * 
     538     * @return mixed true/false on success, a MDB2 error on failure 
     539     * @access public 
     540     */ 
     541    function databaseExists($name) 
     542    { 
     543        $res = $this->_doConnect($this->dsn['username'], 
     544                                 $this->dsn['password'], 
     545                                 $this->escape($name), 
     546                                 $this->options['persistent']); 
     547        if (!PEAR::isError($res)) { 
     548            return true; 
     549        } 
     550 
     551        return false; 
    511552    } 
    512553 
     
    561602    function &standaloneQuery($query, $types = null, $is_manip = false) 
    562603    { 
    563         $connection = $this->_doConnect('template1', false); 
     604        $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username']; 
     605        $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password']; 
     606        $connection = $this->_doConnect($user, $pass, $this->database_name, $this->options['persistent']); 
    564607        if (PEAR::isError($connection)) { 
    565             $err =& $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null, 
    566                 'Cannot connect to template1', __FUNCTION__); 
    567             return $err; 
     608            return $connection; 
    568609        } 
    569610 
     
    573614        $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); 
    574615 
    575         $result =& $this->_doQuery($query, $is_manip, $connection, false); 
     616        $result =& $this->_doQuery($query, $is_manip, $connection, $this->database_name); 
     617        if (!PEAR::isError($result)) { 
     618            if ($is_manip) { 
     619                $result =  $this->_affectedRows($connection, $result); 
     620            } else { 
     621                $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset); 
     622            } 
     623        } 
     624 
    576625        @pg_close($connection); 
    577         if (PEAR::isError($result)) { 
    578             return $result; 
    579         } 
    580  
    581         if ($is_manip) { 
    582             $affected_rows =  $this->_affectedRows($connection, $result); 
    583             return $affected_rows; 
    584         } 
    585         $result =& $this->_wrapResult($result, $types, true, false, $limit, $offset); 
    586626        return $result; 
    587627    } 
     
    911951        } 
    912952        static $prep_statement_counter = 1; 
    913         $statement_name = sprintf($this->options['statement_format'], $this->phptype, sha1(microtime() + mt_rand())) . $prep_statement_counter++; 
    914         $statement_name = strtolower($statement_name); 
     953        $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand())); 
     954        $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']); 
    915955        if ($pgtypes === false) { 
    916956            $result = @pg_prepare($connection, $statement_name, $query); 
     
    9761016                             AND d.adnum = a.attnum 
    9771017                             AND a.atthasdef 
    978                          ) FROM 'nextval[^\']*\'([^\']*)') 
     1018                         ) FROM 'nextval[^'']*''([^'']*)') 
    9791019                        FROM pg_attribute a 
    9801020                    LEFT JOIN pg_class c ON c.oid = a.attrelid 
     
    10181058        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); 
    10191059        $query = "SELECT NEXTVAL('$sequence_name')"; 
     1060        $this->pushErrorHandling(PEAR_ERROR_RETURN); 
    10201061        $this->expectError(MDB2_ERROR_NOSUCHTABLE); 
    10211062        $result = $this->queryOne($query, 'integer'); 
    10221063        $this->popExpect(); 
     1064        $this->popErrorHandling(); 
    10231065        if (PEAR::isError($result)) { 
    10241066            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { 
     
    10531095        } 
    10541096        $seq = $table.(empty($field) ? '' : '_'.$field); 
    1055         $sequence_name = $this->getSequenceName($seq); 
     1097        $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true); 
    10561098        return $this->queryOne("SELECT currval('$sequence_name')", 'integer'); 
    10571099    } 
  • program/lib/MDB2/Driver/sqlite.php

    r95ebbc98 rd1403fd  
    44// | PHP versions 4 and 5                                                 | 
    55// +----------------------------------------------------------------------+ 
    6 // | Copyright (c) 1998-2007 Manuel Lemos, Tomas V.V.Cox,                 | 
     6// | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox,                 | 
    77// | Stig. S. Bakken, Lukas Smith                                         | 
    88// | All rights reserved.                                                 | 
     
    4444// +----------------------------------------------------------------------+ 
    4545// 
    46 // $Id: sqlite.php,v 1.152 2007/11/27 07:44:41 quipo Exp $ 
     46// $Id: sqlite.php,v 1.158 2008/03/08 14:18:39 quipo Exp $ 
    4747// 
    4848 
     
    9090        $this->supported['savepoints'] = false; 
    9191        $this->supported['sub_selects'] = true; 
     92        $this->supported['triggers'] = true; 
    9293        $this->supported['auto_increment'] = true; 
    9394        $this->supported['primary_key'] = false; // requires alter table implementation 
     
    9899        $this->supported['new_link'] = false; 
    99100 
     101        $this->options['DBA_username'] = false; 
     102        $this->options['DBA_password'] = false; 
    100103        $this->options['base_transaction_name'] = '___php_MDB2_sqlite_auto_commit_off'; 
    101104        $this->options['fixed_float'] = 0; 
     
    103106        $this->options['database_extension'] = ''; 
    104107        $this->options['server_version'] = ''; 
     108        $this->options['max_identifiers_length'] = 128; //no real limit 
    105109    } 
    106110 
     
    126130        // PHP 5.2+ prepends the function name to $php_errormsg, so we need 
    127131        // this hack to work around it, per bug #9599. 
    128         $native_msg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $native_msg); 
     132        $native_msg = preg_replace('/^sqlite[a-z_]+\(\)[^:]*: /', '', $native_msg); 
    129133 
    130134        if (is_null($error)) { 
     
    426430 
    427431    // }}} 
     432    // {{{ databaseExists() 
     433 
     434    /** 
     435     * check if given database name is exists? 
     436     * 
     437     * @param string $name    name of the database that should be checked 
     438     * 
     439     * @return mixed true/false on success, a MDB2 error on failure 
     440     * @access public 
     441     */ 
     442    function databaseExists($name) 
     443    { 
     444        $database_file = $this->_getDatabaseFile($name); 
     445        $result = file_exists($database_file); 
     446        return $result; 
     447    } 
     448 
     449    // }}} 
    428450    // {{{ disconnect() 
    429451 
     
    722744                $values.= ','; 
    723745            } 
    724             $query.= $name; 
     746            $query.= $this->quoteIdentifier($name, true); 
    725747            if (isset($fields[$name]['null']) && $fields[$name]['null']) { 
    726748                $value = 'NULL'; 
     
    751773        } 
    752774 
     775        $table = $this->quoteIdentifier($table, true); 
    753776        $query = "REPLACE INTO $table ($query) VALUES ($values)"; 
    754777        $result =& $this->_doQuery($query, true, $connection); 
     
    778801        $seqcol_name = $this->options['seqcol_name']; 
    779802        $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; 
     803        $this->pushErrorHandling(PEAR_ERROR_RETURN); 
    780804        $this->expectError(MDB2_ERROR_NOSUCHTABLE); 
    781805        $result =& $this->_doQuery($query, true); 
    782806        $this->popExpect(); 
     807        $this->popErrorHandling(); 
    783808        if (PEAR::isError($result)) { 
    784809            if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { 
Note: See TracChangeset for help on using the changeset viewer.