Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #217 from dshafik/mysql-pdo

Use ext/pdo_mysql instead of ext/mysql
  • Loading branch information...
commit 31c2945eac5787cc32f0ef63edafdb1fcacb8201 2 parents 2fd2b9f + 81d3198
@nateabele nateabele authored
View
91 data/source/database/adapter/MySql.php
@@ -9,6 +9,7 @@
namespace lithium\data\source\database\adapter;
use lithium\data\model\QueryException;
+use \PDO, \PDOStatement, \PDOException;
/**
* Extends the `Database` class to implement the necessary SQL-formatting and resultset-fetching
@@ -20,6 +21,11 @@
*/
class MySql extends \lithium\data\source\Database {
+ /**
+ * @var PDO
+ */
+ public $connection;
+
protected $_classes = array(
'entity' => 'lithium\data\entity\Record',
'set' => 'lithium\data\collection\RecordSet',
@@ -96,7 +102,7 @@ public function __construct(array $config = array()) {
*/
public static function enabled($feature = null) {
if (!$feature) {
- return extension_loaded('mysql');
+ return extension_loaded('pdo_mysql');
}
$features = array(
'arrays' => false,
@@ -122,27 +128,27 @@ public function connect() {
return false;
}
- if (!$config['persistent']) {
- $this->connection = mysql_connect($host, $config['login'], $config['password'], true);
- } else {
- $this->connection = mysql_pconnect($host, $config['login'], $config['password']);
- }
+ $options = array(
+ PDO::ATTR_PERSISTENT => $config['persistent'],
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
+ );
- if (!$this->connection) {
+ try {
+ list($host, $port) = array(1 => "3306") + explode(':', $host);
+ $dsn = sprintf("mysql:host=%s;port=%s;dbname=%s", $host, $port, $config['database']);
+ $this->connection = new PDO($dsn, $config['login'], $config['password'], $options);
+ } catch (PDOException $e) {
return false;
}
- if (mysql_select_db($config['database'], $this->connection)) {
- $this->_isConnected = true;
- } else {
- return false;
- }
+ $this->_isConnected = true;
if ($config['encoding']) {
$this->encoding($config['encoding']);
}
- $info = mysql_get_server_info($this->connection);
+ $info = $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION);
+
$this->_useAlias = (boolean) version_compare($info, "4.1", ">=");
return $this->_isConnected;
}
@@ -154,8 +160,9 @@ public function connect() {
*/
public function disconnect() {
if ($this->_isConnected) {
- $this->_isConnected = !mysql_close($this->connection);
- return !$this->_isConnected;
+ unset($this->connection);
+ $this->_isConnected = false;
+ return true;
}
return true;
}
@@ -180,7 +187,7 @@ public function sources($model = null) {
$sources = array();
while ($data = $result->next()) {
- list($sources[]) = $data;
+ $sources[] = array_shift($data);
}
return $sources;
});
@@ -233,11 +240,17 @@ public function encoding($encoding = null) {
$encodingMap = array('UTF-8' => 'utf8');
if (empty($encoding)) {
- $encoding = mysql_client_encoding($this->connection);
+ $query = $this->connection->query("SHOW VARIABLES LIKE 'character_set_client'");
+ $encoding = $query->fetchColumn(1);
return ($key = array_search($encoding, $encodingMap)) ? $key : $encoding;
}
$encoding = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encoding;
- return mysql_set_charset($encoding, $this->connection);
+ try {
+ $this->connection->exec("SET NAMES '$encoding'");
+ return true;
+ } catch (PDOException $e) {
+ return false;
+ }
}
/**
@@ -252,7 +265,7 @@ public function value($value, array $schema = array()) {
if (($result = parent::value($value, $schema)) !== null) {
return $result;
}
- return "'" . mysql_real_escape_string((string) $value, $this->connection) . "'";
+ return $this->connection->quote((string) $value);
}
/**
@@ -270,10 +283,11 @@ public function schema($query, $resource = null, $context = null) {
}
$result = array();
- $count = mysql_num_fields($resource->resource());
+ $count = $resource->resource()->columnCount();
for ($i = 0; $i < $count; $i++) {
- $result[] = mysql_field_name($resource->resource(), $i);
+ $meta = $resource->resource()->getColumnMeta($i);
+ $result[] = $meta['name'];
}
return $result;
}
@@ -284,8 +298,8 @@ public function schema($query, $resource = null, $context = null) {
* @return array
*/
public function error() {
- if (mysql_error($this->connection)) {
- return array(mysql_errno($this->connection), mysql_error($this->connection));
+ if ($error = $this->connection->errorInfo()) {
+ return array($error[1], $error[2]);
}
return null;
}
@@ -324,34 +338,35 @@ public function conditions($conditions, $context, array $options = array()) {
protected function _execute($sql, array $options = array()) {
$defaults = array('buffered' => true);
$options += $defaults;
- mysql_select_db($this->_config['database'], $this->connection);
+ $this->connection->exec('USE ' . $this->_config['database']);
- return $this->_filter(__METHOD__, compact('sql', 'options'), function($self, $params) {
+ $conn = $this->connection;
+
+ $params = compact('sql', 'options');
+
+ return $this->_filter(__METHOD__, $params, function($self, $params) use ($conn) {
$sql = $params['sql'];
$options = $params['options'];
- $func = ($options['buffered']) ? 'mysql_query' : 'mysql_unbuffered_query';
- $resource = $func($sql, $self->connection);
+ $conn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $options['buffered']);
- if ($resource === true) {
- return true;
- }
- if (is_resource($resource)) {
- return $self->invokeMethod('_instance', array('result', compact('resource')));
+ if (!($resource = $conn->query($sql)) instanceof PDOStatement) {
+ list($code, $error) = $self->error();
+ throw new QueryException("{$sql}: {$error}", $code);
}
- list($code, $error) = $self->error();
- throw new QueryException("{$sql}: {$error}", $code);
+ return $self->invokeMethod('_instance', array('result', compact('resource')));
});
}
protected function _results($results) {
- $numFields = mysql_num_fields($results);
+ /* @var $results PDOStatement */
+ $numFields = $results->columnCount();
$index = $j = 0;
while ($j < $numFields) {
- $column = mysql_fetch_field($results, $j);
- $name = $column->name;
- $table = $column->table;
+ $column = $results->getColumnMeta($j);
+ $name = $column['name'];
+ $table = $column['table'];
$this->map[$index++] = empty($table) ? array(0, $name) : array($table, $name);
$j++;
}
View
102 data/source/database/adapter/my_sql/Result.php
@@ -8,36 +8,106 @@
namespace lithium\data\source\database\adapter\my_sql;
-class Result extends \lithium\data\source\database\Result {
+use \PDO, \PDOStatement;
+
+class Result extends \lithium\core\Object implements \Iterator {
+ protected $_previousResultsCache = null;
+
+ protected $_iterator = 0;
+
+ protected $_maxIteration = 0;
+
+ protected $_current = null;
+
+ /**
+ * @var PDOStatement
+ */
+ protected $_resource = null;
+
+ protected $_autoConfig = array('resource');
+
+ public function resource() {
+ return $this->_resource;
+ }
+
+ public function rewind() {
+ $this->_iterator = 0;
+ $this->_current = null;
+ return null;
+ }
+
+ public function valid() {
+ return $this->_current;
+ }
+
+ public function current() {
+ return $this->_current;
+ }
+
+ public function key() {
+ return $this->_iterator;
+ }
public function prev() {
- if ($this->_current = $this->_prev()) {
- $this->_iterator--;
+ if (!$this->_resource) {
+ return;
+ }
+
+ $this->_iterator--;
+
+ // Return the previous result from the previous results cache
+ if (isset($this->_previousResultsCache[$this->_iterator])) {
+ $this->_current = $this->_previousResultsCache[$this->_iterator];
return $this->_current;
+ } else {
+ return;
}
}
- protected function _prev() {
- if ($this->_resource && $this->_iterator) {
- if (mysql_data_seek($this->_resource, $this->_iterator -1)) {
- return mysql_fetch_row($this->_resource);
+ public function next() {
+ if ($this->_validResultSet()) {
+ if (($result = $this->_fetchFromCache()) || ($result = $this->_fetchFromResource())) {
+ return $result;
}
+
+ unset($this->_resource);
+ $this->_resource = null;
}
+
+ return;
}
- protected function _next() {
- if ($this->_resource) {
- $inRange = $this->_iterator < mysql_num_rows($this->_resource);
- if ($inRange && mysql_data_seek($this->_resource, $this->_iterator)) {
- return mysql_fetch_row($this->_resource);
- }
+ protected function _validResultSet() {
+ if (!$this->_resource && empty($this->_previousResultsCache)) {
+ return false;
}
+
+ return true;
}
- protected function _close() {
- if ($this->_resource) {
- mysql_free_result($this->_resource);
+
+ protected function _fetchFromCache() {
+ if ($this->_iterator < $this->_maxIteration) {
+ $this->_iterator++;
+ return $this->_previousResultsCache[$this->_iterator];
}
+
+ return false;
+ }
+
+ protected function _fetchFromResource() {
+ if ($this->_resource instanceof PDOStatement
+ && $this->_iterator < $this->_resource->rowCount()
+ && $result = $this->_resource->fetch(PDO::FETCH_ASSOC)) {
+
+ $this->_iterator++;
+ $this->_maxIteration = $this->_iterator;
+ $this->_previousResultsCache[$this->_iterator] = $result;
+
+ return $result;
+ }
+
+ return false;
}
}
View
48 tests/cases/data/source/database/adapter/MySqlTest.php
@@ -253,6 +253,54 @@ public function testDescribe() {
);
$this->assertEqual($expected, $result);
}
+
+ public function testResultSetMovement() {
+ $this->assertTrue($this->db->create(
+ 'INSERT INTO companies (name) VALUES (?)',
+ array('Test 1')
+ ));
+ $this->assertTrue($this->db->create(
+ 'INSERT INTO companies (name) VALUES (?)',
+ array('Test 2')
+ ));
+ $this->assertTrue($this->db->create(
+ 'INSERT INTO companies (name) VALUES (?)',
+ array('Test 3')
+ ));
+
+ $result = $this->db->read('SELECT * From companies AS Company WHERE name IN ("Test 1", "Test 2", "Test 3")', array(
+ 'return' => 'resource'
+ ));
+
+ $row = $result->next();
+ $this->assertEqual('Test 1', $row['name']);
+
+ $row = $result->next();
+ $this->assertEqual('Test 2', $row['name']);
+
+ $row = $result->prev();
+ $this->assertEqual('Test 1', $row['name']);
+
+ $row = $result->next();
+ $this->assertEqual('Test 2', $row['name']);
+
+ $row = $result->next();
+ $this->assertEqual('Test 3', $row['name']);
+
+ $row = $result->next();
+ $this->assertNull($row);
+
+ $result->rewind();
+ $row = $result->next();
+ $this->assertEqual('Test 1', $row['name']);
+
+ $result->next(); $result->next();
+
+ $row = $result->next();
+ $this->assertNull($row);
+
+ $this->assertTrue($this->db->delete('DELETE From companies WHERE name IN ("Test 1", "Test 2", "Test 3")'));
+ }
}
?>
Please sign in to comment.
Something went wrong with that request. Please try again.