diff --git a/MysqliDb.php b/MysqliDb.php index 7165bbbf..85a97500 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 * @@ -107,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 @@ -187,13 +201,16 @@ 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(); $this->_groupBy = array(); $this->_bindParams = array(''); // Create the empty 0 index $this->_query = null; - $this->count = 0; + $this->_queryOptions = array(); } /** @@ -238,9 +255,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 +274,37 @@ 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) { + $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; } /** @@ -267,7 +313,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 +330,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 +340,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 +771,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]; } @@ -934,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; } @@ -1170,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 e7b06849..847ce301 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 @@ -452,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); ?>