Skip to content

Commit

Permalink
Fix multi-connection and performance bug
Browse files Browse the repository at this point in the history
Remove escaping from numbers in set's
Add log for non sql errors
Add SetSaveStats method to enable saving query statistics
  • Loading branch information
alexdnepro committed Apr 16, 2022
1 parent 966f857 commit 5f2959f
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 48 deletions.
11 changes: 11 additions & 0 deletions src/DB.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,17 @@ public static function lastQuery()
return self::instance()->lastQuery();
}

/**
* Function to save query statistics
*
* @param bool $value
* @return void
*/
public static function SetSaveStats(bool $value)
{
self::instance()->SetSaveStats($value);
}

/**
* Function to get all query statistics.
*
Expand Down
116 changes: 68 additions & 48 deletions src/mDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class mDB
* @var bool|string Log all errors to filename
*/
private $error_log = false;
/**
* @var bool Save query statistics
*/
private $save_stats = false;

/**
* Call standard methods from mysqli instance
Expand All @@ -66,6 +70,16 @@ public function __call(string $name, array $arguments)
return call_user_func_array(array($this->getInstance(), $name), $arguments);
}

/**
* @param bool $value
* @return mDB
*/
public function SetSaveStats(bool $value): mDB
{
$this->save_stats = $value;
return $this;
}

public function SetLogSql(string $file_name, bool $add_debug = false): mDB
{
$this->log_sql = $file_name;
Expand Down Expand Up @@ -150,13 +164,18 @@ private function ConnectBase()
{
$this->instance->set_charset($this->config['charset']) or $this->ShowError($this->instance->error);
}
$this->connected = true;
}

/**
* @param bool|string $msg
*/
public function ShowError($msg = false )
public function ShowError($msg = false, $add_error_log = false )
{
if ($add_error_log)
{
$this->log_error($msg);
}
if (!$msg) {
$msg = 'Database query error';
}
Expand Down Expand Up @@ -541,6 +560,10 @@ public function filterArray(array $input, array $allowed): array
*/
public function lastQuery()
{
if (!$this->save_stats)
{
return null;
}
$last = end($this->stats);
return $last['query'];
}
Expand Down Expand Up @@ -569,31 +592,35 @@ protected function rawQuery(string $query)
if ($this->log_sql !== false) {
$this->log_sql($query);
}
$start = microtime(TRUE);
$res = mysqli_query($this->instance, $query);
$timer = microtime(TRUE) - $start;

$this->stats[] = array(
'query' => $query,
'start' => $start,
'timer' => $timer,
'rows' => 0
);
end($this->stats);
$key = key($this->stats);
if (!$res)
$start = 0;
if ($this->save_stats) {
$start = microtime(TRUE);
}
$res = mysqli_query($this->instance, $query);
if ($this->save_stats)
{
$error = mysqli_error($this->instance);
$this->stats[$key]['error'] = $error;
$timer = microtime(TRUE) - $start;

$this->stats[] = array(
'query' => $query,
'start' => $start,
'timer' => $timer,
'rows' => 0
);
end($this->stats);
$key = key($this->stats);
if (!$res) {
$error = mysqli_error($this->instance);
$this->stats[$key]['error'] = $error;
$this->cutStats();

$this->log_error($query);
$this->ShowError();
} else {
$this->stats[$key]['rows'] = $this->instance->affected_rows;
}
$this->cutStats();

$this->log_error($query);
$this->ShowError();
} else
{
$this->stats[$key]['rows'] = $this->instance->affected_rows;
}
$this->cutStats();
return $res;
}

Expand All @@ -607,7 +634,7 @@ public function prepareQuery($args):string
$placeholders_num = (int)floor(count($array) / 2);
if ( $placeholders_num !== $arguments_num )
{
$this->ShowError("Number of args ($arguments_num) doesn't match number of placeholders ($placeholders_num) in [$raw]");
$this->ShowError("Number of args ($arguments_num) doesn't match number of placeholders ($placeholders_num) in [$raw]", true);
die();
}

Expand Down Expand Up @@ -654,7 +681,7 @@ protected function escapeInt($value)
}
if(!is_numeric($value))
{
$this->ShowError( "Integer (?i) placeholder expects numeric value, ".gettype($value)." given");
$this->ShowError( "Integer (?i) placeholder expects numeric value, ".gettype($value)." given", true);
die();
}
if (is_float($value))
Expand All @@ -680,15 +707,15 @@ protected function escapeIdent($value): string
{
return '`' .str_replace('`', '``',$value). '`';
}
$this->ShowError('Empty value for identifier (?n) placeholder');
$this->ShowError('Empty value for identifier (?n) placeholder', true);
return false;
}

protected function createIN($data):string
{
if (!is_array($data))
{
$this->ShowError('Value for IN (?a) placeholder should be array');
$this->ShowError('Value for IN (?a) placeholder should be array', true);
}
if (!$data)
{
Expand All @@ -707,17 +734,20 @@ protected function createSET($data):string
{
if (!is_array($data))
{
$this->ShowError( 'SET (?u) placeholder expects array, ' .gettype($data). ' given');
$this->ShowError( 'SET (?u) placeholder expects array, ' .gettype($data). ' given', true);
}
if (!$data)
{
$this->ShowError('Empty array for SET (?u) placeholder');
$this->ShowError('Empty array for SET (?u) placeholder', true);
}
$query = $comma = '';
foreach ($data as $key => $value)
{
// Check if value is DB::pure object
if (is_object($value) && isset($value->sql)) {
// Check if value is DB::pure object
if (is_numeric($value))
{
$str = $this->escapeInt($value);
} elseif (is_object($value) && isset($value->sql)) {
$str = $value->sql;
} else {
$str = $this->escapeString($value);
Expand All @@ -734,7 +764,7 @@ protected function createSET($data):string
*/
protected function cutStats()
{
if ( count($this->stats) > 100 )
if ( $this->save_stats && count($this->stats) > 100 )
{
reset($this->stats);
$first = key($this->stats);
Expand Down Expand Up @@ -798,32 +828,22 @@ private static function GetBacktraceInfo($max_id = 2): string

private function log_sql($sql)
{
$dh = fopen ($this->log_sql, 'ab+');
if ($dh)
$msg = self::GetDate().' '.$sql.PHP_EOL;
if ($this->log_sql_debug)
{
fwrite($dh, self::GetDate().' '.$sql."\n");
if ($this->log_sql_debug)
{
fwrite($dh, self::GetBacktraceInfo());
fwrite($dh, "\n");
}
fclose($dh);
$msg .= self::GetBacktraceInfo().PHP_EOL;
}
file_put_contents($this->log_sql, $msg, FILE_APPEND);
}

private function log_error($sql)
{
$msg = self::GetDate().' '.$this->GetError()."\nQuery: ".$sql."\n".self::GetBacktraceInfo(10)."\n";
$msg = self::GetDate().' '.$this->GetError().PHP_EOL.'Query: '.$sql.PHP_EOL.self::GetBacktraceInfo(10).PHP_EOL;
if ($this->error_log === false)
{
error_log($msg);
return;
}
$dh = fopen ($this->error_log, 'ab+');
if ($dh)
{
fwrite($dh, $msg);
fclose($dh);
}
file_put_contents($this->error_log, $msg, FILE_APPEND);
}
}

0 comments on commit 5f2959f

Please sign in to comment.