mirror of
https://github.com/vrana/adminer.git
synced 2025-08-14 02:23:59 +02:00
Reintegrate sqlite branch
git-svn-id: https://adminer.svn.sourceforge.net/svnroot/adminer/trunk@1466 7c3ca157-0c34-0410-bff1-cbf682f78f5c
This commit is contained in:
406
adminer/drivers/mssql.inc.php
Normal file
406
adminer/drivers/mssql.inc.php
Normal file
@@ -0,0 +1,406 @@
|
||||
<?php
|
||||
/**
|
||||
* @author Jakub Cernohuby
|
||||
* @author Vladimir Stastka
|
||||
* @author Jakub Vrana
|
||||
*/
|
||||
|
||||
$possible_drivers[] = "SQLSRV";
|
||||
$possible_drivers[] = "MSSQL";
|
||||
if (extension_loaded("sqlsrv") || extension_loaded("mssql")) {
|
||||
$drivers["mssql"] = "MS SQL";
|
||||
}
|
||||
|
||||
if (isset($_GET["mssql"])) {
|
||||
define("DRIVER", "mssql");
|
||||
if (extension_loaded("sqlsrv")) {
|
||||
class Min_DB {
|
||||
var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $error;
|
||||
|
||||
function _get_error() {
|
||||
$this->error = "";
|
||||
foreach (sqlsrv_errors() as $error) {
|
||||
$this->error .= "$error[message]\n";
|
||||
}
|
||||
$this->error = rtrim($this->error);
|
||||
}
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @sqlsrv_connect($server, array("UID" => $username, "PWD" => $password));
|
||||
if ($this->_link) {
|
||||
$info = sqlsrv_server_info($this->_link);
|
||||
$this->server_info = $info['SQLServerVersion'];
|
||||
} else {
|
||||
$this->_get_error();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . str_replace("'", "''", $string) . "'";
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return $this->query("USE $database");
|
||||
}
|
||||
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = sqlsrv_query($this->_link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
|
||||
if (!$result) {
|
||||
$this->_get_error();
|
||||
return false;
|
||||
}
|
||||
return $this->store_result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
$this->_result = sqlsrv_query($this->_link, $query);
|
||||
if (!$this->_result) {
|
||||
$this->_get_error();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function store_result($result = null) {
|
||||
if (!$result) {
|
||||
$result = $this->_result;
|
||||
}
|
||||
if (sqlsrv_field_metadata($result)) {
|
||||
return new Min_Result($result);
|
||||
}
|
||||
$this->affected_rows = sqlsrv_rows_affected($result);
|
||||
return true;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return sqlsrv_next_result($this->_result);
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->fetch_row();
|
||||
return $row[$field];
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $_fields, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = sqlsrv_has_rows($result); //! sqlsrv_num_rows($result)
|
||||
}
|
||||
|
||||
function _convert($row) {
|
||||
foreach ((array) $row as $key => $val) {
|
||||
if (is_a($val, 'DateTime')) {
|
||||
$row[$key] = $val->format("Y-m-d H:i:s");
|
||||
}
|
||||
//! stream
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_ASSOC, SQLSRV_SCROLL_NEXT));
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_NUMERIC, SQLSRV_SCROLL_NEXT));
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
if (!$this->_fields) {
|
||||
$this->_fields = sqlsrv_field_metadata($this->_result);
|
||||
}
|
||||
$field = $this->_fields[$this->_offset++];
|
||||
$return = new stdClass;
|
||||
$return->name = $field["Name"];
|
||||
$return->orgname = $field["Name"];
|
||||
$return->type = ($field["Type"] == 1 ? 254 : 0);
|
||||
return $return;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
sqlsrv_free_stmt($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("mssql")) {
|
||||
class Min_DB {
|
||||
var $extension = "MSSQL", $_link, $_result, $server_info, $affected_rows, $error;
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @mssql_connect($server, $username, $password);
|
||||
if ($this->_link) {
|
||||
$result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
|
||||
$row = $result->fetch_row();
|
||||
$this->server_info = $this->result("sp_server_info 2", 2)." [$row[0]] $row[1]";
|
||||
} else {
|
||||
$this->error = mssql_get_last_message();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . str_replace("'", "''", $string) . "'";
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return mssql_select_db($database);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = mssql_query($query, $this->_link); //! $unbuffered
|
||||
if (!$result) {
|
||||
$this->error = mssql_get_last_message();
|
||||
return false;
|
||||
}
|
||||
if ($result === true) {
|
||||
$this->affected_rows = mssql_rows_affected($this->_link);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return mssql_next_result($this->_result);
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
return mssql_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $_fields, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = mssql_num_rows($result);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return mssql_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return mssql_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
function num_rows() {
|
||||
return mssql_num_rows($this->_result);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$return = mssql_fetch_field($this->_result);
|
||||
$return->orgtable = $return->table;
|
||||
$return->orgname = $return->name;
|
||||
return $return;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
mssql_free_result($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function idf_escape($idf) {
|
||||
return "[" . str_replace("]", "]]", $idf) . "]";
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return get_vals("EXEC sp_databases");
|
||||
}
|
||||
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return (isset($limit) ? " TOP ($limit)" : "") . " $query"; //! offset
|
||||
}
|
||||
|
||||
function limit1($query, $limit, $offset = 0) {
|
||||
return limit($query, 1);
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT collation_name FROM sys.databases WHERE name = " . $connection->quote($db));
|
||||
}
|
||||
|
||||
function engines() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT SUSER_NAME()");
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES");
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
$connection->select_db($db);
|
||||
$return[$db] = $connection->result("SELECT COUNT(*) FROM information_schema.TABLES");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT TABLE_NAME AS Name, TABLE_TYPE AS Engine FROM information_schema.TABLES" . ($name != "" ? " WHERE TABLE_NAME = " . $connection->quote($name) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = " . $connection->quote($table));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["COLUMN_NAME"]] = array(
|
||||
"field" => $row["COLUMN_NAME"],
|
||||
"full_type" => $row["DATA_TYPE"],
|
||||
"type" => $row["DATA_TYPE"],
|
||||
"length" => $row["CHARACTER_MAXIMUM_LENGTH"], //! NUMERIC_, DATETIME_?
|
||||
"default" => $row["COLUMN_DEFAULT"],
|
||||
"null" => ($row["IS_NULLABLE"] == "YES"),
|
||||
"collation" => $row["COLLATION_NAME"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1),
|
||||
//! primary - is_identity in sys.columns
|
||||
);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) {
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
// sp_statistics doesn't return information about primary key
|
||||
$result = $connection2->query("SELECT indexes.name, key_ordinal, is_unique, is_primary_key, columns.name AS column_name
|
||||
FROM sys.indexes
|
||||
INNER JOIN sys.index_columns ON indexes.object_id = index_columns.object_id AND indexes.index_id = index_columns.index_id
|
||||
INNER JOIN sys.columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id
|
||||
WHERE OBJECT_NAME(indexes.object_id) = " . $connection2->quote($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["name"]]["type"] = ($row["is_primary_key"] ? "PRIMARY" : ($row["is_unique"] ? "UNIQUE" : "INDEX"));
|
||||
$return[$row["name"]]["columns"][$row["key_ordinal"]] = $row["column_name"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function collations() {
|
||||
$return = array();
|
||||
foreach (get_vals("SELECT name FROM fn_helpcollations()") as $collation) {
|
||||
$return[ereg_replace("_.*", "", $collation)][] = $collation;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function error() {
|
||||
global $connection;
|
||||
return nl_br(h(ereg_replace("^(\\[[^]]*])+", "", $connection->error)));
|
||||
}
|
||||
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return $connection->quote($val);
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
if ($collation) {
|
||||
queries("ALTER DATABASE " . idf_escape(DB) . " COLLATE " . idf_escape($collation));
|
||||
}
|
||||
return queries("ALTER DATABASE " . idf_escape(DB) . " MODIFY NAME = " . idf_escape($name)); //! false negative "The database name 'test2' has been set."
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return " IDENTITY";
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
$connection->query("SET SHOWPLAN_ALL ON");
|
||||
$return = $connection->query($query);
|
||||
$connection->query("SET SHOWPLAN_ALL OFF"); // connection is used also for indexes
|
||||
return $return;
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return ereg('^(view|routine|trigger)$', $feature);
|
||||
}
|
||||
|
||||
$driver = "mssql";
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array(
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
|
||||
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
|
||||
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
|
||||
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
$unsigned = array();
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
|
||||
$functions = array("len", "lower", "round", "upper");
|
||||
$grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
$edit_functions = array(
|
||||
array(
|
||||
"date|time" => "getdate",
|
||||
), array(
|
||||
"int|decimal|real|float|money|datetime" => "+/-",
|
||||
"char|text" => "+",
|
||||
)
|
||||
);
|
||||
}
|
713
adminer/drivers/mysql.inc.php
Normal file
713
adminer/drivers/mysql.inc.php
Normal file
@@ -0,0 +1,713 @@
|
||||
<?php
|
||||
$possible_drivers[] = "MySQLi";
|
||||
$possible_drivers[] = "MySQL";
|
||||
$possible_drivers[] = "PDO_MySQL";
|
||||
if (extension_loaded("mysqli") || extension_loaded("mysql") || extension_loaded("pdo_mysql")) {
|
||||
$drivers = array("server" => "MySQL") + $drivers;
|
||||
}
|
||||
|
||||
if (!defined("DRIVER")) {
|
||||
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) {
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
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")) {
|
||||
class Min_DB {
|
||||
var
|
||||
$extension = "MySQL", ///< @var string extension name
|
||||
$server_info, ///< @var string server version
|
||||
$affected_rows, ///< @var int number of affected rows
|
||||
$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);
|
||||
} 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
|
||||
if (!$result) {
|
||||
$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) {
|
||||
return false;
|
||||
}
|
||||
return mysql_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var
|
||||
$num_rows, ///< @var int number of rows in the result
|
||||
$_result ///< @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);
|
||||
$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); //! not called in PHP 4 which is a problem with mysql.trace_mode
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_mysql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_MySQL";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:([0-9])~', ';port=\\1', $server)), $username, $password);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Escape database identifier
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function idf_escape($idf) {
|
||||
return "`" . str_replace("`", "``", $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");
|
||||
$connection->query("SET NAMES utf8");
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
/** Get cached list of databases
|
||||
* @param bool
|
||||
* @return array
|
||||
*/
|
||||
function get_databases($flush = true) {
|
||||
// SHOW DATABASES can take a very long time so it is cached
|
||||
$return = &get_session("databases");
|
||||
if (!isset($return)) {
|
||||
if ($flush) {
|
||||
restart_session();
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
$return = get_vals("SHOW DATABASES");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Formulate SQL query with limit
|
||||
* @param string everything after SELECT
|
||||
* @param int
|
||||
* @param int
|
||||
* @return string
|
||||
*/
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
|
||||
}
|
||||
|
||||
/** Formulate SQL modification query with limit 1
|
||||
* @param string everything after UPDATE or DELETE
|
||||
* @return string
|
||||
*/
|
||||
function limit1($query) {
|
||||
return limit($query, 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]][0];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get supported engines
|
||||
* @return array
|
||||
*/
|
||||
function engines() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW ENGINES");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if (ereg("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
|
||||
*/
|
||||
function tables_list() {
|
||||
global $connection;
|
||||
return get_key_vals("SHOW" . ($connection->server_info >= 5 ? " FULL" : "") . " 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
|
||||
* @return array
|
||||
*/
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . $connection->quote(addcslashes($name, "%_")) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
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["Rows"])) {
|
||||
$row["Engine"] = "VIEW";
|
||||
$row["Comment"] = "";
|
||||
}
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Check if table supports foreign keys
|
||||
* @param array result of table_status
|
||||
* @return bool
|
||||
*/
|
||||
function fk_support($table_status) {
|
||||
return ($table_status["Engine"] == "InnoDB");
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW FULL COLUMNS FROM " . idf_escape($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
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"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
|
||||
"null" => ($row["Null"] == "YES"),
|
||||
"auto_increment" => ($row["Extra"] == "auto_increment"),
|
||||
"on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
|
||||
"collation" => $row["Collation"],
|
||||
"privileges" => array_flip(explode(",", $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()))
|
||||
*/
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
$result = $connection2->query("SHOW INDEX FROM " . idf_escape($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$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 $return;
|
||||
}
|
||||
|
||||
/** Get foreign keys in table
|
||||
* @param string
|
||||
* @return array array($name => array("db" => , "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 " . idf_escape($table), 1);
|
||||
if ($create_table) {
|
||||
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $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],
|
||||
"on_update" => $match[7],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get view SELECT
|
||||
* @param string
|
||||
* @return array array("select" => )
|
||||
*/
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result("SHOW CREATE VIEW " . idf_escape($name), 1)));
|
||||
}
|
||||
|
||||
/** Get sorted grouped list of collations
|
||||
* @return array
|
||||
*/
|
||||
function collations() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW COLLATION");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Charset"]][] = $row["Collation"];
|
||||
}
|
||||
ksort($return);
|
||||
foreach ($return as $key => $val) {
|
||||
sort($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");
|
||||
}
|
||||
|
||||
/** 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));
|
||||
}
|
||||
|
||||
/** Return expression for binary comparison
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return "BINARY " . $connection->quote($val);
|
||||
}
|
||||
|
||||
/** Rename database from DB
|
||||
* @param string new name
|
||||
* @return string
|
||||
* @return bool
|
||||
*/
|
||||
function rename_database($name, $collation) {
|
||||
global $connection;
|
||||
$return = false;
|
||||
if (queries("CREATE DATABASE " . idf_escape($name) . ($collation ? " COLLATE " . $connection->quote($collation) : ""))) {
|
||||
//! move triggers
|
||||
$return = true; // table list may by empty
|
||||
foreach (tables_list() as $table) {
|
||||
if (!queries("RENAME TABLE " . idf_escape($table) . " TO " . idf_escape($name) . "." . idf_escape($table))) {
|
||||
$return = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($return) {
|
||||
queries("DROP DATABASE " . idf_escape(DB));
|
||||
//! saved to history of removed database
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
global $connection;
|
||||
$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=" . $connection->quote($comment)
|
||||
. ($engine ? " ENGINE=" . $connection->quote($engine) : "")
|
||||
. ($collation ? " COLLATE " . $connection->quote($collation) : "")
|
||||
. ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "")
|
||||
. $partitioning
|
||||
;
|
||||
if ($table == "") {
|
||||
return queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n) $status");
|
||||
}
|
||||
if ($table != $name) {
|
||||
$alter[] = "RENAME TO " . idf_escape($name);
|
||||
}
|
||||
$alter[] = $status;
|
||||
return queries("ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
|
||||
}
|
||||
|
||||
/** Run commands to alter indexes
|
||||
* @param string escaped table name
|
||||
* @param array of array("index type", "(columns definition)") or array("index type", "escaped name", "DROP")
|
||||
* @return bool
|
||||
*/
|
||||
function alter_indexes($table, $alter) {
|
||||
foreach ($alter as $key => $val) {
|
||||
$alter[$key] = ($val[2] ? "\nDROP INDEX " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
|
||||
}
|
||||
return queries("ALTER TABLE " . idf_escape($table) . implode(",", $alter));
|
||||
}
|
||||
|
||||
/** Run commands to truncate tables
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function truncate_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
if (!queries("TRUNCATE TABLE " . idf_escape($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Drop views
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function drop_views($views) {
|
||||
return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
|
||||
}
|
||||
|
||||
/** Drop tables
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function drop_tables($tables) {
|
||||
return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
|
||||
}
|
||||
|
||||
/** Get information about trigger
|
||||
* @param string trigger name
|
||||
* @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
|
||||
*/
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
$result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($name));
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
/** Get defined triggers
|
||||
* @param string
|
||||
* @return array array($name => array($timing, $event))
|
||||
*/
|
||||
function triggers($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_")));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Trigger"]] = array($row["Timing"], $row["Event"]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Explain select
|
||||
* @param Min_DB
|
||||
* @param string
|
||||
* @return Min_Result
|
||||
*/
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN $query");
|
||||
}
|
||||
|
||||
/** Get SQL command to create table
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function create_sql($table) {
|
||||
global $connection;
|
||||
return $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
|
||||
}
|
||||
|
||||
/** Check whether a feature is supported
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function support($feature) {
|
||||
global $connection;
|
||||
$features = array(
|
||||
"view" => ($connection->server_info >= 5),
|
||||
"routine" => ($connection->server_info >= 5),
|
||||
"trigger" => ($connection->server_info >= 5),
|
||||
"event" => ($connection->server_info >= 5.1),
|
||||
"partitioning" => ($connection->server_info >= 5.1),
|
||||
);
|
||||
return (isset($features[$feature]) ? $features[$feature] : true);
|
||||
}
|
||||
|
||||
$driver = "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('Binary') => array("binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
|
||||
lang('Lists') => array("enum" => 65535, "set" => 64),
|
||||
) 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"); ///< @var array operators used in select
|
||||
$functions = array("char_length", "from_unixtime", "hex", "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
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
"int|float|double|decimal" => "+/-",
|
||||
"date" => "+ interval/- interval",
|
||||
"time" => "addtime/subtime",
|
||||
"char|text" => "concat",
|
||||
)
|
||||
);
|
||||
}
|
443
adminer/drivers/pgsql.inc.php
Normal file
443
adminer/drivers/pgsql.inc.php
Normal file
@@ -0,0 +1,443 @@
|
||||
<?php
|
||||
$possible_drivers[] = "PgSQL";
|
||||
$possible_drivers[] = "PDO_PgSQL";
|
||||
if (extension_loaded("pgsql") || extension_loaded("pdo_pgsql")) {
|
||||
$drivers["pgsql"] = "PostgreSQL";
|
||||
}
|
||||
|
||||
if (isset($_GET["pgsql"])) {
|
||||
define("DRIVER", "pgsql");
|
||||
if (extension_loaded("pgsql")) {
|
||||
class Min_DB {
|
||||
var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error;
|
||||
|
||||
function _error($errno, $error) {
|
||||
if (ini_bool("html_errors")) {
|
||||
$error = html_entity_decode(strip_tags($error));
|
||||
}
|
||||
$error = ereg_replace('^[^:]*: ', '', $error);
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
set_error_handler(array($this, '_error'));
|
||||
$this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
|
||||
$this->_link = @pg_connect($this->_string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), PGSQL_CONNECT_FORCE_NEW);
|
||||
if (!$this->_link && DB != "") {
|
||||
// try to connect directly with database for performance
|
||||
$this->_database = false;
|
||||
$this->_link = @pg_connect($this->_string, PGSQL_CONNECT_FORCE_NEW);
|
||||
}
|
||||
restore_error_handler();
|
||||
if ($this->_link) {
|
||||
$version = pg_version($this->_link);
|
||||
$this->server_info = $version["server"];
|
||||
pg_set_client_encoding($this->_link, "UTF8");
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . pg_escape_string($this->_link, $string) . "'"; //! bytea
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
if ($database == DB) {
|
||||
return $this->_database;
|
||||
}
|
||||
$link = @pg_connect($this->_connection . " dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
|
||||
if ($link) {
|
||||
$this->_link = $link;
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = @pg_query($this->_link, $query);
|
||||
if (!$result) {
|
||||
$this->error = pg_last_error($this->_link);
|
||||
return false;
|
||||
} elseif (!pg_num_fields($result)) {
|
||||
$this->affected_rows = pg_affected_rows($result);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
// PgSQL extension doesn't support multiple results
|
||||
return false;
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
return pg_fetch_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = pg_num_rows($result);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return pg_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return pg_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
$row = new stdClass;
|
||||
$row->orgtable = pg_field_table($this->_result, $column);
|
||||
$row->name = pg_field_name($this->_result, $column);
|
||||
$row->orgname = $row->name;
|
||||
$row->type = pg_field_type($this->_result, $column);
|
||||
$row->charsetnr = ($row->type == "bytea" ? 63 : 0);
|
||||
return $row;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
pg_free_result($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_pgsql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_PgSQL";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$string = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' options='-c client_encoding=utf8'";
|
||||
$this->dsn($string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), $username, $password);
|
||||
//! connect without DB in case of an error
|
||||
return true;
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return (DB == $database);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function idf_escape($idf) {
|
||||
return '"' . str_replace('"', '""', $idf) . '"';
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return get_vals("SELECT datname FROM pg_database");
|
||||
}
|
||||
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
|
||||
}
|
||||
|
||||
function limit1($query) {
|
||||
return " $query";
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SHOW LC_COLLATE"); //! respect $db
|
||||
}
|
||||
|
||||
function engines() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT user");
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
global $connection;
|
||||
return get_key_vals("SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name");
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
return array(); // would require reconnect
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT relname AS \"Name\", CASE relkind WHEN 'r' THEN '' ELSE 'view' END AS \"Engine\", pg_relation_size(oid) AS \"Data_length\", pg_catalog.obj_description(oid, 'pg_class') AS \"Comment\" FROM pg_catalog.pg_class WHERE relkind IN ('r','v') AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')" . ($name != "" ? " AND relname = " . $connection->quote($name) : "")); //! Index_length, Auto_increment
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return ($name != "" ? $return[$name] : $return);
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$table_oid = $connection->result("SELECT oid FROM pg_class WHERE relname = " . $connection->quote($table));
|
||||
$result = $connection->query("SELECT *, col_description($table_oid, ordinal_position) AS comment FROM information_schema.columns WHERE table_name = " . $connection->quote($table) . " ORDER BY ordinal_position");
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$length = $row["character_maximum_length"];
|
||||
$return[$row["column_name"]] = array(
|
||||
"field" => $row["column_name"],
|
||||
"full_type" => $row["data_type"] . ($length ? "($length)" : ""),
|
||||
"type" => $row["data_type"],
|
||||
"length" => $length,
|
||||
"default" => $row["column_default"],
|
||||
"null" => ($row["is_nullable"] == "YES"),
|
||||
"auto_increment" => eregi("^nextval\\(", $row["column_default"]),
|
||||
"on_update" => "", //!
|
||||
"collation" => $row["collation_name"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1), //! is_updatable
|
||||
"primary" => false, //!
|
||||
"comment" => $row["comment"],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) {
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
$table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relname = " . $connection2->quote($table));
|
||||
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
|
||||
$result = $connection2->query("SELECT relname, indisunique, indisprimary, indkey FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["relname"]]["type"] = ($row["indisprimary"] == "t" ? "PRIMARY" : ($row["indisunique"] == "t" ? "UNIQUE" : "INDEX"));
|
||||
$return[$row["relname"]]["columns"] = array();
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$row["relname"]]["columns"][] = $columns[$indkey];
|
||||
}
|
||||
$return[$row["relname"]]["lengths"] = array();
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function foreign_keys($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT tc.constraint_name, kcu.column_name, rc.update_rule AS on_update, rc.delete_rule AS on_delete, ccu.table_name AS table, ccu.column_name AS ref
|
||||
FROM information_schema.table_constraints tc
|
||||
LEFT JOIN information_schema.key_column_usage kcu USING (constraint_catalog, constraint_schema, constraint_name)
|
||||
LEFT JOIN information_schema.referential_constraints rc USING (constraint_catalog, constraint_schema, constraint_name)
|
||||
LEFT JOIN information_schema.constraint_column_usage ccu ON rc.unique_constraint_catalog = ccu.constraint_catalog AND rc.unique_constraint_schema = ccu.constraint_schema AND rc.unique_constraint_name = ccu.constraint_name
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = " . $connection->quote($table)); //! there can be more unique_constraint_name
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$foreign_key = &$return[$row["constraint_name"]];
|
||||
if (!$foreign_key) {
|
||||
$foreign_key = $row;
|
||||
}
|
||||
$foreign_key["source"][] = $row["column_name"];
|
||||
$foreign_key["target"][] = $row["ref"];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => $connection->result("SELECT pg_get_viewdef(" . $connection->quote($name) . ")"));
|
||||
}
|
||||
|
||||
function collations() {
|
||||
//! supported in CREATE DATABASE
|
||||
return array();
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return ($db == "information_schema");
|
||||
}
|
||||
|
||||
function error() {
|
||||
global $connection;
|
||||
$return = h($connection->error);
|
||||
if (preg_match('~^(.*\\n)?([^\\n]*)\\n( *)\\^(\\n.*)?$~s', $return, $match)) {
|
||||
$return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\\1<b>\\2</b>', $match[2]) . $match[4];
|
||||
}
|
||||
return nl_br($return);
|
||||
}
|
||||
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return $connection->quote($val);
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
//! current database cannot be renamed
|
||||
return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name));
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
global $connection;
|
||||
$alter = array();
|
||||
$queries = array();
|
||||
foreach ($fields as $field) {
|
||||
$column = idf_escape($field[0]);
|
||||
$val = $field[1];
|
||||
if (!$val) {
|
||||
$alter[] = "DROP $column";
|
||||
} else {
|
||||
$val5 = $val[5];
|
||||
unset($val[5]);
|
||||
if ($val[6]) { // auto_increment
|
||||
$val = array($val[0], ($val[1] == "bigint" ? "big" : "") . "serial");
|
||||
}
|
||||
if ($field[0] == "") {
|
||||
$alter[] = ($table != "" ? "ADD " : " ") . implode("", $val);
|
||||
} else {
|
||||
if ($column != $val[0]) {
|
||||
$queries[] = "ALTER TABLE " . idf_escape($table) . " RENAME $column TO $val[0]";
|
||||
}
|
||||
$alter[] = "ALTER $column TYPE $val[1]";
|
||||
if (!$val[6]) {
|
||||
$alter[] = "ALTER $column" . ($val[3] ? " SET$val[3]" : " DROP DEFAULT"); //! quoting
|
||||
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
|
||||
}
|
||||
}
|
||||
if ($table != "" || $val5 != "") {
|
||||
$queries[] = "COMMENT ON COLUMN " . idf_escape($table) . ".$val[0] IS " . substr($val5, 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
if ($table == "") {
|
||||
array_unshift($queries, "CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n)");
|
||||
} elseif ($alter) {
|
||||
array_unshift($queries, "ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
|
||||
}
|
||||
if ($table != "" && $table != $name) {
|
||||
$queries[] = "ALTER TABLE " . idf_escape($table) . " RENAME TO " . idf_escape($name);
|
||||
}
|
||||
if ($table != "" || $comment != "") {
|
||||
$queries[] = "COMMENT ON TABLE " . idf_escape($name) . " IS " . $connection->quote($comment);
|
||||
}
|
||||
if ($auto_increment != "") {
|
||||
//! $queries[] = "SELECT setval(pg_get_serial_sequence(" . $connection->quote($name) . ", ), $auto_increment)";
|
||||
}
|
||||
foreach ($queries as $query) {
|
||||
if (!queries($query)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function alter_indexes($table, $alter) {
|
||||
$create = array();
|
||||
$drop = array();
|
||||
foreach ($alter as $val) {
|
||||
if ($val[0] != "INDEX") {
|
||||
$create[] = ($val[2] ? "\nDROP CONSTRAINT " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
|
||||
} elseif ($val[2]) {
|
||||
$drop[] = $val[1];
|
||||
} elseif (!queries("CREATE INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table) . " $val[1]")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ((!$create || queries("ALTER TABLE " . idf_escape($table) . implode(",", $create)))
|
||||
&& (!$drop || queries("DROP INDEX " . implode(", ", $drop)))
|
||||
);
|
||||
}
|
||||
|
||||
function truncate_tables($tables) {
|
||||
return queries("TRUNCATE " . implode(", ", array_map('idf_escape', $tables)));
|
||||
return true;
|
||||
}
|
||||
|
||||
function drop_views($views) {
|
||||
return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
|
||||
}
|
||||
|
||||
function drop_tables($tables) {
|
||||
return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
|
||||
}
|
||||
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
$result = $connection->query('SELECT trigger_name AS "Trigger", condition_timing AS "Timing", event_manipulation AS "Event", action_statement AS "Statement" FROM information_schema.triggers WHERE event_object_table = ' . $connection->quote($_GET["trigger"]) . ' AND trigger_name = ' . $connection->quote($name));
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
function triggers($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT * FROM information_schema.triggers WHERE event_object_table = " . $connection->quote($table));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["trigger_name"]] = array($row["condition_timing"], $row["event_manipulation"]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN $query");
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return ereg('^(comment|view|routine|trigger)$', $feature);
|
||||
}
|
||||
|
||||
$driver = "pgsql";
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array( //! arrays
|
||||
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
|
||||
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "interval" => 0),
|
||||
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
|
||||
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
|
||||
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "txid_snapshot" => 0),
|
||||
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
$unsigned = array();
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
|
||||
$functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
|
||||
$grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
$edit_functions = array(
|
||||
array(
|
||||
"char" => "md5",
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
"int|numeric|real|money" => "+/-",
|
||||
"date|time" => "+ interval/- interval", //! escape
|
||||
"char|text" => "||",
|
||||
)
|
||||
);
|
||||
}
|
479
adminer/drivers/sqlite.inc.php
Normal file
479
adminer/drivers/sqlite.inc.php
Normal file
@@ -0,0 +1,479 @@
|
||||
<?php
|
||||
$possible_drivers[] = "SQLite";
|
||||
$possible_drivers[] = "SQLite3";
|
||||
$possible_drivers[] = "PDO_SQLite";
|
||||
if (extension_loaded("sqlite3") || extension_loaded("pdo_sqlite")) {
|
||||
$drivers["sqlite"] = "SQLite 3";
|
||||
}
|
||||
if (extension_loaded("sqlite") || extension_loaded("pdo_sqlite")) {
|
||||
$drivers["sqlite2"] = "SQLite 2";
|
||||
}
|
||||
|
||||
if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
define("DRIVER", (isset($_GET["sqlite"]) ? "sqlite" : "sqlite2"));
|
||||
if (extension_loaded(isset($_GET["sqlite2"]) ? "sqlite" : "sqlite3")) {
|
||||
if (isset($_GET["sqlite2"])) {
|
||||
|
||||
class Min_SQLite {
|
||||
var $extension = "SQLite", $server_info, $affected_rows, $error, $_connection;
|
||||
|
||||
function __construct() {
|
||||
$this->server_info = sqlite_libversion();
|
||||
}
|
||||
|
||||
function open($filename) {
|
||||
$this->_connection = new SQLiteDatabase($filename);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$method = ($unbuffered ? "unbufferedQuery" : "query");
|
||||
$result = @$this->_connection->$method($query, SQLITE_BOTH, $error);
|
||||
if (!$result) {
|
||||
$this->error = $error;
|
||||
return false;
|
||||
} elseif ($result === true) {
|
||||
$this->affected_rows = $this->changes();
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . sqlite_escape_string($string) . "'";
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetch();
|
||||
return $row[$field];
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
if (method_exists($result, 'numRows')) { // not available in unbuffered query
|
||||
$this->num_rows = $result->numRows();
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
$row = $this->_result->fetch(SQLITE_ASSOC);
|
||||
if (!$row) {
|
||||
return false;
|
||||
}
|
||||
$return = array();
|
||||
foreach ($row as $key => $val) {
|
||||
$return[($key[0] == '"' ? idf_unescape($key) : $key)] = $val;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetch(SQLITE_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
return (object) array(
|
||||
"name" => $this->_result->fieldName($this->_offset++),
|
||||
//! type, orgtable, charsetnr
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
class Min_SQLite extends SQLite3 {
|
||||
var $extension = "SQLite3", $server_info, $affected_rows, $error;
|
||||
|
||||
function __construct() {
|
||||
$version = $this->version();
|
||||
$this->server_info = $version["versionString"];
|
||||
}
|
||||
|
||||
function open($filename) {
|
||||
parent::__construct($filename);
|
||||
}
|
||||
|
||||
function query($query) {
|
||||
$result = @parent::query($query);
|
||||
if (!$result) {
|
||||
$this->error = $this->lastErrorMsg();
|
||||
return false;
|
||||
} elseif ($result->numColumns()) {
|
||||
return new Min_Result($result);
|
||||
}
|
||||
$this->affected_rows = $this->changes();
|
||||
return true;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . $this->escapeString($string) . "'";
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetchArray();
|
||||
return $row[$field];
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = 1; //!
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->_result->fetchArray(SQLITE3_ASSOC);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetchArray(SQLITE3_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
return (object) array(
|
||||
"name" => $this->_result->columnName($column),
|
||||
"type" => $this->_result->columnType($column),
|
||||
//! orgtable, charsetnr
|
||||
);
|
||||
}
|
||||
|
||||
function __desctruct() {
|
||||
return $this->_result->finalize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Min_DB extends Min_SQLite {
|
||||
|
||||
function select_db($filename) {
|
||||
static $connected = false;
|
||||
if ($connected) {
|
||||
return true;
|
||||
}
|
||||
set_exception_handler('connect_error'); // try/catch is not compatible with PHP 4
|
||||
$this->open($filename);
|
||||
$connected = true;
|
||||
restore_exception_handler();
|
||||
return true;
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_sqlite")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_SQLite";
|
||||
|
||||
function select_db($filename) {
|
||||
static $connected = false;
|
||||
if ($connected) {
|
||||
return true;
|
||||
}
|
||||
$connected = true;
|
||||
$this->dsn(DRIVER . ":$filename", "", "", "connect_error");
|
||||
//! $this->server_info needs to be filled in __construct()
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function idf_escape($idf) {
|
||||
return '"' . str_replace('"', '""', $idf) . '"';
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $connection;
|
||||
if ($connection) {
|
||||
return $connection; // can connect only once, function to get number of rows doesn't exist anyway
|
||||
}
|
||||
return new Min_DB;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
|
||||
}
|
||||
|
||||
function limit1($query) {
|
||||
global $connection;
|
||||
return ($connection->result("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')") ? limit($query, 1) : " $query");
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function engines() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
return ""; //! OS user
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
return get_key_vals("SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view')", 1);
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
return array();
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT name AS Name, type AS Engine FROM sqlite_master WHERE type IN ('table', 'view')" . ($name != "" ? " AND name = " . $connection->quote($name) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
$result = $connection->query("SELECT * FROM sqlite_sequence");
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["name"]]["Auto_increment"] = $row["seq"];
|
||||
}
|
||||
}
|
||||
return ($name != "" ? $return[$name] : $return);
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
global $connection;
|
||||
return !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("PRAGMA table_info(" . idf_escape($table) . ")");
|
||||
if (is_object($result)) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$type = strtolower($row["type"]);
|
||||
$return[$row["name"]] = array(
|
||||
"field" => $row["name"],
|
||||
"type" => (eregi("int", $type) ? "integer" : (eregi("char|clob|text", $type) ? "text" : (eregi("blob", $type) ? "blob" : (eregi("real|floa|doub", $type) ? "real" : "numeric")))),
|
||||
"full_type" => $type,
|
||||
"default" => $row["dflt_value"],
|
||||
"null" => !$row["notnull"],
|
||||
"auto_increment" => eregi('^integer$', $type) && $row["pk"], //! possible false positive
|
||||
"collation" => null, //!
|
||||
"privileges" => array("select" => 1, "insert" => 1, "update" => 1),
|
||||
"primary" => $row["pk"],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$primary = array();
|
||||
foreach (fields($table) as $field) {
|
||||
if ($field["primary"]) {
|
||||
$primary[] = $field["field"];
|
||||
}
|
||||
}
|
||||
if ($primary) {
|
||||
$return[""] = array("type" => "PRIMARY", "columns" => $primary, "lengths" => array());
|
||||
}
|
||||
$result = $connection->query("PRAGMA index_list(" . idf_escape($table) . ")");
|
||||
if (is_object($result)) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX");
|
||||
$return[$row["name"]]["lengths"] = array();
|
||||
$result1 = $connection->query("PRAGMA index_info(" . idf_escape($row["name"]) . ")");
|
||||
while ($row1 = $result1->fetch_assoc()) {
|
||||
$return[$row["name"]]["columns"][] = $row1["name"];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function foreign_keys($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("PRAGMA foreign_key_list(" . idf_escape($table) . ")");
|
||||
if (is_object($result)) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$foreign_key = &$return[$row["id"]];
|
||||
if (!$foreign_key) {
|
||||
$foreign_key = $row;
|
||||
}
|
||||
$foreign_key["source"][] = $row["from"];
|
||||
$foreign_key["target"][] = $row["to"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($name)))); //! identifiers may be inside []
|
||||
}
|
||||
|
||||
function collations() {
|
||||
return get_vals("PRAGMA collation_list", 1);
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function error() {
|
||||
global $connection;
|
||||
return h($connection->error);
|
||||
}
|
||||
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return $connection->quote($val);
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
global $connection;
|
||||
$connection->close(); //! not available with all extensions
|
||||
return rename(DB, $name);
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return " PRIMARY KEY" . (DRIVER == "sqlite" ? " AUTOINCREMENT" : "");
|
||||
}
|
||||
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
global $connection;
|
||||
$alter = array();
|
||||
foreach ($fields as $field) {
|
||||
$alter[] = ($table != "" && $field[0] == "" ? "ADD " : " ") . implode("", $field[1]);
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
if ($table != "") {
|
||||
foreach ($alter as $val) {
|
||||
if (!queries("ALTER TABLE " . idf_escape($table) . " $val")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($table != $name && !queries("ALTER TABLE " . idf_escape($table) . " RENAME TO " . idf_escape($name))) {
|
||||
return false;
|
||||
}
|
||||
} elseif (!queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n)")) {
|
||||
return false;
|
||||
}
|
||||
if ($auto_increment) {
|
||||
return queries("UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . $connection->quote($name) . "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function alter_indexes($table, $alter) {
|
||||
foreach ($alter as $val) {
|
||||
if (!queries(($val[2] ? "DROP INDEX" : "CREATE" . ($val[0] != "INDEX" ? " UNIQUE" : "") . " INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table)) . " $val[1]")) { //! primary key must be created in CREATE TABLE
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function truncate_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
if (!queries("DELETE FROM " . idf_escape($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function drop_views($views) {
|
||||
foreach ($views as $view) {
|
||||
if (!queries("DROP VIEW " . idf_escape($view))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function drop_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
if (!queries("DROP TABLE " . idf_escape($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s+([a-z]+)\\s+ON\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*(?:FOR\\s*EACH\\s*ROW\\s)?(.*)~is', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($name)), $match);
|
||||
return array("Timing" => strtoupper($match[1]), "Event" => strtoupper($match[2]), "Trigger" => $name, "Statement" => $match[3]);
|
||||
}
|
||||
|
||||
function triggers($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . $connection->quote($table));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s*([a-z]+)~i', $row["sql"], $match);
|
||||
$return[$row["name"]] = array($match[1], $match[2]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN $query");
|
||||
}
|
||||
|
||||
function create_sql($table) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($table));
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return ereg('^(view|trigger)$', $feature);
|
||||
}
|
||||
|
||||
$driver = "sqlite";
|
||||
$types = array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0);
|
||||
$structured_types = array_keys($types);
|
||||
$unsigned = array();
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // REGEXP can be user defined function
|
||||
$functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
|
||||
$grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
|
||||
$edit_functions = array(
|
||||
array(
|
||||
// "text" => "date('now')/time('now')/datetime('now')",
|
||||
), array(
|
||||
"integer|real|numeric" => "+/-",
|
||||
// "text" => "date/time/datetime",
|
||||
"text" => "||",
|
||||
)
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user