Source for file jDbPDOConnection.class.php

Documentation is available at jDbPDOConnection.class.php

  1. <?php
  2. /**
  3. @package    jelix
  4. @subpackage db
  5. @author     Laurent Jouanneau
  6. @contributor Gwendal Jouannic, Thomas, Julien Issler, Vincent Herr
  7. @copyright  2005-2010 Laurent Jouanneau
  8. @copyright  2008 Gwendal Jouannic, 2009 Thomas
  9. @copyright  2009 Julien Issler
  10. @copyright  2011 Vincent Herr
  11. @link      http://www.jelix.org
  12. @licence  http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file
  13. */
  14.  
  15. /**
  16.  * A connection object based on PDO
  17.  * @package  jelix
  18.  * @subpackage db
  19.  */
  20. class jDbPDOConnection extends PDO {
  21.  
  22.     private $_mysqlCharsets array('UTF-8'=>'utf8''ISO-8859-1'=>'latin1');
  23.     private $_pgsqlCharsets array('UTF-8'=>'UNICODE''ISO-8859-1'=>'LATIN1');
  24.  
  25.     /**
  26.      * the profile the connection is using
  27.      * @var array 
  28.      */
  29.     public $profile;
  30.  
  31.     /**
  32.      * The database type name (mysql, pgsql ...)
  33.      * @var string 
  34.      */
  35.     public $dbms;
  36.  
  37.     /**
  38.      * Use a profile to do the connection
  39.      * @param array $profile the profile data readed from the ini file
  40.      */
  41.     function __construct($profile{
  42.         $this->profile = $profile;
  43.         $prof $profile;
  44.         $user '';
  45.         $password '';
  46.         $dsn '';
  47.         if (isset($profile['dsn'])) {
  48.             $this->dbms = substr($profile['dsn'],0,strpos($profile['dsn'],':'));
  49.             $dsn $profile['dsn'];
  50.             unset($prof['dsn']);
  51.             if ($this->dbms == 'sqlite')
  52.                 $dsn str_replace(array('app:','lib:','var:')array(jApp::appPath()LIB_PATHjApp::varPath())$dsn);
  53.         }
  54.         else {
  55.             $this->dbms = $profile['driver'];
  56.             $db $profile['database'];
  57.             $dsn $this->dbms.':host='.$profile['host'].';dbname='.$db;
  58.             if($this->dbms != 'sqlite')
  59.                 $dsn $this->dbms.':host='.$profile['host'].';dbname='.$db;
  60.             else {
  61.                 if (preg_match('/^(app|lib|var)\:/'$db$m))
  62.                     $dsn 'sqlite:'.str_replace(array('app:','lib:','var:')array(jApp::appPath()LIB_PATHjApp::varPath())$db);
  63.                 else
  64.                     $dsn 'sqlite:'.jApp::varPath('db/sqlite/'.$db);
  65.             }
  66.         }
  67.         if(isset($prof['usepdo']))
  68.             unset($prof['usepdo']);
  69.  
  70.         // we check user and password because some db like sqlite doesn't have user/password
  71.         if (isset($prof['user'])) {
  72.             $user $prof['user'];
  73.             unset($prof['user']);
  74.         }
  75.  
  76.         if (isset($prof['password'])) {
  77.             $password $profile['password'];
  78.             unset($prof['password']);
  79.         }
  80.  
  81.         unset($prof['driver']);
  82.  
  83.         parent::__construct($dsn$user$password$prof);
  84.  
  85.         $this->setAttribute(PDO::ATTR_STATEMENT_CLASSarray('jDbPDOResultSet'));
  86.         $this->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION);
  87.  
  88.         // we cannot launch two queries at the same time with PDO ! except if
  89.         // we use mysql with the attribute MYSQL_ATTR_USE_BUFFERED_QUERY
  90.         // TODO check if PHP 5.3 or higher fixes this issue
  91.         if ($this->dbms == 'mysql')
  92.             $this->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERYtrue);
  93.  
  94.         // Oracle returns names of columns in upper case by default. so here
  95.         // we force the case in lower.
  96.         if ($this->dbms == 'oci')
  97.             $this->setAttribute(PDO::ATTR_CASEPDO::CASE_LOWER);
  98.  
  99.         if (isset($prof['force_encoding']&& $prof['force_encoding']==true{
  100.             if ($this->dbms == 'mysql' && isset($this->_mysqlCharsets[$GLOBALS['gJConfig']->charset])) {
  101.                 $this->exec("SET NAMES '".$this->_mysqlCharsets[$GLOBALS['gJConfig']->charset]."'");
  102.             }
  103.             elseif($this->dbms == 'pgsql' && isset($this->_pgsqlCharsets[$GLOBALS['gJConfig']->charset])) {
  104.                 $this->exec("SET client_encoding to '".$this->_pgsqlCharsets[$GLOBALS['gJConfig']->charset]."'");
  105.             }
  106.         }
  107.     }
  108.  
  109.     /**
  110.      * @internal the implementation of Iterator on PDOStatement doesn't call
  111.      *  fetch method of classes which inherit of PDOStatement.
  112.      *  so, we cannot indicate to fetch object directly in jDbPDOResultSet::fetch().
  113.      *  So we overload query() to do it.
  114.      *  TODO check if this is still the case in PHP 5.3
  115.      */
  116.     public function query({
  117.         $args func_get_args();
  118.  
  119.         switch (count($args)) {
  120.         case 1:
  121.             $log new jSQLLogMessage($args[0]);
  122.             $rs parent::query($args[0]);
  123.             $log->endQuery();
  124.             jLog::log($log,'sql');
  125.             $rs->setFetchMode(PDO::FETCH_OBJ);
  126.             return $rs;
  127.         case 2:
  128.             $log new jSQLLogMessage($args[0]);
  129.             $result parent::query($args[0]$args[1]);
  130.             $log->endQuery();
  131.             jLog::log($log,'sql');
  132.             return $result;
  133.         case 3:
  134.             $log new jSQLLogMessage($args[0]);
  135.             $result parent::query($args[0]$args[1]$args[2]);
  136.             $log->endQuery();
  137.             jLog::log($log,'sql');
  138.             return $result;
  139.         default:
  140.             throw new Exception('jDbPDOConnection: bad argument number in query');
  141.         }
  142.     }
  143.  
  144.     public function exec($query{
  145.         $log new jSQLLogMessage($query);
  146.         $result parent::exec($query);
  147.         $log->endQuery();
  148.         jLog::log($log,'sql');
  149.         return $result;
  150.     }
  151.  
  152.     /**
  153.     * Launch a SQL Query with limit parameter (so only a subset of a result)
  154.     * @param   string   $queryString   the SQL query
  155.     * @param   integer  $limitOffset   the offset of the first row to return
  156.     * @param   integer  $limitCount    the maximum of number of rows to return
  157.     * @return  jDbPDOResultSet|boolean SQL Select. False if the query has failed.
  158.     */
  159.     public function limitQuery ($queryString$limitOffset null$limitCount null{
  160.         if ($limitOffset !== null && $limitCount !== null{
  161.             if ($this->dbms == 'mysql' || $this->dbms == 'sqlite'{
  162.                 $queryString.= ' LIMIT '.intval($limitOffset).','intval($limitCount);
  163.             }
  164.             elseif ($this->dbms == 'pgsql'{
  165.                 $queryString .= ' LIMIT '.intval($limitCount).' OFFSET '.intval($limitOffset);
  166.             }
  167.             elseif ($this->dbms == 'oci'{
  168.                 $limitOffset $limitOffset 1// rnum begins at 1
  169.                 $queryString 'SELECT * FROM ( SELECT ocilimit.*, rownum rnum FROM ('.$queryString.') ocilimit WHERE
  170.                     rownum<'.(intval($limitOffset)+intval($limitCount)).'  ) WHERE rnum >='.intval($limitOffset);
  171.             }
  172.         }
  173.         return $this->query ($queryString);
  174.     }
  175.  
  176.     /**
  177.      * sets the autocommit state
  178.      * @param boolean $state the status of autocommit
  179.      */
  180.     public function setAutoCommit($state=true{
  181.         $this->setAttribute(PDO::ATTR_AUTOCOMMIT,$state);
  182.     }
  183.  
  184.     /**
  185.      * return the maximum value of the given primary key in a table
  186.      * @param string $fieldName the name of the primary key
  187.      * @param string $tableName the name of the table
  188.      * @return integer the maximum value
  189.      */
  190.     public function lastIdInTable($fieldName$tableName{
  191.       $rs $this->query ('SELECT MAX('.$fieldName.') as ID FROM '.$tableName);
  192.       if (($rs !== null&& $r $rs->fetch ()){
  193.          return $r->ID;
  194.       }
  195.       return 0;
  196.     }
  197.  
  198.     /**
  199.      * Prefix the given table with the prefix specified in the connection's profile
  200.      * If there's no prefix for the connection's profile, return the table's name unchanged.
  201.      *
  202.      * @param string $table the table's name
  203.      * @return string the prefixed table's name
  204.      * @author Julien Issler
  205.      * @since 1.0
  206.      */
  207.     public function prefixTable($table_name{
  208.         if (!isset($this->profile['table_prefix']))
  209.             return $table_name;
  210.         return $this->profile['table_prefix'].$table_name;
  211.     }
  212.  
  213.     /**
  214.      * Check if the current connection has a table prefix set
  215.      *
  216.      * @return boolean 
  217.      * @author Julien Issler
  218.      * @since 1.0
  219.      */
  220.     public function hasTablePrefix({
  221.         return (isset($this->profile['table_prefix']&& $this->profile['table_prefix']!='');
  222.     }
  223.  
  224.     /**
  225.      * enclose the field name
  226.      * @param string $fieldName the field name
  227.      * @return string the enclosed field name
  228.      * @since 1.1.2
  229.      */
  230.     public function encloseName($fieldName{
  231.         switch ($this->dbms{
  232.             case 'mysql'return '`'.$fieldName.'`';
  233.             case 'pgsql'return '"'.$fieldName.'"';
  234.             defaultreturn $fieldName;
  235.         }
  236.     }
  237.  
  238.     /**
  239.     * Escape and quotes strings. if null, will only return the text "NULL"
  240.     * @param string $text   string to quote
  241.     * @param boolean $checknull if true, check if $text is a null value, and then return NULL
  242.     * @param boolean $binary  set to true if $text contains a binary string
  243.     * @return string escaped string
  244.     * @since 1.2
  245.     * @todo $binary parameter is not really supported, check if PDOConnection::quote supports binary strings
  246.     */
  247.     public function quote2 ($text$checknull=true$binary=false{
  248.         if ($checknull)
  249.             return (is_null ($text'NULL' $this->quote($text));
  250.         else
  251.             return $this->quote($text);
  252.     }
  253.  
  254.     /**
  255.      * @var jDbTools 
  256.      */
  257.     protected $_tools = null;
  258.  
  259.     /**
  260.      * @return jDbTools 
  261.      */
  262.     public function tools ({
  263.         if (!$this->_tools{
  264.             $this->_tools = jApp::loadPlugin($this->dbms'db''.dbtools.php'$this->dbms.'DbTools'$this);
  265.             if (is_null($this->_tools))
  266.                 throw new jException('jelix~db.error.driver.notfound'$this->dbms);
  267.         }
  268.  
  269.         return $this->_tools;
  270.     }
  271.  
  272.     /**
  273.      * Get the ID of the last inserted row
  274.      * Mssql pdo driver does not support this feature.
  275.      * so, we use a custom query
  276.      * @param string $fromSequence the sequence name, if needed
  277.      * @return string 
  278.      */
  279.     public function lastInsertId($fromSequence=null{
  280.         if ($this->dbms == 'mssql'{
  281.             $res $this->query('SELECT SCOPE_IDENTITY()');
  282.             return (int) $res->fetchColumn();
  283.         }
  284.  
  285.         return parent::lastInsertId($fromSequence);
  286.     }
  287.  
  288. }

Documentation generated on Wed, 24 Sep 2014 21:58:31 +0200 by phpDocumentor 1.4.3