Changeset d1403fd in github
- Timestamp:
- May 2, 2008 3:35:00 AM (5 years ago)
- Branches:
- master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
- Children:
- c5cc386
- Parents:
- bbf15d8
- Files:
-
- 29 edited
-
CHANGELOG (modified) (1 diff)
-
program/lib/MDB2.php (modified) (14 diffs)
-
program/lib/MDB2/Driver/Datatype/Common.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Datatype/mssql.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Datatype/mysql.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Datatype/mysqli.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Datatype/pgsql.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Datatype/sqlite.php (modified) (3 diffs)
-
program/lib/MDB2/Driver/Function/Common.php (modified) (10 diffs)
-
program/lib/MDB2/Driver/Function/mssql.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Function/mysql.php (modified) (3 diffs)
-
program/lib/MDB2/Driver/Function/mysqli.php (modified) (3 diffs)
-
program/lib/MDB2/Driver/Function/pgsql.php (modified) (3 diffs)
-
program/lib/MDB2/Driver/Function/sqlite.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Manager/Common.php (modified) (5 diffs)
-
program/lib/MDB2/Driver/Manager/mssql.php (modified) (10 diffs)
-
program/lib/MDB2/Driver/Manager/mysql.php (modified) (12 diffs)
-
program/lib/MDB2/Driver/Manager/mysqli.php (modified) (12 diffs)
-
program/lib/MDB2/Driver/Manager/pgsql.php (modified) (9 diffs)
-
program/lib/MDB2/Driver/Manager/sqlite.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Reverse/Common.php (modified) (2 diffs)
-
program/lib/MDB2/Driver/Reverse/mssql.php (modified) (2 diffs)
-
program/lib/MDB2/Driver/Reverse/pgsql.php (modified) (4 diffs)
-
program/lib/MDB2/Driver/Reverse/sqlite.php (modified) (2 diffs)
-
program/lib/MDB2/Driver/mssql.php (modified) (15 diffs)
-
program/lib/MDB2/Driver/mysql.php (modified) (20 diffs)
-
program/lib/MDB2/Driver/mysqli.php (modified) (21 diffs)
-
program/lib/MDB2/Driver/pgsql.php (modified) (21 diffs)
-
program/lib/MDB2/Driver/sqlite.php (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r7ec922f rd1403fd 1 1 CHANGELOG RoundCube Webmail 2 2 --------------------------- 3 4 2008/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) 3 10 4 11 2008/05/01 (alec) -
program/lib/MDB2.php
r95ebbc98 rd1403fd 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: MDB2.php,v 1.3 07 2007/11/10 13:29:05quipo Exp $46 // $Id: MDB2.php,v 1.318 2008/03/08 14:18:38 quipo Exp $ 47 47 // 48 48 … … 101 101 define('MDB2_ERROR_LOADMODULE', -34); 102 102 define('MDB2_ERROR_INSUFFICIENT_DATA', -35); 103 define('MDB2_ERROR_NO_PERMISSION', -36); 104 103 105 // }}} 104 106 // {{{ Verbose constants … … 565 567 function apiVersion() 566 568 { 567 return '2.5.0 a2';569 return '2.5.0b1'; 568 570 } 569 571 … … 765 767 MDB2_ERROR_TRUNCATED => 'truncated', 766 768 MDB2_ERROR_DEADLOCK => 'deadlock detected', 769 MDB2_ERROR_NO_PERMISSION => 'no permission', 767 770 ); 768 771 } … … 889 892 //e.g. "scott/tiger@//mymachine:1521/oracle" 890 893 $proto_opts = $dsn; 891 $dsn = null;894 $dsn = substr($proto_opts, strrpos($proto_opts, '/') + 1); 892 895 } elseif (strpos($dsn, '/') !== false) { 893 896 list($proto_opts, $dsn) = explode('/', $dsn, 2); … … 1096 1099 'replace' => false, 1097 1100 'sub_selects' => false, 1101 'triggers' => false, 1098 1102 'auto_increment' => false, 1099 1103 'primary_key' => false, … … 1143 1147 * <li>$options['datatype_map_callback'] -> array: callback function/method that should be called</li> 1144 1148 * <li>$options['bindname_format'] -> string: regular expression pattern for named parameters 1149 * <li>$options['max_identifiers_length'] -> integer: max identifier length</li> 1145 1150 * </ul> 1146 1151 * … … 1191 1196 'lob_allow_url_include' => false, 1192 1197 'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)', 1198 'max_identifiers_length' => 30, 1193 1199 ); 1194 1200 … … 2220 2226 2221 2227 // }}} 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 // }}} 2222 2245 // {{{ setCharset($charset, $connection = null) 2223 2246 … … 2278 2301 $previous_database_name = (isset($this->database_name)) ? $this->database_name : ''; 2279 2302 $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 } 2281 2306 return $previous_database_name; 2282 2307 } … … 2796 2821 'key value '.$name.' may not be NULL', __FUNCTION__); 2797 2822 } 2798 $condition[] = $ name. '=' . $value;2823 $condition[] = $this->quoteIdentifier($name, true) . '=' . $value; 2799 2824 } 2800 2825 } … … 2816 2841 2817 2842 $condition = ' WHERE '.implode(' AND ', $condition); 2818 $query = "DELETE FROM $table$condition";2843 $query = 'DELETE FROM ' . $this->quoteIdentifier($table, true) . $condition; 2819 2844 $result =& $this->_doQuery($query, true, $connection); 2820 2845 if (!PEAR::isError($result)) { 2821 2846 $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 } 2823 2851 $values = implode(', ', $values); 2824 $query = "INSERT INTO $table($insert) VALUES ($values)";2852 $query = 'INSERT INTO '. $this->quoteIdentifier($table, true) . "($insert) VALUES ($values)"; 2825 2853 $result =& $this->_doQuery($query, true, $connection); 2826 2854 if (!PEAR::isError($result)) { … … 2999 3027 } 3000 3028 } 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); 3002 3030 $position = $end_quote + 1; 3003 3031 return $position; … … 3981 4009 $parameters = array_keys($values); 3982 4010 foreach ($parameters as $key => $parameter) { 4011 $this->db->pushErrorHandling(PEAR_ERROR_RETURN); 3983 4012 $this->db->expectError(MDB2_ERROR_NOT_FOUND); 3984 4013 $err = $this->bindValue($parameter, $values[$parameter], $types[$key]); 3985 4014 $this->db->popExpect(); 4015 $this->db->popErrorHandling(); 3986 4016 if (PEAR::isError($err)) { 3987 4017 if ($err->getCode() == MDB2_ERROR_NOT_FOUND) { -
program/lib/MDB2/Driver/Datatype/Common.php
r95ebbc98 rd1403fd 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: Common.php,v 1.1 28 2007/11/09 20:54:58 quipoExp $45 // $Id: Common.php,v 1.137 2008/02/17 18:53:40 afz Exp $ 46 46 47 47 require_once 'MDB2/LOB.php'; … … 498 498 ' '.$this->_getCharsetFieldDeclaration($field['charset']); 499 499 500 $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; 500 501 $default = ''; 501 502 if (array_key_exists('default', $field)) { … … 505 506 return $db; 506 507 } 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)) { 516 511 $field['default'] = ' '; 517 512 } 518 513 } 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 526 519 $collation = empty($field['collation']) ? '' : 527 520 ' '.$this->_getCollationFieldDeclaration($field['collation']); 521 528 522 return $charset.$default.$notnull.$collation; 529 523 } … … 1491 1485 $value = (string)$value; 1492 1486 $value = preg_replace('/[^\d\.,\-+eE]/', '', $value); 1493 if (preg_match('/[^ .0-9]/', $value)) {1487 if (preg_match('/[^\.\d]/', $value)) { 1494 1488 if (strpos($value, ',')) { 1495 1489 // 1000,00 -
program/lib/MDB2/Driver/Datatype/mssql.php
r95ebbc98 rd1403fd 45 45 // +----------------------------------------------------------------------+ 46 46 // 47 // $Id: mssql.php,v 1. 59 2007/12/03 20:59:50 quipoExp $47 // $Id: mssql.php,v 1.65 2008/02/19 14:54:17 afz Exp $ 48 48 // 49 49 … … 186 186 187 187 // }}} 188 // {{{ _getDeclaration()189 190 /**191 * Obtain DBMS specific SQL code portion needed to declare a generic type192 * 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 properties196 * of the field being declared as array indexes. Currently, the types197 * of supported field properties are as follows:198 *199 * length200 * Integer value that determines the maximum length of the text201 * field. If this argument is missing the field should be202 * declared to have the longest length allowed by the DBMS.203 *204 * default205 * Text value to be used as default for this field.206 *207 * notnull208 * Boolean flag that indicates whether this field is constrained209 * to not be set to null.210 * @return string DBMS specific SQL code portion that should be used to211 * declare the specified field.212 * @access protected213 */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 // }}}250 188 // {{{ _getIntegerDeclaration() 251 189 … … 283 221 } 284 222 285 $default = $autoinc = '';; 223 $notnull = empty($field['notnull']) ? ' NULL' : ' NOT NULL'; 224 $default = $autoinc = ''; 286 225 if (!empty($field['autoincrement'])) { 287 226 $autoinc = ' IDENTITY PRIMARY KEY'; 288 227 } elseif (array_key_exists('default', $field)) { 289 228 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 301 238 if (!empty($field['unsigned'])) { 302 239 $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; 303 240 } 241 304 242 $name = $db->quoteIdentifier($name, true); 305 return $name.' '.$this->getTypeDeclaration($field).$ default.$notnull.$autoinc;243 return $name.' '.$this->getTypeDeclaration($field).$notnull.$default.$autoinc; 306 244 } 307 245 … … 397 335 return $value; 398 336 } 399 $value = bin2hex("0x".$this->_readFile($value));337 $value = '0x'.bin2hex($this->_readFile($value)); 400 338 return $value; 401 339 } -
program/lib/MDB2/Driver/Datatype/mysql.php
r95ebbc98 rd1403fd 4 4 // | PHP versions 4 and 5 | 5 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |6 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 7 7 // | Stig. S. Bakken, Lukas Smith | 8 8 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: mysql.php,v 1.6 2 2007/11/09 20:54:58quipo Exp $46 // $Id: mysql.php,v 1.65 2008/02/22 19:23:49 quipo Exp $ 47 47 // 48 48 … … 233 233 } 234 234 $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 235 } elseif (empty($field['notnull'])) {236 $default = ' DEFAULT NULL';237 235 } 238 236 … … 241 239 $name = $db->quoteIdentifier($name, true); 242 240 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; 243 330 } 244 331 -
program/lib/MDB2/Driver/Datatype/mysqli.php
r95ebbc98 rd1403fd 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: mysqli.php,v 1.6 1 2007/11/09 20:54:58quipo Exp $46 // $Id: mysqli.php,v 1.63 2008/02/22 19:23:49 quipo Exp $ 47 47 // 48 48 … … 233 233 } 234 234 $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 235 } elseif (empty($field['notnull'])) {236 $default = ' DEFAULT NULL';237 235 } 238 236 … … 241 239 $name = $db->quoteIdentifier($name, true); 242 240 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; 243 330 } 244 331 … … 357 444 case 'longtext': 358 445 case 'text': 359 case 'text':360 446 case 'varchar': 361 447 $fixed = false; -
program/lib/MDB2/Driver/Datatype/pgsql.php
r95ebbc98 rd1403fd 43 43 // +----------------------------------------------------------------------+ 44 44 // 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 $ 46 46 47 47 require_once 'MDB2/Driver/Datatype/Common.php'; … … 218 218 } 219 219 $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 220 } elseif (empty($field['notnull'])) {221 $default = ' DEFAULT NULL';222 220 } 223 221 … … 454 452 case 'datetime': 455 453 case 'timestamp': 454 case 'timestamptz': 456 455 $type[] = 'timestamp'; 457 456 $length = null; … … 462 461 break; 463 462 case 'float': 463 case 'float4': 464 464 case 'float8': 465 465 case 'double': -
program/lib/MDB2/Driver/Datatype/sqlite.php
r95ebbc98 rd1403fd 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: sqlite.php,v 1.6 5 2007/12/03 20:59:51quipo Exp $46 // $Id: sqlite.php,v 1.67 2008/02/22 19:58:06 quipo Exp $ 47 47 // 48 48 … … 213 213 } 214 214 $default = ' DEFAULT '.$this->quote($field['default'], 'integer'); 215 } elseif (empty($field['notnull'])) {216 $default = ' DEFAULT NULL';217 215 } 218 216 … … 395 393 return $db; 396 394 } 397 398 395 return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null, 399 396 'unknown database attribute type: '.$db_type, __FUNCTION__); -
program/lib/MDB2/Driver/Function/Common.php
r95ebbc98 rd1403fd 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: Common.php,v 1. 19 2007/09/09 13:47:36quipo Exp $45 // $Id: Common.php,v 1.21 2008/02/17 18:51:39 quipo Exp $ 46 46 // 47 47 … … 58 58 * $mdb->loadModule('Function'); 59 59 * 60 * @package MDB260 * @package MDB2 61 61 * @category Database 62 * @author Lukas Smith <smith@pooteeweet.org>62 * @author Lukas Smith <smith@pooteeweet.org> 63 63 */ 64 64 class MDB2_Driver_Function_Common extends MDB2_Module_Common … … 75 75 * @param mixed $result_class string which specifies which result class to use 76 76 * @param mixed $result_wrap_class string which specifies which class to wrap results in 77 * 77 78 * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure 78 79 * @access public … … 113 114 * - CURRENT_DATE (date, DATE type) 114 115 * - CURRENT_TIME (time, TIME type) 116 * 117 * @param string $type 'timestamp' | 'time' | 'date' 115 118 * 116 119 * @return string to call a variable with the current timestamp … … 131 134 132 135 // }}} 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 // }}} 133 159 // {{{ substring() 134 160 … … 145 171 } 146 172 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)"; 147 187 } 148 188 … … 156 196 * @param string $value2 157 197 * @param string $values... 198 * 158 199 * @return string to concatenate two strings 159 200 * @access public … … 186 227 * 187 228 * @param string $expression 229 * 188 230 * @return return string to lower case of an expression 189 231 * @access public … … 201 243 * 202 244 * @param string $expression 245 * 203 246 * @return return string to upper case of an expression 204 247 * @access public … … 216 259 * 217 260 * @param string $expression 261 * 218 262 * @return return string to get the string expression length 219 263 * @access public -
program/lib/MDB2/Driver/Function/mssql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: mssql.php,v 1.1 5 2007/08/11 16:02:22quipo Exp $45 // $Id: mssql.php,v 1.16 2008/02/17 18:54:08 quipo Exp $ 46 46 // 47 47 … … 58 58 class MDB2_Driver_Function_mssql extends MDB2_Driver_Function_Common 59 59 { 60 // }}}61 60 // {{{ executeStoredProc() 62 61 … … 107 106 return 'GETDATE()'; 108 107 } 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())'; 109 124 } 110 125 -
program/lib/MDB2/Driver/Function/mysql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: mysql.php,v 1.1 1 2007/01/12 11:29:12quipo Exp $45 // $Id: mysql.php,v 1.12 2008/02/17 18:54:08 quipo Exp $ 46 46 // 47 47 … … 85 85 86 86 // }}} 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 // }}} 87 103 // {{{ concat() 88 104 -
program/lib/MDB2/Driver/Function/mysqli.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: mysqli.php,v 1.1 3 2007/01/12 11:29:12quipo Exp $45 // $Id: mysqli.php,v 1.14 2008/02/17 18:54:08 quipo Exp $ 46 46 // 47 47 … … 93 93 94 94 // }}} 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 // }}} 95 111 // {{{ concat() 96 112 -
program/lib/MDB2/Driver/Function/pgsql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: pgsql.php,v 1. 9 2006/06/12 21:48:43 lsmithExp $45 // $Id: pgsql.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ 46 46 47 47 require_once 'MDB2/Driver/Function/Common.php'; … … 82 82 } 83 83 // }}} 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 // }}} 84 100 // {{{ random() 85 101 -
program/lib/MDB2/Driver/Function/sqlite.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: sqlite.php,v 1. 8 2006/06/13 22:55:55 lsmithExp $45 // $Id: sqlite.php,v 1.10 2008/02/17 18:54:08 quipo Exp $ 46 46 // 47 47 … … 91 91 92 92 // }}} 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 // }}} 93 109 // {{{ substring() 94 110 … … 122 138 123 139 // }}} 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 // }}} 124 161 } 125 162 ?> -
program/lib/MDB2/Driver/Manager/Common.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 40 40 // | POSSIBILITY OF SUCH DAMAGE. | 41 41 // +----------------------------------------------------------------------+ 42 // | Author: Lukas Smith <smith@pooteeweet.org> | 42 // | Authors: Lukas Smith <smith@pooteeweet.org> | 43 // | Lorenzo Alberton <l.alberton@quipo.it> | 43 44 // +----------------------------------------------------------------------+ 44 45 // 45 // $Id: Common.php,v 1. 68 2007/12/03 20:59:15quipo Exp $46 // $Id: Common.php,v 1.71 2008/02/12 23:12:27 quipo Exp $ 46 47 // 47 48 … … 50 51 * @category Database 51 52 * @author Lukas Smith <smith@pooteeweet.org> 53 * @author Lorenzo Alberton <l.alberton@quipo.it> 52 54 */ 53 55 … … 189 191 */ 190 192 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()) 191 216 { 192 217 $db =& $this->getDBInstance(); … … 358 383 $name = $db->quoteIdentifier($name, true); 359 384 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__); 360 435 } 361 436 -
program/lib/MDB2/Driver/Manager/mssql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 45 45 // +----------------------------------------------------------------------+ 46 46 // 47 // $Id: mssql.php,v 1. 93 2007/12/03 20:59:15 quipoExp $47 // $Id: mssql.php,v 1.109 2008/03/05 12:55:57 afz Exp $ 48 48 // 49 49 … … 91 91 } 92 92 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; 93 126 } 94 127 … … 198 231 } 199 232 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); 200 291 } 201 292 … … 299 390 return $db; 300 391 } 392 $name_quoted = $db->quoteIdentifier($name, true); 301 393 302 394 foreach ($changes as $change_name => $change) { 303 395 switch ($change_name) { 396 case 'remove': 397 case 'rename': 304 398 case 'add': 399 case 'change': 400 case 'name': 305 401 break; 306 case 'remove':307 break;308 case 'name':309 case 'rename':310 case 'change':311 402 default: 312 403 return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, … … 319 410 } 320 411 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'); 332 414 333 415 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 = ''; 334 428 foreach ($changes['remove'] as $field_name => $field) { 335 429 if ($query) { … … 337 431 } 338 432 $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); 349 663 } 350 664 … … 401 715 return $db; 402 716 } 403 717 404 718 $table = $db->quoteIdentifier($table, true); 405 719 $columns = $db->queryCol("SELECT c.name … … 682 996 } 683 997 $table = $db->quoteIdentifier($table, true); 684 998 685 999 $query = "SELECT c.constraint_name 686 1000 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS c … … 712 1026 * create sequence 713 1027 * 714 * @param string $seq_name name of the sequence to be created715 * @param string $start start value of the sequence; default is 11028 * @param string $seq_name name of the sequence to be created 1029 * @param string $start start value of the sequence; default is 1 716 1030 * 717 1031 * @return mixed MDB2_OK on success, a MDB2 error on failure -
program/lib/MDB2/Driver/Manager/mysql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: mysql.php,v 1.10 0 2007/12/03 20:59:15quipo Exp $45 // $Id: mysql.php,v 1.108 2008/03/11 19:58:12 quipo Exp $ 46 46 // 47 47 … … 80 80 $query = 'CREATE DATABASE ' . $name; 81 81 if (!empty($options['charset'])) { 82 $query .= ' DEFAULT CHARACTER SET ' . $ options['charset'];82 $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); 83 83 } 84 84 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); 92 117 } 93 118 … … 111 136 $name = $db->quoteIdentifier($name, true); 112 137 $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); 118 139 } 119 140 … … 189 210 } 190 211 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 191 233 $query = $this->_getCreateTableQuery($name, $fields, $options); 192 234 if (PEAR::isError($query)) { 193 235 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); 194 241 } 195 242 … … 223 270 if (PEAR::isError($result)) { 224 271 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); 225 378 } 226 379 return MDB2_OK; … … 630 783 * 631 784 * @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() 658 810 * ) 811 * ) 812 * 659 813 * @return mixed MDB2_OK on success, a MDB2 error on failure 660 814 * @access public … … 801 955 } 802 956 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"; 805 959 if (!empty($definition['foreign'])) { 806 $query .= ' FOREIGN KEY ';960 $query .= ' FOREIGN KEY'; 807 961 } 808 962 $fields = array(); … … 820 974 $query .= $this->_getAdvancedFKOptions($definition); 821 975 } 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; 823 984 } 824 985 … … 842 1003 } 843 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 } 1025 844 1026 $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"; 851 1029 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; 852 1207 } 853 1208 … … 905 1260 $definition = $db->queryOne($query, 'text', 1); 906 1261 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) { 909 1264 foreach ($matches[1] as $constraint) { 910 1265 $result[$constraint] = true; … … 975 1330 } 976 1331 $res = $db->exec($query); 977 978 1332 if (PEAR::isError($res)) { 979 1333 return $res; -
program/lib/MDB2/Driver/Manager/mysqli.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: mysqli.php,v 1. 87 2007/12/03 20:59:15quipo Exp $45 // $Id: mysqli.php,v 1.95 2008/03/11 19:58:12 quipo Exp $ 46 46 // 47 47 … … 80 80 $query = 'CREATE DATABASE ' . $name; 81 81 if (!empty($options['charset'])) { 82 $query .= ' DEFAULT CHARACTER SET ' . $ options['charset'];82 $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text'); 83 83 } 84 84 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); 92 117 } 93 118 … … 111 136 $name = $db->quoteIdentifier($name, true); 112 137 $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); 118 139 } 119 140 … … 189 210 } 190 211 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 191 233 $query = $this->_getCreateTableQuery($name, $fields, $options); 192 234 if (PEAR::isError($query)) { 193 235 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); 194 241 } 195 242 … … 223 270 if (PEAR::isError($result)) { 224 271 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); 225 378 } 226 379 return MDB2_OK; … … 657 810 * ) 658 811 * ) 812 * 659 813 * @return mixed MDB2_OK on success, a MDB2 error on failure 660 814 * @access public … … 801 955 } 802 956 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"; 805 959 if (!empty($definition['foreign'])) { 806 $query .= ' FOREIGN KEY ';960 $query .= ' FOREIGN KEY'; 807 961 } 808 962 $fields = array(); … … 820 974 $query .= $this->_getAdvancedFKOptions($definition); 821 975 } 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; 823 984 } 824 985 … … 841 1002 return $db; 842 1003 } 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 } 843 1025 844 1026 $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"; 851 1029 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; 852 1207 } 853 1208 … … 905 1260 $definition = $db->queryOne($query, 'text', 1); 906 1261 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) { 909 1264 foreach ($matches[1] as $constraint) { 910 1265 $result[$constraint] = true; … … 970 1325 } 971 1326 972 if (!empty($options_strings)) {973 $query.= ' '.implode(' ', $options_strings);974 }975 976 1327 $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))"; 977 1328 if (!empty($options_strings)) { -
program/lib/MDB2/Driver/Manager/pgsql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: pgsql.php,v 1. 74 2007/12/03 20:59:15 quipoExp $45 // $Id: pgsql.php,v 1.82 2008/03/05 12:55:57 afz Exp $ 46 46 47 47 require_once 'MDB2/Driver/Manager/Common.php'; … … 83 83 84 84 // }}} 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 // }}} 85 114 // {{{ dropDatabase() 86 115 … … 100 129 101 130 $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); 103 133 } 104 134 … … 137 167 } 138 168 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); 139 232 } 140 233 … … 257 350 } 258 351 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; 262 356 $result = $db->exec("ALTER TABLE $name $query"); 263 357 if (PEAR::isError($result)) { … … 267 361 } 268 362 269 if (!empty($changes['re move']) && is_array($changes['remove'])) {270 foreach ($changes['re move'] as $field_name => $field) {363 if (!empty($changes['rename']) && is_array($changes['rename'])) { 364 foreach ($changes['rename'] as $field_name => $field) { 271 365 $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); 273 376 $result = $db->exec("ALTER TABLE $name $query"); 274 377 if (PEAR::isError($result)) { … … 314 417 } 315 418 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 326 419 $name = $db->quoteIdentifier($name, true); 327 420 if (!empty($changes['name'])) { … … 663 756 664 757 $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; 668 762 $constraints = $db->queryCol($query); 669 763 if (PEAR::isError($constraints)) { -
program/lib/MDB2/Driver/Manager/sqlite.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith, Lorenzo Alberton | 7 7 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: sqlite.php,v 1.7 2 2007/12/03 20:59:15quipo Exp $46 // $Id: sqlite.php,v 1.74 2008/03/05 11:08:53 quipo Exp $ 47 47 // 48 48 … … 402 402 $name = $db->quoteIdentifier($name, true); 403 403 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); 404 435 } 405 436 … … 1208 1239 return $table_def; 1209 1240 } 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)) { 1211 1242 $result['primary'] = true; 1212 1243 } -
program/lib/MDB2/Driver/Reverse/Common.php
r95ebbc98 rd1403fd 43 43 // +----------------------------------------------------------------------+ 44 44 // 45 // $Id: Common.php,v 1.4 1 2007/09/09 13:47:36quipo Exp $45 // $Id: Common.php,v 1.42 2008/01/12 12:50:58 quipo Exp $ 46 46 // 47 47 … … 467 467 } 468 468 469 $res = array(); 470 469 471 if ($mode) { 470 472 $res['num_fields'] = count($fields); -
program/lib/MDB2/Driver/Reverse/mssql.php
r95ebbc98 rd1403fd 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: mssql.php,v 1.4 8 2007/11/25 13:38:29quipo Exp $46 // $Id: mssql.php,v 1.49 2008/02/17 15:30:57 quipo Exp $ 47 47 // 48 48 … … 455 455 $trg_body = $db->queryCol('EXEC sp_helptext '. $db->quote($trigger, 'text'), 'text'); 456 456 if (!PEAR::isError($trg_body)) { 457 $def['trigger_body'] = implode(' ', $trg_body);457 $def['trigger_body'] = implode(' ', $trg_body); 458 458 } 459 459 return $def; -
program/lib/MDB2/Driver/Reverse/pgsql.php
r95ebbc98 rd1403fd 3 3 // | PHP versions 4 and 5 | 4 4 // +----------------------------------------------------------------------+ 5 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |5 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 6 6 // | Stig. S. Bakken, Lukas Smith | 7 7 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 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 $ 47 47 48 48 require_once 'MDB2/Driver/Reverse/Common.php'; … … 359 359 FROM pg_constraint c 360 360 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.con key)361 LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey) 362 362 WHERE c.conname = %s 363 363 AND t.relname = ' . $db->quote($definition['references']['table'], 'text'); … … 425 425 WHEN 12 THEN 'INSERT, DELETE' 426 426 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, 428 431 obj_description(trg.oid, 'pg_trigger') AS trigger_comment 429 432 FROM pg_trigger trg, -
program/lib/MDB2/Driver/Reverse/sqlite.php
r95ebbc98 rd1403fd 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: sqlite.php,v 1.7 8 2007/12/01 10:46:13 quipo Exp $46 // $Id: sqlite.php,v 1.79 2008/03/05 11:08:53 quipo Exp $ 47 47 // 48 48 … … 394 394 return $definition; 395 395 } 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 } 396 408 } else { 397 409 // search in table definition for FOREIGN KEYs -
program/lib/MDB2/Driver/mssql.php
r95ebbc98 rd1403fd 4 4 // | PHP versions 4 and 5 | 5 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |6 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 7 7 // | Stig. S. Bakken, Lukas Smith, Frank M. Kromann | 8 8 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: mssql.php,v 1.1 61 2007/11/18 17:52:00quipo Exp $46 // $Id: mssql.php,v 1.174 2008/03/08 14:18:39 quipo Exp $ 47 47 // 48 48 // {{{ Class MDB2_Driver_mssql … … 87 87 $this->supported['replace'] = 'emulated'; 88 88 $this->supported['sub_selects'] = true; 89 $this->supported['triggers'] = true; 89 90 $this->supported['auto_increment'] = true; 90 91 $this->supported['primary_key'] = true; … … 94 95 $this->supported['new_link'] = true; 95 96 97 $this->options['DBA_username'] = false; 98 $this->options['DBA_password'] = false; 96 99 $this->options['database_device'] = false; 97 100 $this->options['database_size'] = false; 101 $this->options['max_identifiers_length'] = 128; // MS Access: 64 98 102 } 99 103 … … 108 112 * @access public 109 113 */ 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 112 120 $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); 115 123 if ($result) { 116 124 $native_code = @mssql_result($result, 0, 0); … … 137 145 515 => MDB2_ERROR_CONSTRAINT_NOT_NULL, 138 146 547 => MDB2_ERROR_CONSTRAINT, 147 911 => MDB2_ERROR_NOT_FOUND, 139 148 1018 => MDB2_ERROR_SYNTAX, 140 149 1035 => MDB2_ERROR_SYNTAX, 150 1801 => MDB2_ERROR_ALREADY_EXISTS, 141 151 1913 => MDB2_ERROR_ALREADY_EXISTS, 142 152 2209 => MDB2_ERROR_SYNTAX, … … 297 307 298 308 // }}} 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 // }}} 299 371 // {{{ connect() 300 372 … … 316 388 } 317 389 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'] 327 394 ); 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 } 363 398 364 399 $this->connection = $connection; … … 380 415 381 416 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; 382 452 } 383 453 … … 418 488 419 489 // }}} 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 // }}} 420 526 // {{{ _doQuery() 421 527 … … 547 653 $this->connected_server_info = $server_info; 548 654 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)) { 550 656 $server_info = array( 551 657 'major' => $tmp[1], … … 610 716 $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); 611 717 $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); 718 $this->pushErrorHandling(PEAR_ERROR_RETURN); 612 719 $this->expectError(MDB2_ERROR_NOSUCHTABLE); 613 720 … … 622 729 $result =& $this->_doQuery($query, true); 623 730 $this->popExpect(); 731 $this->popErrorHandling(); 624 732 if (PEAR::isError($result)) { 625 733 if ($ondemand && !$this->_checkSequence($sequence_name)) { … … 670 778 * @param string $table name of the table into which a new row was inserted 671 779 * @param string $field name of the field into which a new row was inserted 780 * 672 781 * @return mixed MDB2 Error Object or id 673 782 * @access public … … 679 788 && $server_info['major'] >= 8 680 789 ) { 681 $query = "SELECT SCOPE_IDENTITY()";790 $query = "SELECT IDENT_CURRENT('$table')"; 682 791 } else { 683 792 $query = "SELECT @@IDENTITY"; 793 if (!is_null($table)) { 794 $query .= ' FROM '.$this->quoteIdentifier($table, true); 795 } 684 796 } 685 797 -
program/lib/MDB2/Driver/mysql.php
r95ebbc98 rd1403fd 4 4 // | PHP versions 4 and 5 | 5 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |6 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 7 7 // | Stig. S. Bakken, Lukas Smith | 8 8 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: mysql.php,v 1. 195 2007/11/10 13:27:03 quipoExp $46 // $Id: mysql.php,v 1.208 2008/03/13 03:31:55 afz Exp $ 47 47 // 48 48 … … 99 99 $this->supported['replace'] = true; 100 100 $this->supported['sub_selects'] = 'emulated'; 101 $this->supported['triggers'] = false; 101 102 $this->supported['auto_increment'] = true; 102 103 $this->supported['primary_key'] = true; … … 107 108 $this->supported['new_link'] = true; 108 109 110 $this->options['DBA_username'] = false; 111 $this->options['DBA_password'] = false; 109 112 $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(); 110 170 } 111 171 … … 178 238 1217 => MDB2_ERROR_CONSTRAINT, 179 239 1227 => MDB2_ERROR_ACCESS_VIOLATION, 240 1235 => MDB2_ERROR_CANNOT_CREATE, 180 241 1299 => MDB2_ERROR_INVALID_DATE, 181 242 1300 => MDB2_ERROR_INVALID, … … 196 257 1546 => MDB2_ERROR_CONSTRAINT, 197 258 1582 => MDB2_ERROR_CONSTRAINT, 259 2003 => MDB2_ERROR_CONNECT_FAILED, 260 2019 => MDB2_ERROR_INVALID, 198 261 ); 199 262 } … … 423 486 424 487 // }}} 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 { 445 498 if (!PEAR::loadExtension($this->phptype)) { 446 499 return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, … … 458 511 } 459 512 } 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) { 463 516 if (isset($this->dsn['new_link']) 464 517 && ($this->dsn['new_link'] == 'true' || $this->dsn['new_link'] === true) … … 473 526 ? $this->dsn['client_flags'] : null; 474 527 } 475 $connect_function = $ this->options['persistent']? 'mysql_pconnect' : 'mysql_connect';528 $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; 476 529 477 530 $connection = @call_user_func_array($connect_function, $params); … … 489 542 $result = $this->setCharset($this->dsn['charset'], $connection); 490 543 if (PEAR::isError($result)) { 544 $this->disconnect(false); 491 545 return $result; 492 546 } 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; 493 580 } 494 581 … … 510 597 } 511 598 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 533 599 $this->_getServerCapabilities(); 534 600 … … 542 608 * Set the charset on the current connection 543 609 * 544 * @param string charset 610 * @param string charset (or array(charset, collation)) 545 611 * @param resource connection handle 546 612 * … … 555 621 } 556 622 } 623 $collation = null; 624 if (is_array($charset) && 2 == count($charset)) { 625 $collation = array_pop($charset); 626 $charset = array_pop($charset); 627 } 557 628 $query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'"; 629 if (!is_null($collation)) { 630 $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; 631 } 558 632 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; 559 659 } 560 660 … … 595 695 596 696 // }}} 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 // }}} 597 733 // {{{ _doQuery() 598 734 … … 794 930 $this->supported['sub_selects'] = 'emulated'; 795 931 $this->supported['prepared_statements'] = 'emulated'; 932 $this->supported['triggers'] = false; 796 933 $this->start_transaction = false; 797 934 $this->varchar_max_length = 255; … … 799 936 $server_info = $this->getServerVersion(); 800 937 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', '<')) { 802 941 $this->supported['sub_selects'] = true; 803 942 $this->supported['prepared_statements'] = true; 804 943 } 805 944 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; 810 952 } 811 953 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', '<')) { 813 955 $this->start_transaction = true; 814 956 } 815 957 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', '<')) { 817 959 $this->varchar_max_length = 65532; 960 } 961 962 if (!version_compare($server_version, '5.0.2', '<')) { 963 $this->supported['triggers'] = true; 818 964 } 819 965 } … … 959 1105 } 960 1106 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']); 962 1109 $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text'); 963 1110 $statement =& $this->_doQuery($query, true, $connection); … … 1050 1197 $values.= ','; 1051 1198 } 1052 $query.= $ name;1199 $query.= $this->quoteIdentifier($name, true); 1053 1200 if (isset($fields[$name]['null']) && $fields[$name]['null']) { 1054 1201 $value = 'NULL'; … … 1079 1226 } 1080 1227 1228 $table = $this->quoteIdentifier($table, true); 1081 1229 $query = "REPLACE INTO $table ($query) VALUES ($values)"; 1082 1230 $result =& $this->_doQuery($query, true, $connection); … … 1106 1254 $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); 1107 1255 $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; 1256 $this->pushErrorHandling(PEAR_ERROR_RETURN); 1108 1257 $this->expectError(MDB2_ERROR_NOSUCHTABLE); 1109 1258 $result =& $this->_doQuery($query, true); 1110 1259 $this->popExpect(); 1260 $this->popErrorHandling(); 1111 1261 if (PEAR::isError($result)) { 1112 1262 if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { -
program/lib/MDB2/Driver/mysqli.php
r95ebbc98 rd1403fd 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: mysqli.php,v 1.1 76 2007/11/10 13:27:03 quipoExp $46 // $Id: mysqli.php,v 1.188 2008/03/13 03:31:55 afz Exp $ 47 47 // 48 48 … … 99 99 $this->supported['replace'] = true; 100 100 $this->supported['sub_selects'] = 'emulated'; 101 $this->supported['triggers'] = false; 101 102 $this->supported['auto_increment'] = true; 102 103 $this->supported['primary_key'] = true; … … 107 108 $this->supported['new_link'] = true; 108 109 110 $this->options['DBA_username'] = false; 111 $this->options['DBA_password'] = false; 109 112 $this->options['default_table_type'] = ''; 110 113 $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(); 111 171 } 112 172 … … 179 239 1217 => MDB2_ERROR_CONSTRAINT, 180 240 1227 => MDB2_ERROR_ACCESS_VIOLATION, 241 1235 => MDB2_ERROR_CANNOT_CREATE, 181 242 1299 => MDB2_ERROR_INVALID_DATE, 182 243 1300 => MDB2_ERROR_INVALID, … … 197 258 1546 => MDB2_ERROR_CONSTRAINT, 198 259 1582 => MDB2_ERROR_CONSTRAINT, 260 2003 => MDB2_ERROR_CONNECT_FAILED, 199 261 2019 => MDB2_ERROR_INVALID, 200 262 ); … … 421 483 422 484 // }}} 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 { 440 495 if (!PEAR::loadExtension($this->phptype)) { 441 496 return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null, … … 447 502 @mysqli_options($connection, MYSQLI_SET_CHARSET_NAME, $this->dsn['charset']); 448 503 } 449 450 504 451 505 if ($this->options['ssl']) { … … 463 517 $connection, 464 518 $this->dsn['hostspec'], 465 $ this->dsn['username'],466 $ this->dsn['password'],519 $username, 520 $password, 467 521 $this->database_name, 468 522 $this->dsn['port'], 469 523 $this->dsn['socket'] 470 524 )) { 471 472 525 if (($err = @mysqli_connect_error()) != '') { 473 526 return $this->raiseError(null, … … 486 539 } 487 540 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 488 570 $this->connection = $connection; 489 571 $this->connected_dsn = $this->dsn; … … 491 573 $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; 492 574 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 514 575 $this->_getServerCapabilities(); 515 576 … … 523 584 * Set the charset on the current connection 524 585 * 525 * @param string charset 586 * @param string charset (or array(charset, collation)) 526 587 * @param resource connection handle 527 588 * … … 535 596 return $connection; 536 597 } 598 } 599 $collation = null; 600 if (is_array($charset) && 2 == count($charset)) { 601 $collation = array_pop($charset); 602 $charset = array_pop($charset); 537 603 } 538 604 $client_info = mysqli_get_client_version(); … … 541 607 ) { 542 608 $query = "SET NAMES '".mysqli_real_escape_string($connection, $charset)."'"; 609 if (!is_null($collation)) { 610 $query .= " COLLATE '".mysqli_real_escape_string($connection, $collation)."'"; 611 } 543 612 return $this->_doQuery($query, true, $connection); 544 613 } … … 548 617 return $err; 549 618 } 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 550 644 return $result; 551 645 } … … 587 681 588 682 // }}} 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 // }}} 589 719 // {{{ _doQuery() 590 720 … … 804 934 $this->supported['sub_selects'] = 'emulated'; 805 935 $this->supported['prepared_statements'] = 'emulated'; 936 $this->supported['triggers'] = false; 806 937 $this->start_transaction = false; 807 938 $this->varchar_max_length = 255; … … 809 940 $server_info = $this->getServerVersion(); 810 941 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', '<')) { 812 945 $this->supported['sub_selects'] = true; 813 946 $this->supported['prepared_statements'] = true; 814 947 } 815 948 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; 820 956 } 821 957 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', '<')) { 823 959 $this->start_transaction = true; 824 960 } 825 961 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', '<')) { 827 963 $this->varchar_max_length = 65532; 964 } 965 966 if (!version_compare($server_version, '5.0.2', '<')) { 967 $this->supported['triggers'] = true; 828 968 } 829 969 } … … 971 1111 if (!$is_manip) { 972 1112 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']); 974 1115 $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text'); 975 1116 … … 1072 1213 $values.= ','; 1073 1214 } 1074 $query.= $ name;1215 $query.= $this->quoteIdentifier($name, true); 1075 1216 if (isset($fields[$name]['null']) && $fields[$name]['null']) { 1076 1217 $value = 'NULL'; … … 1101 1242 } 1102 1243 1244 $table = $this->quoteIdentifier($table, true); 1103 1245 $query = "REPLACE INTO $table ($query) VALUES ($values)"; 1104 1246 $result =& $this->_doQuery($query, true, $connection); … … 1128 1270 $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true); 1129 1271 $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; 1272 $this->pushErrorHandling(PEAR_ERROR_RETURN); 1130 1273 $this->expectError(MDB2_ERROR_NOSUCHTABLE); 1131 1274 $result =& $this->_doQuery($query, true); 1132 1275 $this->popExpect(); 1276 $this->popErrorHandling(); 1133 1277 if (PEAR::isError($result)) { 1134 1278 if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { -
program/lib/MDB2/Driver/pgsql.php
r95ebbc98 rd1403fd 4 4 // | PHP versions 4 and 5 | 5 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1998-200 6Manuel Lemos, Tomas V.V.Cox, |6 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 7 7 // | Stig. S. Bakken, Lukas Smith | 8 8 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: pgsql.php,v 1.1 86 2007/11/10 13:27:03quipo Exp $46 // $Id: pgsql.php,v 1.197 2008/03/08 14:18:39 quipo Exp $ 47 47 48 48 /** … … 84 84 $this->supported['replace'] = 'emulated'; 85 85 $this->supported['sub_selects'] = true; 86 $this->supported['triggers'] = true; 86 87 $this->supported['auto_increment'] = 'emulated'; 87 88 $this->supported['primary_key'] = true; … … 92 93 $this->supported['new_link'] = true; 93 94 95 $this->options['DBA_username'] = false; 96 $this->options['DBA_password'] = false; 94 97 $this->options['multi_query'] = false; 95 98 $this->options['disable_smart_seqname'] = false; 99 $this->options['max_identifiers_length'] = 63; 96 100 } 97 101 … … 120 124 $error_code = MDB2_ERROR_CONNECT_FAILED; 121 125 } 126 } else { 127 $native_msg = @pg_last_error(); 122 128 } 123 129 … … 129 135 '/(relation|sequence|table).*does not exist|class .* not found/i' 130 136 => MDB2_ERROR_NOSUCHTABLE, 137 '/database .* does not exist/' 138 => MDB2_ERROR_NOT_FOUND, 131 139 '/index .* does not exist/' 132 140 => MDB2_ERROR_NOT_FOUND, 141 '/database .* already exists/i' 142 => MDB2_ERROR_ALREADY_EXISTS, 133 143 '/relation .* already exists/i' 134 144 => MDB2_ERROR_ALREADY_EXISTS, … … 203 213 return $connection; 204 214 } 205 if ( version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {215 if (is_resource($connection) && version_compare(PHP_VERSION, '5.2.0RC5', '>=')) { 206 216 $text = @pg_escape_string($connection, $text); 207 217 } else { … … 354 364 355 365 /** 356 * Do esthe grunt work of connecting to the database366 * Do the grunt work of connecting to the database 357 367 * 358 368 * @return mixed connection resource on success, MDB2 Error Object on failure 359 369 * @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 363 378 if ($database_name == '') { 364 379 $database_name = 'template1'; … … 387 402 $params[0].= ' dbname=\'' . addslashes($database_name) . '\''; 388 403 } 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) . '\''; 394 409 } 395 410 if (!empty($this->dsn['options'])) { … … 418 433 419 434 $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; 420 421 435 $connection = @call_user_func_array($connect_function, $params); 422 436 if (!$connection) { … … 450 464 * @return true on success, MDB2 Error Object on failure 451 465 * @access public 452 * */466 */ 453 467 function connect() 454 468 { … … 464 478 } 465 479 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 471 480 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']); 473 485 if (PEAR::isError($connection)) { 474 486 return $connection; 475 487 } 488 476 489 $this->connection = $connection; 477 490 $this->connected_dsn = $this->dsn; … … 480 493 $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype; 481 494 } 495 482 496 return MDB2_OK; 483 497 } … … 502 516 } 503 517 } 504 518 if (is_array($charset)) { 519 $charset = array_shift($charset); 520 $this->warnings[] = 'postgresql does not support setting client collation'; 521 } 505 522 $result = @pg_set_client_encoding($connection, $charset); 506 523 if ($result == -1) { … … 509 526 } 510 527 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; 511 552 } 512 553 … … 561 602 function &standaloneQuery($query, $types = null, $is_manip = false) 562 603 { 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']); 564 607 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; 568 609 } 569 610 … … 573 614 $query = $this->_modifyQuery($query, $is_manip, $limit, $offset); 574 615 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 576 625 @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);586 626 return $result; 587 627 } … … 911 951 } 912 952 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 = s trtolower($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']); 915 955 if ($pgtypes === false) { 916 956 $result = @pg_prepare($connection, $statement_name, $query); … … 976 1016 AND d.adnum = a.attnum 977 1017 AND a.atthasdef 978 ) FROM 'nextval[^ \']*\'([^\']*)')1018 ) FROM 'nextval[^'']*''([^'']*)') 979 1019 FROM pg_attribute a 980 1020 LEFT JOIN pg_class c ON c.oid = a.attrelid … … 1018 1058 $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true); 1019 1059 $query = "SELECT NEXTVAL('$sequence_name')"; 1060 $this->pushErrorHandling(PEAR_ERROR_RETURN); 1020 1061 $this->expectError(MDB2_ERROR_NOSUCHTABLE); 1021 1062 $result = $this->queryOne($query, 'integer'); 1022 1063 $this->popExpect(); 1064 $this->popErrorHandling(); 1023 1065 if (PEAR::isError($result)) { 1024 1066 if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) { … … 1053 1095 } 1054 1096 $seq = $table.(empty($field) ? '' : '_'.$field); 1055 $sequence_name = $this-> getSequenceName($seq);1097 $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true); 1056 1098 return $this->queryOne("SELECT currval('$sequence_name')", 'integer'); 1057 1099 } -
program/lib/MDB2/Driver/sqlite.php
r95ebbc98 rd1403fd 4 4 // | PHP versions 4 and 5 | 5 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1998-200 7Manuel Lemos, Tomas V.V.Cox, |6 // | Copyright (c) 1998-2008 Manuel Lemos, Tomas V.V.Cox, | 7 7 // | Stig. S. Bakken, Lukas Smith | 8 8 // | All rights reserved. | … … 44 44 // +----------------------------------------------------------------------+ 45 45 // 46 // $Id: sqlite.php,v 1.15 2 2007/11/27 07:44:41quipo Exp $46 // $Id: sqlite.php,v 1.158 2008/03/08 14:18:39 quipo Exp $ 47 47 // 48 48 … … 90 90 $this->supported['savepoints'] = false; 91 91 $this->supported['sub_selects'] = true; 92 $this->supported['triggers'] = true; 92 93 $this->supported['auto_increment'] = true; 93 94 $this->supported['primary_key'] = false; // requires alter table implementation … … 98 99 $this->supported['new_link'] = false; 99 100 101 $this->options['DBA_username'] = false; 102 $this->options['DBA_password'] = false; 100 103 $this->options['base_transaction_name'] = '___php_MDB2_sqlite_auto_commit_off'; 101 104 $this->options['fixed_float'] = 0; … … 103 106 $this->options['database_extension'] = ''; 104 107 $this->options['server_version'] = ''; 108 $this->options['max_identifiers_length'] = 128; //no real limit 105 109 } 106 110 … … 126 130 // PHP 5.2+ prepends the function name to $php_errormsg, so we need 127 131 // 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); 129 133 130 134 if (is_null($error)) { … … 426 430 427 431 // }}} 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 // }}} 428 450 // {{{ disconnect() 429 451 … … 722 744 $values.= ','; 723 745 } 724 $query.= $ name;746 $query.= $this->quoteIdentifier($name, true); 725 747 if (isset($fields[$name]['null']) && $fields[$name]['null']) { 726 748 $value = 'NULL'; … … 751 773 } 752 774 775 $table = $this->quoteIdentifier($table, true); 753 776 $query = "REPLACE INTO $table ($query) VALUES ($values)"; 754 777 $result =& $this->_doQuery($query, true, $connection); … … 778 801 $seqcol_name = $this->options['seqcol_name']; 779 802 $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)"; 803 $this->pushErrorHandling(PEAR_ERROR_RETURN); 780 804 $this->expectError(MDB2_ERROR_NOSUCHTABLE); 781 805 $result =& $this->_doQuery($query, true); 782 806 $this->popExpect(); 807 $this->popErrorHandling(); 783 808 if (PEAR::isError($result)) { 784 809 if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
Note: See TracChangeset
for help on using the changeset viewer.
