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*/); }