X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=classes%2Fxdb.php;h=ea728d44b2b4b08d4382f9667d2bac5ab890effa;hb=0ef5bd4bceb37a6ed6a1afb719d403f25c71ef02;hp=3aa45cdeee0fbc136e9f6bc039f630a9f80b978d;hpb=2b1ee50b0196216dbe4f37e3b039469d6003ca23;p=platal.git diff --git a/classes/xdb.php b/classes/xdb.php index 3aa45cd..ea728d4 100644 --- a/classes/xdb.php +++ b/classes/xdb.php @@ -1,6 +1,6 @@ dbhost, $globals->dbuser, $globals->dbpwd, $globals->dbdb); - if ($globals->debug & 1) { + self::$mysqli = new mysqli($globals->dbhost, $globals->dbuser, $globals->dbpwd, $globals->dbdb); + if ($globals->debug & DEBUG_BT) { $bt = new PlBacktrace('MySQL'); if (mysqli_connect_errno()) { $bt->newEvent("MySQLI connection", 0, mysqli_connect_error()); return false; } } - XDB::$mysqli->autocommit(true); - XDB::$mysqli->set_charset($globals->dbcharset); + self::$mysqli->autocommit(true); + self::$mysqli->set_charset($globals->dbcharset); return true; } public static function _prepare($args) { - $query = array_map(Array('XDB', '_db_escape'), $args); + $query = array_map(Array('XDB', 'escape'), $args); $query[0] = str_replace('{?}', '%s', str_replace('%', '%%', $args[0])); return call_user_func_array('sprintf', $query); } @@ -75,14 +75,16 @@ class XDB { global $globals; - if (!XDB::$mysqli && !XDB::connect()) { - return false; + if (!self::$mysqli && !self::connect()) { + header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error'); + Platal::page()->kill('Impossible de se connecter à la base de données.'); + exit; } - if ($globals->debug & 1) { + if ($globals->debug & DEBUG_BT) { $explain = array(); if (strpos($query, 'FOUND_ROWS()') === false) { - $res = XDB::$mysqli->query("EXPLAIN $query"); + $res = self::$mysqli->query("EXPLAIN $query"); if ($res) { while ($row = $res->fetch_assoc()) { $explain[] = $row; @@ -94,56 +96,174 @@ class XDB } $res = XDB::$mysqli->query($query); - - if ($globals->debug & 1) { - PlBacktrace::$bt['MySQL']->stop(@$res->num_rows ? $res->num_rows : XDB::$mysqli->affected_rows, - XDB::$mysqli->error, + + if ($globals->debug & DEBUG_BT) { + PlBacktrace::$bt['MySQL']->stop(@$res->num_rows ? $res->num_rows : self::$mysqli->affected_rows, + self::$mysqli->error, $explain); } + + if ($res === false) { + header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error'); + if (strpos($query, 'INSERT') === false && strpos($query, 'UPDATE') === false + && strpos($query, 'REPLACE') === false && strpos($query, 'DELETE') === false) { + $text = 'Erreur lors de l\'interrogation de la base de données'; + } else { + $text = 'Erreur lors de l\'écriture dans la base de données'; + } + if ($globals->debug) { + $text .= '
' . pl_entities(XDB::_reformatQuery($query)) . '
'; + } else { + $file = fopen($globals->spoolroot . '/spool/tmp/query_errors', 'a'); + fwrite($file, '
' . pl_entities(XDB::_reformatQuery($query)) . '
' + . '
' . XDB::$mysqli->error . '
' . "\n"); + fclose($file); + } + Platal::page()->kill($text); + exit; + } return $res; } + private static function queryv($query) + { + return new XOrgDBResult(self::_prepare($query)); + } + public static function query() { - return new XOrgDBResult(XDB::_prepare(func_get_args())); + return self::queryv(func_get_args()); + } + + public static function format() + { + return self::_prepare(func_get_args()); + } + + // Produce the SQL statement for setting/unsetting a flag + public static function changeFlag($fieldname, $flagname, $state) + { + if ($state) { + return XDB::format($fieldname . ' = CONCAT({?}, \',\', ' . $fieldname . ')', $flagname); + } else { + return XDB::format($fieldname . ' = REPLACE(' . $fieldname . ', {?}, \'\')', $flagname); + } + } + + // Produce the SQL statement representing an array + public static function formatArray(array $array) + { + return '(' . implode(', ', array_map(array('XDB', 'escape'), $array)) . ')'; } public static function execute() { - return XDB::_query(XDB::_prepare(func_get_args())); + global $globals; + $args = func_get_args(); + if ($globals->mode != 'rw' && !strpos($args[0], 'logger')) { + return; + } + return self::_query(XDB::_prepare($args)); } public static function iterator() { - return new XOrgDBIterator(XDB::_prepare(func_get_args())); + return new XOrgDBIterator(self::_prepare(func_get_args())); } public static function iterRow() { - return new XOrgDBIterator(XDB::_prepare(func_get_args()), MYSQL_NUM); + return new XOrgDBIterator(self::_prepare(func_get_args()), MYSQL_NUM); + } + + private static function findQuery($params, $default = array()) + { + for ($i = 0 ; $i < count($default) ; ++$i) { + $is_query = false; + foreach (array('insert', 'select', 'replace', 'delete', 'update') as $kwd) { + if (stripos($params[0], $kwd) !== false) { + $is_query = true; + break; + } + } + if ($is_query) { + break; + } else { + $default[$i] = array_shift($params); + } + } + return array($default, $params); + } + + /** Fetch all rows returned by the given query. + * This functions can take 2 optional arguments (cf XOrgDBResult::fetchAllRow()). + * Optional arguments are given *before* the query. + */ + public static function fetchAllRow() + { + list($args, $query) = self::findQuery(func_get_args(), array(false, false)); + return self::queryv($query)->fetchAllRow($args[0], $args[1]); + } + + /** Fetch all rows returned by the given query. + * This functions can take 2 optional arguments (cf XOrgDBResult::fetchAllAssoc()). + * Optional arguments are given *before* the query. + */ + public static function fetchAllAssoc() + { + list($args, $query) = self::findQuery(func_get_args(), array(false, false)); + return self::queryv($query)->fetchAllAssoc($args[0], $args[1]); + } + + public static function fetchOneCell() + { + list($args, $query) = self::findQuery(func_get_args()); + return self::queryv($query)->fetchOneCell(); + } + + public static function fetchOneRow() + { + list($args, $query) = self::findQuery(func_get_args()); + return self::queryv($query)->fetchOneRow(); + } + + public static function fetchOneAssoc() + { + list($args, $query) = self::findQuery(func_get_args()); + return self::queryv($query)->fetchOneAssoc(); + } + + /** Fetch a column from the result of the given query. + * This functions can take 1 optional arguments (cf XOrgDBResult::fetchColumn()). + * Optional arguments are given *before* the query. + */ + public static function fetchColumn() + { + list($args, $query) = self::findQuery(func_get_args(), array(0)); + return self::queryv($query)->fetchColumn(); } public static function insertId() { - return XDB::$mysqli->insert_id; + return self::$mysqli->insert_id; } public static function errno() { - return XDB::$mysqli->errno; + return self::$mysqli->errno; } public static function error() - { - return XDB::$mysqli->error; + { + return self::$mysqli->error; } public static function affectedRows() { - return XDB::$mysqli->affected_rows; + return self::$mysqli->affected_rows; } - public static function _db_escape($var) + public static function escape($var) { switch (gettype($var)) { case 'boolean': @@ -161,6 +281,9 @@ class XDB return 'NULL'; case 'object': + if ($var instanceof PlFlagSet) { + return "'" . addslashes($var->flags()) . "'"; + } case 'array': return "'".addslashes(serialize($var))."'"; @@ -175,67 +298,99 @@ class XOrgDBResult private $_res; - function XOrgDBResult($query) + public function __construct($query) { $this->_res = XDB::_query($query); } - function free() + public function free() { - $this->_res->free(); + if ($this->_res) { + $this->_res->free(); + } unset($this); } - function _fetchRow() + protected function _fetchRow() { - return $this->_res->fetch_row(); + return $this->_res ? $this->_res->fetch_row() : null; } - function _fetchAssoc() + protected function _fetchAssoc() { - return $this->_res->fetch_assoc(); + return $this->_res ? $this->_res->fetch_assoc() : null; } - function fetchAllRow() + public function fetchAllRow($id = false, $keep_array = false) { $result = Array(); - while ($result[] = $this->_res->fetch_row()); - array_pop($result); + if (!$this->_res) { + return $result; + } + while (($data = $this->_res->fetch_row())) { + if ($id !== false) { + $key = $data[$id]; + unset($data[$id]); + if (!$keep_array && count($data) == 1) { + reset($data); + $result[$key] = current($data); + } else { + $result[$key] = $data; + } + } else { + $result[] = $data; + } + } $this->free(); return $result; } - function fetchAllAssoc() + public function fetchAllAssoc($id = false, $keep_array = false) { $result = Array(); - while ($result[] = $this->_res->fetch_assoc()); - array_pop($result); + if (!$this->_res) { + return $result; + } + while (($data = $this->_res->fetch_assoc())) { + if ($id !== false) { + $key = $data[$id]; + unset($data[$id]); + if (!$keep_array && count($data) == 1) { + reset($data); + $result[$key] = current($data); + } else { + $result[$key] = $data; + } + } else { + $result[] = $data; + } + } $this->free(); return $result; } - function fetchOneAssoc() + public function fetchOneAssoc() { $tmp = $this->_fetchAssoc(); $this->free(); return $tmp; } - function fetchOneRow() + public function fetchOneRow() { $tmp = $this->_fetchRow(); $this->free(); return $tmp; } - function fetchOneCell() + public function fetchOneCell() { $tmp = $this->_fetchRow(); $this->free(); return $tmp[0]; } - function fetchColumn($key = 0) + public function fetchColumn($key = 0) { $res = Array(); if (is_numeric($key)) { @@ -251,32 +406,32 @@ class XOrgDBResult return $res; } - function fetchOneField() + public function fetchOneField() { - return $this->_res->fetch_field(); + return $this->_res ? $this->_res->fetch_field() : null; } - function fetchFields() + public function fetchFields() { $res = array(); while ($res[] = $this->fetchOneField()); return $res; } - function numRows() + public function numRows() { - return $this->_res->num_rows; + return $this->_res ? $this->_res->num_rows : 0; } - function fieldCount() + public function fieldCount() { - return $this->_res->field_count; + return $this->_res ? $this->_res->field_count : 0; } } require_once dirname(__FILE__) . '/pliterator.php'; -class XOrgDBIterator implements PlIterator +class XOrgDBIterator extends XOrgDBResult implements PlIterator { private $_result; private $_pos; @@ -285,62 +440,62 @@ class XOrgDBIterator implements PlIterator private $_fields; private $_mode = MYSQL_ASSOC; - function __construct($query, $mode = MYSQL_ASSOC) + public function __construct($query, $mode = MYSQL_ASSOC) { - $this->_result = new XOrgDBResult($query); + parent::__construct($query); $this->_pos = 0; - $this->_total = $this->_result->numRows(); + $this->_total = $this->numRows(); $this->_fpost = 0; - $this->_fields = $this->_result->fieldCount(); + $this->_fields = $this->fieldCount(); $this->_mode = $mode; } - function next() + public function next() { $this->_pos ++; if ($this->_pos > $this->_total) { - $this->_result->free(); + $this->free(); unset($this); return null; } - return $this->_mode != MYSQL_ASSOC ? $this->_result->_fetchRow() : $this->_result->_fetchAssoc(); + return $this->_mode != MYSQL_ASSOC ? $this->_fetchRow() : $this->_fetchAssoc(); } - function first() + public function first() { return $this->_pos == 1; } - function last() + public function last() { return $this->_pos == $this->_total; } - function total() + public function total() { return $this->_total; } - function nextField() + public function nextField() { $this->_fpos++; if ($this->_fpos > $this->_fields) { return null; } - return $this->_result->fetchOneField(); + return $this->fetchOneField(); } - function firstField() + public function firstField() { return $this->_fpos == 1; } - function lastField() + public function lastField() { return $this->_fpos == $this->_fields; } - function totalFields() + public function totalFields() { return $this->_fields; }