From 7429e5a89b8387579a8809747ad2c7a379910fc9 Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 10 May 2015 09:56:56 +0000 Subject: [PATCH 1/3] Added setQueryOption method --- MysqliDb.php | 47 ++++++++++++++++++++++++++++++++++++----------- readme.md | 24 +++++++++++++++++++++++- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index 7165bbbf..a9dbf5ad 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -43,6 +43,12 @@ class MysqliDb * @var string */ protected $_lastQuery; + /** + * The SQL query options required after SELECT, INSERT, UPDATE or DELETE + * + * @var string + */ + protected $_queryOptions = array(); /** * An array that holds where joins * @@ -81,7 +87,6 @@ class MysqliDb * @var string */ public $totalCount = 0; - protected $fetchTotalCount = false; /** * Variable which holds last statement error * @@ -193,7 +198,7 @@ protected function reset() $this->_groupBy = array(); $this->_bindParams = array(''); // Create the empty 0 index $this->_query = null; - $this->count = 0; + $this->_queryOptions = array(); } /** @@ -238,9 +243,10 @@ public function rawQuery ($query, $bindParams = null, $sanitize = true) $stmt->execute(); $this->_stmtError = $stmt->error; $this->_lastQuery = $this->replacePlaceHolders ($this->_query, $params); + $res = $this->_dynamicBindResults($stmt); $this->reset(); - return $this->_dynamicBindResults($stmt); + return $res; } /** @@ -256,9 +262,28 @@ public function query($query, $numRows = null) $stmt = $this->_buildQuery($numRows); $stmt->execute(); $this->_stmtError = $stmt->error; + $res = $this->_dynamicBindResults($stmt); $this->reset(); - return $this->_dynamicBindResults($stmt); + return $res; + } + + /** + * This method allows you to specify multiple (method chaining optional) options for SQL queries. + * + * @uses $MySqliDb->setQueryOption('name'); + * + * @param string/array $options The optons name of the query. + * + * @return MysqliDb + */ + public function setQueryOption ($options) { + if (is_array ($options)) + $this->_queryOptions = array_merge ($this->_queryOptions, $options); + else + $this->_queryOptions[] = $options; + + return $this; } /** @@ -267,7 +292,7 @@ public function query($query, $numRows = null) * @return MysqliDb */ public function withTotalCount () { - $this->fetchTotalCount = true; + $this->setQueryOption ('SQL_CALC_FOUND_ROWS'); return $this; } @@ -284,9 +309,9 @@ public function get($tableName, $numRows = null, $columns = '*') if (empty ($columns)) $columns = '*'; - $this->_query = $this->fetchTotalCount == true ? 'SELECT SQL_CALC_FOUND_ROWS ' : 'SELECT '; $column = is_array($columns) ? implode(', ', $columns) : $columns; - $this->_query .= "$column FROM " .self::$_prefix . $tableName; + $this->_query = 'SELECT ' . implode(' ', $this->_queryOptions) . ' ' . + $column . " FROM " .self::$_prefix . $tableName; $stmt = $this->_buildQuery($numRows); if ($this->isSubQuery) @@ -294,9 +319,10 @@ public function get($tableName, $numRows = null, $columns = '*') $stmt->execute(); $this->_stmtError = $stmt->error; + $res = $this->_dynamicBindResults($stmt); $this->reset(); - return $this->_dynamicBindResults($stmt); + return $res; } /** @@ -724,9 +750,8 @@ protected function _dynamicBindResults(mysqli_stmt $stmt) if ($this->_mysqli->more_results()) $this->_mysqli->next_result(); - if ($this->fetchTotalCount === true) { - $this->fetchTotalCount = false; - $stmt = $this->_mysqli->query ('SELECT FOUND_ROWS();'); + if (in_array ('SQL_CALC_FOUND_ROWS', $this->_queryOptions)) { + $stmt = $this->_mysqli->query ('SELECT FOUND_ROWS()'); $totalCount = $stmt->fetch_row(); $this->totalCount = $totalCount[0]; } diff --git a/readme.md b/readme.md index e7b06849..8f3495ee 100644 --- a/readme.md +++ b/readme.md @@ -7,6 +7,7 @@ MysqliDb -- Simple MySQLi wrapper with prepared statements **[Select Query](#select-query)** **[Delete Query](#delete-query)** **[Generic Query](#generic-query-method)** +**[Query Keywords](#query-keywords)** **[Raw Query](#raw-query-method)** **[Where Conditions](#where-method)** **[Order Conditions](#ordering-method)** @@ -287,6 +288,28 @@ $users = $db->withTotalCount()->get('users', Array ($offset, $count)); echo "Showing {$count} from {$db->totalCount}"; ``` +### Query Keywords +To add LOW PRIORITY | DELAYED | HIGH PRIORITY | IGNORE and the rest of mysql keywords to INSERT , SELECT , UPDATE, DELETE query: +```php +$db->setQueryOption('LOW_PRIORITY'); +$db->insert($table,$param); +// GIVES: INSERT LOW_PRIORITY INTO table ... +``` + +Also you can use an array of keywords: +```php +$db->setQueryOption(Array('LOW_PRIORITY', 'IGNORE')); +$db->insert($table,$param); +// GIVES: INSERT LOW_PRIORITY IGNORE INTO table ... +``` + +Same way keywords could be used in SELECT queries as well: +```php +$db->setQueryOption('SQL_NO_CACHE'); +$db->get("users"); +// GIVES: SELECT SQL_NO_CACHE * FROM USERS; +``` + Optionally you can use method chaining to call where multiple times without referencing your object over an over: ```php @@ -418,7 +441,6 @@ if($db->has("users")) { return "Wrong user/password"; } ``` - ### Helper commands Reconnect in case mysql connection died ```php From 6f810c663b2f41d02ff35048ff708d5114a8716c Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 10 May 2015 10:10:53 +0000 Subject: [PATCH 2/3] Added whitelist to setQueryOption --- MysqliDb.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index a9dbf5ad..c5522ac1 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -278,10 +278,19 @@ public function query($query, $numRows = null) * @return MysqliDb */ public function setQueryOption ($options) { - if (is_array ($options)) - $this->_queryOptions = array_merge ($this->_queryOptions, $options); - else - $this->_queryOptions[] = $options; + $allowedOptions = Array ('ALL','DISTINCT','DISTINCTROW','HIGH_PRIORITY','STRAIGHT_JOIN','SQL_SMALL_RESULT', + 'SQL_BIG_RESULT','SQL_BUFFER_RESULT','SQL_CACHE','SQL_NO_CACHE', 'SQL_CALC_FOUND_ROWS', + 'LOW_PRIORITY','IGNORE','QUICK'); + if (!is_array ($options)) + $options = Array ($options); + + foreach ($options as $option) { + $option = strtoupper ($option); + if (!in_array ($option, $allowedOptions)) + die ('Wrong query option: '.$option); + + $this->_queryOptions[] = $option; + } return $this; } From 97c09d9fb3855a0f800b247db4220f07d247f7ec Mon Sep 17 00:00:00 2001 From: Alexander Butenko Date: Sun, 10 May 2015 16:11:27 +0000 Subject: [PATCH 3/3] Query execution tracing functions added --- MysqliDb.php | 41 +++++++++++++++++++++++++++++++++++++++++ readme.md | 28 ++++++++++++++++++++++++++++ tests.php | 7 +++++-- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index c5522ac1..85a97500 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -112,6 +112,15 @@ class MysqliDb */ protected $isSubQuery = false; + /** + * Variables for query execution tracing + * + */ + protected $traceStartQ; + protected $traceEnabled; + protected $traceStripPrefix; + public $trace = array(); + /** * @param string $host * @param string $username @@ -192,6 +201,9 @@ public static function getInstance() */ protected function reset() { + if ($this->traceEnabled) + $this->trace[] = array ($this->_lastQuery, (microtime(true) - $this->traceStartQ) , $this->_traceGetCaller()); + $this->_where = array(); $this->_join = array(); $this->_orderBy = array(); @@ -968,6 +980,9 @@ protected function _prepareQuery() if (!$stmt = $this->_mysqli->prepare($this->_query)) { trigger_error("Problem preparing query ($this->_query) " . $this->_mysqli->error, E_USER_ERROR); } + if ($this->traceEnabled) + $this->traceStartQ = microtime (true); + return $stmt; } @@ -1204,5 +1219,31 @@ public function _transaction_status_check () { return; $this->rollback (); } + + /** + * Query exection time tracking switch + * + * @param bool $enabled Enable execution time tracking + * @param string $stripPrefix Prefix to strip from the path in exec log + **/ + public function setTrace ($enabled, $stripPrefix = null) { + $this->traceEnabled = $enabled; + $this->traceStripPrefix = $stripPrefix; + return $this; + } + /** + * Get where and what function was called for query stored in MysqliDB->trace + * + * @return string with information + */ + private function _traceGetCaller () { + $dd = debug_backtrace (); + $caller = next ($dd); + while (isset ($caller) && $caller["file"] == __FILE__ ) + $caller = next($dd); + + return __CLASS__ . "->" . $caller["function"] . "() >> file \"" . + str_replace ($this->traceStripPrefix, '', $caller["file"] ) . "\" line #" . $caller["line"] . " " ; + } } // END class ?> diff --git a/readme.md b/readme.md index 8f3495ee..847ce301 100644 --- a/readme.md +++ b/readme.md @@ -474,3 +474,31 @@ if (!$db->insert ('myTable', $insertData)) { $db->commit(); } ``` + +### Query exectution time benchmarking +To track query execution time setTrace() function should be called. +```php +$db->setTrace (true); +// As a second parameter it is possible to define prefix of the path which should be striped from filename +// $db->setTrace (true, $_SERVER['SERVER_ROOT']); +$db->get("users"); +$db->get("test"); +print_r ($db->trace); +``` + +``` + [0] => Array + ( + [0] => SELECT * FROM t_users ORDER BY `id` ASC + [1] => 0.0010669231414795 + [2] => MysqliDb->get() >> file "/avb/work/PHP-MySQLi-Database-Class/tests.php" line #151 + ) + + [1] => Array + ( + [0] => SELECT * FROM t_test + [1] => 0.00069189071655273 + [2] => MysqliDb->get() >> file "/avb/work/PHP-MySQLi-Database-Class/tests.php" line #152 + ) + +``` diff --git a/tests.php b/tests.php index bff6360d..d6ba3c94 100644 --- a/tests.php +++ b/tests.php @@ -5,6 +5,9 @@ $db = new Mysqlidb('localhost', 'root', '', 'testdb'); if(!$db) die("Database error"); +$mysqli = new mysqli ('localhost', 'root', '', 'testdb'); +$db = new Mysqlidb($mysqli); + $db = new Mysqlidb(Array ( 'host' => 'localhost', 'username' => 'root', @@ -13,11 +16,10 @@ 'charset' => null)); if(!$db) die("Database error"); -$mysqli = new mysqli ('localhost', 'root', '', 'testdb'); -$db = new Mysqlidb($mysqli); $prefix = 't_'; $db->setPrefix($prefix); +$db->setTrace(true); $tables = Array ( 'users' => Array ( @@ -360,4 +362,5 @@ function createTable ($name, $data) { //print_r($db->rawQuery("CALL simpleproc(?)",Array("test"))); +print_r ($db->trace); ?>