SamsonGame/utils/gme/db.inc.php

340 lines
7.4 KiB
PHP
Raw Normal View History

2021-12-29 20:50:11 +03:00
<?php
class gmeDB
{
const OPT_FORCE_STMT = 0x1;
const OPT_NASSOC = 0x4;
public $config = array();
private $conn = null;
public $db_host;
public $db_port = null;
public $db_sock = null;
public $db_user;
public $db_pass;
public $db_name;
public $db_pconn = false;
public $db_charset = null;
function __construct(array $conf)
{
$this->config = $conf;
foreach($this->config as $k => $v)
$this->$k = $v;
$this->conn = null;
}
function getConnection()
{
if(!$this->conn)
$this->connect();
return $this->conn;
}
function connect()
{
$this->conn = mysqli_connect(
($this->db_pconn ? 'p:'.$this->db_host : $this->db_host),
$this->db_user,
$this->db_pass,
$this->db_name,
$this->db_port,
$this->db_sock
);
if(!$this->conn)
throw new Exception("Could not connect to mysql server");
if($this->db_charset !== null && !mysqli_set_charset($this->conn, $this->db_charset))
$this->_raise("Charset setup error");
}
function disconnect()
{
if(!$this->conn)
return;
mysqli_close($this->conn);
$this->conn = null;
}
function fetch($sql, array $args = array(), $opts = 0, &$meta = array())
{
if($args || ($opts & self::OPT_FORCE_STMT))
{
$stmt = $this->_newStatement($sql, $args);
$res = $this->_fetchStatement($stmt, $opts, $meta);
}
else
$res = $this->_fetchQuery($sql, $opts, $meta);
return $res;
}
function fetchRow($sql, array $args = array(), $opts = 0, &$meta = array())
{
$rows = $this->fetch($sql, $args, $opts, $meta);
if(isset($rows[0]))
return $rows[0];
}
function fetchOne($sql, array $args = array(), $opts = 0)
{
$row = $this->fetchRow($sql, $args, $opts | self::OPT_NASSOC);
if(!$row || !isset($row[0]))
return NULL;
return $row[0];
}
function execute($sql, array $args = array())
{
if($args)
$this->_newStatement($sql, $args);
else
$this->_newQuery($sql);
}
function sanify($what)
{
if(is_string($what))
return $this->escape($what);
if(is_null($what))
return "NULL";
if(is_array($what))
{
foreach($what as $k => &$v)
$v = $this->sanify($v);
return $what;
}
return 1*$what;
}
function escape($what, $quote = true)
{
if(is_null($what))
return "NULL";
$what = mysqli_escape_string($this->getConnection(), $what);
return $quote ? "'" . $what . "'" : $what;
}
function lastInsertId()
{
return mysqli_insert_id($this->getConnection());
}
function affectedRows()
{
return mysqli_affected_rows($this->getConnection());
}
function getLastError()
{
return array(mysqli_errno($this->conn), mysqli_error($this->conn));
}
private function _newQuery($sql)
{
if(!$this->conn)
$this->connect();
if(!$result = mysqli_query($this->conn, $sql))
$this->_raise("Query error: $sql");
return $result;
}
private function _fetchQuery($sql, $opts = 0, &$meta = array())
{
$result = $this->_newQuery($sql);
$rows = array();
if($opts & self::OPT_NASSOC)
{
while($row = $result->fetch_row())
$rows[] = $row;
}
else
{
while($row = $result->fetch_assoc())
$rows[] = $row;
}
$result->free();
return $rows;
}
private function _newStatement($sql, array $args = array())
{
if(!$this->conn)
$this->connect();
$stmt = mysqli_prepare($this->conn, $sql);
if(!$stmt)
$this->_raise("Stmt prepare error: $sql");
if($args)
$this->_bindArgs($stmt, $args);
if(!mysqli_stmt_execute($stmt))
$this->_raise("Stmt exec error: $sql");
return $stmt;
}
private function _fetchStatement($stmt, $opts = 0, &$meta = array())
{
$rows = array();
$res_meta = mysqli_stmt_result_metadata($stmt);
$fields = array();
$out = array();
$fields[0] = &$stmt;
$count = 1;
while($field = mysqli_fetch_field($res_meta))
{
$fields[$count++] = &$out[$field->name];
$meta[$field->name] = $field;
}
mysqli_stmt_store_result($stmt);
call_user_func_array('mysqli_stmt_bind_result', $fields);
if($opts & self::OPT_NASSOC)
{
while(mysqli_stmt_fetch($stmt))
{
$out_deref = array();
foreach($out as $v)
$out_deref[] = $v;
$rows[] = $out_deref;
}
}
else
{
while(mysqli_stmt_fetch($stmt))
{
$out_deref = array();
foreach($out as $k => $v)
$out_deref[$k] = $v;
$rows[] = $out_deref;
}
}
mysqli_stmt_free_result($stmt);
mysqli_stmt_close($stmt);
return $rows;
}
private function _bindArgs($stmt, array $args)
{
$types = '';
$blob = null;
$blob_pos = -1;
$c = 0;
foreach($args as $key => $arg)
{
if(is_string($key))
{
$types .= $key;
//NOTE: supporting exactly one blob special case
if($key === 'b')
{
$blob = &$args[$key];
$blob_pos = $c;
}
}
else
{
if(is_string($arg) || is_null($arg))
$types .= 's';
else if(is_int($arg) || is_bool($arg))
$types .= 'i';
else if(is_float($arg))
$types .= 'd';
else
throw new Exception("Unknown type of variable '" . serialize($arg) . "'");
}
++$c;
}
$res = call_user_func_array('mysqli_stmt_bind_param', array_merge(array($stmt, $types), $this->_refValues($args)));
if(!$res)
$this->_raise("Stmt bind error");
if($blob !== null)
{
if(!mysqli_stmt_send_long_data($stmt, $blob_pos, $blob))
$this->_raise("Stmt blob send error");
}
}
private function _refValues(array $arr)
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
private function _raise($err)
{
throw new Exception($err . ", MySQLi error:" . mysqli_error($this->conn));
}
}
function gme_db_insert_or_update_sql_ex($table, array $fields, array $rows)
{
$update = array();
foreach($fields as $field)
$update[] = $field.'=VALUES('.$field.')';
$sql = '';
$sql .= 'INSERT INTO '.$table.' ('.implode(',', $fields).') VALUES ';
foreach($rows as $row)
$sql .= '('.implode(',', $row).'),';
$sql = rtrim($sql, ',');
$sql .= 'ON DUPLICATE KEY UPDATE '.implode(',', $update);
return $sql;
}
function gme_db_insert_or_update_sql($table, array $row)
{
return gme_db_insert_or_update_sql_ex($table, array_keys($row), array($row));
}
function gme_db_insert_sql_ex($table, array $fields, array $rows, $delayed = false, $replace = false)
{
$sql = '';
$sql .= $replace ? 'REPLACE ' : 'INSERT ';
$sql .= $delayed ? ' DELAYED ' : '';
$sql .= 'INTO '.$table.' ('.implode(',', $fields).') VALUES ';
foreach($rows as $row)
$sql .= '('.implode(',', $row).'),';
$sql = rtrim($sql, ',');
return $sql;
}
function gme_db_insert_sql($table, array $row, $delayed = false)
{
return gme_db_insert_sql_ex($table, array_keys($row), array($row), $delayed);
}
function gme_db_replace_sql_ex($table, array $fields, array $rows, $delayed = false)
{
return gme_db_insert_sql_ex($table, $fields, $rows, $delayed, true/*replace*/);
}
function gme_db_replace_sql($table, array $row, $delayed = false)
{
return gme_db_insert_sql_ex($table, array_keys($row), array($row), $delayed, true/*replace*/);
}