Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2012
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 12.94 KB | None | 0 0
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3.  * MySQL database connection.
  4.  *
  5.  * @package    Kohana/Database
  6.  * @category   Drivers
  7.  * @author     Kohana Team
  8.  * @copyright  (c) 2008-2009 Kohana Team
  9.  * @license    http://kohanaphp.com/license
  10.  */
  11. class Kohana_Database_MySQL extends Database {
  12.  
  13.     // Database in use by each connection
  14.     protected static $_current_databases = array();
  15.  
  16.     // Use SET NAMES to set the character set
  17.     protected static $_set_names;
  18.  
  19.     // Identifier for this connection within the PHP driver
  20.     protected $_connection_id;
  21.  
  22.     // MySQL uses a backtick for identifiers
  23.     protected $_identifier = '`';
  24.  
  25.     public function connect()
  26.     {
  27.         if ($this->_connection)
  28.             return;
  29.  
  30.         if (Database_MySQL::$_set_names === NULL)
  31.         {
  32.             // Determine if we can use mysql_set_charset(), which is only
  33.             // available on PHP 5.2.3+ when compiled against MySQL 5.0+
  34.             Database_MySQL::$_set_names = ! function_exists('mysql_set_charset');
  35.         }
  36.  
  37.         // Extract the connection parameters, adding required variabels
  38.         extract($this->_config['connection'] + array(
  39.             'database'   => '',
  40.             'hostname'   => '',
  41.             'username'   => '',
  42.             'password'   => '',
  43.             'persistent' => FALSE,
  44.         ));
  45.  
  46.         // Prevent this information from showing up in traces
  47.         unset($this->_config['connection']['username'], $this->_config['connection']['password']);
  48.  
  49.         try
  50.         {
  51.             if ($persistent)
  52.             {
  53.                 // Create a persistent connection
  54.                 $this->_connection = mysql_pconnect($hostname, $username, $password);
  55.             }
  56.             else
  57.             {
  58.                 // Create a connection and force it to be a new link
  59.                 $this->_connection = mysql_connect($hostname, $username, $password, TRUE);
  60.             }
  61.         }
  62.         catch (Exception $e)
  63.         {
  64.             // No connection exists
  65.             $this->_connection = NULL;
  66.  
  67.             throw new Database_Exception(':error',
  68.                 array(':error' => $e->getMessage()),
  69.                 $e->getCode());
  70.         }
  71.  
  72.         // \xFF is a better delimiter, but the PHP driver uses underscore
  73.         $this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
  74.  
  75.         $this->_select_db($database);
  76.  
  77.         if ( ! empty($this->_config['charset']))
  78.         {
  79.             // Set the character set
  80.             $this->set_charset($this->_config['charset']);
  81.         }
  82.  
  83.         if ( ! empty($this->_config['connection']['variables']))
  84.         {
  85.             // Set session variables
  86.             $variables = array();
  87.  
  88.             foreach ($this->_config['connection']['variables'] as $var => $val)
  89.             {
  90.                 $variables[] = 'SESSION '.$var.' = '.$this->quote($val);
  91.             }
  92.  
  93.             mysql_query('SET '.implode(', ', $variables), $this->_connection);
  94.         }
  95.     }
  96.  
  97.     /**
  98.      * Select the database
  99.      *
  100.      * @param   string  Database
  101.      * @return  void
  102.      */
  103.     protected function _select_db($database)
  104.     {
  105.         if ( ! mysql_select_db($database, $this->_connection))
  106.         {
  107.             // Unable to select database
  108.             throw new Database_Exception(':error',
  109.                 array(':error' => mysql_error($this->_connection)),
  110.                 mysql_errno($this->_connection));
  111.         }
  112.  
  113.         Database_MySQL::$_current_databases[$this->_connection_id] = $database;
  114.     }
  115.  
  116.     public function disconnect()
  117.     {
  118.         try
  119.         {
  120.             // Database is assumed disconnected
  121.             $status = TRUE;
  122.  
  123.             if (is_resource($this->_connection))
  124.             {
  125.                 if ($status = mysql_close($this->_connection))
  126.                 {
  127.                     // Clear the connection
  128.                     $this->_connection = NULL;
  129.  
  130.                     // Clear the instance
  131.                     parent::disconnect();
  132.                 }
  133.             }
  134.         }
  135.         catch (Exception $e)
  136.         {
  137.             // Database is probably not disconnected
  138.             $status = ! is_resource($this->_connection);
  139.         }
  140.  
  141.         return $status;
  142.     }
  143.  
  144.     public function set_charset($charset)
  145.     {
  146.         // Make sure the database is connected
  147.         $this->_connection or $this->connect();
  148.  
  149.         if (Database_MySQL::$_set_names === TRUE)
  150.         {
  151.             // PHP is compiled against MySQL 4.x
  152.             $status = (bool) mysql_query('SET NAMES '.$this->quote($charset), $this->_connection);
  153.         }
  154.         else
  155.         {
  156.             // PHP is compiled against MySQL 5.x
  157.             $status = mysql_set_charset($charset, $this->_connection);
  158.         }
  159.  
  160.         if ($status === FALSE)
  161.         {
  162.             throw new Database_Exception(':error',
  163.                 array(':error' => mysql_error($this->_connection)),
  164.                 mysql_errno($this->_connection));
  165.         }
  166.     }
  167.  
  168.     public function query($type, $sql, $as_object = FALSE, array $params = NULL)
  169.     {
  170.         // Make sure the database is connected
  171.         $this->_connection or $this->connect();
  172.  
  173.         if ( ! empty($this->_config['profiling']))
  174.         {
  175.             // Benchmark this query for the current instance
  176.             $benchmark = Profiler::start("Database ({$this->_instance})", $sql);
  177.         }
  178.  
  179.         if ( ! empty($this->_config['connection']['persistent']) AND $this->_config['connection']['database'] !== Database_MySQL::$_current_databases[$this->_connection_id])
  180.         {
  181.             // Select database on persistent connections
  182.             $this->_select_db($this->_config['connection']['database']);
  183.         }
  184.  
  185.         // Execute the query
  186.         if (($result = mysql_query($sql, $this->_connection)) === FALSE)
  187.         {
  188.             if (isset($benchmark))
  189.             {
  190.                 // This benchmark is worthless
  191.                 Profiler::delete($benchmark);
  192.             }
  193.  
  194.             throw new Database_Exception(':error [ :query ]',
  195.                 array(':error' => mysql_error($this->_connection), ':query' => $sql),
  196.                 mysql_errno($this->_connection));
  197.         }
  198.  
  199.         if (isset($benchmark))
  200.         {
  201.             Profiler::stop($benchmark);
  202.         }
  203.  
  204.         // Set the last query
  205.         $this->last_query = $sql;
  206.  
  207.         if ($type === Database::SELECT)
  208.         {
  209.             // Return an iterator of results
  210.             return new Database_MySQL_Result($result, $sql, $as_object, $params);
  211.         }
  212.         elseif ($type === Database::INSERT)
  213.         {
  214.             // Return a list of insert id and rows created
  215.             return array(
  216.                 mysql_insert_id($this->_connection),
  217.                 mysql_affected_rows($this->_connection),
  218.             );
  219.         }
  220.         else
  221.         {
  222.             // Return the number of rows affected
  223.             return mysql_affected_rows($this->_connection);
  224.         }
  225.     }
  226.  
  227.     public function datatype($type)
  228.     {
  229.         static $types = array
  230.         (
  231.             'blob'                      => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '65535'),
  232.             'bool'                      => array('type' => 'bool'),
  233.             'bigint unsigned'           => array('type' => 'int', 'min' => '0', 'max' => '18446744073709551615'),
  234.             'datetime'                  => array('type' => 'string'),
  235.             'decimal unsigned'          => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
  236.             'double'                    => array('type' => 'float'),
  237.             'double precision unsigned' => array('type' => 'float', 'min' => '0'),
  238.             'double unsigned'           => array('type' => 'float', 'min' => '0'),
  239.             'enum'                      => array('type' => 'string'),
  240.             'fixed'                     => array('type' => 'float', 'exact' => TRUE),
  241.             'fixed unsigned'            => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
  242.             'float unsigned'            => array('type' => 'float', 'min' => '0'),
  243.             'int unsigned'              => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
  244.             'integer unsigned'          => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
  245.             'longblob'                  => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '4294967295'),
  246.             'longtext'                  => array('type' => 'string', 'character_maximum_length' => '4294967295'),
  247.             'mediumblob'                => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '16777215'),
  248.             'mediumint'                 => array('type' => 'int', 'min' => '-8388608', 'max' => '8388607'),
  249.             'mediumint unsigned'        => array('type' => 'int', 'min' => '0', 'max' => '16777215'),
  250.             'mediumtext'                => array('type' => 'string', 'character_maximum_length' => '16777215'),
  251.             'national varchar'          => array('type' => 'string'),
  252.             'numeric unsigned'          => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
  253.             'nvarchar'                  => array('type' => 'string'),
  254.             'point'                     => array('type' => 'string', 'binary' => TRUE),
  255.             'real unsigned'             => array('type' => 'float', 'min' => '0'),
  256.             'set'                       => array('type' => 'string'),
  257.             'smallint unsigned'         => array('type' => 'int', 'min' => '0', 'max' => '65535'),
  258.             'text'                      => array('type' => 'string', 'character_maximum_length' => '65535'),
  259.             'tinyblob'                  => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '255'),
  260.             'tinyint'                   => array('type' => 'int', 'min' => '-128', 'max' => '127'),
  261.             'tinyint unsigned'          => array('type' => 'int', 'min' => '0', 'max' => '255'),
  262.             'tinytext'                  => array('type' => 'string', 'character_maximum_length' => '255'),
  263.             'year'                      => array('type' => 'string'),
  264.         );
  265.  
  266.         $type = str_replace(' zerofill', '', $type);
  267.  
  268.         if (isset($types[$type]))
  269.             return $types[$type];
  270.  
  271.         return parent::datatype($type);
  272.     }
  273.  
  274.     /**
  275.      * Start a SQL transaction
  276.      *
  277.      * @link http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
  278.      *
  279.      * @param string Isolation level
  280.      * @return boolean
  281.      */
  282.     public function begin($mode = NULL)
  283.     {
  284.         // Make sure the database is connected
  285.         $this->_connection or $this->connect();
  286.  
  287.         if ($mode AND ! mysql_query("SET TRANSACTION ISOLATION LEVEL $mode", $this->_connection))
  288.         {
  289.             throw new Database_Exception(':error',
  290.                 array(':error' => mysql_error($this->_connection)),
  291.                 mysql_errno($this->_connection));
  292.         }
  293.  
  294.         return (bool) mysql_query('START TRANSACTION', $this->_connection);
  295.     }
  296.  
  297.     /**
  298.      * Commit a SQL transaction
  299.      *
  300.      * @param string Isolation level
  301.      * @return boolean
  302.      */
  303.     public function commit()
  304.     {
  305.         // Make sure the database is connected
  306.         $this->_connection or $this->connect();
  307.  
  308.         return (bool) mysql_query('COMMIT', $this->_connection);
  309.     }
  310.  
  311.     /**
  312.      * Rollback a SQL transaction
  313.      *
  314.      * @param string Isolation level
  315.      * @return boolean
  316.      */
  317.     public function rollback()
  318.     {
  319.         // Make sure the database is connected
  320.         $this->_connection or $this->connect();
  321.  
  322.         return (bool) mysql_query('ROLLBACK', $this->_connection);
  323.     }
  324.  
  325.     public function list_tables($like = NULL)
  326.     {
  327.         if (is_string($like))
  328.         {
  329.             // Search for table names
  330.             $result = $this->query(Database::SELECT, 'SHOW TABLES LIKE '.$this->quote($like), FALSE);
  331.         }
  332.         else
  333.         {
  334.             // Find all table names
  335.             $result = $this->query(Database::SELECT, 'SHOW TABLES', FALSE);
  336.         }
  337.  
  338.         $tables = array();
  339.         foreach ($result as $row)
  340.         {
  341.             $tables[] = reset($row);
  342.         }
  343.  
  344.         return $tables;
  345.     }
  346.  
  347.     public function list_columns($table, $like = NULL, $add_prefix = TRUE)
  348.     {
  349.         // Quote the table name
  350.         $table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
  351.  
  352.         if (is_string($like))
  353.         {
  354.             // Search for column names
  355.             $result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table.' LIKE '.$this->quote($like), FALSE);
  356.         }
  357.         else
  358.         {
  359.             // Find all column names
  360.             $result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table, FALSE);
  361.         }
  362.  
  363.         $count = 0;
  364.         $columns = array();
  365.         foreach ($result as $row)
  366.         {
  367.             list($type, $length) = $this->_parse_type($row['Type']);
  368.  
  369.             $column = $this->datatype($type);
  370.  
  371.             $column['column_name']      = $row['Field'];
  372.             $column['column_default']   = $row['Default'];
  373.             $column['data_type']        = $type;
  374.             $column['is_nullable']      = ($row['Null'] == 'YES');
  375.             $column['ordinal_position'] = ++$count;
  376.  
  377.             switch ($column['type'])
  378.             {
  379.                 case 'float':
  380.                     if (isset($length))
  381.                     {
  382.                         list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
  383.                     }
  384.                 break;
  385.                 case 'int':
  386.                     if (isset($length))
  387.                     {
  388.                         // MySQL attribute
  389.                         $column['display'] = $length;
  390.                     }
  391.                 break;
  392.                 case 'string':
  393.                     switch ($column['data_type'])
  394.                     {
  395.                         case 'binary':
  396.                         case 'varbinary':
  397.                             $column['character_maximum_length'] = $length;
  398.                         break;
  399.                         case 'char':
  400.                         case 'varchar':
  401.                             $column['character_maximum_length'] = $length;
  402.                         case 'text':
  403.                         case 'tinytext':
  404.                         case 'mediumtext':
  405.                         case 'longtext':
  406.                             $column['collation_name'] = $row['Collation'];
  407.                         break;
  408.                         case 'enum':
  409.                         case 'set':
  410.                             $column['collation_name'] = $row['Collation'];
  411.                             $column['options'] = explode('\',\'', substr($length, 1, -1));
  412.                         break;
  413.                     }
  414.                 break;
  415.             }
  416.  
  417.             // MySQL attributes
  418.             $column['comment']      = $row['Comment'];
  419.             $column['extra']        = $row['Extra'];
  420.             $column['key']          = $row['Key'];
  421.             $column['privileges']   = $row['Privileges'];
  422.  
  423.             $columns[$row['Field']] = $column;
  424.         }
  425.  
  426.         return $columns;
  427.     }
  428.  
  429.     public function escape($value)
  430.     {
  431.         // Make sure the database is connected
  432.         $this->_connection or $this->connect();
  433.  
  434.         if (($value = mysql_real_escape_string( (string) $value, $this->_connection)) === FALSE)
  435.         {
  436.             throw new Database_Exception(':error',
  437.                 array(':error' => mysql_error($this->_connection)),
  438.                 mysql_errno($this->_connection));
  439.         }
  440.  
  441.         // SQL standard is to use single-quotes for all values
  442.         return "'$value'";
  443.     }
  444.  
  445. } // End Database_MySQL
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement