DatabaseMysql: fix bugs, reconnect support, parameter hash

master
Vitaliy Filippov 2013-02-18 13:54:46 +00:00
parent 018d0ec1fc
commit a1dc99440b
1 changed files with 58 additions and 37 deletions

View File

@ -19,9 +19,14 @@ if (!defined('MS_HASH'))
class DatabaseException extends Exception {} class DatabaseException extends Exception {}
class DatabaseMysql if (!interface_exists('Database'))
{ {
var $host, $port, $socket, $username, $password, $dbName; interface Database {}
}
class DatabaseMysql implements Database
{
var $host, $port, $socket, $username, $password, $dbname;
var $tableNames = array(); var $tableNames = array();
var $queryLogFile; var $queryLogFile;
@ -34,33 +39,37 @@ class DatabaseMysql
/** /**
* Creates a MySQL connection object. * Creates a MySQL connection object.
* *
* @param string $host either 'host', 'host:port', or ':/var/run/mysqld/mysqld.sock' * @param array $options Possible options:
* @param string $username * host Host name or IP address to connect to [localhost]
* @param string $password * socket Path to UNIX socket to connect to [/var/run/mysqld/mysqld.sock]
* @param string $dbname * port TCP port to connect to [3306]
* @param string $port (optional) * dbname DB name to use
* @param string $socket (optional) * username Username
* password Password
* reconnect Whether to reconnect on idle timeout [true]
* queryLogFile Path to query log file
*/ */
function __construct($host, $username, $password, $dbname, $port = NULL, $socket = NULL) function __construct($options)
{ {
$host = explode(':', $host, 2); $defOpts = array(
if (!$host[0]) 'host' => 'localhost',
'port' => 3306,
'socket' => '/var/run/mysqld/mysqld.sock',
'dbname' => '',
'username' => '',
'password' => '',
'reconnect' => true,
'queryLogFile' => '',
);
$options += $defOpts;
if ($options['socket'])
{ {
$socket = $host[1]; $options['host'] = 'localhost';
$host = 'localhost';
} }
else foreach ($defOpts as $k => $v)
{ {
if (isset($host[1])) $this->$k = $options[$k];
{
$port = $host[1];
}
$host = $host[0];
} }
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->dbname = $dbname;
} }
function connect() function connect()
@ -77,7 +86,17 @@ class DatabaseMysql
{ {
$this->link = new mysqli($this->host, $this->username, $this->password, $this->dbname); $this->link = new mysqli($this->host, $this->username, $this->password, $this->dbname);
} }
$this->link->set_charset('utf8'); $errno = $this->link->connect_errno;
$error = $this->link->connect_error;
if ($errno)
{
$this->link = NULL;
throw new DatabaseException($error, $errno);
}
else
{
$this->link->set_charset('utf8');
}
} }
function getDBName() function getDBName()
@ -211,13 +230,13 @@ class DatabaseMysql
$wh = array(); $wh = array();
foreach ($where as $k => $v) foreach ($where as $k => $v)
{ {
if (ctype_digit($k)) if (ctype_digit("$k"))
$wh[] = $v; $wh[] = $v;
elseif (is_array($v)) elseif (is_array($v))
{ {
if (!$v) if (!$v)
{ {
throw new DatabaseException(E_DB_EMPTY_IN, "Error: empty array for '$k IN (...)', don't know what to do"); throw new DatabaseException("Error: empty array for '$k IN (...)', don't know what to do");
} }
else else
{ {
@ -266,13 +285,13 @@ class DatabaseMysql
else else
{ {
foreach ($options as $k => $v) foreach ($options as $k => $v)
if (ctype_digit($k)) if (ctype_digit("$k"))
$options[$v] = true; $options[$v] = true;
} }
if (is_array($fields)) if (is_array($fields))
{ {
foreach ($fields as $k => $v) foreach ($fields as $k => $v)
if (!ctype_digit($k)) if (!ctype_digit("$k"))
$fields[$k] = "$v AS ".$this->quoteId($k); $fields[$k] = "$v AS ".$this->quoteId($k);
$fields = join(',', $fields); $fields = join(',', $fields);
} }
@ -294,7 +313,7 @@ class DatabaseMysql
$g1 = array(); $g1 = array();
foreach ($g as $k => $v) foreach ($g as $k => $v)
{ {
if (ctype_digit($k)) if (ctype_digit("$k"))
$g1[] = $v; $g1[] = $v;
else else
$g1[] = "$k $v"; $g1[] = "$k $v";
@ -311,7 +330,7 @@ class DatabaseMysql
$g1 = array(); $g1 = array();
foreach ($g as $k => $v) foreach ($g as $k => $v)
{ {
if (ctype_digit($k)) if (ctype_digit("$k"))
$g1[] = $v; $g1[] = $v;
else else
$g1[] = "$k $v"; $g1[] = "$k $v";
@ -365,7 +384,7 @@ class DatabaseMysql
$t = ''; $t = '';
foreach ($tables as $k => $v) foreach ($tables as $k => $v)
{ {
if (!ctype_digit($k)) if (!ctype_digit("$k"))
{ {
if (is_array($v)) if (is_array($v))
{ {
@ -429,7 +448,7 @@ class DatabaseMysql
*/ */
function select($tables, $fields = '*', $where = 1, $options = NULL, $format = 0) function select($tables, $fields = '*', $where = 1, $options = NULL, $format = 0)
{ {
if (ctype_digit("$fields")) if (is_int($fields) || is_string($fields) && ctype_digit($fields))
{ {
$sql = $tables; $sql = $tables;
$format = $fields; $format = $fields;
@ -502,7 +521,7 @@ class DatabaseMysql
* @param boolean $onduplicatekey If true, include * @param boolean $onduplicatekey If true, include
* ON DUPLICATE KEY UPDATE column=VALUES(column) for all columns. * ON DUPLICATE KEY UPDATE column=VALUES(column) for all columns.
*/ */
function insert_builder($table, $rows, $onduplicatekey = false) function insert_builder($table, $rows, $onduplicatekey = false, $replace = false)
{ {
if (isset($this->tableNames[$table])) if (isset($this->tableNames[$table]))
{ {
@ -519,7 +538,8 @@ class DatabaseMysql
foreach ($key as &$k) foreach ($key as &$k)
if (strpos($k, '`') === false) if (strpos($k, '`') === false)
$k = $this->quoteId($k); $k = $this->quoteId($k);
$sql = "INSERT INTO $table (".implode(",",$key).") VALUES ".implode(",",$rows); $sql = ($replace ? "REPLACE" : "INSERT").
" INTO $table (".implode(",",$key).") VALUES ".implode(",",$rows);
if ($onduplicatekey) if ($onduplicatekey)
{ {
foreach ($key as &$k) foreach ($key as &$k)
@ -560,6 +580,7 @@ class DatabaseMysql
* @param array $options Options for update query: * @param array $options Options for update query:
* 'LIMIT' => array($limit, $offset) or array($limit) or just $limit * 'LIMIT' => array($limit, $offset) or array($limit) or just $limit
* 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit * 'OFFSET' => $offset, for the case when 'LIMIT' is just $limit
* 'REPLACE' => true to use REPLACE instead of INSERT
*/ */
function update($table, $rows, $where = NULL, $options = NULL) function update($table, $rows, $where = NULL, $options = NULL)
{ {
@ -569,9 +590,9 @@ class DatabaseMysql
{ {
if (!is_array($rows)) if (!is_array($rows))
return false; return false;
if (!is_array($rows[0])) if (!is_array(@$rows[0]))
$rows = array($rows); $rows = array($rows);
$sql = $this->insert_builder($table, $rows, true); $sql = $this->insert_builder($table, $rows, true, !empty($options['replace']));
} }
else else
{ {
@ -580,7 +601,7 @@ class DatabaseMysql
$rows = array($rows); $rows = array($rows);
foreach ($rows as $k => $v) foreach ($rows as $k => $v)
{ {
if (!ctype_digit($k)) if (!ctype_digit("$k"))
$sql[] = $k.'='.$this->quote($v); $sql[] = $k.'='.$this->quote($v);
else else
$sql[] = $v; $sql[] = $v;