[ Index ]
 

Code source de PHP PEAR 1.4.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/DB/ -> sqlite.php (source)

   1  <?php
   2  
   3  /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
   4  
   5  /**
   6   * The PEAR DB driver for PHP's sqlite extension
   7   * for interacting with SQLite databases
   8   *
   9   * PHP versions 4 and 5
  10   *
  11   * LICENSE: This source file is subject to version 3.0 of the PHP license
  12   * that is available through the world-wide-web at the following URI:
  13   * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  14   * the PHP License and are unable to obtain it through the web, please
  15   * send a note to license@php.net so we can mail you a copy immediately.
  16   *
  17   * @category   Database
  18   * @package    DB
  19   * @author     Urs Gehrig <urs@circle.ch>
  20   * @author     Mika Tuupola <tuupola@appelsiini.net>
  21   * @author     Daniel Convissor <danielc@php.net>
  22   * @copyright  1997-2005 The PHP Group
  23   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0 3.0
  24   * @version    CVS: $Id: sqlite.php,v 1.114 2007/01/12 02:41:07 aharvey Exp $
  25   * @link       http://pear.php.net/package/DB
  26   */
  27  
  28  /**
  29   * Obtain the DB_common class so it can be extended from
  30   */
  31  require_once  'DB/common.php';
  32  
  33  /**
  34   * The methods PEAR DB uses to interact with PHP's sqlite extension
  35   * for interacting with SQLite databases
  36   *
  37   * These methods overload the ones declared in DB_common.
  38   *
  39   * NOTICE:  This driver needs PHP's track_errors ini setting to be on.
  40   * It is automatically turned on when connecting to the database.
  41   * Make sure your scripts don't turn it off.
  42   *
  43   * @category   Database
  44   * @package    DB
  45   * @author     Urs Gehrig <urs@circle.ch>
  46   * @author     Mika Tuupola <tuupola@appelsiini.net>
  47   * @author     Daniel Convissor <danielc@php.net>
  48   * @copyright  1997-2005 The PHP Group
  49   * @license    http://www.php.net/license/3_0.txt  PHP License 3.0 3.0
  50   * @version    Release: 1.7.9
  51   * @link       http://pear.php.net/package/DB
  52   */
  53  class DB_sqlite extends DB_common
  54  {
  55      // {{{ properties
  56  
  57      /**
  58       * The DB driver type (mysql, oci8, odbc, etc.)
  59       * @var string
  60       */
  61      var $phptype = 'sqlite';
  62  
  63      /**
  64       * The database syntax variant to be used (db2, access, etc.), if any
  65       * @var string
  66       */
  67      var $dbsyntax = 'sqlite';
  68  
  69      /**
  70       * The capabilities of this DB implementation
  71       *
  72       * The 'new_link' element contains the PHP version that first provided
  73       * new_link support for this DBMS.  Contains false if it's unsupported.
  74       *
  75       * Meaning of the 'limit' element:
  76       *   + 'emulate' = emulate with fetch row by number
  77       *   + 'alter'   = alter the query
  78       *   + false     = skip rows
  79       *
  80       * @var array
  81       */
  82      var $features = array(
  83          'limit'         => 'alter',
  84          'new_link'      => false,
  85          'numrows'       => true,
  86          'pconnect'      => true,
  87          'prepare'       => false,
  88          'ssl'           => false,
  89          'transactions'  => false,
  90      );
  91  
  92      /**
  93       * A mapping of native error codes to DB error codes
  94       *
  95       * {@internal  Error codes according to sqlite_exec.  See the online
  96       * manual at http://sqlite.org/c_interface.html for info.
  97       * This error handling based on sqlite_exec is not yet implemented.}}
  98       *
  99       * @var array
 100       */
 101      var $errorcode_map = array(
 102      );
 103  
 104      /**
 105       * The raw database connection created by PHP
 106       * @var resource
 107       */
 108      var $connection;
 109  
 110      /**
 111       * The DSN information for connecting to a database
 112       * @var array
 113       */
 114      var $dsn = array();
 115  
 116  
 117      /**
 118       * SQLite data types
 119       *
 120       * @link http://www.sqlite.org/datatypes.html
 121       *
 122       * @var array
 123       */
 124      var $keywords = array (
 125          'BLOB'      => '',
 126          'BOOLEAN'   => '',
 127          'CHARACTER' => '',
 128          'CLOB'      => '',
 129          'FLOAT'     => '',
 130          'INTEGER'   => '',
 131          'KEY'       => '',
 132          'NATIONAL'  => '',
 133          'NUMERIC'   => '',
 134          'NVARCHAR'  => '',
 135          'PRIMARY'   => '',
 136          'TEXT'      => '',
 137          'TIMESTAMP' => '',
 138          'UNIQUE'    => '',
 139          'VARCHAR'   => '',
 140          'VARYING'   => '',
 141      );
 142  
 143      /**
 144       * The most recent error message from $php_errormsg
 145       * @var string
 146       * @access private
 147       */
 148      var $_lasterror = '';
 149  
 150  
 151      // }}}
 152      // {{{ constructor
 153  
 154      /**
 155       * This constructor calls <kbd>$this->DB_common()</kbd>
 156       *
 157       * @return void
 158       */
 159      function DB_sqlite()
 160      {
 161          $this->DB_common();
 162      }
 163  
 164      // }}}
 165      // {{{ connect()
 166  
 167      /**
 168       * Connect to the database server, log in and open the database
 169       *
 170       * Don't call this method directly.  Use DB::connect() instead.
 171       *
 172       * PEAR DB's sqlite driver supports the following extra DSN options:
 173       *   + mode  The permissions for the database file, in four digit
 174       *            chmod octal format (eg "0600").
 175       *
 176       * Example of connecting to a database in read-only mode:
 177       * <code>
 178       * require_once 'DB.php';
 179       * 
 180       * $dsn = 'sqlite:///path/and/name/of/db/file?mode=0400';
 181       * $options = array(
 182       *     'portability' => DB_PORTABILITY_ALL,
 183       * );
 184       * 
 185       * $db =& DB::connect($dsn, $options);
 186       * if (PEAR::isError($db)) {
 187       *     die($db->getMessage());
 188       * }
 189       * </code>
 190       *
 191       * @param array $dsn         the data source name
 192       * @param bool  $persistent  should the connection be persistent?
 193       *
 194       * @return int  DB_OK on success. A DB_Error object on failure.
 195       */
 196      function connect($dsn, $persistent = false)
 197      {
 198          if (!PEAR::loadExtension('sqlite')) {
 199              return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
 200          }
 201  
 202          $this->dsn = $dsn;
 203          if ($dsn['dbsyntax']) {
 204              $this->dbsyntax = $dsn['dbsyntax'];
 205          }
 206  
 207          if (!$dsn['database']) {
 208              return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION);
 209          }
 210  
 211          if ($dsn['database'] !== ':memory:') {
 212              if (!file_exists($dsn['database'])) {
 213                  if (!touch($dsn['database'])) {
 214                      return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
 215                  }
 216                  if (!isset($dsn['mode']) ||
 217                      !is_numeric($dsn['mode']))
 218                  {
 219                      $mode = 0644;
 220                  } else {
 221                      $mode = octdec($dsn['mode']);
 222                  }
 223                  if (!chmod($dsn['database'], $mode)) {
 224                      return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
 225                  }
 226                  if (!file_exists($dsn['database'])) {
 227                      return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
 228                  }
 229              }
 230              if (!is_file($dsn['database'])) {
 231                  return $this->sqliteRaiseError(DB_ERROR_INVALID);
 232              }
 233              if (!is_readable($dsn['database'])) {
 234                  return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION);
 235              }
 236          }
 237  
 238          $connect_function = $persistent ? 'sqlite_popen' : 'sqlite_open';
 239  
 240          // track_errors must remain on for simpleQuery()
 241          @ini_set('track_errors', 1);
 242          $php_errormsg = '';
 243  
 244          if (!$this->connection = @$connect_function($dsn['database'])) {
 245              return $this->raiseError(DB_ERROR_NODBSELECTED,
 246                                       null, null, null,
 247                                       $php_errormsg);
 248          }
 249          return DB_OK;
 250      }
 251  
 252      // }}}
 253      // {{{ disconnect()
 254  
 255      /**
 256       * Disconnects from the database server
 257       *
 258       * @return bool  TRUE on success, FALSE on failure
 259       */
 260      function disconnect()
 261      {
 262          $ret = @sqlite_close($this->connection);
 263          $this->connection = null;
 264          return $ret;
 265      }
 266  
 267      // }}}
 268      // {{{ simpleQuery()
 269  
 270      /**
 271       * Sends a query to the database server
 272       *
 273       * NOTICE:  This method needs PHP's track_errors ini setting to be on.
 274       * It is automatically turned on when connecting to the database.
 275       * Make sure your scripts don't turn it off.
 276       *
 277       * @param string  the SQL query string
 278       *
 279       * @return mixed  + a PHP result resrouce for successful SELECT queries
 280       *                + the DB_OK constant for other successful queries
 281       *                + a DB_Error object on failure
 282       */
 283      function simpleQuery($query)
 284      {
 285          $ismanip = $this->_checkManip($query);
 286          $this->last_query = $query;
 287          $query = $this->modifyQuery($query);
 288  
 289          $php_errormsg = '';
 290  
 291          $result = @sqlite_query($query, $this->connection);
 292          $this->_lasterror = $php_errormsg ? $php_errormsg : '';
 293  
 294          $this->result = $result;
 295          if (!$this->result) {
 296              return $this->sqliteRaiseError(null);
 297          }
 298  
 299          // sqlite_query() seems to allways return a resource
 300          // so cant use that. Using $ismanip instead
 301          if (!$ismanip) {
 302              $numRows = $this->numRows($result);
 303              if (is_object($numRows)) {
 304                  // we've got PEAR_Error
 305                  return $numRows;
 306              }
 307              return $result;
 308          }
 309          return DB_OK;
 310      }
 311  
 312      // }}}
 313      // {{{ nextResult()
 314  
 315      /**
 316       * Move the internal sqlite result pointer to the next available result
 317       *
 318       * @param resource $result  the valid sqlite result resource
 319       *
 320       * @return bool  true if a result is available otherwise return false
 321       */
 322      function nextResult($result)
 323      {
 324          return false;
 325      }
 326  
 327      // }}}
 328      // {{{ fetchInto()
 329  
 330      /**
 331       * Places a row from the result set into the given array
 332       *
 333       * Formating of the array and the data therein are configurable.
 334       * See DB_result::fetchInto() for more information.
 335       *
 336       * This method is not meant to be called directly.  Use
 337       * DB_result::fetchInto() instead.  It can't be declared "protected"
 338       * because DB_result is a separate object.
 339       *
 340       * @param resource $result    the query result resource
 341       * @param array    $arr       the referenced array to put the data in
 342       * @param int      $fetchmode how the resulting array should be indexed
 343       * @param int      $rownum    the row number to fetch (0 = first row)
 344       *
 345       * @return mixed  DB_OK on success, NULL when the end of a result set is
 346       *                 reached or on failure
 347       *
 348       * @see DB_result::fetchInto()
 349       */
 350      function fetchInto($result, &$arr, $fetchmode, $rownum = null)
 351      {
 352          if ($rownum !== null) {
 353              if (!@sqlite_seek($this->result, $rownum)) {
 354                  return null;
 355              }
 356          }
 357          if ($fetchmode & DB_FETCHMODE_ASSOC) {
 358              $arr = @sqlite_fetch_array($result, SQLITE_ASSOC);
 359              if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
 360                  $arr = array_change_key_case($arr, CASE_LOWER);
 361              }
 362          } else {
 363              $arr = @sqlite_fetch_array($result, SQLITE_NUM);
 364          }
 365          if (!$arr) {
 366              return null;
 367          }
 368          if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
 369              /*
 370               * Even though this DBMS already trims output, we do this because
 371               * a field might have intentional whitespace at the end that
 372               * gets removed by DB_PORTABILITY_RTRIM under another driver.
 373               */
 374              $this->_rtrimArrayValues($arr);
 375          }
 376          if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
 377              $this->_convertNullArrayValuesToEmpty($arr);
 378          }
 379          return DB_OK;
 380      }
 381  
 382      // }}}
 383      // {{{ freeResult()
 384  
 385      /**
 386       * Deletes the result set and frees the memory occupied by the result set
 387       *
 388       * This method is not meant to be called directly.  Use
 389       * DB_result::free() instead.  It can't be declared "protected"
 390       * because DB_result is a separate object.
 391       *
 392       * @param resource $result  PHP's query result resource
 393       *
 394       * @return bool  TRUE on success, FALSE if $result is invalid
 395       *
 396       * @see DB_result::free()
 397       */
 398      function freeResult(&$result)
 399      {
 400          // XXX No native free?
 401          if (!is_resource($result)) {
 402              return false;
 403          }
 404          $result = null;
 405          return true;
 406      }
 407  
 408      // }}}
 409      // {{{ numCols()
 410  
 411      /**
 412       * Gets the number of columns in a result set
 413       *
 414       * This method is not meant to be called directly.  Use
 415       * DB_result::numCols() instead.  It can't be declared "protected"
 416       * because DB_result is a separate object.
 417       *
 418       * @param resource $result  PHP's query result resource
 419       *
 420       * @return int  the number of columns.  A DB_Error object on failure.
 421       *
 422       * @see DB_result::numCols()
 423       */
 424      function numCols($result)
 425      {
 426          $cols = @sqlite_num_fields($result);
 427          if (!$cols) {
 428              return $this->sqliteRaiseError();
 429          }
 430          return $cols;
 431      }
 432  
 433      // }}}
 434      // {{{ numRows()
 435  
 436      /**
 437       * Gets the number of rows in a result set
 438       *
 439       * This method is not meant to be called directly.  Use
 440       * DB_result::numRows() instead.  It can't be declared "protected"
 441       * because DB_result is a separate object.
 442       *
 443       * @param resource $result  PHP's query result resource
 444       *
 445       * @return int  the number of rows.  A DB_Error object on failure.
 446       *
 447       * @see DB_result::numRows()
 448       */
 449      function numRows($result)
 450      {
 451          $rows = @sqlite_num_rows($result);
 452          if ($rows === null) {
 453              return $this->sqliteRaiseError();
 454          }
 455          return $rows;
 456      }
 457  
 458      // }}}
 459      // {{{ affected()
 460  
 461      /**
 462       * Determines the number of rows affected by a data maniuplation query
 463       *
 464       * 0 is returned for queries that don't manipulate data.
 465       *
 466       * @return int  the number of rows.  A DB_Error object on failure.
 467       */
 468      function affectedRows()
 469      {
 470          return @sqlite_changes($this->connection);
 471      }
 472  
 473      // }}}
 474      // {{{ dropSequence()
 475  
 476      /**
 477       * Deletes a sequence
 478       *
 479       * @param string $seq_name  name of the sequence to be deleted
 480       *
 481       * @return int  DB_OK on success.  A DB_Error object on failure.
 482       *
 483       * @see DB_common::dropSequence(), DB_common::getSequenceName(),
 484       *      DB_sqlite::nextID(), DB_sqlite::createSequence()
 485       */
 486      function dropSequence($seq_name)
 487      {
 488          return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
 489      }
 490  
 491      /**
 492       * Creates a new sequence
 493       *
 494       * @param string $seq_name  name of the new sequence
 495       *
 496       * @return int  DB_OK on success.  A DB_Error object on failure.
 497       *
 498       * @see DB_common::createSequence(), DB_common::getSequenceName(),
 499       *      DB_sqlite::nextID(), DB_sqlite::dropSequence()
 500       */
 501      function createSequence($seq_name)
 502      {
 503          $seqname = $this->getSequenceName($seq_name);
 504          $query   = 'CREATE TABLE ' . $seqname .
 505                     ' (id INTEGER UNSIGNED PRIMARY KEY) ';
 506          $result  = $this->query($query);
 507          if (DB::isError($result)) {
 508              return($result);
 509          }
 510          $query   = "CREATE TRIGGER $seqname}_cleanup AFTER INSERT ON $seqname
 511                      BEGIN
 512                          DELETE FROM $seqname WHERE id<LAST_INSERT_ROWID();
 513                      END ";
 514          $result  = $this->query($query);
 515          if (DB::isError($result)) {
 516              return($result);
 517          }
 518      }
 519  
 520      // }}}
 521      // {{{ nextId()
 522  
 523      /**
 524       * Returns the next free id in a sequence
 525       *
 526       * @param string  $seq_name  name of the sequence
 527       * @param boolean $ondemand  when true, the seqence is automatically
 528       *                            created if it does not exist
 529       *
 530       * @return int  the next id number in the sequence.
 531       *               A DB_Error object on failure.
 532       *
 533       * @see DB_common::nextID(), DB_common::getSequenceName(),
 534       *      DB_sqlite::createSequence(), DB_sqlite::dropSequence()
 535       */
 536      function nextId($seq_name, $ondemand = true)
 537      {
 538          $seqname = $this->getSequenceName($seq_name);
 539  
 540          do {
 541              $repeat = 0;
 542              $this->pushErrorHandling(PEAR_ERROR_RETURN);
 543              $result = $this->query("INSERT INTO $seqname (id) VALUES (NULL)");
 544              $this->popErrorHandling();
 545              if ($result === DB_OK) {
 546                  $id = @sqlite_last_insert_rowid($this->connection);
 547                  if ($id != 0) {
 548                      return $id;
 549                  }
 550              } elseif ($ondemand && DB::isError($result) &&
 551                        $result->getCode() == DB_ERROR_NOSUCHTABLE)
 552              {
 553                  $result = $this->createSequence($seq_name);
 554                  if (DB::isError($result)) {
 555                      return $this->raiseError($result);
 556                  } else {
 557                      $repeat = 1;
 558                  }
 559              }
 560          } while ($repeat);
 561  
 562          return $this->raiseError($result);
 563      }
 564  
 565      // }}}
 566      // {{{ getDbFileStats()
 567  
 568      /**
 569       * Get the file stats for the current database
 570       *
 571       * Possible arguments are dev, ino, mode, nlink, uid, gid, rdev, size,
 572       * atime, mtime, ctime, blksize, blocks or a numeric key between
 573       * 0 and 12.
 574       *
 575       * @param string $arg  the array key for stats()
 576       *
 577       * @return mixed  an array on an unspecified key, integer on a passed
 578       *                arg and false at a stats error
 579       */
 580      function getDbFileStats($arg = '')
 581      {
 582          $stats = stat($this->dsn['database']);
 583          if ($stats == false) {
 584              return false;
 585          }
 586          if (is_array($stats)) {
 587              if (is_numeric($arg)) {
 588                  if (((int)$arg <= 12) & ((int)$arg >= 0)) {
 589                      return false;
 590                  }
 591                  return $stats[$arg ];
 592              }
 593              if (array_key_exists(trim($arg), $stats)) {
 594                  return $stats[$arg ];
 595              }
 596          }
 597          return $stats;
 598      }
 599  
 600      // }}}
 601      // {{{ escapeSimple()
 602  
 603      /**
 604       * Escapes a string according to the current DBMS's standards
 605       *
 606       * In SQLite, this makes things safe for inserts/updates, but may
 607       * cause problems when performing text comparisons against columns
 608       * containing binary data. See the
 609       * {@link http://php.net/sqlite_escape_string PHP manual} for more info.
 610       *
 611       * @param string $str  the string to be escaped
 612       *
 613       * @return string  the escaped string
 614       *
 615       * @since Method available since Release 1.6.1
 616       * @see DB_common::escapeSimple()
 617       */
 618      function escapeSimple($str)
 619      {
 620          return @sqlite_escape_string($str);
 621      }
 622  
 623      // }}}
 624      // {{{ modifyLimitQuery()
 625  
 626      /**
 627       * Adds LIMIT clauses to a query string according to current DBMS standards
 628       *
 629       * @param string $query   the query to modify
 630       * @param int    $from    the row to start to fetching (0 = the first row)
 631       * @param int    $count   the numbers of rows to fetch
 632       * @param mixed  $params  array, string or numeric data to be used in
 633       *                         execution of the statement.  Quantity of items
 634       *                         passed must match quantity of placeholders in
 635       *                         query:  meaning 1 placeholder for non-array
 636       *                         parameters or 1 placeholder per array element.
 637       *
 638       * @return string  the query string with LIMIT clauses added
 639       *
 640       * @access protected
 641       */
 642      function modifyLimitQuery($query, $from, $count, $params = array())
 643      {
 644          return "$query LIMIT $count OFFSET $from";
 645      }
 646  
 647      // }}}
 648      // {{{ modifyQuery()
 649  
 650      /**
 651       * Changes a query string for various DBMS specific reasons
 652       *
 653       * This little hack lets you know how many rows were deleted
 654       * when running a "DELETE FROM table" query.  Only implemented
 655       * if the DB_PORTABILITY_DELETE_COUNT portability option is on.
 656       *
 657       * @param string $query  the query string to modify
 658       *
 659       * @return string  the modified query string
 660       *
 661       * @access protected
 662       * @see DB_common::setOption()
 663       */
 664      function modifyQuery($query)
 665      {
 666          if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) {
 667              if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
 668                  $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
 669                                        'DELETE FROM \1 WHERE 1=1', $query);
 670              }
 671          }
 672          return $query;
 673      }
 674  
 675      // }}}
 676      // {{{ sqliteRaiseError()
 677  
 678      /**
 679       * Produces a DB_Error object regarding the current problem
 680       *
 681       * @param int $errno  if the error is being manually raised pass a
 682       *                     DB_ERROR* constant here.  If this isn't passed
 683       *                     the error information gathered from the DBMS.
 684       *
 685       * @return object  the DB_Error object
 686       *
 687       * @see DB_common::raiseError(),
 688       *      DB_sqlite::errorNative(), DB_sqlite::errorCode()
 689       */
 690      function sqliteRaiseError($errno = null)
 691      {
 692          $native = $this->errorNative();
 693          if ($errno === null) {
 694              $errno = $this->errorCode($native);
 695          }
 696  
 697          $errorcode = @sqlite_last_error($this->connection);
 698          $userinfo = "$errorcode ** $this->last_query";
 699  
 700          return $this->raiseError($errno, null, null, $userinfo, $native);
 701      }
 702  
 703      // }}}
 704      // {{{ errorNative()
 705  
 706      /**
 707       * Gets the DBMS' native error message produced by the last query
 708       *
 709       * {@internal This is used to retrieve more meaningfull error messages
 710       * because sqlite_last_error() does not provide adequate info.}}
 711       *
 712       * @return string  the DBMS' error message
 713       */
 714      function errorNative()
 715      {
 716          return $this->_lasterror;
 717      }
 718  
 719      // }}}
 720      // {{{ errorCode()
 721  
 722      /**
 723       * Determines PEAR::DB error code from the database's text error message
 724       *
 725       * @param string $errormsg  the error message returned from the database
 726       *
 727       * @return integer  the DB error number
 728       */
 729      function errorCode($errormsg)
 730      {
 731          static $error_regexps;
 732          
 733          // PHP 5.2+ prepends the function name to $php_errormsg, so we need
 734          // this hack to work around it, per bug #9599.
 735          $errormsg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $errormsg);
 736          
 737          if (!isset($error_regexps)) {
 738              $error_regexps = array(
 739                  '/^no such table:/' => DB_ERROR_NOSUCHTABLE,
 740                  '/^no such index:/' => DB_ERROR_NOT_FOUND,
 741                  '/^(table|index) .* already exists$/' => DB_ERROR_ALREADY_EXISTS,
 742                  '/PRIMARY KEY must be unique/i' => DB_ERROR_CONSTRAINT,
 743                  '/is not unique/' => DB_ERROR_CONSTRAINT,
 744                  '/columns .* are not unique/i' => DB_ERROR_CONSTRAINT,
 745                  '/uniqueness constraint failed/' => DB_ERROR_CONSTRAINT,
 746                  '/may not be NULL/' => DB_ERROR_CONSTRAINT_NOT_NULL,
 747                  '/^no such column:/' => DB_ERROR_NOSUCHFIELD,
 748                  '/column not present in both tables/i' => DB_ERROR_NOSUCHFIELD,
 749                  '/^near ".*": syntax error$/' => DB_ERROR_SYNTAX,
 750                  '/[0-9]+ values for [0-9]+ columns/i' => DB_ERROR_VALUE_COUNT_ON_ROW,
 751              );
 752          }
 753          foreach ($error_regexps as $regexp => $code) {
 754              if (preg_match($regexp, $errormsg)) {
 755                  return $code;
 756              }
 757          }
 758          // Fall back to DB_ERROR if there was no mapping.
 759          return DB_ERROR;
 760      }
 761  
 762      // }}}
 763      // {{{ tableInfo()
 764  
 765      /**
 766       * Returns information about a table
 767       *
 768       * @param string         $result  a string containing the name of a table
 769       * @param int            $mode    a valid tableInfo mode
 770       *
 771       * @return array  an associative array with the information requested.
 772       *                 A DB_Error object on failure.
 773       *
 774       * @see DB_common::tableInfo()
 775       * @since Method available since Release 1.7.0
 776       */
 777      function tableInfo($result, $mode = null)
 778      {
 779          if (is_string($result)) {
 780              /*
 781               * Probably received a table name.
 782               * Create a result resource identifier.
 783               */
 784              $id = @sqlite_array_query($this->connection,
 785                                        "PRAGMA table_info('$result');",
 786                                        SQLITE_ASSOC);
 787              $got_string = true;
 788          } else {
 789              $this->last_query = '';
 790              return $this->raiseError(DB_ERROR_NOT_CAPABLE, null, null, null,
 791                                       'This DBMS can not obtain tableInfo' .
 792                                       ' from result sets');
 793          }
 794  
 795          if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
 796              $case_func = 'strtolower';
 797          } else {
 798              $case_func = 'strval';
 799          }
 800  
 801          $count = count($id);
 802          $res   = array();
 803  
 804          if ($mode) {
 805              $res['num_fields'] = $count;
 806          }
 807  
 808          for ($i = 0; $i < $count; $i++) {
 809              if (strpos($id[$i]['type'], '(') !== false) {
 810                  $bits = explode('(', $id[$i]['type']);
 811                  $type = $bits[0];
 812                  $len  = rtrim($bits[1],')');
 813              } else {
 814                  $type = $id[$i]['type'];
 815                  $len  = 0;
 816              }
 817  
 818              $flags = '';
 819              if ($id[$i]['pk']) {
 820                  $flags .= 'primary_key ';
 821              }
 822              if ($id[$i]['notnull']) {
 823                  $flags .= 'not_null ';
 824              }
 825              if ($id[$i]['dflt_value'] !== null) {
 826                  $flags .= 'default_' . rawurlencode($id[$i]['dflt_value']);
 827              }
 828              $flags = trim($flags);
 829  
 830              $res[$i] = array(
 831                  'table' => $case_func($result),
 832                  'name'  => $case_func($id[$i]['name']),
 833                  'type'  => $type,
 834                  'len'   => $len,
 835                  'flags' => $flags,
 836              );
 837  
 838              if ($mode & DB_TABLEINFO_ORDER) {
 839                  $res['order'][$res[$i]['name']] = $i;
 840              }
 841              if ($mode & DB_TABLEINFO_ORDERTABLE) {
 842                  $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
 843              }
 844          }
 845  
 846          return $res;
 847      }
 848  
 849      // }}}
 850      // {{{ getSpecialQuery()
 851  
 852      /**
 853       * Obtains the query string needed for listing a given type of objects
 854       *
 855       * @param string $type  the kind of objects you want to retrieve
 856       * @param array  $args  SQLITE DRIVER ONLY: a private array of arguments
 857       *                       used by the getSpecialQuery().  Do not use
 858       *                       this directly.
 859       *
 860       * @return string  the SQL query string or null if the driver doesn't
 861       *                  support the object type requested
 862       *
 863       * @access protected
 864       * @see DB_common::getListOf()
 865       */
 866      function getSpecialQuery($type, $args = array())
 867      {
 868          if (!is_array($args)) {
 869              return $this->raiseError('no key specified', null, null, null,
 870                                       'Argument has to be an array.');
 871          }
 872  
 873          switch ($type) {
 874              case 'master':
 875                  return 'SELECT * FROM sqlite_master;';
 876              case 'tables':
 877                  return "SELECT name FROM sqlite_master WHERE type='table' "
 878                         . 'UNION ALL SELECT name FROM sqlite_temp_master '
 879                         . "WHERE type='table' ORDER BY name;";
 880              case 'schema':
 881                  return 'SELECT sql FROM (SELECT * FROM sqlite_master '
 882                         . 'UNION ALL SELECT * FROM sqlite_temp_master) '
 883                         . "WHERE type!='meta' "
 884                         . 'ORDER BY tbl_name, type DESC, name;';
 885              case 'schemax':
 886              case 'schema_x':
 887                  /*
 888                   * Use like:
 889                   * $res = $db->query($db->getSpecialQuery('schema_x',
 890                   *                   array('table' => 'table3')));
 891                   */
 892                  return 'SELECT sql FROM (SELECT * FROM sqlite_master '
 893                         . 'UNION ALL SELECT * FROM sqlite_temp_master) '
 894                         . "WHERE tbl_name LIKE '{$args['table']}' "
 895                         . "AND type!='meta' "
 896                         . 'ORDER BY type DESC, name;';
 897              case 'alter':
 898                  /*
 899                   * SQLite does not support ALTER TABLE; this is a helper query
 900                   * to handle this. 'table' represents the table name, 'rows'
 901                   * the news rows to create, 'save' the row(s) to keep _with_
 902                   * the data.
 903                   *
 904                   * Use like:
 905                   * $args = array(
 906                   *     'table' => $table,
 907                   *     'rows'  => "id INTEGER PRIMARY KEY, firstname TEXT, surname TEXT, datetime TEXT",
 908                   *     'save'  => "NULL, titel, content, datetime"
 909                   * );
 910                   * $res = $db->query( $db->getSpecialQuery('alter', $args));
 911                   */
 912                  $rows = strtr($args['rows'], $this->keywords);
 913  
 914                  $q = array(
 915                      'BEGIN TRANSACTION',
 916                      "CREATE TEMPORARY TABLE {$args['table']}_backup ({$args['rows']})",
 917                      "INSERT INTO {$args['table']}_backup SELECT {$args['save']} FROM {$args['table']}",
 918                      "DROP TABLE {$args['table']}",
 919                      "CREATE TABLE {$args['table']} ({$args['rows']})",
 920                      "INSERT INTO {$args['table']} SELECT {$rows} FROM {$args['table']}_backup",
 921                      "DROP TABLE {$args['table']}_backup",
 922                      'COMMIT',
 923                  );
 924  
 925                  /*
 926                   * This is a dirty hack, since the above query will not get
 927                   * executed with a single query call so here the query method
 928                   * will be called directly and return a select instead.
 929                   */
 930                  foreach ($q as $query) {
 931                      $this->query($query);
 932                  }
 933                  return "SELECT * FROM {$args['table']};";
 934              default:
 935                  return null;
 936          }
 937      }
 938  
 939      // }}}
 940  }
 941  
 942  /*
 943   * Local variables:
 944   * tab-width: 4
 945   * c-basic-offset: 4
 946   * End:
 947   */
 948  
 949  ?>


Généré le : Sun Feb 25 14:08:00 2007 par Balluche grâce à PHPXref 0.7