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 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 $queryLogFile;
@ -34,33 +39,37 @@ class DatabaseMysql
/**
* Creates a MySQL connection object.
*
* @param string $host either 'host', 'host:port', or ':/var/run/mysqld/mysqld.sock'
* @param string $username
* @param string $password
* @param string $dbname
* @param string $port (optional)
* @param string $socket (optional)
* @param array $options Possible options:
* host Host name or IP address to connect to [localhost]
* socket Path to UNIX socket to connect to [/var/run/mysqld/mysqld.sock]
* port TCP port to connect to [3306]
* dbname DB name to use
* 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);
if (!$host[0])
$defOpts = array(
'host' => 'localhost',
'port' => 3306,
'socket' => '/var/run/mysqld/mysqld.sock',
'dbname' => '',
'username' => '',
'password' => '',
'reconnect' => true,
'queryLogFile' => '',
);
$options += $defOpts;
if ($options['socket'])
{
$socket = $host[1];
$host = 'localhost';
$options['host'] = 'localhost';
}
else
foreach ($defOpts as $k => $v)
{
if (isset($host[1]))
{
$port = $host[1];
}
$host = $host[0];
$this->$k = $options[$k];
}
$this->host = $host;
$this->username = $username;
$this->password = $password;
$this->dbname = $dbname;
}
function connect()
@ -77,7 +86,17 @@ class DatabaseMysql
{
$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()
@ -211,13 +230,13 @@ class DatabaseMysql
$wh = array();
foreach ($where as $k => $v)
{
if (ctype_digit($k))
if (ctype_digit("$k"))
$wh[] = $v;
elseif (is_array($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
{
@ -266,13 +285,13 @@ class DatabaseMysql
else
{
foreach ($options as $k => $v)
if (ctype_digit($k))
if (ctype_digit("$k"))
$options[$v] = true;
}
if (is_array($fields))
{
foreach ($fields as $k => $v)
if (!ctype_digit($k))
if (!ctype_digit("$k"))
$fields[$k] = "$v AS ".$this->quoteId($k);
$fields = join(',', $fields);
}
@ -294,7 +313,7 @@ class DatabaseMysql
$g1 = array();
foreach ($g as $k => $v)
{
if (ctype_digit($k))
if (ctype_digit("$k"))
$g1[] = $v;
else
$g1[] = "$k $v";
@ -311,7 +330,7 @@ class DatabaseMysql
$g1 = array();
foreach ($g as $k => $v)
{
if (ctype_digit($k))
if (ctype_digit("$k"))
$g1[] = $v;
else
$g1[] = "$k $v";
@ -365,7 +384,7 @@ class DatabaseMysql
$t = '';
foreach ($tables as $k => $v)
{
if (!ctype_digit($k))
if (!ctype_digit("$k"))
{
if (is_array($v))
{
@ -429,7 +448,7 @@ class DatabaseMysql
*/
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;
$format = $fields;
@ -502,7 +521,7 @@ class DatabaseMysql
* @param boolean $onduplicatekey If true, include
* 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]))
{
@ -519,7 +538,8 @@ class DatabaseMysql
foreach ($key as &$k)
if (strpos($k, '`') === false)
$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)
{
foreach ($key as &$k)
@ -560,6 +580,7 @@ class DatabaseMysql
* @param array $options Options for update query:
* 'LIMIT' => array($limit, $offset) or array($limit) or 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)
{
@ -569,9 +590,9 @@ class DatabaseMysql
{
if (!is_array($rows))
return false;
if (!is_array($rows[0]))
if (!is_array(@$rows[0]))
$rows = array($rows);
$sql = $this->insert_builder($table, $rows, true);
$sql = $this->insert_builder($table, $rows, true, !empty($options['replace']));
}
else
{
@ -580,7 +601,7 @@ class DatabaseMysql
$rows = array($rows);
foreach ($rows as $k => $v)
{
if (!ctype_digit($k))
if (!ctype_digit("$k"))
$sql[] = $k.'='.$this->quote($v);
else
$sql[] = $v;