[ Index ] |
|
Code source de SPIP Agora 1.4 |
1 <?php 2 /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ 3 // +----------------------------------------------------------------------+ 4 // | PHP Version 4 | 5 // +----------------------------------------------------------------------+ 6 // | Copyright (c) 1997-2004 The PHP Group | 7 // +----------------------------------------------------------------------+ 8 // | This source file is subject to version 2.02 of the PHP license, | 9 // | that is bundled with this package in the file LICENSE, and is | 10 // | available at through the world-wide-web at | 11 // | http://www.php.net/license/2_02.txt. | 12 // | If you did not receive a copy of the PHP license and are unable to | 13 // | obtain it through the world-wide-web, please send a note to | 14 // | license@php.net so we can mail you a copy immediately. | 15 // +----------------------------------------------------------------------+ 16 // | Author: Stig Bakken <ssb@php.net> | 17 // | Maintainer: Daniel Convissor <danielc@php.net> | 18 // +----------------------------------------------------------------------+ 19 // 20 // $Id: odbc.php,v 1.47 2004/10/04 17:14:32 danielc Exp $ 21 22 23 // XXX legend: 24 // More info on ODBC errors could be found here: 25 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp 26 // 27 // XXX ERRORMSG: The error message from the odbc function should 28 // be registered here. 29 30 31 require_once 'DB/common.php'; 32 33 /** 34 * Database independent query interface definition for PHP's ODBC 35 * extension. 36 * 37 * @package DB 38 * @version $Id: odbc.php,v 1.47 2004/10/04 17:14:32 danielc Exp $ 39 * @category Database 40 * @author Stig Bakken <ssb@php.net> 41 */ 42 class DB_odbc extends DB_common 43 { 44 // {{{ properties 45 46 var $connection; 47 var $phptype, $dbsyntax; 48 var $row = array(); 49 50 // }}} 51 // {{{ constructor 52 53 function DB_odbc() 54 { 55 $this->DB_common(); 56 $this->phptype = 'odbc'; 57 $this->dbsyntax = 'sql92'; 58 $this->features = array( 59 'prepare' => true, 60 'pconnect' => true, 61 'transactions' => false, 62 'limit' => 'emulate' 63 ); 64 $this->errorcode_map = array( 65 '01004' => DB_ERROR_TRUNCATED, 66 '07001' => DB_ERROR_MISMATCH, 67 '21S01' => DB_ERROR_MISMATCH, 68 '21S02' => DB_ERROR_MISMATCH, 69 '22003' => DB_ERROR_INVALID_NUMBER, 70 '22005' => DB_ERROR_INVALID_NUMBER, 71 '22008' => DB_ERROR_INVALID_DATE, 72 '22012' => DB_ERROR_DIVZERO, 73 '23000' => DB_ERROR_CONSTRAINT, 74 '23502' => DB_ERROR_CONSTRAINT_NOT_NULL, 75 '23503' => DB_ERROR_CONSTRAINT, 76 '23505' => DB_ERROR_CONSTRAINT, 77 '24000' => DB_ERROR_INVALID, 78 '34000' => DB_ERROR_INVALID, 79 '37000' => DB_ERROR_SYNTAX, 80 '42000' => DB_ERROR_SYNTAX, 81 '42601' => DB_ERROR_SYNTAX, 82 'IM001' => DB_ERROR_UNSUPPORTED, 83 'S0000' => DB_ERROR_NOSUCHTABLE, 84 'S0001' => DB_ERROR_ALREADY_EXISTS, 85 'S0002' => DB_ERROR_NOSUCHTABLE, 86 'S0011' => DB_ERROR_ALREADY_EXISTS, 87 'S0012' => DB_ERROR_NOT_FOUND, 88 'S0021' => DB_ERROR_ALREADY_EXISTS, 89 'S0022' => DB_ERROR_NOSUCHFIELD, 90 'S1000' => DB_ERROR_CONSTRAINT_NOT_NULL, 91 'S1009' => DB_ERROR_INVALID, 92 'S1090' => DB_ERROR_INVALID, 93 'S1C00' => DB_ERROR_NOT_CAPABLE 94 ); 95 } 96 97 // }}} 98 // {{{ connect() 99 100 /** 101 * Connect to a database and log in as the specified user. 102 * 103 * @param $dsn the data source name (see DB::parseDSN for syntax) 104 * @param $persistent (optional) whether the connection should 105 * be persistent 106 * 107 * @return int DB_OK on success, a DB error code on failure 108 */ 109 function connect($dsninfo, $persistent = false) 110 { 111 if (!DB::assertExtension('odbc')) { 112 return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); 113 } 114 115 $this->dsn = $dsninfo; 116 if ($dsninfo['dbsyntax']) { 117 $this->dbsyntax = $dsninfo['dbsyntax']; 118 } 119 switch ($this->dbsyntax) { 120 case 'solid': 121 $this->features = array( 122 'prepare' => true, 123 'pconnect' => true, 124 'transactions' => true 125 ); 126 break; 127 case 'navision': 128 // the Navision driver doesn't support fetch row by number 129 $this->features['limit'] = false; 130 } 131 132 /* 133 * This is hear for backwards compatibility. 134 * Should have been using 'database' all along, but used hostspec. 135 */ 136 if ($dsninfo['database']) { 137 $odbcdsn = $dsninfo['database']; 138 } elseif ($dsninfo['hostspec']) { 139 $odbcdsn = $dsninfo['hostspec']; 140 } else { 141 $odbcdsn = 'localhost'; 142 } 143 144 if ($this->provides('pconnect')) { 145 $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect'; 146 } else { 147 $connect_function = 'odbc_connect'; 148 } 149 150 if (empty($dsninfo['cursor'])) { 151 $conn = @$connect_function($odbcdsn, $dsninfo['username'], 152 $dsninfo['password']); 153 } else { 154 $conn = @$connect_function($odbcdsn, $dsninfo['username'], 155 $dsninfo['password'], 156 $dsninfo['cursor']); 157 } 158 159 if (!is_resource($conn)) { 160 return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null, 161 null, $this->errorNative()); 162 } 163 $this->connection = $conn; 164 return DB_OK; 165 } 166 167 // }}} 168 // {{{ disconnect() 169 170 function disconnect() 171 { 172 $err = @odbc_close($this->connection); 173 $this->connection = null; 174 return $err; 175 } 176 177 // }}} 178 // {{{ simpleQuery() 179 180 /** 181 * Send a query to ODBC and return the results as a ODBC resource 182 * identifier. 183 * 184 * @param $query the SQL query 185 * 186 * @return int returns a valid ODBC result for successful SELECT 187 * queries, DB_OK for other successful queries. A DB error code 188 * is returned on failure. 189 */ 190 function simpleQuery($query) 191 { 192 $this->last_query = $query; 193 $query = $this->modifyQuery($query); 194 $result = @odbc_exec($this->connection, $query); 195 if (!$result) { 196 return $this->odbcRaiseError(); // XXX ERRORMSG 197 } 198 // Determine which queries that should return data, and which 199 // should return an error code only. 200 if (DB::isManip($query)) { 201 $this->manip_result = $result; // For affectedRows() 202 return DB_OK; 203 } 204 $this->row[(int)$result] = 0; 205 $this->manip_result = 0; 206 return $result; 207 } 208 209 // }}} 210 // {{{ nextResult() 211 212 /** 213 * Move the internal odbc result pointer to the next available result 214 * 215 * @param a valid fbsql result resource 216 * 217 * @access public 218 * 219 * @return true if a result is available otherwise return false 220 */ 221 function nextResult($result) 222 { 223 return @odbc_next_result($result); 224 } 225 226 // }}} 227 // {{{ fetchInto() 228 229 /** 230 * Fetch a row and insert the data into an existing array. 231 * 232 * Formating of the array and the data therein are configurable. 233 * See DB_result::fetchInto() for more information. 234 * 235 * @param resource $result query result identifier 236 * @param array $arr (reference) array where data from the row 237 * should be placed 238 * @param int $fetchmode how the resulting array should be indexed 239 * @param int $rownum the row number to fetch 240 * 241 * @return mixed DB_OK on success, null when end of result set is 242 * reached or on failure 243 * 244 * @see DB_result::fetchInto() 245 * @access private 246 */ 247 function fetchInto($result, &$arr, $fetchmode, $rownum=null) 248 { 249 $arr = array(); 250 if ($rownum !== null) { 251 $rownum++; // ODBC first row is 1 252 if (version_compare(phpversion(), '4.2.0', 'ge')) { 253 $cols = @odbc_fetch_into($result, $arr, $rownum); 254 } else { 255 $cols = @odbc_fetch_into($result, $rownum, $arr); 256 } 257 } else { 258 $cols = @odbc_fetch_into($result, $arr); 259 } 260 261 if (!$cols) { 262 /* XXX FIXME: doesn't work with unixODBC and easysoft 263 (get corrupted $errno values) 264 if ($errno = @odbc_error($this->connection)) { 265 return $this->RaiseError($errno); 266 }*/ 267 return null; 268 } 269 if ($fetchmode !== DB_FETCHMODE_ORDERED) { 270 for ($i = 0; $i < count($arr); $i++) { 271 $colName = @odbc_field_name($result, $i+1); 272 $a[$colName] = $arr[$i]; 273 } 274 if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { 275 $a = array_change_key_case($a, CASE_LOWER); 276 } 277 $arr = $a; 278 } 279 if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { 280 $this->_rtrimArrayValues($arr); 281 } 282 if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { 283 $this->_convertNullArrayValuesToEmpty($arr); 284 } 285 return DB_OK; 286 } 287 288 // }}} 289 // {{{ freeResult() 290 291 function freeResult($result) 292 { 293 unset($this->row[(int)$result]); 294 return @odbc_free_result($result); 295 } 296 297 // }}} 298 // {{{ numCols() 299 300 function numCols($result) 301 { 302 $cols = @odbc_num_fields($result); 303 if (!$cols) { 304 return $this->odbcRaiseError(); 305 } 306 return $cols; 307 } 308 309 // }}} 310 // {{{ affectedRows() 311 312 /** 313 * Returns the number of rows affected by a manipulative query 314 * (INSERT, DELETE, UPDATE) 315 * @return mixed int affected rows, 0 when non manip queries or 316 * DB error on error 317 */ 318 function affectedRows() 319 { 320 if (empty($this->manip_result)) { // In case of SELECT stms 321 return 0; 322 } 323 $nrows = @odbc_num_rows($this->manip_result); 324 if ($nrows == -1) { 325 return $this->odbcRaiseError(); 326 } 327 return $nrows; 328 } 329 330 // }}} 331 // {{{ numRows() 332 333 /** 334 * ODBC may or may not support counting rows in the result set of 335 * SELECTs. 336 * 337 * @param $result the odbc result resource 338 * @return the number of rows, or 0 339 */ 340 function numRows($result) 341 { 342 $nrows = @odbc_num_rows($result); 343 if ($nrows == -1) { 344 return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED); 345 } 346 return $nrows; 347 } 348 349 // }}} 350 // {{{ quoteIdentifier() 351 352 /** 353 * Quote a string so it can be safely used as a table / column name 354 * 355 * Quoting style depends on which dbsyntax was passed in the DSN. 356 * 357 * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked 358 * "Use ANSI quoted identifiers" when setting up the ODBC data source. 359 * 360 * @param string $str identifier name to be quoted 361 * 362 * @return string quoted identifier string 363 * 364 * @since 1.6.0 365 * @access public 366 */ 367 function quoteIdentifier($str) 368 { 369 switch ($this->dsn['dbsyntax']) { 370 case 'access': 371 return '[' . $str . ']'; 372 case 'mssql': 373 case 'sybase': 374 return '[' . str_replace(']', ']]', $str) . ']'; 375 case 'mysql': 376 case 'mysqli': 377 return '`' . $str . '`'; 378 default: 379 return '"' . str_replace('"', '""', $str) . '"'; 380 } 381 } 382 383 // }}} 384 // {{{ quote() 385 386 /** 387 * @deprecated Deprecated in release 1.6.0 388 * @internal 389 */ 390 function quote($str) { 391 return $this->quoteSmart($str); 392 } 393 394 // }}} 395 // {{{ errorNative() 396 397 /** 398 * Get the native error code of the last error (if any) that 399 * occured on the current connection. 400 * 401 * @access public 402 * 403 * @return int ODBC error code 404 */ 405 function errorNative() 406 { 407 if (!isset($this->connection) || !is_resource($this->connection)) { 408 return @odbc_error() . ' ' . @odbc_errormsg(); 409 } 410 return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection); 411 } 412 413 // }}} 414 // {{{ nextId() 415 416 /** 417 * Returns the next free id in a sequence 418 * 419 * @param string $seq_name name of the sequence 420 * @param boolean $ondemand when true, the seqence is automatically 421 * created if it does not exist 422 * 423 * @return int the next id number in the sequence. DB_Error if problem. 424 * 425 * @internal 426 * @see DB_common::nextID() 427 * @access public 428 */ 429 function nextId($seq_name, $ondemand = true) 430 { 431 $seqname = $this->getSequenceName($seq_name); 432 $repeat = 0; 433 do { 434 $this->pushErrorHandling(PEAR_ERROR_RETURN); 435 $result = $this->query("update $seqname} set id = id + 1"); 436 $this->popErrorHandling(); 437 if ($ondemand && DB::isError($result) && 438 $result->getCode() == DB_ERROR_NOSUCHTABLE) { 439 $repeat = 1; 440 $this->pushErrorHandling(PEAR_ERROR_RETURN); 441 $result = $this->createSequence($seq_name); 442 $this->popErrorHandling(); 443 if (DB::isError($result)) { 444 return $this->raiseError($result); 445 } 446 $result = $this->query("insert into $seqname} (id) values(0)"); 447 } else { 448 $repeat = 0; 449 } 450 } while ($repeat); 451 452 if (DB::isError($result)) { 453 return $this->raiseError($result); 454 } 455 456 $result = $this->query("select id from $seqname}"); 457 if (DB::isError($result)) { 458 return $result; 459 } 460 461 $row = $result->fetchRow(DB_FETCHMODE_ORDERED); 462 if (DB::isError($row || !$row)) { 463 return $row; 464 } 465 466 return $row[0]; 467 } 468 469 /** 470 * Creates a new sequence 471 * 472 * @param string $seq_name name of the new sequence 473 * 474 * @return int DB_OK on success. A DB_Error object is returned if 475 * problems arise. 476 * 477 * @internal 478 * @see DB_common::createSequence() 479 * @access public 480 */ 481 function createSequence($seq_name) 482 { 483 $seqname = $this->getSequenceName($seq_name); 484 return $this->query("CREATE TABLE $seqname} ". 485 '(id integer NOT NULL,'. 486 ' PRIMARY KEY(id))'); 487 } 488 489 // }}} 490 // {{{ dropSequence() 491 492 /** 493 * Deletes a sequence 494 * 495 * @param string $seq_name name of the sequence to be deleted 496 * 497 * @return int DB_OK on success. DB_Error if problems. 498 * 499 * @internal 500 * @see DB_common::dropSequence() 501 * @access public 502 */ 503 function dropSequence($seq_name) 504 { 505 $seqname = $this->getSequenceName($seq_name); 506 return $this->query("DROP TABLE $seqname}"); 507 } 508 509 // }}} 510 // {{{ autoCommit() 511 512 function autoCommit($onoff = false) 513 { 514 if (!@odbc_autocommit($this->connection, $onoff)) { 515 return $this->odbcRaiseError(); 516 } 517 return DB_OK; 518 } 519 520 // }}} 521 // {{{ commit() 522 523 function commit() 524 { 525 if (!@odbc_commit($this->connection)) { 526 return $this->odbcRaiseError(); 527 } 528 return DB_OK; 529 } 530 531 // }}} 532 // {{{ rollback() 533 534 function rollback() 535 { 536 if (!@odbc_rollback($this->connection)) { 537 return $this->odbcRaiseError(); 538 } 539 return DB_OK; 540 } 541 542 // }}} 543 // {{{ odbcRaiseError() 544 545 /** 546 * Gather information about an error, then use that info to create a 547 * DB error object and finally return that object. 548 * 549 * @param integer $errno PEAR error number (usually a DB constant) if 550 * manually raising an error 551 * @return object DB error object 552 * @see errorNative() 553 * @see DB_common::errorCode() 554 * @see DB_common::raiseError() 555 */ 556 function odbcRaiseError($errno = null) 557 { 558 if ($errno === null) { 559 switch ($this->dbsyntax) { 560 case 'access': 561 if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { 562 $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD; 563 } else { 564 // Doing this in case mode changes during runtime. 565 $this->errorcode_map['07001'] = DB_ERROR_MISMATCH; 566 } 567 } 568 $errno = $this->errorCode(odbc_error($this->connection)); 569 } 570 return $this->raiseError($errno, null, null, null, 571 $this->errorNative()); 572 } 573 574 // }}} 575 576 } 577 578 /* 579 * Local variables: 580 * tab-width: 4 581 * c-basic-offset: 4 582 * End: 583 */ 584 585 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 14:40:03 2007 | par Balluche grâce à PHPXref 0.7 |