Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb36858f1a | ||
|
|
1d797b306e | ||
|
|
7c819bfc24 | ||
|
|
1d147e169a | ||
|
|
391702700d | ||
|
|
37fd169be3 | ||
|
|
7c5c03c576 | ||
|
|
a0a2f702e2 | ||
|
|
2707bcba7d | ||
|
|
7b0da839de | ||
|
|
1d51c2b674 | ||
|
|
de63573e98 | ||
|
|
26fcce650a |
72
db.class.php
72
db.class.php
@@ -36,6 +36,8 @@ class DB {
|
||||
public static $throw_exception_on_nonsql_error = false;
|
||||
public static $nested_transactions = false;
|
||||
public static $usenull = true;
|
||||
public static $ssl = array('key' => '', 'cert' => '', 'ca_cert' => '', 'ca_path' => '', 'cipher' => '');
|
||||
public static $connect_options = array(MYSQLI_OPT_CONNECT_TIMEOUT => 30);
|
||||
|
||||
// internal
|
||||
protected static $mdb = null;
|
||||
@@ -47,19 +49,21 @@ class DB {
|
||||
$mdb = DB::$mdb = new MeekroDB();
|
||||
}
|
||||
|
||||
if ($mdb->param_char !== DB::$param_char) $mdb->param_char = DB::$param_char;
|
||||
if ($mdb->named_param_seperator !== DB::$named_param_seperator) $mdb->named_param_seperator = DB::$named_param_seperator;
|
||||
if ($mdb->success_handler !== DB::$success_handler) $mdb->success_handler = DB::$success_handler;
|
||||
if ($mdb->error_handler !== DB::$error_handler) $mdb->error_handler = DB::$error_handler;
|
||||
if ($mdb->throw_exception_on_error !== DB::$throw_exception_on_error) $mdb->throw_exception_on_error = DB::$throw_exception_on_error;
|
||||
if ($mdb->nonsql_error_handler !== DB::$nonsql_error_handler) $mdb->nonsql_error_handler = DB::$nonsql_error_handler;
|
||||
if ($mdb->throw_exception_on_nonsql_error !== DB::$throw_exception_on_nonsql_error) $mdb->throw_exception_on_nonsql_error = DB::$throw_exception_on_nonsql_error;
|
||||
if ($mdb->nested_transactions !== DB::$nested_transactions) $mdb->nested_transactions = DB::$nested_transactions;
|
||||
if ($mdb->usenull !== DB::$usenull) $mdb->usenull = DB::$usenull;
|
||||
static $variables_to_sync = array('param_char', 'named_param_seperator', 'success_handler', 'error_handler', 'throw_exception_on_error',
|
||||
'nonsql_error_handler', 'throw_exception_on_nonsql_error', 'nested_transactions', 'usenull', 'ssl', 'connect_options');
|
||||
|
||||
$db_class_vars = get_class_vars('DB'); // the DB::$$var syntax only works in 5.3+
|
||||
|
||||
foreach ($variables_to_sync as $variable) {
|
||||
if ($mdb->$variable !== $db_class_vars[$variable]) {
|
||||
$mdb->$variable = $db_class_vars[$variable];
|
||||
}
|
||||
}
|
||||
|
||||
return $mdb;
|
||||
}
|
||||
|
||||
// yes, this is ugly. __callStatic() only works in 5.3+
|
||||
public static function get() { $args = func_get_args(); return call_user_func_array(array(DB::getMDB(), 'get'), $args); }
|
||||
public static function disconnect() { $args = func_get_args(); return call_user_func_array(array(DB::getMDB(), 'disconnect'), $args); }
|
||||
public static function query() { $args = func_get_args(); return call_user_func_array(array(DB::getMDB(), 'query'), $args); }
|
||||
@@ -127,6 +131,8 @@ class MeekroDB {
|
||||
public $throw_exception_on_nonsql_error = false;
|
||||
public $nested_transactions = false;
|
||||
public $usenull = true;
|
||||
public $ssl = array('key' => '', 'cert' => '', 'ca_cert' => '', 'ca_path' => '', 'cipher' => '');
|
||||
public $connect_options = array(MYSQLI_OPT_CONNECT_TIMEOUT => 30);
|
||||
|
||||
// internal
|
||||
public $internal_mysql = null;
|
||||
@@ -160,7 +166,19 @@ class MeekroDB {
|
||||
if (!($mysql instanceof MySQLi)) {
|
||||
if (! $this->port) $this->port = ini_get('mysqli.default_port');
|
||||
$this->current_db = $this->dbName;
|
||||
$mysql = new mysqli($this->host, $this->user, $this->password, $this->dbName, $this->port);
|
||||
$mysql = new mysqli();
|
||||
|
||||
$connect_flags = 0;
|
||||
if ($this->ssl['key']) {
|
||||
$mysql->ssl_set($this->ssl['key'], $this->ssl['cert'], $this->ssl['ca_cert'], $this->ssl['ca_path'], $this->ssl['cipher']);
|
||||
$connect_flags |= MYSQLI_CLIENT_SSL;
|
||||
}
|
||||
foreach ($this->connect_options as $key => $value) {
|
||||
$mysql->options($key, $value);
|
||||
}
|
||||
|
||||
// suppress warnings, since we will check connect_error anyway
|
||||
@$mysql->real_connect($this->host, $this->user, $this->password, $this->dbName, $this->port, null, $connect_flags);
|
||||
|
||||
if ($mysql->connect_error) {
|
||||
$this->nonSQLError('Unable to connect to MySQL server! Error: ' . $mysql->connect_error);
|
||||
@@ -201,7 +219,7 @@ class MeekroDB {
|
||||
$this->success_handler = $handler;
|
||||
}
|
||||
|
||||
public function serverVersion() { return $this->server_info; }
|
||||
public function serverVersion() { $this->get(); return $this->server_info; }
|
||||
public function transactionDepth() { return $this->nested_transactions_count; }
|
||||
public function insertId() { return $this->insert_id; }
|
||||
public function affectedRows() { return $this->affected_rows; }
|
||||
@@ -281,7 +299,7 @@ class MeekroDB {
|
||||
$params = array_shift($args);
|
||||
$where = array_shift($args);
|
||||
|
||||
$query = "UPDATE %b SET %? WHERE " . $where;
|
||||
$query = str_replace('%', $this->param_char, "UPDATE %b SET %? WHERE ") . $where;
|
||||
|
||||
array_unshift($args, $params);
|
||||
array_unshift($args, $table);
|
||||
@@ -309,17 +327,23 @@ class MeekroDB {
|
||||
|
||||
if (isset($options['update']) && is_array($options['update']) && $options['update'] && strtolower($which) == 'insert') {
|
||||
if (array_values($options['update']) !== $options['update']) {
|
||||
return $this->query("INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE %?", $table, $keys, $values, $options['update']);
|
||||
return $this->query(
|
||||
str_replace('%', $this->param_char, "INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE %?"),
|
||||
$table, $keys, $values, $options['update']);
|
||||
} else {
|
||||
$update_str = array_shift($options['update']);
|
||||
$query_param = array("INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE $update_str", $table, $keys, $values);
|
||||
$query_param = array(
|
||||
str_replace('%', $this->param_char, "INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE ") . $update_str,
|
||||
$table, $keys, $values);
|
||||
$query_param = array_merge($query_param, $options['update']);
|
||||
return call_user_func_array(array($this, 'query'), $query_param);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $this->query("%l INTO %b %lb VALUES %?", $which, $table, $keys, $values);
|
||||
return $this->query(
|
||||
str_replace('%', $this->param_char, "%l INTO %b %lb VALUES %?"),
|
||||
$which, $table, $keys, $values);
|
||||
}
|
||||
|
||||
public function insert($table, $data) { return $this->insertOrReplace('INSERT', $table, $data); }
|
||||
@@ -361,7 +385,7 @@ class MeekroDB {
|
||||
}
|
||||
|
||||
public function columnList($table) {
|
||||
return $this->queryOneColumn('Field', "SHOW COLUMNS FROM $table");
|
||||
return $this->queryOneColumn('Field', "SHOW COLUMNS FROM %b", $table);
|
||||
}
|
||||
|
||||
public function tableList($db = null) {
|
||||
@@ -614,12 +638,13 @@ class MeekroDB {
|
||||
call_user_func($error_handler, array(
|
||||
'type' => 'sql',
|
||||
'query' => $sql,
|
||||
'error' => $db->error
|
||||
'error' => $db->error,
|
||||
'code' => $db->errno
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->throw_exception_on_error) {
|
||||
$e = new MeekroDBException($db->error, $sql);
|
||||
$e = new MeekroDBException($db->error, $sql, $db->errno);
|
||||
throw $e;
|
||||
}
|
||||
} else if ($this->success_handler) {
|
||||
@@ -673,7 +698,7 @@ class MeekroDB {
|
||||
public function queryFirstRow() {
|
||||
$args = func_get_args();
|
||||
$result = call_user_func_array(array($this, 'query'), $args);
|
||||
if (! $result) return null;
|
||||
if (!$result || !is_array($result)) return null;
|
||||
return reset($result);
|
||||
}
|
||||
|
||||
@@ -681,7 +706,7 @@ class MeekroDB {
|
||||
public function queryFirstList() {
|
||||
$args = func_get_args();
|
||||
$result = call_user_func_array(array($this, 'queryAllLists'), $args);
|
||||
if (! $result) return null;
|
||||
if (!$result || !is_array($result)) return null;
|
||||
return reset($result);
|
||||
}
|
||||
|
||||
@@ -789,12 +814,11 @@ class WhereClause {
|
||||
}
|
||||
|
||||
function textAndArgs() {
|
||||
$sql = '';
|
||||
$sql = array();
|
||||
$args = array();
|
||||
|
||||
if (count($this->clauses) == 0) return array('(1)', $args);
|
||||
|
||||
$sql = array();
|
||||
foreach ($this->clauses as $clause) {
|
||||
if ($clause instanceof WhereClause) {
|
||||
list($clause_sql, $clause_args) = $clause->textAndArgs();
|
||||
@@ -807,7 +831,6 @@ class WhereClause {
|
||||
$args = array_merge($args, $clause_args);
|
||||
}
|
||||
|
||||
$sql = array_unique($sql);
|
||||
if ($this->type == 'and') $sql = implode(' AND ', $sql);
|
||||
else $sql = implode(' OR ', $sql);
|
||||
|
||||
@@ -840,9 +863,10 @@ class DBTransaction {
|
||||
class MeekroDBException extends Exception {
|
||||
protected $query = '';
|
||||
|
||||
function __construct($message='', $query='') {
|
||||
function __construct($message='', $query='', $code = 0) {
|
||||
parent::__construct($message);
|
||||
$this->query = $query;
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
public function getQuery() { return $this->query; }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
class BasicTest extends SimpleTest {
|
||||
function __construct() {
|
||||
foreach (DB::tableList() as $table) {
|
||||
DB::query("DROP TABLE $table");
|
||||
DB::query("DROP TABLE %b", $table);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ class BasicTest extends SimpleTest {
|
||||
$bart = DB::queryFirstRow("SELECT * FROM accounts WHERE age IN ###li AND height IN ###ld AND username IN ###ls",
|
||||
array(15, 25), array(10.371, 150.123), array('Bart', 'Barts'));
|
||||
$this->assert($bart['username'] === 'Bart');
|
||||
DB::insert('accounts', array('username' => 'f_u'));
|
||||
DB::query("DELETE FROM accounts WHERE username=###s", 'f_u');
|
||||
DB::$param_char = '%';
|
||||
|
||||
$charlie_password = DB::queryFirstField("SELECT password FROM accounts WHERE username IN %ls AND username = %s",
|
||||
@@ -264,20 +266,24 @@ class BasicTest extends SimpleTest {
|
||||
|
||||
|
||||
function test_5_insert_blobs() {
|
||||
DB::query("CREATE TABLE `storedata` (
|
||||
DB::query("CREATE TABLE `store data` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
|
||||
`picture` BLOB
|
||||
) ENGINE = InnoDB");
|
||||
|
||||
$columns = DB::columnList('store data');
|
||||
$this->assert(count($columns) === 2);
|
||||
$this->assert($columns[1] === 'picture');
|
||||
|
||||
|
||||
$smile = file_get_contents('smile1.jpg');
|
||||
DB::insert('storedata', array(
|
||||
DB::insert('store data', array(
|
||||
'picture' => $smile,
|
||||
));
|
||||
DB::query("INSERT INTO storedata (picture) VALUES (%s)", $smile);
|
||||
DB::queryOneRow("INSERT INTO %b (picture) VALUES (%s)", 'store data', $smile);
|
||||
|
||||
$getsmile = DB::queryFirstField("SELECT picture FROM storedata WHERE id=1");
|
||||
$getsmile2 = DB::queryFirstField("SELECT picture FROM storedata WHERE id=2");
|
||||
$getsmile = DB::queryFirstField("SELECT picture FROM %b WHERE id=1", 'store data');
|
||||
$getsmile2 = DB::queryFirstField("SELECT picture FROM %b WHERE id=2", 'store data');
|
||||
$this->assert($smile === $getsmile);
|
||||
$this->assert($smile === $getsmile2);
|
||||
}
|
||||
@@ -394,6 +400,20 @@ class BasicTest extends SimpleTest {
|
||||
$this->assert($r[0]['1+1'] === '2');
|
||||
}
|
||||
|
||||
function test_901_updatewithspecialchar() {
|
||||
$data = 'www.mysite.com/product?s=t-%s-%%3d%%3d%i&RCAID=24322';
|
||||
DB::update('profile', array('signature' => $data), 'id=%i', 1);
|
||||
$signature = DB::queryFirstField("SELECT signature FROM profile WHERE id=%i", 1);
|
||||
$this->assert($signature === $data);
|
||||
|
||||
DB::update('profile',array('signature'=> "%li "),"id = %d",1);
|
||||
$signature = DB::queryFirstField("SELECT signature FROM profile WHERE id=%i", 1);
|
||||
$this->assert($signature === "%li ");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?
|
||||
<?php
|
||||
|
||||
function new_error_callback($params) {
|
||||
global $error_callback_worked;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?
|
||||
<?php
|
||||
class ErrorTest_53 extends SimpleTest {
|
||||
function test_1_error_handler() {
|
||||
global $anonymous_error_callback_worked;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?
|
||||
<?php
|
||||
class HelperTest extends SimpleTest {
|
||||
function test_1_verticalslice() {
|
||||
$all = DB::query("SELECT * FROM accounts ORDER BY id ASC");
|
||||
|
||||
@@ -6,7 +6,7 @@ class ObjectTest extends SimpleTest {
|
||||
$this->mdb = new MeekroDB();
|
||||
|
||||
foreach ($this->mdb->tableList() as $table) {
|
||||
$this->mdb->query("DROP TABLE $table");
|
||||
$this->mdb->query("DROP TABLE %b", $table);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?
|
||||
<?php
|
||||
class TransactionTest extends SimpleTest {
|
||||
function test_1_transactions() {
|
||||
DB::$nested_transactions = false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?
|
||||
<?php
|
||||
class TransactionTest_55 extends SimpleTest {
|
||||
function test_1_transactions() {
|
||||
DB::$nested_transactions = true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?
|
||||
<?php
|
||||
class WhereClauseTest extends SimpleTest {
|
||||
function test_1_basic_where() {
|
||||
$where = new WhereClause('and');
|
||||
@@ -57,6 +57,15 @@ class WhereClauseTest extends SimpleTest {
|
||||
$this->assert(count($result) === 1);
|
||||
$this->assert($result[0]['age'] === '15');
|
||||
}
|
||||
|
||||
function test_6_or() {
|
||||
$where = new WhereClause('or');
|
||||
$where->add('username=%s', 'Bart');
|
||||
$where->add('username=%s', 'Abe');
|
||||
|
||||
$result = DB::query("SELECT * FROM accounts WHERE %l", $where);
|
||||
$this->assert(count($result) === 2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user