"MySQL") + $drivers; if (!defined("DRIVER")) { $possible_drivers = array("MySQLi", "MySQL", "PDO_MySQL"); define("DRIVER", "server"); // server - backwards compatibility // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable if (extension_loaded("mysqli")) { class Min_DB extends MySQLi { var $extension = "MySQLi"; function Min_DB() { parent::init(); } function connect($server, $username, $password) { mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4 list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket $return = @$this->real_connect( ($server != "" ? $host : ini_get("mysqli.default_host")), ($server . $username != "" ? $username : ini_get("mysqli.default_user")), ($server . $username . $password != "" ? $password : ini_get("mysqli.default_pw")), null, (is_numeric($port) ? $port : ini_get("mysqli.default_port")), (!is_numeric($port) ? $port : null) ); if ($return) { if (method_exists($this, 'set_charset')) { $this->set_charset("utf8"); } else { $this->query("SET NAMES utf8"); } } return $return; } function result($query, $field = 0) { $result = $this->query($query); if (!$result) { return false; } $row = $result->fetch_array(); return $row[$field]; } function quote($string) { return "'" . $this->escape_string($string) . "'"; } } } elseif (extension_loaded("mysql") && !(ini_get("sql.safe_mode") && extension_loaded("pdo_mysql"))) { class Min_DB { var $extension = "MySQL", ///< @var string extension name $server_info, ///< @var string server version $affected_rows, ///< @var int number of affected rows $errno, ///< @var int last error code $error, ///< @var string last error message $_link, $_result ///< @access private ; /** Connect to server * @param string * @param string * @param string * @return bool */ function connect($server, $username, $password) { $this->_link = @mysql_connect( ($server != "" ? $server : ini_get("mysql.default_host")), ("$server$username" != "" ? $username : ini_get("mysql.default_user")), ("$server$username$password" != "" ? $password : ini_get("mysql.default_password")), true, 131072 // CLIENT_MULTI_RESULTS for CALL ); if ($this->_link) { $this->server_info = mysql_get_server_info($this->_link); if (function_exists('mysql_set_charset')) { mysql_set_charset("utf8", $this->_link); } else { $this->query("SET NAMES utf8"); } } else { $this->error = mysql_error(); } return (bool) $this->_link; } /** Quote string to use in SQL * @param string * @return string escaped string enclosed in ' */ function quote($string) { return "'" . mysql_real_escape_string($string, $this->_link) . "'"; } /** Select database * @param string * @return bool */ function select_db($database) { return mysql_select_db($database, $this->_link); } /** Send query * @param string * @param bool * @return mixed bool or Min_Result */ function query($query, $unbuffered = false) { $result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode $this->error = ""; if (!$result) { $this->errno = mysql_errno($this->_link); $this->error = mysql_error($this->_link); return false; } if ($result === true) { $this->affected_rows = mysql_affected_rows($this->_link); $this->info = mysql_info($this->_link); return true; } return new Min_Result($result); } /** Send query with more resultsets * @param string * @return bool */ function multi_query($query) { return $this->_result = $this->query($query); } /** Get current resultset * @return Min_Result */ function store_result() { return $this->_result; } /** Fetch next resultset * @return bool */ function next_result() { // MySQL extension doesn't support multiple results return false; } /** Get single field from result * @param string * @param int * @return string */ function result($query, $field = 0) { $result = $this->query($query); if (!$result || !$result->num_rows) { return false; } return mysql_result($result->_result, 0, $field); } } class Min_Result { var $num_rows, ///< @var int number of rows in the result $_result, $_offset = 0 ///< @access private ; /** Constructor * @param resource */ function Min_Result($result) { $this->_result = $result; $this->num_rows = mysql_num_rows($result); } /** Fetch next row as associative array * @return array */ function fetch_assoc() { return mysql_fetch_assoc($this->_result); } /** Fetch next row as numbered array * @return array */ function fetch_row() { return mysql_fetch_row($this->_result); } /** Fetch next field * @return object properties: name, type, orgtable, orgname, charsetnr */ function fetch_field() { $return = mysql_fetch_field($this->_result, $this->_offset++); // offset required under certain conditions $return->orgtable = $return->table; $return->orgname = $return->name; $return->charsetnr = ($return->blob ? 63 : 0); return $return; } /** Free result set */ function __destruct() { mysql_free_result($this->_result); } } } elseif (extension_loaded("pdo_mysql")) { class Min_DB extends Min_PDO { var $extension = "PDO_MySQL"; function connect($server, $username, $password) { $this->dsn("mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\\d)~', ';port=\\1', $server)), $username, $password); $this->query("SET NAMES utf8"); // charset in DSN is ignored before PHP 5.3.6 return true; } function select_db($database) { // database selection is separated from the connection so dbname in DSN can't be used return $this->query("USE " . idf_escape($database)); } function query($query, $unbuffered = false) { $this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY return parent::query($query, $unbuffered); } } } class Min_Driver extends Min_SQL { function insert($table, $set) { return ($set ? parent::insert($table, $set) : queries("INSERT INTO " . table($table) . " ()\nVALUES ()")); } function insertUpdate($table, $rows, $primary) { $columns = array_keys(reset($rows)); $prefix = "INSERT INTO " . table($table) . " (" . implode(", ", $columns) . ") VALUES\n"; $values = array(); foreach ($columns as $key) { $values[$key] = "$key = VALUES($key)"; } $suffix = "\nON DUPLICATE KEY UPDATE " . implode(", ", $values); $values = array(); $length = 0; foreach ($rows as $set) { $value = "(" . implode(", ", $set) . ")"; if ($values && (strlen($prefix) + $length + strlen($value) + strlen($suffix) > 1e6)) { // 1e6 - default max_allowed_packet if (!queries($prefix . implode(",\n", $values) . $suffix)) { return false; } $values = array(); $length = 0; } $values[] = $value; $length += strlen($value) + 2; // 2 - strlen(",\n") } return queries($prefix . implode(",\n", $values) . $suffix); } } /** Escape database identifier * @param string * @return string */ function idf_escape($idf) { return "`" . str_replace("`", "``", $idf) . "`"; } /** Get escaped table name * @param string * @return string */ function table($idf) { return idf_escape($idf); } /** Connect to the database * @return mixed Min_DB or string for error */ function connect() { global $adminer; $connection = new Min_DB; $credentials = $adminer->credentials(); if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) { $connection->query("SET sql_quote_show_create = 1, autocommit = 1"); return $connection; } $return = $connection->error; if (function_exists('iconv') && !is_utf8($return) && strlen($s = iconv("windows-1250", "utf-8", $return)) > strlen($return)) { // windows-1250 - most common Windows encoding $return = $s; } return $return; } /** Get cached list of databases * @param bool * @return array */ function get_databases($flush) { global $connection; // SHOW DATABASES can take a very long time so it is cached $return = get_session("dbs"); if ($return === null) { $query = ($connection->server_info >= 5 ? "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA" : "SHOW DATABASES" ); // SHOW DATABASES can be disabled by skip_show_database $return = ($flush ? slow_query($query) : get_vals($query)); restart_session(); set_session("dbs", $return); stop_session(); } return $return; } /** Formulate SQL query with limit * @param string everything after SELECT * @param string including WHERE * @param int * @param int * @param string * @return string */ function limit($query, $where, $limit, $offset = 0, $separator = " ") { return " $query$where" . ($limit !== null ? $separator . "LIMIT $limit" . ($offset ? " OFFSET $offset" : "") : ""); } /** Formulate SQL modification query with limit 1 * @param string everything after UPDATE or DELETE * @param string * @return string */ function limit1($query, $where) { return limit($query, $where, 1); } /** Get database collation * @param string * @param array result of collations() * @return string */ function db_collation($db, $collations) { global $connection; $return = null; $create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1); if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) { $return = $match[1]; } elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) { // default collation $return = $collations[$match[1]][-1]; } return $return; } /** Get supported engines * @return array */ function engines() { $return = array(); foreach (get_rows("SHOW ENGINES") as $row) { if (preg_match("~YES|DEFAULT~", $row["Support"])) { $return[] = $row["Engine"]; } } return $return; } /** Get logged user * @return string */ function logged_user() { global $connection; return $connection->result("SELECT USER()"); } /** Get tables list * @return array array($name => $type) */ function tables_list() { global $connection; return get_key_vals($connection->server_info >= 5 ? "SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME" : "SHOW TABLES" ); } /** Count tables in all databases * @param array * @return array array($db => $tables) */ function count_tables($databases) { $return = array(); foreach ($databases as $db) { $return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db))); } return $return; } /** Get table status * @param string * @param bool return only "Name", "Engine" and "Comment" fields * @return array array($name => array("Name" => , "Engine" => , "Comment" => , "Oid" => , "Rows" => , "Collation" => , "Auto_increment" => , "Data_length" => , "Index_length" => , "Data_free" => )) or only inner array with $name */ function table_status($name = "", $fast = false) { global $connection; $return = array(); foreach (get_rows($fast && $connection->server_info >= 5 ? "SELECT TABLE_NAME AS Name, Engine, TABLE_COMMENT AS Comment FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() " . ($name != "" ? "AND TABLE_NAME = " . q($name) : "ORDER BY Name") : "SHOW TABLE STATUS" . ($name != "" ? " LIKE " . q(addcslashes($name, "%_\\")) : "") ) as $row) { if ($row["Engine"] == "InnoDB") { // ignore internal comment, unnecessary since MySQL 5.1.21 $row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]); } if (!isset($row["Engine"])) { $row["Comment"] = ""; } if ($name != "") { return $row; } $return[$row["Name"]] = $row; } return $return; } /** Find out whether the identifier is view * @param array * @return bool */ function is_view($table_status) { return $table_status["Engine"] === null; } /** Check if table supports foreign keys * @param array result of table_status * @return bool */ function fk_support($table_status) { return preg_match('~InnoDB|IBMDB2I~i', $table_status["Engine"]); } /** Get information about fields * @param string * @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => )) */ function fields($table) { $return = array(); foreach (get_rows("SHOW FULL COLUMNS FROM " . table($table)) as $row) { preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match); $return[$row["Field"]] = array( "field" => $row["Field"], "full_type" => $row["Type"], "type" => $match[1], "length" => $match[2], "unsigned" => ltrim($match[3] . $match[4]), "default" => ($row["Default"] != "" || preg_match("~char|set~", $match[1]) ? $row["Default"] : null), "null" => ($row["Null"] == "YES"), "auto_increment" => ($row["Extra"] == "auto_increment"), "on_update" => (preg_match('~^on update (.+)~i', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23 "collation" => $row["Collation"], "privileges" => array_flip(preg_split('~, *~', $row["Privileges"])), "comment" => $row["Comment"], "primary" => ($row["Key"] == "PRI"), ); } return $return; } /** Get table indexes * @param string * @param string Min_DB to use * @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array(), "descs" => array())) */ function indexes($table, $connection2 = null) { $return = array(); foreach (get_rows("SHOW INDEX FROM " . table($table), $connection2) as $row) { $return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE"))); $return[$row["Key_name"]]["columns"][] = $row["Column_name"]; $return[$row["Key_name"]]["lengths"][] = $row["Sub_part"]; $return[$row["Key_name"]]["descs"][] = null; } return $return; } /** Get foreign keys in table * @param string * @return array array($name => array("db" => , "ns" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => )) */ function foreign_keys($table) { global $connection, $on_actions; static $pattern = '`(?:[^`]|``)+`'; $return = array(); $create_table = $connection->result("SHOW CREATE TABLE " . table($table), 1); if ($create_table) { preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE ($on_actions))?(?: ON UPDATE ($on_actions))?~", $create_table, $matches, PREG_SET_ORDER); foreach ($matches as $match) { preg_match_all("~$pattern~", $match[2], $source); preg_match_all("~$pattern~", $match[5], $target); $return[idf_unescape($match[1])] = array( "db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]), "table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]), "source" => array_map('idf_unescape', $source[0]), "target" => array_map('idf_unescape', $target[0]), "on_delete" => ($match[6] ? $match[6] : "RESTRICT"), "on_update" => ($match[7] ? $match[7] : "RESTRICT"), ); } } return $return; } /** Get view SELECT * @param string * @return array array("select" => ) */ function view($name) { global $connection; return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\\s+AS\\s+~isU', '', $connection->result("SHOW CREATE VIEW " . table($name), 1))); } /** Get sorted grouped list of collations * @return array */ function collations() { $return = array(); foreach (get_rows("SHOW COLLATION") as $row) { if ($row["Default"]) { $return[$row["Charset"]][-1] = $row["Collation"]; } else { $return[$row["Charset"]][] = $row["Collation"]; } } ksort($return); foreach ($return as $key => $val) { asort($return[$key]); } return $return; } /** Find out if database is information_schema * @param string * @return bool */ function information_schema($db) { global $connection; return ($connection->server_info >= 5 && $db == "information_schema") || ($connection->server_info >= 5.5 && $db == "performance_schema"); } /** Get escaped error message * @return string */ function error() { global $connection; return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error)); } /** Get line of error * @return int 0 for first line */ function error_line() { global $connection; if (preg_match('~ at line ([0-9]+)$~', $connection->error, $regs)) { return $regs[1] - 1; } } /** Create database * @param string * @param string * @return string */ function create_database($db, $collation) { set_session("dbs", null); return queries("CREATE DATABASE " . idf_escape($db) . ($collation ? " COLLATE " . q($collation) : "")); } /** Drop databases * @param array * @return bool */ function drop_databases($databases) { restart_session(); set_session("dbs", null); return apply_queries("DROP DATABASE", $databases, 'idf_escape'); } /** Rename database from DB * @param string new name * @param string * @return bool */ function rename_database($name, $collation) { if (create_database($name, $collation)) { //! move triggers $rename = array(); foreach (tables_list() as $table => $type) { $rename[] = table($table) . " TO " . idf_escape($name) . "." . table($table); } if (!$rename || queries("RENAME TABLE " . implode(", ", $rename))) { queries("DROP DATABASE " . idf_escape(DB)); return true; } } return false; } /** Generate modifier for auto increment column * @return string */ function auto_increment() { $auto_increment_index = " PRIMARY KEY"; // don't overwrite primary key by auto_increment if ($_GET["create"] != "" && $_POST["auto_increment_col"]) { foreach (indexes($_GET["create"]) as $index) { if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) { $auto_increment_index = ""; break; } if ($index["type"] == "PRIMARY") { $auto_increment_index = " UNIQUE"; } } } return " AUTO_INCREMENT$auto_increment_index"; } /** Run commands to create or alter table * @param string "" to create * @param string new name * @param array of array($orig, $process_field, $after) * @param array of strings * @param string * @param string * @param string * @param int * @param string * @return bool */ function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) { $alter = array(); foreach ($fields as $field) { $alter[] = ($field[1] ? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "") : "DROP " . idf_escape($field[0]) ); } $alter = array_merge($alter, $foreign); $status = "COMMENT=" . q($comment) . ($engine ? " ENGINE=" . q($engine) : "") . ($collation ? " COLLATE " . q($collation) : "") . ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "") . $partitioning ; if ($table == "") { return queries("CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n) $status"); } if ($table != $name) { $alter[] = "RENAME TO " . table($name); } $alter[] = $status; return queries("ALTER TABLE " . table($table) . "\n" . implode(",\n", $alter)); } /** Run commands to alter indexes * @param string escaped table name * @param array of array("index type", "name", array("column definition", ...)) or array("index type", "name", "DROP") * @return bool */ function alter_indexes($table, $alter) { foreach ($alter as $key => $val) { $alter[$key] = ($val[2] == "DROP" ? "\nDROP INDEX " . idf_escape($val[1]) : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "") . ($val[1] != "" ? idf_escape($val[1]) . " " : "") . "(" . implode(", ", $val[2]) . ")" ); } return queries("ALTER TABLE " . table($table) . implode(",", $alter)); } /** Run commands to truncate tables * @param array * @return bool */ function truncate_tables($tables) { return apply_queries("TRUNCATE TABLE", $tables); } /** Drop views * @param array * @return bool */ function drop_views($views) { return queries("DROP VIEW " . implode(", ", array_map('table', $views))); } /** Drop tables * @param array * @return bool */ function drop_tables($tables) { return queries("DROP TABLE " . implode(", ", array_map('table', $tables))); } /** Move tables to other schema * @param array * @param array * @param string * @return bool */ function move_tables($tables, $views, $target) { $rename = array(); foreach (array_merge($tables, $views) as $table) { // views will report SQL error $rename[] = table($table) . " TO " . idf_escape($target) . "." . table($table); } return queries("RENAME TABLE " . implode(", ", $rename)); //! move triggers } /** Copy tables to other schema * @param array * @param array * @param string * @return bool */ function copy_tables($tables, $views, $target) { queries("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'"); foreach ($tables as $table) { $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table)); if (!queries("\nDROP TABLE IF EXISTS $name") || !queries("CREATE TABLE $name LIKE " . table($table)) || !queries("INSERT INTO $name SELECT * FROM " . table($table)) ) { return false; } } foreach ($views as $table) { $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table)); $view = view($table); if (!queries("DROP VIEW IF EXISTS $name") || !queries("CREATE VIEW $name AS $view[select]") //! USE to avoid db.table ) { return false; } } return true; } /** Get information about trigger * @param string trigger name * @return array array("Trigger" => , "Timing" => , "Event" => , "Of" => , "Type" => , "Statement" => ) */ function trigger($name) { if ($name == "") { return array(); } $rows = get_rows("SHOW TRIGGERS WHERE `Trigger` = " . q($name)); return reset($rows); } /** Get defined triggers * @param string * @return array array($name => array($timing, $event)) */ function triggers($table) { $return = array(); foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\"))) as $row) { $return[$row["Trigger"]] = array($row["Timing"], $row["Event"]); } return $return; } /** Get trigger options * @return array ("Timing" => array(), "Event" => array(), "Type" => array()) */ function trigger_options() { return array( "Timing" => array("BEFORE", "AFTER"), "Event" => array("INSERT", "UPDATE", "DELETE"), "Type" => array("FOR EACH ROW"), ); } /** Get information about stored routine * @param string * @param string "FUNCTION" or "PROCEDURE" * @return array ("fields" => array("field" => , "type" => , "length" => , "unsigned" => , "inout" => , "collation" => ), "returns" => , "definition" => , "language" => ) */ function routine($name, $type) { global $connection, $enum_length, $inout, $types; $aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar"); $type_pattern = "((" . implode("|", array_merge(array_keys($types), $aliases)) . ")\\b(?:\\s*\\(((?:[^'\")]|$enum_length)++)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?)(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s]+)['\"]?)?"; $pattern = "\\s*(" . ($type == "FUNCTION" ? "" : $inout) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern"; $create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2); preg_match("~\\(((?:$pattern\\s*,?)*)\\)\\s*" . ($type == "FUNCTION" ? "RETURNS\\s+$type_pattern\\s+" : "") . "(.*)~is", $create, $match); $fields = array(); preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER); foreach ($matches as $param) { $name = str_replace("``", "`", $param[2]) . $param[3]; $fields[] = array( "field" => $name, "type" => strtolower($param[5]), "length" => preg_replace_callback("~$enum_length~s", 'normalize_enum', $param[6]), "unsigned" => strtolower(preg_replace('~\\s+~', ' ', trim("$param[8] $param[7]"))), "null" => 1, "full_type" => $param[4], "inout" => strtoupper($param[1]), "collation" => strtolower($param[9]), ); } if ($type != "FUNCTION") { return array("fields" => $fields, "definition" => $match[11]); } return array( "fields" => $fields, "returns" => array("type" => $match[12], "length" => $match[13], "unsigned" => $match[15], "collation" => $match[16]), "definition" => $match[17], "language" => "SQL", // available in information_schema.ROUTINES.PARAMETER_STYLE ); } /** Get list of routines * @return array ("ROUTINE_TYPE" => , "ROUTINE_NAME" => , "DTD_IDENTIFIER" => ) */ function routines() { return get_rows("SELECT ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q(DB)); } /** Get list of available routine languages * @return array */ function routine_languages() { return array(); // "SQL" not required } /** Get last auto increment ID * @return string */ function last_id() { global $connection; return $connection->result("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint } /** Explain select * @param Min_DB * @param string * @return Min_Result */ function explain($connection, $query) { return $connection->query("EXPLAIN " . ($connection->server_info >= 5.1 ? "PARTITIONS " : "") . $query); } /** Get approximate number of rows * @param array * @param array * @return int or null if approximate number can't be retrieved */ function found_rows($table_status, $where) { return ($where || $table_status["Engine"] != "InnoDB" ? null : $table_status["Rows"]); } /** Get user defined types * @return array */ function types() { return array(); } /** Get existing schemas * @return array */ function schemas() { return array(); } /** Get current schema * @return string */ function get_schema() { return ""; } /** Set current schema * @param string * @return bool */ function set_schema($schema) { return true; } /** Get SQL command to create table * @param string * @param bool * @return string */ function create_sql($table, $auto_increment) { global $connection; $return = $connection->result("SHOW CREATE TABLE " . table($table), 1); if (!$auto_increment) { $return = preg_replace('~ AUTO_INCREMENT=\\d+~', '', $return); //! skip comments } return $return; } /** Get SQL command to truncate table * @param string * @return string */ function truncate_sql($table) { return "TRUNCATE " . table($table); } /** Get SQL command to change database * @param string * @return string */ function use_sql($database) { return "USE " . idf_escape($database); } /** Get SQL commands to create triggers * @param string * @param string * @return string */ function trigger_sql($table, $style) { $return = ""; foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\")), null, "-- ") as $row) { $return .= "\n" . ($style == 'CREATE+ALTER' ? "DROP TRIGGER IF EXISTS " . idf_escape($row["Trigger"]) . ";;\n" : "") . "CREATE TRIGGER " . idf_escape($row["Trigger"]) . " $row[Timing] $row[Event] ON " . table($row["Table"]) . " FOR EACH ROW\n$row[Statement];;\n"; } return $return; } /** Get server variables * @return array ($name => $value) */ function show_variables() { return get_key_vals("SHOW VARIABLES"); } /** Get process list * @return array ($row) */ function process_list() { return get_rows("SHOW FULL PROCESSLIST"); } /** Get status variables * @return array ($name => $value) */ function show_status() { return get_key_vals("SHOW STATUS"); } /** Convert field in select and edit * @param array one element from fields() * @return string */ function convert_field($field) { if (preg_match("~binary~", $field["type"])) { return "HEX(" . idf_escape($field["field"]) . ")"; } if ($field["type"] == "bit") { return "BIN(" . idf_escape($field["field"]) . " + 0)"; // + 0 is required outside MySQLnd } if (preg_match("~geometry|point|linestring|polygon~", $field["type"])) { return "AsWKT(" . idf_escape($field["field"]) . ")"; } } /** Convert value in edit after applying functions back * @param array one element from fields() * @param string * @return string */ function unconvert_field($field, $return) { if (preg_match("~binary~", $field["type"])) { $return = "UNHEX($return)"; } if ($field["type"] == "bit") { $return = "CONV($return, 2, 10) + 0"; } if (preg_match("~geometry|point|linestring|polygon~", $field["type"])) { $return = "GeomFromText($return)"; } return $return; } /** Check whether a feature is supported * @param string "comment", "copy", "database", "drop_col", "dump", "event", "kill", "partitioning", "privileges", "procedure", "processlist", "routine", "scheme", "sequence", "status", "table", "trigger", "type", "variables", "view", "view_trigger" * @return bool */ function support($feature) { global $connection; return !preg_match("~scheme|sequence|type|view_trigger" . ($connection->server_info < 5.1 ? "|event|partitioning" . ($connection->server_info < 5 ? "|routine|trigger|view" : "") : "") . "~", $feature); } $jush = "sql"; ///< @var string JUSH identifier $types = array(); ///< @var array ($type => $maximum_unsigned_length, ...) $structured_types = array(); ///< @var array ($description => array($type, ...), ...) foreach (array( lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21), lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4), lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295), lang('Lists') => array("enum" => 65535, "set" => 64), lang('Binary') => array("bit" => 20, "binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295), lang('Geometry') => array("geometry" => 0, "point" => 0, "linestring" => 0, "polygon" => 0, "multipoint" => 0, "multilinestring" => 0, "multipolygon" => 0, "geometrycollection" => 0), ) as $key => $val) { $types += $val; $structured_types[$key] = array_keys($val); } $unsigned = array("unsigned", "zerofill", "unsigned zerofill"); ///< @var array number variants $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL", "SQL"); ///< @var array operators used in select $functions = array("char_length", "date", "from_unixtime", "lower", "round", "sec_to_time", "time_to_sec", "upper"); ///< @var array functions used in select $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select $edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only array( "char" => "md5/sha1/password/encrypt/uuid", //! JavaScript for disabling maxlength "binary" => "md5/sha1", "date|time" => "now", ), array( "(^|[^o])int|float|double|decimal" => "+/-", // not point "date" => "+ interval/- interval", "time" => "addtime/subtime", "char|text" => "concat", ) ); }