Advertisement
Guest User

Untitled

a guest
Jun 18th, 2012
542
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.81 KB | None | 0 0
  1. <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3.  * CodeIgniter
  4.  *
  5.  * An open source application development framework for PHP 5.1.6 or newer
  6.  *
  7.  * @package     CodeIgniter
  8.  * @copyright   Copyright (c) 2008 - 2011, EllisLab, Inc.
  9.  * @license     http://codeigniter.com/user_guide/license.html
  10.  * @author      EllisLab Dev Team
  11.  * @link        http://codeigniter.com
  12.  * @since       Version 2.1.0
  13.  * @filesource
  14.  */
  15.  
  16. // ------------------------------------------------------------------------
  17.  
  18. /**
  19.  * PDO Database Adapter Class
  20.  *
  21.  * Note: _DB is an extender class that the app controller
  22.  * creates dynamically based on whether the active record
  23.  * class is being used or not.
  24.  *
  25.  * @package     CodeIgniter
  26.  * @subpackage  Drivers
  27.  * @category    Database
  28.  * @author      EllisLab Dev Team
  29.  * @link        http://codeigniter.com/user_guide/database/
  30.  */
  31. class CI_DB_pdo_driver extends CI_DB {
  32.  
  33.     var $dbdriver = 'pdo';
  34.  
  35.     // the character used to excape - not necessary for PDO
  36.     var $_escape_char = '';
  37.     var $_like_escape_str;
  38.     var $_like_escape_chr;
  39.    
  40.  
  41.     /**
  42.      * The syntax to count rows is slightly different across different
  43.      * database engines, so this string appears in each driver and is
  44.      * used for the count_all() and count_all_results() functions.
  45.      */
  46.     var $_count_string = "SELECT COUNT(*) AS ";
  47.     var $_random_keyword;
  48.    
  49.     var $options = array();
  50.  
  51.     function __construct($params)
  52.     {
  53.         parent::__construct($params);
  54.        
  55.         // clause and character used for LIKE escape sequences
  56.         if (strpos($this->hostname, 'mysql') !== FALSE)
  57.         {
  58.             $this->_like_escape_str = '';
  59.             $this->_like_escape_chr = '';
  60.            
  61.             //Prior to this version, the charset can't be set in the dsn
  62.             if(is_php('5.3.6'))
  63.             {
  64.                 $this->hostname .= ";charset={$this->char_set}";
  65.             }
  66.            
  67.             //Set the charset with the connection options
  68.             $this->options['PDO::MYSQL_ATTR_INIT_COMMAND'] = "SET NAMES {$this->char_set}";
  69.         }
  70.         else if (strpos($this->hostname, 'odbc') !== FALSE)
  71.         {
  72.             $this->_like_escape_str = " {escape '%s'} ";
  73.             $this->_like_escape_chr = '!';
  74.         }
  75.         else
  76.         {
  77.             $this->_like_escape_str = " ESCAPE '%s' ";
  78.             $this->_like_escape_chr = '!';
  79.         }
  80.        
  81.         $this->hostname = 'mysql:dbname='.$this->database.';host='.$this->hostname;
  82.  
  83.         $this->trans_enabled = FALSE;
  84.  
  85.         $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
  86.     }
  87.  
  88.     /**
  89.      * Non-persistent database connection
  90.      *
  91.      * @access  private called by the base class
  92.      * @return  resource
  93.      */
  94.     function db_connect()
  95.     {
  96.         $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT;
  97.        
  98.         return new PDO($this->hostname, $this->username, $this->password, $this->options);
  99.     }
  100.  
  101.     // --------------------------------------------------------------------
  102.  
  103.     /**
  104.      * Persistent database connection
  105.      *
  106.      * @access  private called by the base class
  107.      * @return  resource
  108.      */
  109.     function db_pconnect()
  110.     {
  111.         $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT;
  112.         $this->options['PDO::ATTR_PERSISTENT'] = TRUE;
  113.    
  114.         return new PDO($this->hostname, $this->username, $this->password, $this->options);
  115.     }
  116.  
  117.     // --------------------------------------------------------------------
  118.  
  119.     /**
  120.      * Reconnect
  121.      *
  122.      * Keep / reestablish the db connection if no queries have been
  123.      * sent for a length of time exceeding the server's idle timeout
  124.      *
  125.      * @access  public
  126.      * @return  void
  127.      */
  128.     function reconnect()
  129.     {
  130.         if ($this->db->db_debug)
  131.         {
  132.             return $this->db->display_error('db_unsuported_feature');
  133.         }
  134.         return FALSE;
  135.     }
  136.  
  137.     // --------------------------------------------------------------------
  138.  
  139.     /**
  140.      * Select the database
  141.      *
  142.      * @access  private called by the base class
  143.      * @return  resource
  144.      */
  145.     function db_select()
  146.     {
  147.         // Not needed for PDO
  148.         return TRUE;
  149.     }
  150.  
  151.     // --------------------------------------------------------------------
  152.  
  153.     /**
  154.      * Set client character set
  155.      *
  156.      * @access  public
  157.      * @param   string
  158.      * @param   string
  159.      * @return  resource
  160.      */
  161.     function db_set_charset($charset, $collation)
  162.     {
  163.         // @todo - add support if needed
  164.         return TRUE;
  165.     }
  166.  
  167.     // --------------------------------------------------------------------
  168.  
  169.     /**
  170.      * Version number query string
  171.      *
  172.      * @access  public
  173.      * @return  string
  174.      */
  175.     function _version()
  176.     {
  177.         return $this->conn_id->getAttribute(PDO::ATTR_CLIENT_VERSION);
  178.     }
  179.  
  180.     // --------------------------------------------------------------------
  181.  
  182.     /**
  183.      * Execute the query
  184.      *
  185.      * @access  private called by the base class
  186.      * @param   string  an SQL query
  187.      * @return  object
  188.      */
  189.     function _execute($sql)
  190.     {
  191.         $sql = $this->_prep_query($sql);
  192.         $result_id = $this->conn_id->query($sql);
  193.        
  194.         if (is_object($result_id))
  195.         {
  196.             $this->affect_rows = $result_id->rowCount();
  197.         }
  198.         else
  199.         {
  200.             $this->affect_rows = 0;
  201.         }
  202.        
  203.         return $result_id;
  204.     }
  205.  
  206.     // --------------------------------------------------------------------
  207.  
  208.     /**
  209.      * Prep the query
  210.      *
  211.      * If needed, each database adapter can prep the query string
  212.      *
  213.      * @access  private called by execute()
  214.      * @param   string  an SQL query
  215.      * @return  string
  216.      */
  217.     function _prep_query($sql)
  218.     {
  219.         return $sql;
  220.     }
  221.  
  222.     // --------------------------------------------------------------------
  223.  
  224.     /**
  225.      * Begin Transaction
  226.      *
  227.      * @access  public
  228.      * @return  bool
  229.      */
  230.     function trans_begin($test_mode = FALSE)
  231.     {
  232.         if ( ! $this->trans_enabled)
  233.         {
  234.             return TRUE;
  235.         }
  236.  
  237.         // When transactions are nested we only begin/commit/rollback the outermost ones
  238.         if ($this->_trans_depth > 0)
  239.         {
  240.             return TRUE;
  241.         }
  242.  
  243.         // Reset the transaction failure flag.
  244.         // If the $test_mode flag is set to TRUE transactions will be rolled back
  245.         // even if the queries produce a successful result.
  246.         $this->_trans_failure = (bool) ($test_mode === TRUE);
  247.  
  248.         return $this->conn_id->beginTransaction();
  249.     }
  250.  
  251.     // --------------------------------------------------------------------
  252.  
  253.     /**
  254.      * Commit Transaction
  255.      *
  256.      * @access  public
  257.      * @return  bool
  258.      */
  259.     function trans_commit()
  260.     {
  261.         if ( ! $this->trans_enabled)
  262.         {
  263.             return TRUE;
  264.         }
  265.  
  266.         // When transactions are nested we only begin/commit/rollback the outermost ones
  267.         if ($this->_trans_depth > 0)
  268.         {
  269.             return TRUE;
  270.         }
  271.  
  272.         $ret = $this->conn->commit();
  273.         return $ret;
  274.     }
  275.  
  276.     // --------------------------------------------------------------------
  277.  
  278.     /**
  279.      * Rollback Transaction
  280.      *
  281.      * @access  public
  282.      * @return  bool
  283.      */
  284.     function trans_rollback()
  285.     {
  286.         if ( ! $this->trans_enabled)
  287.         {
  288.             return TRUE;
  289.         }
  290.  
  291.         // When transactions are nested we only begin/commit/rollback the outermost ones
  292.         if ($this->_trans_depth > 0)
  293.         {
  294.             return TRUE;
  295.         }
  296.  
  297.         $ret = $this->conn_id->rollBack();
  298.         return $ret;
  299.     }
  300.  
  301.     // --------------------------------------------------------------------
  302.  
  303.     /**
  304.      * Escape String
  305.      *
  306.      * @access  public
  307.      * @param   string
  308.      * @param   bool    whether or not the string will be used in a LIKE condition
  309.      * @return  string
  310.      */
  311.     function escape_str($str, $like = FALSE)
  312.     {
  313.         if (is_array($str))
  314.         {
  315.             foreach ($str as $key => $val)
  316.             {
  317.                 $str[$key] = $this->escape_str($val, $like);
  318.             }
  319.  
  320.             return $str;
  321.         }
  322.        
  323.         //Escape the string
  324.         $str = $this->conn_id->quote($str);
  325.        
  326.         //If there are duplicated quotes, trim them away
  327.         if (strpos($str, "'") === 0)
  328.         {
  329.             $str = substr($str, 1, -1);
  330.         }
  331.        
  332.         // escape LIKE condition wildcards
  333.         if ($like === TRUE)
  334.         {
  335.             $str = str_replace( array('%', '_', $this->_like_escape_chr),
  336.                                 array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
  337.                                 $str);
  338.         }
  339.  
  340.         return $str;
  341.     }
  342.  
  343.     // --------------------------------------------------------------------
  344.  
  345.     /**
  346.      * Affected Rows
  347.      *
  348.      * @access  public
  349.      * @return  integer
  350.      */
  351.     function affected_rows()
  352.     {
  353.         return $this->affect_rows;
  354.     }
  355.  
  356.     // --------------------------------------------------------------------
  357.  
  358.     /**
  359.      * Insert ID
  360.      *
  361.      * @access  public
  362.      * @return  integer
  363.      */
  364.     function insert_id($name=NULL)
  365.     {
  366.         //Convenience method for postgres insertid
  367.         if (strpos($this->hostname, 'pgsql') !== FALSE)
  368.         {
  369.             $v = $this->_version();
  370.  
  371.             $table  = func_num_args() > 0 ? func_get_arg(0) : NULL;
  372.  
  373.             if ($table == NULL && $v >= '8.1')
  374.             {
  375.                 $sql='SELECT LASTVAL() as ins_id';
  376.             }
  377.             $query = $this->query($sql);
  378.             $row = $query->row();
  379.             return $row->ins_id;
  380.         }
  381.         else
  382.         {
  383.             return $this->conn_id->lastInsertId($name);
  384.         }
  385.     }
  386.  
  387.     // --------------------------------------------------------------------
  388.  
  389.     /**
  390.      * "Count All" query
  391.      *
  392.      * Generates a platform-specific query string that counts all records in
  393.      * the specified database
  394.      *
  395.      * @access  public
  396.      * @param   string
  397.      * @return  string
  398.      */
  399.     function count_all($table = '')
  400.     {
  401.         if ($table == '')
  402.         {
  403.             return 0;
  404.         }
  405.  
  406.         $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
  407.  
  408.         if ($query->num_rows() == 0)
  409.         {
  410.             return 0;
  411.         }
  412.  
  413.         $row = $query->row();
  414.         $this->_reset_select();
  415.         return (int) $row->numrows;
  416.     }
  417.  
  418.     // --------------------------------------------------------------------
  419.  
  420.     /**
  421.      * Show table query
  422.      *
  423.      * Generates a platform-specific query string so that the table names can be fetched
  424.      *
  425.      * @access  private
  426.      * @param   boolean
  427.      * @return  string
  428.      */
  429.     function _list_tables($prefix_limit = FALSE)
  430.     {
  431.         $sql = "SHOW TABLES FROM `".$this->database."`";
  432.  
  433.         if ($prefix_limit !== FALSE AND $this->dbprefix != '')
  434.         {
  435.             //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
  436.             return FALSE; // not currently supported
  437.         }
  438.  
  439.         return $sql;
  440.     }
  441.  
  442.     // --------------------------------------------------------------------
  443.  
  444.     /**
  445.      * Show column query
  446.      *
  447.      * Generates a platform-specific query string so that the column names can be fetched
  448.      *
  449.      * @access  public
  450.      * @param   string  the table name
  451.      * @return  string
  452.      */
  453.     function _list_columns($table = '')
  454.     {
  455.         return "SHOW COLUMNS FROM ".$table;
  456.     }
  457.  
  458.     // --------------------------------------------------------------------
  459.  
  460.     /**
  461.      * Field data query
  462.      *
  463.      * Generates a platform-specific query so that the column data can be retrieved
  464.      *
  465.      * @access  public
  466.      * @param   string  the table name
  467.      * @return  object
  468.      */
  469.     function _field_data($table)
  470.     {
  471.         return "SELECT TOP 1 FROM ".$table;
  472.     }
  473.  
  474.     // --------------------------------------------------------------------
  475.  
  476.     /**
  477.      * The error message string
  478.      *
  479.      * @access  private
  480.      * @return  string
  481.      */
  482.     function _error_message()
  483.     {
  484.         $error_array = $this->conn_id->errorInfo();
  485.         return $error_array[2];
  486.     }
  487.  
  488.     // --------------------------------------------------------------------
  489.  
  490.     /**
  491.      * The error message number
  492.      *
  493.      * @access  private
  494.      * @return  integer
  495.      */
  496.     function _error_number()
  497.     {
  498.         return $this->conn_id->errorCode();
  499.     }
  500.  
  501.     // --------------------------------------------------------------------
  502.  
  503.     /**
  504.      * Escape the SQL Identifiers
  505.      *
  506.      * This function escapes column and table names
  507.      *
  508.      * @access  private
  509.      * @param   string
  510.      * @return  string
  511.      */
  512.     function _escape_identifiers($item)
  513.     {
  514.         if ($this->_escape_char == '')
  515.         {
  516.             return $item;
  517.         }
  518.  
  519.         foreach ($this->_reserved_identifiers as $id)
  520.         {
  521.             if (strpos($item, '.'.$id) !== FALSE)
  522.             {
  523.                 $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
  524.  
  525.                 // remove duplicates if the user already included the escape
  526.                 return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
  527.             }
  528.         }
  529.  
  530.         if (strpos($item, '.') !== FALSE)
  531.         {
  532.             $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
  533.            
  534.         }
  535.         else
  536.         {
  537.             $str = $this->_escape_char.$item.$this->_escape_char;
  538.         }
  539.  
  540.         // remove duplicates if the user already included the escape
  541.         return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
  542.     }
  543.  
  544.     // --------------------------------------------------------------------
  545.  
  546.     /**
  547.      * From Tables
  548.      *
  549.      * This function implicitly groups FROM tables so there is no confusion
  550.      * about operator precedence in harmony with SQL standards
  551.      *
  552.      * @access  public
  553.      * @param   type
  554.      * @return  type
  555.      */
  556.     function _from_tables($tables)
  557.     {
  558.         if ( ! is_array($tables))
  559.         {
  560.             $tables = array($tables);
  561.         }
  562.  
  563.         return (count($tables) == 1) ? $tables[0] : '('.implode(', ', $tables).')';
  564.     }
  565.  
  566.     // --------------------------------------------------------------------
  567.  
  568.     /**
  569.      * Insert statement
  570.      *
  571.      * Generates a platform-specific insert string from the supplied data
  572.      *
  573.      * @access  public
  574.      * @param   string  the table name
  575.      * @param   array   the insert keys
  576.      * @param   array   the insert values
  577.      * @return  string
  578.      */
  579.     function _insert($table, $keys, $values)
  580.     {
  581.         return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
  582.     }
  583.    
  584.     // --------------------------------------------------------------------
  585.  
  586.     /**
  587.      * Insert_batch statement
  588.      *
  589.      * Generates a platform-specific insert string from the supplied data
  590.      *
  591.      * @access  public
  592.      * @param   string  the table name
  593.      * @param   array   the insert keys
  594.      * @param   array   the insert values
  595.      * @return  string
  596.      */
  597.     function _insert_batch($table, $keys, $values)
  598.     {
  599.         return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
  600.     }
  601.  
  602.     // --------------------------------------------------------------------
  603.  
  604.     /**
  605.      * Update statement
  606.      *
  607.      * Generates a platform-specific update string from the supplied data
  608.      *
  609.      * @access  public
  610.      * @param   string  the table name
  611.      * @param   array   the update data
  612.      * @param   array   the where clause
  613.      * @param   array   the orderby clause
  614.      * @param   array   the limit clause
  615.      * @return  string
  616.      */
  617.     function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
  618.     {
  619.         foreach ($values as $key => $val)
  620.         {
  621.             $valstr[] = $key." = ".$val;
  622.         }
  623.  
  624.         $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
  625.  
  626.         $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
  627.  
  628.         $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
  629.  
  630.         $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
  631.  
  632.         $sql .= $orderby.$limit;
  633.  
  634.         return $sql;
  635.     }
  636.    
  637.     // --------------------------------------------------------------------
  638.  
  639.     /**
  640.      * Update_Batch statement
  641.      *
  642.      * Generates a platform-specific batch update string from the supplied data
  643.      *
  644.      * @access  public
  645.      * @param   string  the table name
  646.      * @param   array   the update data
  647.      * @param   array   the where clause
  648.      * @return  string
  649.      */
  650.     function _update_batch($table, $values, $index, $where = NULL)
  651.     {
  652.         $ids = array();
  653.         $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
  654.  
  655.         foreach ($values as $key => $val)
  656.         {
  657.             $ids[] = $val[$index];
  658.  
  659.             foreach (array_keys($val) as $field)
  660.             {
  661.                 if ($field != $index)
  662.                 {
  663.                     $final[$field][] =  'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
  664.                 }
  665.             }
  666.         }
  667.  
  668.         $sql = "UPDATE ".$table." SET ";
  669.         $cases = '';
  670.  
  671.         foreach ($final as $k => $v)
  672.         {
  673.             $cases .= $k.' = CASE '."\n";
  674.             foreach ($v as $row)
  675.             {
  676.                 $cases .= $row."\n";
  677.             }
  678.  
  679.             $cases .= 'ELSE '.$k.' END, ';
  680.         }
  681.  
  682.         $sql .= substr($cases, 0, -2);
  683.  
  684.         $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
  685.  
  686.         return $sql;
  687.     }
  688.  
  689.  
  690.     // --------------------------------------------------------------------
  691.  
  692.     /**
  693.      * Truncate statement
  694.      *
  695.      * Generates a platform-specific truncate string from the supplied data
  696.      * If the database does not support the truncate() command
  697.      * This function maps to "DELETE FROM table"
  698.      *
  699.      * @access  public
  700.      * @param   string  the table name
  701.      * @return  string
  702.      */
  703.     function _truncate($table)
  704.     {
  705.         return $this->_delete($table);
  706.     }
  707.  
  708.     // --------------------------------------------------------------------
  709.  
  710.     /**
  711.      * Delete statement
  712.      *
  713.      * Generates a platform-specific delete string from the supplied data
  714.      *
  715.      * @access  public
  716.      * @param   string  the table name
  717.      * @param   array   the where clause
  718.      * @param   string  the limit clause
  719.      * @return  string
  720.      */
  721.     function _delete($table, $where = array(), $like = array(), $limit = FALSE)
  722.     {
  723.         $conditions = '';
  724.  
  725.         if (count($where) > 0 OR count($like) > 0)
  726.         {
  727.             $conditions = "\nWHERE ";
  728.             $conditions .= implode("\n", $this->ar_where);
  729.  
  730.             if (count($where) > 0 && count($like) > 0)
  731.             {
  732.                 $conditions .= " AND ";
  733.             }
  734.             $conditions .= implode("\n", $like);
  735.         }
  736.  
  737.         $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
  738.  
  739.         return "DELETE FROM ".$table.$conditions.$limit;
  740.     }
  741.  
  742.     // --------------------------------------------------------------------
  743.  
  744.     /**
  745.      * Limit string
  746.      *
  747.      * Generates a platform-specific LIMIT clause
  748.      *
  749.      * @access  public
  750.      * @param   string  the sql query string
  751.      * @param   integer the number of rows to limit the query to
  752.      * @param   integer the offset value
  753.      * @return  string
  754.      */
  755.     function _limit($sql, $limit, $offset)
  756.     {
  757.         if (strpos($this->hostname, 'cubrid') !== FALSE || strpos($this->hostname, 'sqlite') !== FALSE)
  758.         {
  759.             if ($offset == 0)
  760.             {
  761.                 $offset = '';
  762.             }
  763.             else
  764.             {
  765.                 $offset .= ", ";
  766.             }
  767.  
  768.             return $sql."LIMIT ".$offset.$limit;
  769.         }
  770.         else
  771.         {
  772.             $sql .= "LIMIT ".$limit;
  773.  
  774.             if ($offset > 0)
  775.             {
  776.                 $sql .= " OFFSET ".$offset;
  777.             }
  778.            
  779.             return $sql;
  780.         }
  781.     }
  782.  
  783.     // --------------------------------------------------------------------
  784.  
  785.     /**
  786.      * Close DB Connection
  787.      *
  788.      * @access  public
  789.      * @param   resource
  790.      * @return  void
  791.      */
  792.     function _close($conn_id)
  793.     {
  794.         $this->conn_id = null;
  795.     }
  796.  
  797.  
  798. }
  799.  
  800.  
  801.  
  802. /* End of file pdo_driver.php */
  803. /* Location: ./system/database/drivers/pdo/pdo_driver.php */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement