2010-04-21 12:01:32 +00:00
< ? php
2010-10-29 13:24:06 +00:00
$drivers = array ( " server " => " MySQL " ) + $drivers ;
2010-04-21 12:01:32 +00:00
if ( ! defined ( " DRIVER " )) {
2010-10-29 13:24:06 +00:00
$possible_drivers = array ( " MySQLi " , " MySQL " , " PDO_MySQL " );
2010-04-21 12:01:32 +00:00
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 ) {
2010-09-09 20:02:35 +00:00
mysqli_report ( MYSQLI_REPORT_OFF ); // stays between requests, not required since PHP 5.3.4
2010-04-21 12:01:32 +00:00
list ( $host , $port ) = explode ( " : " , $server , 2 ); // part after : is used for port or socket
2010-10-10 09:12:53 +00:00
$return = @ $this -> real_connect (
2010-04-21 12:01:32 +00:00
( $server != " " ? $host : ini_get ( " mysqli.default_host " )),
2011-06-22 13:06:46 +00:00
( $server . $username != " " ? $username : ini_get ( " mysqli.default_user " )),
( $server . $username . $password != " " ? $password : ini_get ( " mysqli.default_pw " )),
2010-04-21 12:01:32 +00:00
null ,
( is_numeric ( $port ) ? $port : ini_get ( " mysqli.default_port " )),
( ! is_numeric ( $port ) ? $port : null )
);
2010-10-10 09:12:53 +00:00
if ( $return ) {
if ( method_exists ( $this , 'set_charset' )) {
$this -> set_charset ( " utf8 " );
} else {
$this -> query ( " SET NAMES utf8 " );
}
}
return $return ;
2010-04-21 12:01:32 +00:00
}
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 ) . " ' " ;
}
}
2011-08-25 15:46:25 +00:00
} elseif ( extension_loaded ( " mysql " ) && ! ( ini_get ( " sql.safe_mode " ) && extension_loaded ( " pdo_mysql " ))) {
2010-04-21 12:01:32 +00:00
class Min_DB {
var
$extension = " MySQL " , ///< @var string extension name
$server_info , ///< @var string server version
$affected_rows , ///< @var int number of affected rows
2013-01-10 06:19:38 +00:00
$errno , ///< @var int last error code
2010-04-21 12:01:32 +00:00
$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 );
2010-10-10 09:12:53 +00:00
if ( function_exists ( 'mysql_set_charset' )) {
mysql_set_charset ( " utf8 " , $this -> _link );
} else {
$this -> query ( " SET NAMES utf8 " );
}
2010-04-21 12:01:32 +00:00
} 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
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
if ( ! $result ) {
2013-01-10 20:57:00 +00:00
$this -> errno = mysql_errno ( $this -> _link );
2010-04-21 12:01:32 +00:00
$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 );
2011-02-01 15:26:21 +00:00
if ( ! $result || ! $result -> num_rows ) {
2010-04-21 12:01:32 +00:00
return false ;
}
return mysql_result ( $result -> _result , 0 , $field );
}
}
class Min_Result {
var
$num_rows , ///< @var int number of rows in the result
2010-11-02 13:40:56 +00:00
$_result , $_offset = 0 ///< @access private
2010-04-21 12:01:32 +00:00
;
/** 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 () {
2010-11-02 13:40:56 +00:00
$return = mysql_fetch_field ( $this -> _result , $this -> _offset ++ ); // offset required under certain conditions
2010-04-21 12:01:32 +00:00
$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 ) {
2010-10-22 22:02:24 +00:00
$this -> dsn ( " mysql:host= " . str_replace ( " : " , " ;unix_socket= " , preg_replace ( '~:(\\d)~' , ';port=\\1' , $server )), $username , $password );
2010-10-10 09:12:53 +00:00
$this -> query ( " SET NAMES utf8 " ); // charset in DSN is ignored
2010-04-21 12:01:32 +00:00
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 ) . " ` " ;
}
2010-05-11 14:45:04 +00:00
/** Get escaped table name
* @ param string
* @ return string
*/
function table ( $idf ) {
return idf_escape ( $idf );
}
2010-04-21 12:01:32 +00:00
/** 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 ])) {
2011-09-27 00:24:20 +00:00
$connection -> query ( " SET sql_quote_show_create = 1, autocommit = 1 " );
2010-04-21 12:01:32 +00:00
return $connection ;
}
2011-08-09 09:51:18 +00:00
$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 ;
2010-04-21 12:01:32 +00:00
}
/** Get cached list of databases
* @ param bool
* @ return array
*/
2012-08-19 16:43:31 +00:00
function get_databases ( $flush ) {
2011-03-10 11:00:08 +00:00
global $connection ;
2010-04-21 12:01:32 +00:00
// SHOW DATABASES can take a very long time so it is cached
2012-08-20 00:12:19 +00:00
$return = get_session ( " dbs " );
2012-05-14 06:54:07 +00:00
if ( $return === null ) {
2012-08-20 04:55:00 +00:00
$query = ( $connection -> server_info >= 5
2012-08-20 00:12:19 +00:00
? " SELECT SCHEMA_NAME FROM information_schema.SCHEMATA "
: " SHOW DATABASES "
2012-08-20 04:55:00 +00:00
); // SHOW DATABASES can be disabled by skip_show_database
$return = ( $flush ? slow_query ( $query ) : get_vals ( $query ));
2012-08-19 20:42:13 +00:00
restart_session ();
2012-08-20 00:12:19 +00:00
set_session ( " dbs " , $return );
2012-08-19 20:42:13 +00:00
stop_session ();
2010-04-21 12:01:32 +00:00
}
return $return ;
}
/** Formulate SQL query with limit
* @ param string everything after SELECT
2010-05-14 13:51:54 +00:00
* @ param string including WHERE
2010-04-21 12:01:32 +00:00
* @ param int
* @ param int
2010-04-26 16:19:26 +00:00
* @ param string
2010-04-21 12:01:32 +00:00
* @ return string
*/
2010-05-14 13:51:54 +00:00
function limit ( $query , $where , $limit , $offset = 0 , $separator = " " ) {
2012-05-14 06:54:07 +00:00
return " $query $where " . ( $limit !== null ? $separator . " LIMIT $limit " . ( $offset ? " OFFSET $offset " : " " ) : " " );
2010-04-21 12:01:32 +00:00
}
/** Formulate SQL modification query with limit 1
* @ param string everything after UPDATE or DELETE
2012-09-16 13:43:55 +00:00
* @ param string
2010-04-21 12:01:32 +00:00
* @ return string
*/
2010-05-14 13:51:54 +00:00
function limit1 ( $query , $where ) {
return limit ( $query , $where , 1 );
2010-04-21 12:01:32 +00:00
}
/** 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
2011-02-25 09:49:19 +00:00
$return = $collations [ $match [ 1 ]][ - 1 ];
2010-04-21 12:01:32 +00:00
}
return $return ;
}
/** Get supported engines
* @ return array
*/
function engines () {
$return = array ();
2010-10-13 15:53:59 +00:00
foreach ( get_rows ( " SHOW ENGINES " ) as $row ) {
2010-04-21 12:01:32 +00:00
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
2011-07-27 18:06:50 +00:00
* @ return array array ( $name => $type )
2010-04-21 12:01:32 +00:00
*/
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
2013-04-27 03:04:57 +00:00
* @ param bool return only " Name " , " Engine " and " Comment " fields
2011-07-29 14:41:52 +00:00
* @ 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
2010-04-21 12:01:32 +00:00
*/
2013-04-27 03:04:57 +00:00
function table_status ( $name = " " , $fast = false ) {
global $connection ;
2010-04-21 12:01:32 +00:00
$return = array ();
2013-04-27 03:04:57 +00:00
foreach ( get_rows ( $fast && $connection -> server_info >= 5
2013-05-28 18:12:25 +00:00
? " 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 " )
2013-04-27 03:04:57 +00:00
: " SHOW TABLE STATUS " . ( $name != " " ? " LIKE " . q ( addcslashes ( $name , " %_ \\ " )) : " " )
) as $row ) {
2010-04-21 12:01:32 +00:00
if ( $row [ " Engine " ] == " InnoDB " ) {
// ignore internal comment, unnecessary since MySQL 5.1.21
$row [ " Comment " ] = preg_replace ( '~(?:(.+); )?InnoDB free: .*~' , '\\1' , $row [ " Comment " ]);
}
2013-05-08 18:53:53 +00:00
if ( ! isset ( $row [ " Engine " ])) {
2010-04-21 12:01:32 +00:00
$row [ " Comment " ] = " " ;
}
if ( $name != " " ) {
return $row ;
}
$return [ $row [ " Name " ]] = $row ;
}
return $return ;
}
2010-05-27 11:31:08 +00:00
/** Find out whether the identifier is view
* @ param array
* @ return bool
*/
function is_view ( $table_status ) {
2013-06-24 12:53:48 +00:00
return $table_status [ " Engine " ] === null ;
2010-05-27 11:31:08 +00:00
}
2010-04-21 12:01:32 +00:00
/** Check if table supports foreign keys
* @ param array result of table_status
* @ return bool
*/
function fk_support ( $table_status ) {
2011-05-17 15:20:32 +00:00
return eregi ( " InnoDB|IBMDB2I " , $table_status [ " Engine " ]);
2010-04-21 12:01:32 +00:00
}
/** 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 " => ))
*/
2010-11-11 09:47:32 +00:00
function fields ( $table ) {
2010-04-21 12:01:32 +00:00
$return = array ();
2010-10-13 15:53:59 +00:00
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 ]),
2013-01-10 06:57:13 +00:00
" default " => ( $row [ " Default " ] != " " || ereg ( " char|set " , $match [ 1 ]) ? $row [ " Default " ] : null ),
2010-10-13 15:53:59 +00:00
" 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 " ),
);
2010-04-21 12:01:32 +00:00
}
return $return ;
}
/** Get table indexes
* @ param string
* @ param string Min_DB to use
2013-07-03 17:32:31 +00:00
* @ return array array ( $key_name => array ( " type " => , " columns " => array (), " lengths " => array (), " descs " => array ()))
2010-04-21 12:01:32 +00:00
*/
function indexes ( $table , $connection2 = null ) {
$return = array ();
2010-10-13 15:53:59 +00:00
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 " ];
2013-06-25 16:42:47 +00:00
$return [ $row [ " Key_name " ]][ " descs " ][] = null ;
2010-04-21 12:01:32 +00:00
}
return $return ;
}
/** Get foreign keys in table
* @ param string
2011-07-12 14:03:39 +00:00
* @ return array array ( $name => array ( " db " => , " ns " => , " table " => , " source " => array (), " target " => array (), " on_delete " => , " on_update " => ))
2010-04-21 12:01:32 +00:00
*/
function foreign_keys ( $table ) {
global $connection , $on_actions ;
static $pattern = '`(?:[^`]|``)+`' ;
$return = array ();
2010-05-11 14:45:04 +00:00
$create_table = $connection -> result ( " SHOW CREATE TABLE " . table ( $table ), 1 );
2010-04-21 12:01:32 +00:00
if ( $create_table ) {
2011-08-02 15:46:13 +00:00
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 );
2010-04-21 12:01:32 +00:00
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 ]),
2011-08-29 11:21:02 +00:00
" on_delete " => ( $match [ 6 ] ? $match [ 6 ] : " RESTRICT " ),
" on_update " => ( $match [ 7 ] ? $match [ 7 ] : " RESTRICT " ),
2010-04-21 12:01:32 +00:00
);
}
}
return $return ;
}
/** Get view SELECT
* @ param string
* @ return array array ( " select " => )
*/
function view ( $name ) {
global $connection ;
2010-05-11 14:45:04 +00:00
return array ( " select " => preg_replace ( '~^(?:[^`]|`[^`]*`)*\\s+AS\\s+~isU' , '' , $connection -> result ( " SHOW CREATE VIEW " . table ( $name ), 1 )));
2010-04-21 12:01:32 +00:00
}
/** Get sorted grouped list of collations
* @ return array
*/
function collations () {
$return = array ();
2010-10-13 15:53:59 +00:00
foreach ( get_rows ( " SHOW COLLATION " ) as $row ) {
2011-02-25 09:49:19 +00:00
if ( $row [ " Default " ]) {
$return [ $row [ " Charset " ]][ - 1 ] = $row [ " Collation " ];
} else {
$return [ $row [ " Charset " ]][] = $row [ " Collation " ];
}
2010-04-21 12:01:32 +00:00
}
ksort ( $return );
foreach ( $return as $key => $val ) {
2011-02-25 09:49:19 +00:00
asort ( $return [ $key ]);
2010-04-21 12:01:32 +00:00
}
return $return ;
}
/** Find out if database is information_schema
* @ param string
* @ return bool
*/
function information_schema ( $db ) {
global $connection ;
2012-08-24 05:21:53 +00:00
return ( $connection -> server_info >= 5 && $db == " information_schema " )
|| ( $connection -> server_info >= 5.5 && $db == " performance_schema " );
2010-04-21 12:01:32 +00:00
}
/** 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 ));
}
2012-04-16 06:37:05 +00:00
/** Get line of error
* @ return int 0 for first line
*/
function error_line () {
global $connection ;
if ( ereg ( ' at line ([0-9]+)$' , $connection -> error , $regs )) {
return $regs [ 1 ] - 1 ;
}
}
2010-04-22 23:02:28 +00:00
/** Create database
* @ param string
2012-09-16 13:43:55 +00:00
* @ param string
2010-04-22 23:02:28 +00:00
* @ return string
*/
function create_database ( $db , $collation ) {
2010-10-15 08:58:08 +00:00
set_session ( " dbs " , null );
2010-10-13 16:04:40 +00:00
return queries ( " CREATE DATABASE " . idf_escape ( $db ) . ( $collation ? " COLLATE " . q ( $collation ) : " " ));
2010-04-22 23:02:28 +00:00
}
/** Drop databases
* @ param array
* @ return bool
*/
function drop_databases ( $databases ) {
2013-03-27 16:24:51 +00:00
restart_session ();
2010-10-15 08:58:08 +00:00
set_session ( " dbs " , null );
2010-06-01 20:39:44 +00:00
return apply_queries ( " DROP DATABASE " , $databases , 'idf_escape' );
2010-04-22 23:02:28 +00:00
}
2010-04-21 12:01:32 +00:00
/** Rename database from DB
* @ param string new name
2012-09-16 13:43:55 +00:00
* @ param string
2010-04-21 12:01:32 +00:00
* @ return bool
*/
function rename_database ( $name , $collation ) {
2010-04-22 23:02:28 +00:00
if ( create_database ( $name , $collation )) {
2010-04-21 12:01:32 +00:00
//! move triggers
2010-06-18 14:38:06 +00:00
$rename = array ();
foreach ( tables_list () as $table => $type ) {
$rename [] = table ( $table ) . " TO " . idf_escape ( $name ) . " . " . table ( $table );
2010-04-21 12:01:32 +00:00
}
2010-06-18 14:38:06 +00:00
if ( ! $rename || queries ( " RENAME TABLE " . implode ( " , " , $rename ))) {
2010-04-21 12:01:32 +00:00
queries ( " DROP DATABASE " . idf_escape ( DB ));
2010-06-18 14:38:06 +00:00
return true ;
2010-04-21 12:01:32 +00:00
}
}
2010-06-18 14:38:06 +00:00
return false ;
2010-04-21 12:01:32 +00:00
}
/** 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 ]
2012-07-15 21:38:45 +00:00
? ( $table != " " ? ( $field [ 0 ] != " " ? " CHANGE " . idf_escape ( $field [ 0 ]) : " ADD " ) : " " ) . " " . implode ( $field [ 1 ]) . ( $table != " " ? $field [ 2 ] : " " )
2010-04-21 12:01:32 +00:00
: " DROP " . idf_escape ( $field [ 0 ])
);
}
$alter = array_merge ( $alter , $foreign );
2010-10-13 16:04:40 +00:00
$status = " COMMENT= " . q ( $comment )
. ( $engine ? " ENGINE= " . q ( $engine ) : " " )
. ( $collation ? " COLLATE " . q ( $collation ) : " " )
2010-04-21 12:01:32 +00:00
. ( $auto_increment != " " ? " AUTO_INCREMENT= $auto_increment " : " " )
. $partitioning
;
if ( $table == " " ) {
2010-05-11 14:45:04 +00:00
return queries ( " CREATE TABLE " . table ( $name ) . " ( \n " . implode ( " , \n " , $alter ) . " \n ) $status " );
2010-04-21 12:01:32 +00:00
}
if ( $table != $name ) {
2010-05-11 14:45:04 +00:00
$alter [] = " RENAME TO " . table ( $name );
2010-04-21 12:01:32 +00:00
}
$alter [] = $status ;
2010-05-11 14:45:04 +00:00
return queries ( " ALTER TABLE " . table ( $table ) . " \n " . implode ( " , \n " , $alter ));
2010-04-21 12:01:32 +00:00
}
/** Run commands to alter indexes
* @ param string escaped table name
2011-07-13 13:13:00 +00:00
* @ param array of array ( " index type " , " name " , " (columns definition) " ) or array ( " index type " , " name " , " DROP " )
2010-04-21 12:01:32 +00:00
* @ return bool
*/
function alter_indexes ( $table , $alter ) {
foreach ( $alter as $key => $val ) {
2011-07-13 13:13:00 +00:00
$alter [ $key ] = ( $val [ 2 ] == " DROP "
? " \n DROP INDEX " . idf_escape ( $val [ 1 ])
: " \n ADD $val[0] " . ( $val [ 0 ] == " PRIMARY " ? " KEY " : " " ) . ( $val [ 1 ] != " " ? idf_escape ( $val [ 1 ]) . " " : " " ) . $val [ 2 ]
);
2010-04-21 12:01:32 +00:00
}
2010-05-11 14:45:04 +00:00
return queries ( " ALTER TABLE " . table ( $table ) . implode ( " , " , $alter ));
2010-04-21 12:01:32 +00:00
}
/** Run commands to truncate tables
* @ param array
* @ return bool
*/
function truncate_tables ( $tables ) {
2010-05-17 16:18:32 +00:00
return apply_queries ( " TRUNCATE TABLE " , $tables );
2010-04-21 12:01:32 +00:00
}
/** Drop views
* @ param array
* @ return bool
*/
function drop_views ( $views ) {
2010-05-11 14:45:04 +00:00
return queries ( " DROP VIEW " . implode ( " , " , array_map ( 'table' , $views )));
2010-04-21 12:01:32 +00:00
}
/** Drop tables
* @ param array
* @ return bool
*/
function drop_tables ( $tables ) {
2010-05-11 14:45:04 +00:00
return queries ( " DROP TABLE " . implode ( " , " , array_map ( 'table' , $tables )));
2010-04-21 12:01:32 +00:00
}
2010-05-05 20:11:24 +00:00
/** Move tables to other schema
* @ param array
2011-02-01 13:12:22 +00:00
* @ param array
2010-05-05 20:11:24 +00:00
* @ param string
* @ return bool
*/
function move_tables ( $tables , $views , $target ) {
$rename = array ();
foreach ( array_merge ( $tables , $views ) as $table ) { // views will report SQL error
2010-05-11 14:45:04 +00:00
$rename [] = table ( $table ) . " TO " . idf_escape ( $target ) . " . " . table ( $table );
2010-05-05 20:11:24 +00:00
}
return queries ( " RENAME TABLE " . implode ( " , " , $rename ));
//! move triggers
}
2011-02-01 13:12:22 +00:00
/** Copy tables to other schema
* @ param array
* @ param array
* @ param string
* @ return bool
*/
function copy_tables ( $tables , $views , $target ) {
2011-07-12 13:14:15 +00:00
queries ( " SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO' " );
2011-02-01 13:12:22 +00:00
foreach ( $tables as $table ) {
$name = ( $target == DB ? table ( " copy_ $table " ) : idf_escape ( $target ) . " . " . table ( $table ));
if ( ! queries ( " DROP 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 ;
}
2010-04-21 12:01:32 +00:00
/** Get information about trigger
* @ param string trigger name
2012-07-15 19:04:04 +00:00
* @ return array array ( " Trigger " => , " Timing " => , " Event " => , " Type " => , " Statement " => )
2010-04-21 12:01:32 +00:00
*/
function trigger ( $name ) {
2011-08-08 16:18:16 +00:00
if ( $name == " " ) {
return array ();
}
2010-10-13 16:04:40 +00:00
$rows = get_rows ( " SHOW TRIGGERS WHERE `Trigger` = " . q ( $name ));
2010-10-13 15:53:59 +00:00
return reset ( $rows );
2010-04-21 12:01:32 +00:00
}
/** Get defined triggers
* @ param string
* @ return array array ( $name => array ( $timing , $event ))
*/
function triggers ( $table ) {
$return = array ();
2013-04-27 02:24:07 +00:00
foreach ( get_rows ( " SHOW TRIGGERS LIKE " . q ( addcslashes ( $table , " %_ \\ " ))) as $row ) {
2010-04-21 12:01:32 +00:00
$return [ $row [ " Trigger " ]] = array ( $row [ " Timing " ], $row [ " Event " ]);
}
return $return ;
}
2010-04-22 23:02:28 +00:00
/** Get trigger options
* @ return array ( " Timing " => array (), " Type " => array ())
*/
2010-04-22 15:53:42 +00:00
function trigger_options () {
return array (
" Timing " => array ( " BEFORE " , " AFTER " ),
// Event is always INSERT, UPDATE, DELETE
" Type " => array ( " FOR EACH ROW " ),
);
}
2010-04-28 00:11:39 +00:00
/** Get information about stored routine
* @ param string
2011-06-03 13:45:33 +00:00
* @ param string " FUNCTION " or " PROCEDURE "
* @ return array ( " fields " => array ( " field " => , " type " => , " length " => , " unsigned " => , " inout " => , " collation " => ), " returns " => , " definition " => , " language " => )
2010-04-28 00:11:39 +00:00
*/
function routine ( $name , $type ) {
global $connection , $enum_length , $inout , $types ;
2010-05-25 11:29:53 +00:00
$aliases = array ( " bool " , " boolean " , " integer " , " double precision " , " real " , " dec " , " numeric " , " fixed " , " national char " , " national varchar " );
2012-06-29 23:41:12 +00:00
$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]+)[' \" ]?)? " ;
2011-07-11 14:35:17 +00:00
$pattern = " \\ s*( " . ( $type == " FUNCTION " ? " " : $inout ) . " )? \\ s*(?:`((?:[^`]|``)*)` \\ s*| \\ b( \\ S+) \\ s+) $type_pattern " ;
2010-04-28 00:11:39 +00:00
$create = $connection -> result ( " SHOW CREATE $type " . idf_escape ( $name ), 2 );
2012-05-14 00:19:53 +00:00
preg_match ( " ~ \\ (((?: $pattern\\s *,?)*) \\ ) \\ s* " . ( $type == " FUNCTION " ? " RETURNS \\ s+ $type_pattern\\s + " : " " ) . " (.*)~is " , $create , $match );
2010-04-28 00:11:39 +00:00
$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 ,
2010-05-25 11:29:53 +00:00
" type " => strtolower ( $param [ 5 ]),
2010-04-28 00:11:39 +00:00
" length " => preg_replace_callback ( " ~ $enum_length ~s " , 'normalize_enum' , $param [ 6 ]),
" unsigned " => strtolower ( preg_replace ( '~\\s+~' , ' ' , trim ( " $param[8] $param[7] " ))),
2012-12-12 18:58:13 +00:00
" null " => 1 ,
2010-04-28 00:11:39 +00:00
" 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 ],
2011-06-03 13:45:33 +00:00
" language " => " SQL " , // available in information_schema.ROUTINES.PARAMETER_STYLE
2010-04-28 00:11:39 +00:00
);
}
2011-05-31 05:43:08 +00:00
/** Get list of routines
* @ return array ( " ROUTINE_TYPE " => , " ROUTINE_NAME " => , " DTD_IDENTIFIER " => )
*/
2010-04-28 00:11:39 +00:00
function routines () {
2013-04-27 20:04:54 +00:00
return get_rows ( " SELECT ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . q ( DB ));
2010-04-28 00:11:39 +00:00
}
2011-06-03 13:45:33 +00:00
/** Get list of available routine languages
* @ return array
*/
function routine_languages () {
2011-06-04 01:37:43 +00:00
return array (); // "SQL" not required
2011-06-03 13:45:33 +00:00
}
2010-04-23 23:49:21 +00:00
/** Begin transaction
* @ return bool
*/
function begin () {
return queries ( " BEGIN " );
}
2010-04-23 09:03:27 +00:00
/** Insert data into table
* @ param string
* @ param array
* @ return bool
*/
function insert_into ( $table , $set ) {
2010-05-11 14:45:04 +00:00
return queries ( " INSERT INTO " . table ( $table ) . " ( " . implode ( " , " , array_keys ( $set )) . " ) \n VALUES ( " . implode ( " , " , $set ) . " ) " );
2010-04-23 09:03:27 +00:00
}
2010-05-27 14:10:17 +00:00
/** Insert or update data in the table
* @ param string
* @ param array
2010-07-22 15:57:26 +00:00
* @ param array columns in keys
2010-05-27 14:10:17 +00:00
* @ return bool
*/
2010-07-22 15:57:26 +00:00
function insert_update ( $table , $set , $primary ) {
2010-05-27 14:10:17 +00:00
foreach ( $set as $key => $val ) {
$set [ $key ] = " $key = $val " ;
}
$update = implode ( " , " , $set );
return queries ( " INSERT INTO " . table ( $table ) . " SET $update ON DUPLICATE KEY UPDATE $update " );
}
2010-05-12 16:07:46 +00:00
/** Get last auto increment ID
* @ return string
*/
function last_id () {
global $connection ;
return $connection -> result ( " SELECT LAST_INSERT_ID() " ); // mysql_insert_id() truncates bigint
}
2010-04-21 12:01:32 +00:00
/** Explain select
* @ param Min_DB
* @ param string
* @ return Min_Result
*/
function explain ( $connection , $query ) {
2013-05-11 15:02:28 +00:00
return $connection -> query ( " EXPLAIN " . ( $connection -> server_info >= 5.1 ? " PARTITIONS " : " " ) . $query );
2010-04-21 12:01:32 +00:00
}
2011-07-29 15:08:06 +00:00
/** 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 " ]);
}
2010-05-21 14:07:22 +00:00
/** Get user defined types
* @ return array
*/
function types () {
return array ();
}
2010-05-05 16:30:55 +00:00
/** 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 ;
}
2010-04-21 12:01:32 +00:00
/** Get SQL command to create table
* @ param string
2010-06-03 12:15:23 +00:00
* @ param bool
2010-04-21 12:01:32 +00:00
* @ return string
*/
2010-06-03 12:15:23 +00:00
function create_sql ( $table , $auto_increment ) {
2010-04-21 12:01:32 +00:00
global $connection ;
2010-06-03 12:15:23 +00:00
$return = $connection -> result ( " SHOW CREATE TABLE " . table ( $table ), 1 );
if ( ! $auto_increment ) {
2010-10-22 22:02:24 +00:00
$return = preg_replace ( '~ AUTO_INCREMENT=\\d+~' , '' , $return ); //! skip comments
2010-06-03 12:15:23 +00:00
}
return $return ;
2010-04-21 12:01:32 +00:00
}
2010-05-27 14:10:17 +00:00
/** Get SQL command to truncate table
* @ param string
* @ return string
*/
function truncate_sql ( $table ) {
return " TRUNCATE " . table ( $table );
}
2010-04-21 22:37:16 +00:00
/** Get SQL command to change database
* @ param string
* @ return string
*/
function use_sql ( $database ) {
return " USE " . idf_escape ( $database );
}
2010-05-05 16:28:37 +00:00
/** Get SQL commands to create triggers
* @ param string
* @ param string
* @ return string
*/
function trigger_sql ( $table , $style ) {
$return = " " ;
2013-04-27 02:24:07 +00:00
foreach ( get_rows ( " SHOW TRIGGERS LIKE " . q ( addcslashes ( $table , " %_ \\ " )), null , " -- " ) as $row ) {
2010-10-13 15:53:59 +00:00
$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 " ;
2010-05-05 16:28:37 +00:00
}
return $return ;
}
2010-04-21 22:37:16 +00:00
/** Get server variables
* @ return array ( $name => $value )
*/
2010-04-21 15:09:52 +00:00
function show_variables () {
return get_key_vals ( " SHOW VARIABLES " );
}
2011-05-11 09:48:51 +00:00
/** Get process list
* @ return array ( $row )
*/
2012-08-20 04:55:00 +00:00
function process_list () {
return get_rows ( " SHOW FULL PROCESSLIST " );
2011-05-11 09:48:51 +00:00
}
2010-04-21 22:37:16 +00:00
/** Get status variables
* @ return array ( $name => $value )
*/
2010-04-21 15:09:52 +00:00
function show_status () {
return get_key_vals ( " SHOW STATUS " );
}
2012-09-09 05:56:34 +00:00
/** Convert field in select and edit
* @ param array one element from fields ()
* @ return string
*/
function convert_field ( $field ) {
if ( ereg ( " binary " , $field [ " type " ])) {
return " HEX( " . idf_escape ( $field [ " field " ]) . " ) " ;
}
2013-04-27 03:04:57 +00:00
if ( $field [ " type " ] == " bit " ) {
return " BIN( " . idf_escape ( $field [ " field " ]) . " + 0) " ; // + 0 is required outside MySQLnd
}
2012-09-09 05:56:34 +00:00
if ( ereg ( " 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 ( ereg ( " binary " , $field [ " type " ])) {
2012-12-12 05:25:56 +00:00
$return = " UNHEX( $return ) " ;
2012-09-09 05:56:34 +00:00
}
2013-04-27 03:04:57 +00:00
if ( $field [ " type " ] == " bit " ) {
2013-06-05 02:40:17 +00:00
$return = " CONV( $return , 2, 10) + 0 " ;
2013-04-27 03:04:57 +00:00
}
2012-09-09 05:56:34 +00:00
if ( ereg ( " geometry|point|linestring|polygon " , $field [ " type " ])) {
$return = " GeomFromText( $return ) " ;
}
return $return ;
}
2010-04-21 12:01:32 +00:00
/** Check whether a feature is supported
2011-05-11 09:48:51 +00:00
* @ param string " comment " , " copy " , " drop_col " , " dump " , " event " , " kill " , " partitioning " , " privileges " , " procedure " , " processlist " , " routine " , " scheme " , " sequence " , " status " , " trigger " , " type " , " variables " , " view "
2010-04-21 12:01:32 +00:00
* @ return bool
*/
function support ( $feature ) {
global $connection ;
2010-05-21 14:07:22 +00:00
return ! ereg ( " scheme|sequence|type " . ( $connection -> server_info < 5.1 ? " |event|partitioning " . ( $connection -> server_info < 5 ? " |view|routine|trigger " : " " ) : " " ), $feature );
2010-04-21 12:01:32 +00:00
}
2010-05-07 13:44:22 +00:00
$jush = " sql " ; ///< @var string JUSH identifier
2010-04-21 12:01:32 +00:00
$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 ),
2012-09-09 05:56:34 +00:00
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 ),
2010-04-21 12:01:32 +00:00
) as $key => $val ) {
$types += $val ;
$structured_types [ $key ] = array_keys ( $val );
}
$unsigned = array ( " unsigned " , " zerofill " , " unsigned zerofill " ); ///< @var array number variants
2013-04-26 19:04:28 +00:00
$operators = array ( " = " , " < " , " > " , " <= " , " >= " , " != " , " LIKE " , " LIKE %% " , " REGEXP " , " IN " , " IS NULL " , " NOT LIKE " , " NOT REGEXP " , " NOT IN " , " IS NOT NULL " , " SQL " ); ///< @var array operators used in select
2012-09-09 05:39:15 +00:00
$functions = array ( " char_length " , " date " , " from_unixtime " , " lower " , " round " , " sec_to_time " , " time_to_sec " , " upper " ); ///< @var array functions used in select
2010-04-21 12:01:32 +00:00
$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
2012-09-09 05:39:15 +00:00
" binary " => " md5/sha1 " ,
2010-04-21 12:01:32 +00:00
" date|time " => " now " ,
), array (
2012-09-09 05:56:34 +00:00
" (^|[^o])int|float|double|decimal " => " +/- " , // not point
2010-04-21 12:01:32 +00:00
" date " => " + interval/- interval " ,
" time " => " addtime/subtime " ,
" char|text " => " concat " ,
)
);
}