MDB2
[ class tree: MDB2 ] [ index: MDB2 ] [ all elements ]

Source for file sqlite.php

Documentation is available at sqlite.php

  1. <?php
  2. // vim: set et ts=4 sw=4 fdm=marker:
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  7. // | Stig. S. Bakken, Lukas Smith                                         |
  8. // | All rights reserved.                                                 |
  9. // +----------------------------------------------------------------------+
  10. // | MDB2 is a merge of PEAR DB and Metabases that provides a unified DB  |
  11. // | API as well as database abstraction for PHP applications.            |
  12. // | This LICENSE is in the BSD license style.                            |
  13. // |                                                                      |
  14. // | Redistribution and use in source and binary forms, with or without   |
  15. // | modification, are permitted provided that the following conditions   |
  16. // | are met:                                                             |
  17. // |                                                                      |
  18. // | Redistributions of source code must retain the above copyright       |
  19. // | notice, this list of conditions and the following disclaimer.        |
  20. // |                                                                      |
  21. // | Redistributions in binary form must reproduce the above copyright    |
  22. // | notice, this list of conditions and the following disclaimer in the  |
  23. // | documentation and/or other materials provided with the distribution. |
  24. // |                                                                      |
  25. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  26. // | Lukas Smith nor the names of his contributors may be used to endorse |
  27. // | or promote products derived from this software without specific prior|
  28. // | written permission.                                                  |
  29. // |                                                                      |
  30. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  31. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  32. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  33. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  34. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  35. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  36. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  37. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  38. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  39. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  40. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  41. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  42. // +----------------------------------------------------------------------+
  43. // | Author: Lukas Smith <smith@backendmedia.com>                         |
  44. // +----------------------------------------------------------------------+
  45. //
  46. // $Id: sqlite.php,v 1.15 2004/04/25 10:04:59 lsmith Exp $
  47. //
  48.  
  49. /**
  50.  * MDB2 SQLite driver
  51.  *
  52.  * @package MDB2
  53.  * @category Database
  54.  * @author  Lukas Smith <smith@backendmedia.com>
  55.  */
  56. {
  57.     // {{{ properties
  58.     var $escape_quotes = "'";
  59.     var $database_path = '';
  60.     var $database_extension = '';
  61.  
  62.     var $_lasterror '';
  63.  
  64.     // }}}
  65.     // {{{ constructor
  66.  
  67.     /**
  68.     * Constructor
  69.     */
  70.     function MDB2_Driver_sqlite()
  71.     {
  72.         $this->MDB2_Driver_Common();
  73.         $this->phptype 'sqlite';
  74.         $this->dbsyntax 'sqlite';
  75.  
  76.         $this->supported['sequences'= true;
  77.         $this->supported['indexes'= true;
  78.         $this->supported['affected_rows'= true;
  79.         $this->supported['summary_functions'= true;
  80.         $this->supported['order_by_text'= true;
  81.         $this->supported['current_id'= true;
  82.         $this->supported['limit_queries'= true;
  83.         $this->supported['LOBs'= true;
  84.         $this->supported['replace'= true;
  85.         $this->supported['transactions'= true;
  86.         $this->supported['sub_selects'= true;
  87.  
  88.         $this->options['base_transaction_name''___php_MDB2_sqlite_auto_commit_off';
  89.         $this->options['fixed_float'= 0;
  90.         $this->options['database_path''';
  91.         $this->options['database_extension''';
  92.     }
  93.  
  94.     // }}}
  95.     // {{{ errorInfo()
  96.  
  97.     /**
  98.      * This method is used to collect information about an error
  99.      *
  100.      * @param integer $error 
  101.      * @return array 
  102.      * @access public
  103.      */
  104.     function errorInfo($error = null)
  105.     {
  106.         $native_code @sqlite_last_error($this->connection);
  107.         $native_msg  @sqlite_error_string($native_code);
  108.  
  109.         if (is_null($error)) {
  110.             static $error_regexps;
  111.             if (empty($error_regexps)) {
  112.                 $error_regexps = array(
  113.                     '/^no such table:/' => MDB2_ERROR_NOSUCHTABLE,
  114.                     '/^table .* already exists$/' => MDB2_ERROR_ALREADY_EXISTS,
  115.                     '/PRIMARY KEY must be unique/i' => MDB2_ERROR_CONSTRAINT,
  116.                     '/is not unique/' => MDB2_ERROR_CONSTRAINT,
  117.                     '/uniqueness constraint failed/' => MDB2_ERROR_CONSTRAINT,
  118.                     '/^no such column:/' => MDB2_ERROR_NOSUCHFIELD,
  119.                     '/^near ".*": syntax error$/' => MDB2_ERROR_SYNTAX
  120.                  );
  121.             }
  122.             foreach ($error_regexps as $regexp => $code{
  123.                 if (preg_match($regexp$this->_lasterror)) {
  124.                     $error $code;
  125.                     break;
  126.                 }
  127.             }
  128.         }
  129.         return array($error$native_code$native_msg);
  130.     }
  131.  
  132.     // }}}
  133.     // {{{ escape()
  134.  
  135.     /**
  136.      * Quotes a string so it can be safely used in a query. It will quote
  137.      * the text so it can safely be used within a query.
  138.      *
  139.      * @param string $text the input string to quote
  140.      * @return string quoted string
  141.      * @access public
  142.      */
  143.     function escape($text)
  144.     {
  145.         return @sqlite_escape_string($text);
  146.     }
  147.  
  148.     // }}}
  149.     // {{{ autoCommit()
  150.  
  151.     /**
  152.      * Define whether database changes done on the database be automatically
  153.      * committed. This function may also implicitly start or end a transaction.
  154.      *
  155.      * @param boolean $auto_commit    flag that indicates whether the database
  156.      *                                 changes should be committed right after
  157.      *                                 executing every query statement. If this
  158.      *                                 argument is 0 a transaction implicitly
  159.      *                                 started. Otherwise, if a transaction is
  160.      *                                 in progress it is ended by committing any
  161.      *                                 database changes that were pending.
  162.      *
  163.      * @access public
  164.      *
  165.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  166.      */
  167.     function autoCommit($auto_commit)
  168.     {
  169.         $this->debug(($auto_commit 'On' 'Off')'autoCommit');
  170.         if (!isset($this->supported['transactions'])) {
  171.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  172.                 'autoCommit: transactions are not in use');
  173.         }
  174.         if ($this->auto_commit == $auto_commit{
  175.             return MDB2_OK;
  176.         }
  177.         if ($this->connection{
  178.             if ($auto_commit{
  179.                 $query 'END TRANSACTION '.$this->options['base_transaction_name'];
  180.                 $result $this->query($query);
  181.                 if (MDB2::isError($result)) {
  182.                     return $result;
  183.                 }
  184.             else {
  185.                 $query 'BEGIN TRANSACTION '.$this->options['base_transaction_name'];
  186.                 $result $this->query($query);
  187.                 if (MDB2::isError($result)) {
  188.                     return $result;
  189.                 }
  190.             }
  191.         }
  192.         $this->auto_commit = $auto_commit;
  193.         $this->in_transaction !$auto_commit;
  194.         return MDB2_OK;
  195.     }
  196.  
  197.     // }}}
  198.     // {{{ commit()
  199.  
  200.     /**
  201.      * Commit the database changes done during a transaction that is in
  202.      * progress. This function may only be called when auto-committing is
  203.      * disabled, otherwise it will fail. Therefore, a new transaction is
  204.      * implicitly started after committing the pending changes.
  205.      *
  206.      * @access public
  207.      *
  208.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  209.      */
  210.     function commit()
  211.     {
  212.         $this->debug('commit transaction''commit');
  213.         if (!isset($this->supported['transactions'])) {
  214.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  215.                 'commit: transactions are not in use');
  216.         }
  217.         if ($this->auto_commit{
  218.             return $this->raiseError(MDB2_ERRORnullnull,
  219.             'commit: transaction changes are being auto commited');
  220.         }
  221.         $result $this->query('COMMIT TRANSACTION '.$this->options['base_transaction_name']);
  222.         if (MDB2::isError($result)) {
  223.             return $result;
  224.         }
  225.         return $this->query('BEGIN TRANSACTION '.$this->options['base_transaction_name']);
  226.     }
  227.  
  228.     // }}}
  229.     // {{{ rollback()
  230.  
  231.     /**
  232.      * Cancel any database changes done during a transaction that is in
  233.      * progress. This function may only be called when auto-committing is
  234.      * disabled, otherwise it will fail. Therefore, a new transaction is
  235.      * implicitly started after canceling the pending changes.
  236.      *
  237.      * @access public
  238.      *
  239.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  240.      */
  241.     function rollback()
  242.     {
  243.         $this->debug('rolling back transaction''rollback');
  244.         if (!isset($this->supported['transactions'])) {
  245.             return $this->raiseError(MDB2_ERROR_UNSUPPORTEDnullnull,
  246.                 'rollback: transactions are not in use');
  247.         }
  248.         if ($this->auto_commit{
  249.             return $this->raiseError(MDB2_ERRORnullnull,
  250.                 'rollback: transactions can not be rolled back when changes are auto commited');
  251.         }
  252.         $result $this->query('ROLLBACK TRANSACTION '.$this->options['base_transaction_name']);
  253.         if (MDB2::isError($result)) {
  254.             return $result;
  255.         }
  256.         return $this->query('BEGIN TRANSACTION '.$this->options['base_transaction_name']);
  257.     }
  258.  
  259.     // }}}
  260.     // {{{ getDatabaseFile()
  261.  
  262.     /**
  263.      * Builds the string with path+dbname+extension
  264.      *
  265.      * @return string full database path+file
  266.      * @access private
  267.      */
  268.     function _getDatabaseFile($database_name)
  269.     {
  270.         $this->database_path = $this->options['database_path'];
  271.         $this->database_extension = $this->options['database_extension'];
  272.  
  273.         return $this->database_path.$database_name.$this->database_extension;
  274.     }
  275.  
  276.     // }}}
  277.     // {{{ connect()
  278.  
  279.     /**
  280.      * Connect to the database
  281.      *
  282.      * @return true on success, MDB2 Error Object on failure
  283.      ***/
  284.     function connect()
  285.     {
  286.         $database_file $this->_getDatabaseFile($this->database_name);
  287.         if ($this->connection != 0{
  288.             if (count(array_diff($this->connected_dsn$this->dsn)) == 0
  289.                 && $this->connected_database_name == $database_file
  290.                 && $this->opened_persistent == $this->options['persistent']
  291.             {
  292.                 return MDB2_OK;
  293.             }
  294.             @sqlite_close($this->connection);
  295.             $this->connection = 0;
  296.         }
  297.  
  298.         if (!PEAR::loadExtension($this->phptype)) {
  299.             return $this->raiseError(MDB2_ERROR_NOT_FOUNDnullnull,
  300.                 'connect: extension '.$this->phptype.' is not compiled into PHP');
  301.         }
  302.  
  303.         if ($database_file{
  304.             if (!file_exists($database_file)) {
  305.                 if (!touch($database_file)) {
  306.                     return $this->raiseError(MDB2_ERROR_NOT_FOUND);
  307.                 }
  308.                 if (!isset($this->dsn['mode'])
  309.                     || !is_numeric($this->dsn['mode'])
  310.                 {
  311.                     $mode = 0644;
  312.                 else {
  313.                     $mode octdec($this->dsn['mode']);
  314.                 }
  315.                 if (!chmod($database_file$mode)) {
  316.                     return $this->raiseError(MDB2_ERROR_NOT_FOUND);
  317.                 }
  318.                 if (!file_exists($database_file)) {
  319.                     return $this->raiseError(MDB2_ERROR_NOT_FOUND);
  320.                 }
  321.             }
  322.             if (!is_file($database_file)) {
  323.                 return $this->raiseError(MDB2_ERROR_INVALID);
  324.             }
  325.             if (!is_readable($database_file)) {
  326.                 return $this->raiseError(MDB2_ERROR_ACCESS_VIOLATION);
  327.             }
  328.  
  329.             $function ($this->options['persistent''sqlite_popen' 'sqlite_open');
  330.             $connection @$function($database_file);
  331.             if (!$connection{
  332.                 return $this->raiseError();
  333.             }
  334.             $this->connection $connection;
  335.             $this->connected_dsn $this->dsn;
  336.             $this->connected_database_name $database_file;
  337.             $this->opened_persistent $this->getoption('persistent');
  338.  
  339.             if (!$this->auto_commit{
  340.                 $query 'BEGIN TRANSACTION '.$this->options['base_transaction_name'];
  341.                 if (!@sqlite_query($query$this->connection)) {
  342.                     @sqlite_close($this->connection);
  343.                     $this->connection = 0;
  344.                     return $this->raiseError('connect: Could not start transaction');
  345.                 }
  346.                 $this->in_transaction = true;
  347.             }
  348.         }
  349.         return MDB2_OK;
  350.     }
  351.  
  352.     // }}}
  353.     // {{{ _close()
  354.     /**
  355.      * all the RDBMS specific things needed close a DB connection
  356.      *
  357.      * @return boolean 
  358.      * @access private
  359.      ***/
  360.     function _close()
  361.     {
  362.         if ($this->connection != 0{
  363.             if (isset($this->supported['transactions']&& !$this->auto_commit{
  364.                 $result $this->autoCommit(true);
  365.             }
  366.             @sqlite_close($this->connection);
  367.             $this->connection = 0;
  368.             unset($GLOBALS['_MDB2_databases'][$this->db_index]);
  369.  
  370.             if (isset($result&& MDB2::isError($result)) {
  371.                 return $result;
  372.             }
  373.  
  374.         }
  375.         return MDB2_OK;
  376.     }
  377.  
  378.     // }}}
  379.     // {{{ _modifyQuery()
  380.  
  381.     /**
  382.      * This method is used by backends to alter queries for various
  383.      * reasons.
  384.      *
  385.      * @param string $query  query to modify
  386.      * @return the new (modified) query
  387.      * @access private
  388.      */
  389.     function _modifyQuery($query)
  390.     {
  391.         // "DELETE FROM table" gives 0 affected rows in sqlite.
  392.         // This little hack lets you know how many rows were deleted.
  393.         if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i'$query)) {
  394.             $query preg_replace(
  395.                 '/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
  396.                 'DELETE FROM \1 WHERE 1=1'$query
  397.             );
  398.         }
  399.         return $query;
  400.     }
  401.  
  402.     // }}}
  403.     // {{{ query()
  404.  
  405.     /**
  406.      * Send a query to the database and return any results
  407.      *
  408.      * @param string  $query  the SQL query
  409.      * @param mixed   $types  string or array that contains the types of the
  410.      *                         columns in the result set
  411.      * @param mixed $result_class string which specifies which result class to use
  412.      * @param mixed $result_wrap_class string which specifies which class to wrap results in
  413.      * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
  414.      *
  415.      * @access public
  416.      */
  417.     function &query($query$types = null$result_class = false$result_wrap_class = false)
  418.     {
  419.         $ismanip MDB2::isManip($query);
  420.         $offset $this->row_offset;
  421.         $limit $this->row_limit;
  422.         $this->row_offset $this->row_limit = 0;
  423.         if ($limit > 0{
  424.             if ($ismanip{
  425.                 $query .= " LIMIT $limit";
  426.             else {
  427.                 $query .= " LIMIT $limit OFFSET $offset";
  428.             }
  429.         }
  430.         if ($this->options['portability'MDB2_PORTABILITY_DELETE_COUNT{
  431.             $query $this->_modifyQuery($query);
  432.         }
  433.         $this->last_query = $query;
  434.         $this->debug($query'query');
  435.  
  436.         $connected $this->connect();
  437.         if (MDB2::isError($connected)) {
  438.             return $connected;
  439.         }
  440.  
  441.         $function $this->options['result_buffering']
  442.             ? 'sqlite_query' 'sqlite_unbuffered_query';
  443.         ini_set('track_errors'true);
  444.         $result @$function($query.';'$this->connection);
  445.         ini_restore('track_errors');
  446.         $this->_lasterror = isset($php_errormsg$php_errormsg '';
  447.         if ($result{
  448.             if ($ismanip{
  449.                 return MDB2_OK;
  450.             else {
  451.                 if (!$result_class{
  452.                     $result_class $this->options['result_buffering']
  453.                         ? $this->options['buffered_result_class'$this->options['result_class'];
  454.                 }
  455.                 $class_name sprintf($result_class$this->phptype);
  456.                 $result =new $class_name($this$result);
  457.                 if ($types{
  458.                     $err $result->setResultTypes($types);
  459.                     if (MDB2::isError($err)) {
  460.                         $result->free();
  461.                         return $err;
  462.                     }
  463.                 }
  464.                 if (!$result_wrap_class{
  465.                     $result_wrap_class $this->options['result_wrap_class'];
  466.                 }
  467.                 if ($result_wrap_class{
  468.                     $result =new $result_wrap_class($result);
  469.                 }
  470.                 return $result;
  471.             }
  472.         }
  473.         $error =$this->raiseError();
  474.         return $error;
  475.     }
  476.  
  477.     // }}}
  478.     // {{{ affectedRows()
  479.  
  480.     /**
  481.      * returns the affected rows of a query
  482.      *
  483.      * @return mixed MDB2 Error Object or number of rows
  484.      * @access public
  485.      */
  486.     function affectedRows()
  487.     {
  488.         $affected_rows @sqlite_changes($this->connection);
  489.         if ($affected_rows === false{
  490.             return $this->raiseError(MDB2_ERROR_NEED_MORE_DATA);
  491.         }
  492.         return $affected_rows;
  493.     }
  494.  
  495.     // }}}
  496.     // {{{ replace()
  497.  
  498.     /**
  499.      * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
  500.      * query, except that if there is already a row in the table with the same
  501.      * key field values, the REPLACE query just updates its values instead of
  502.      * inserting a new row.
  503.      *
  504.      * The REPLACE type of query does not make part of the SQL standards. Since
  505.      * practically only SQLite implements it natively, this type of query is
  506.      * emulated through this method for other DBMS using standard types of
  507.      * queries inside a transaction to assure the atomicity of the operation.
  508.      *
  509.      * @access public
  510.      *
  511.      * @param string $table name of the table on which the REPLACE query will
  512.      *   be executed.
  513.      * @param array $fields associative array that describes the fields and the
  514.      *   values that will be inserted or updated in the specified table. The
  515.      *   indexes of the array are the names of all the fields of the table. The
  516.      *   values of the array are also associative arrays that describe the
  517.      *   values and other properties of the table fields.
  518.      *
  519.      *   Here follows a list of field properties that need to be specified:
  520.      *
  521.      *     value:
  522.      *           Value to be assigned to the specified field. This value may be
  523.      *           of specified in database independent type format as this
  524.      *           function can perform the necessary datatype conversions.
  525.      *
  526.      *     Default:
  527.      *           this property is required unless the Null property
  528.      *           is set to 1.
  529.      *
  530.      *     type
  531.      *           Name of the type of the field. Currently, all types Metabase
  532.      *           are supported except for clob and blob.
  533.      *
  534.      *     Default: no type conversion
  535.      *
  536.      *     null
  537.      *           Boolean property that indicates that the value for this field
  538.      *           should be set to null.
  539.      *
  540.      *           The default value for fields missing in INSERT queries may be
  541.      *           specified the definition of a table. Often, the default value
  542.      *           is already null, but since the REPLACE may be emulated using
  543.      *           an UPDATE query, make sure that all fields of the table are
  544.      *           listed in this function argument array.
  545.      *
  546.      *     Default: 0
  547.      *
  548.      *     key
  549.      *           Boolean property that indicates that this field should be
  550.      *           handled as a primary key or at least as part of the compound
  551.      *           unique index of the table that will determine the row that will
  552.      *           updated if it exists or inserted a new row otherwise.
  553.      *
  554.      *           This function will fail if no key field is specified or if the
  555.      *           value of a key field is set to null because fields that are
  556.      *           part of unique index they may not be null.
  557.      *
  558.      *     Default: 0
  559.      *
  560.      * @return mixed MDB2_OK on success, a MDB2 error on failure
  561.      */
  562.     function replace($table$fields)
  563.     {
  564.         $count count($fields);
  565.         for ($keys = 0$query $values '',reset($fields)$colnum = 0;
  566.             $colnum $count;
  567.             next($fields)$colnum++)
  568.         {
  569.             $name key($fields);
  570.             if ($colnum > 0{
  571.                 $query .= ',';
  572.                 $values .= ',';
  573.             }
  574.             $query .= $name;
  575.             if (isset($fields[$name]['null']&& $fields[$name]['null']{
  576.                 $value 'NULL';
  577.             else {
  578.                 $value $this->quote($fields[$name]['value']$fields[$name]['type']);
  579.             }
  580.             $values .= $value;
  581.             if (isset($fields[$name]['key']&& $fields[$name]['key']{
  582.                 if ($value === 'NULL'{
  583.                     return $this->raiseError(MDB2_ERROR_CANNOT_REPLACEnullnull,
  584.                         'replace: key value '.$name.' may not be NULL');
  585.                 }
  586.                 $keys++;
  587.             }
  588.         }
  589.         if ($keys == 0{
  590.             return $this->raiseError(MDB2_ERROR_CANNOT_REPLACEnullnull,
  591.                 'replace: not specified which fields are keys');
  592.         }
  593.         return $this->query("REPLACE INTO $table ($query) VALUES ($values)");
  594.     }
  595.  
  596.     // }}}
  597.     // {{{ nextID()
  598.  
  599.     /**
  600.      * returns the next free id of a sequence
  601.      *
  602.      * @param string  $seq_name name of the sequence
  603.      * @param boolean $ondemand when true the seqence is
  604.      *                           automatic created, if it
  605.      *                           not exists
  606.      *
  607.      * @return mixed MDB2 Error Object or id
  608.      * @access public
  609.      */
  610.     function nextID($seq_name$ondemand = true)
  611.     {
  612.         $sequence_name $this->getSequenceName($seq_name);
  613.         $this->expectError(MDB2_ERROR_NOSUCHTABLE);
  614.         $result $this->query("INSERT INTO $sequence_name VALUES (NULL)");
  615.         $this->popExpect();
  616.         if (MDB2::isError($result)) {
  617.             if ($ondemand && $result->getCode(== MDB2_ERROR_NOSUCHTABLE{
  618.                 $this->loadModule('manager');
  619.                 // Since we are creating the sequence on demand
  620.                 // we know the first id = 1 so initialize the
  621.                 // sequence at 2
  622.                 $result $this->manager->createSequence($seq_name2);
  623.                 if (MDB2::isError($result)) {
  624.                     return $this->raiseError(MDB2_ERRORnullnull,
  625.                         'nextID: on demand sequence '.$seq_name.' could not be created');
  626.                 else {
  627.                     // First ID of a newly created sequence is 1
  628.                     return 1;
  629.                 }
  630.             }
  631.             return $result;
  632.         }
  633.         $value @sqlite_last_insert_rowid($this->connection);
  634.         if (is_numeric($value)
  635.             && MDB2::isError($this->query("DELETE FROM $sequence_name WHERE ".$this->options['seqname_col_name']." < $value"))
  636.         {
  637.             $this->warnings['nextID: could not delete previous sequence table values from '.$seq_name;
  638.         }
  639.         return $value;
  640.     }
  641.  
  642.     // }}}
  643.     // {{{ currID()
  644.  
  645.     /**
  646.      * returns the current id of a sequence
  647.      *
  648.      * @param string  $seq_name name of the sequence
  649.      * @return mixed MDB2 Error Object or id
  650.      * @access public
  651.      */
  652.     function currID($seq_name)
  653.     {
  654.         $sequence_name $this->getSequenceName($seq_name);
  655.         return $this->queryOne("SELECT MAX(".$this->options['seqname_col_name'].") FROM $sequence_name"'integer');
  656.     }
  657. }
  658.  
  659. class MDB2_Result_sqlite extends MDB2_Result_Common
  660. {
  661.     // }}}
  662.     // {{{ constructor
  663.  
  664.     /**
  665.      * Constructor
  666.      */
  667.     function MDB2_Result_mysql(&$mdb&$result)
  668.     {
  669.         parent::MDB2_Result_Common($mdb$result);
  670.     }
  671.  
  672.     // }}}
  673.     // {{{ fetch()
  674.  
  675.     /**
  676.     * fetch value from a result set
  677.     *
  678.     * @param int    $rownum    number of the row where the data can be found
  679.     * @param int    $colnum    field number where the data can be found
  680.     * @return mixed string on success, a MDB2 error on failure
  681.     * @access public
  682.     */
  683.     function fetch($rownum = 0$colnum = 0)
  684.     {
  685.         $seek $this->seek($rownum);
  686.         if (MDB2::isError($seek)) {
  687.             return $seek;
  688.         }
  689.         $fetchmode is_numeric($colnumMDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC;
  690.         $row $this->fetchRow($fetchmode);
  691.         if (!$row || MDB2::isError($row)) {
  692.             return $row;
  693.         }
  694.         if (!array_key_exists($colnum$row)) {
  695.             return null;
  696.         }
  697.         return $row[$colnum];
  698.     }
  699.  
  700.     // }}}
  701.     // {{{ fetchRow()
  702.  
  703.     /**
  704.      * Fetch a row and insert the data into an existing array.
  705.      *
  706.      * @param int       $fetchmode  how the array data should be indexed
  707.      * @return int data array on success, a MDB2 error on failure
  708.      * @access public
  709.      */
  710.     function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT)
  711.     {
  712.         if ($fetchmode == MDB2_FETCHMODE_DEFAULT{
  713.             $fetchmode $this->mdb->fetchmode;
  714.         }
  715.         if ($fetchmode MDB2_FETCHMODE_ASSOC{
  716.             $row @sqlite_fetch_array($this->resultSQLITE_ASSOC);
  717.             if (is_array($row)
  718.                 && $this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE
  719.             {
  720.                 $row array_change_key_case($rowCASE_LOWER);
  721.             }
  722.         else {
  723.            $row @sqlite_fetch_array($this->resultSQLITE_NUM);
  724.         }
  725.         if (!$row{
  726.             if (is_null($this->result)) {
  727.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  728.                     'fetchRow: resultset has already been freed');
  729.             }
  730.             return null;
  731.         }
  732.         if (isset($this->types)) {
  733.             $row $this->mdb->datatype->convertResultRow($this->types$row);
  734.         }
  735.         if ($this->mdb->options['portability'MDB2_PORTABILITY_EMPTY_TO_NULL{
  736.             $this->mdb->_convertEmptyArrayValuesToNull($row);
  737.         }
  738.         ++$this->rownum;
  739.         return $row;
  740.     }
  741.  
  742.     // }}}
  743.     // {{{ getColumnNames()
  744.  
  745.     /**
  746.      * Retrieve the names of columns returned by the DBMS in a query result.
  747.      *
  748.      * @return mixed                an associative array variable
  749.      *                               that will hold the names of columns. The
  750.      *                               indexes of the array are the column names
  751.      *                               mapped to lower case and the values are the
  752.      *                               respective numbers of the columns starting
  753.      *                               from 0. Some DBMS may not return any
  754.      *                               columns when the result set does not
  755.      *                               contain any rows.
  756.      *
  757.      *                               a MDB2 error on failure
  758.      * @access public
  759.      */
  760.     function getColumnNames()
  761.     {
  762.         $columns = array();
  763.         $numcols $this->numCols();
  764.         if (MDB2::isError($numcols)) {
  765.             return $numcols;
  766.         }
  767.         for ($column = 0; $column $numcols$column++{
  768.             $column_name @sqlite_field_name($this->result$column);
  769.             $columns[$column_name$column;
  770.         }
  771.         if ($this->mdb->options['portability'MDB2_PORTABILITY_LOWERCASE{
  772.             $columns array_change_key_case($columnsCASE_LOWER);
  773.         }
  774.         return $columns;
  775.     }
  776.  
  777.     // }}}
  778.     // {{{ numCols()
  779.  
  780.     /**
  781.      * Count the number of columns returned by the DBMS in a query result.
  782.      *
  783.      * @access public
  784.      * @return mixed integer value with the number of columns, a MDB2 error
  785.      *                        on failure
  786.      */
  787.     function numCols()
  788.     {
  789.         $cols @sqlite_num_fields($this->result);
  790.         if (is_null($cols)) {
  791.             if (is_null($this->result)) {
  792.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  793.                     'numCols: resultset has already been freed');
  794.             }
  795.             return $this->mdb->raiseError();
  796.         }
  797.         return $cols;
  798.     }
  799. }
  800.  
  801. class MDB2_BufferedResult_sqlite extends MDB2_Result_sqlite
  802. {
  803.     // }}}
  804.     // {{{ constructor
  805.  
  806.     /**
  807.      * Constructor
  808.      */
  809.     function MDB2_BufferedResult_sqlite(&$mdb&$result)
  810.     {
  811.         parent::MDB2_Result_sqlite($mdb$result);
  812.     }
  813.  
  814.     // }}}
  815.     // {{{ seek()
  816.  
  817.     /**
  818.     * seek to a specific row in a result set
  819.     *
  820.     * @param int    $rownum    number of the row where the data can be found
  821.     * @return mixed MDB2_OK on success, a MDB2 error on failure
  822.     * @access public
  823.     */
  824.     function seek($rownum = 0)
  825.     {
  826.         if (!@sqlite_seek($this->result$rownum)) {
  827.             if (is_null($this->result)) {
  828.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  829.                     'seek: resultset has already been freed');
  830.             }
  831.             return $this->mdb->raiseError(MDB2_ERROR_INVALIDnullnull,
  832.                 'seek: tried to seek to an invalid row number ('.$rownum.')');
  833.         }
  834.         $this->rownum $rownum - 1;
  835.         return MDB2_OK;
  836.     }
  837.  
  838.     // }}}
  839.     // {{{ valid()
  840.  
  841.     /**
  842.     * check if the end of the result set has been reached
  843.     *
  844.     * @return mixed true or false on sucess, a MDB2 error on failure
  845.     * @access public
  846.     */
  847.     function valid()
  848.     {
  849.         $numrows $this->numRows();
  850.         if (MDB2::isError($numrows)) {
  851.             return $numrows;
  852.         }
  853.         return $this->rownum ($numrows - 1);
  854.     }
  855.  
  856.     // }}}
  857.     // {{{ numRows()
  858.  
  859.     /**
  860.     * returns the number of rows in a result object
  861.     *
  862.     * @return mixed MDB2 Error Object or the number of rows
  863.     * @access public
  864.     */
  865.     function numRows()
  866.     {
  867.         $rows @sqlite_num_rows($this->result);
  868.         if (is_null($rows)) {
  869.             if (is_null($this->result)) {
  870.                 return $this->mdb->raiseError(MDB2_ERROR_NEED_MORE_DATAnullnull,
  871.                     'numRows: resultset has already been freed');
  872.             }
  873.             return $this->raiseError();
  874.         }
  875.         return $rows;
  876.     }
  877. }
  878.  
  879. ?>

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