2010-04-21 12:01:32 +00:00
< ? php
2010-10-29 13:24:06 +00:00
$drivers [ " pgsql " ] = " PostgreSQL " ;
2010-04-21 12:01:32 +00:00
if ( isset ( $_GET [ " pgsql " ])) {
2010-10-29 13:24:06 +00:00
$possible_drivers = array ( " PgSQL " , " PDO_PgSQL " );
2010-04-21 12:01:32 +00:00
define ( " DRIVER " , " pgsql " );
if ( extension_loaded ( " pgsql " )) {
class Min_DB {
var $extension = " PgSQL " , $_link , $_result , $_string , $_database = true , $server_info , $affected_rows , $error ;
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function _error ( $errno , $error ) {
if ( ini_bool ( " html_errors " )) {
$error = html_entity_decode ( strip_tags ( $error ));
}
2013-07-24 23:26:41 +00:00
$error = preg_replace ( '~^[^:]*: ~' , '' , $error );
2010-04-21 12:01:32 +00:00
$this -> error = $error ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function connect ( $server , $username , $password ) {
2011-07-19 15:58:44 +00:00
global $adminer ;
$db = $adminer -> database ();
2010-04-21 12:01:32 +00:00
set_error_handler ( array ( $this , '_error' ));
$this -> _string = " host=' " . str_replace ( " : " , " ' port=' " , addcslashes ( $server , " ' \\ " )) . " ' user=' " . addcslashes ( $username , " ' \\ " ) . " ' password=' " . addcslashes ( $password , " ' \\ " ) . " ' " ;
2012-02-24 05:47:26 +00:00
$this -> _link = @ pg_connect ( " $this->_string dbname=' " . ( $db != " " ? addcslashes ( $db , " ' \\ " ) : " postgres " ) . " ' " , PGSQL_CONNECT_FORCE_NEW );
2011-07-19 15:58:44 +00:00
if ( ! $this -> _link && $db != " " ) {
2010-04-21 12:01:32 +00:00
// try to connect directly with database for performance
$this -> _database = false ;
2012-02-24 05:47:26 +00:00
$this -> _link = @ pg_connect ( " $this->_string dbname='postgres' " , PGSQL_CONNECT_FORCE_NEW );
2010-04-21 12:01:32 +00:00
}
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 ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function quote ( $string ) {
return " ' " . pg_escape_string ( $this -> _link , $string ) . " ' " ; //! bytea
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function select_db ( $database ) {
2011-07-19 15:58:44 +00:00
global $adminer ;
if ( $database == $adminer -> database ()) {
2010-04-21 12:01:32 +00:00
return $this -> _database ;
}
2010-08-03 13:08:14 +00:00
$return = @ pg_connect ( " $this->_string dbname=' " . addcslashes ( $database , " ' \\ " ) . " ' " , PGSQL_CONNECT_FORCE_NEW );
2010-05-14 13:51:54 +00:00
if ( $return ) {
$this -> _link = $return ;
2010-04-21 12:01:32 +00:00
}
2010-05-14 13:51:54 +00:00
return $return ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:02:28 +00:00
function close () {
2012-02-24 05:47:26 +00:00
$this -> _link = @ pg_connect ( " $this->_string dbname='postgres' " );
2010-04-22 23:02:28 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function query ( $query , $unbuffered = false ) {
$result = @ pg_query ( $this -> _link , $query );
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
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 );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function multi_query ( $query ) {
return $this -> _result = $this -> query ( $query );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function store_result () {
return $this -> _result ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function next_result () {
// PgSQL extension doesn't support multiple results
return false ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
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 pg_fetch_result ( $result -> _result , 0 , $field );
}
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
class Min_Result {
var $_result , $_offset = 0 , $num_rows ;
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function Min_Result ( $result ) {
$this -> _result = $result ;
$this -> num_rows = pg_num_rows ( $result );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function fetch_assoc () {
return pg_fetch_assoc ( $this -> _result );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function fetch_row () {
return pg_fetch_row ( $this -> _result );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function fetch_field () {
$column = $this -> _offset ++ ;
2010-05-14 13:51:54 +00:00
$return = new stdClass ;
2010-04-21 22:22:23 +00:00
if ( function_exists ( 'pg_field_table' )) {
2010-05-14 13:51:54 +00:00
$return -> orgtable = pg_field_table ( $this -> _result , $column );
2010-04-21 22:22:23 +00:00
}
2010-05-14 13:51:54 +00:00
$return -> name = pg_field_name ( $this -> _result , $column );
$return -> orgname = $return -> name ;
$return -> type = pg_field_type ( $this -> _result , $column );
$return -> charsetnr = ( $return -> type == " bytea " ? 63 : 0 ); // 63 - binary
return $return ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function __destruct () {
pg_free_result ( $this -> _result );
}
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
} elseif ( extension_loaded ( " pdo_pgsql " )) {
class Min_DB extends Min_PDO {
var $extension = " PDO_PgSQL " ;
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function connect ( $server , $username , $password ) {
2011-07-19 15:58:44 +00:00
global $adminer ;
$db = $adminer -> database ();
2010-04-21 12:01:32 +00:00
$string = " pgsql:host=' " . str_replace ( " : " , " ' port=' " , addcslashes ( $server , " ' \\ " )) . " ' options='-c client_encoding=utf8' " ;
2012-02-24 05:47:26 +00:00
$this -> dsn ( " $string dbname=' " . ( $db != " " ? addcslashes ( $db , " ' \\ " ) : " postgres " ) . " ' " , $username , $password );
2010-04-21 12:01:32 +00:00
//! connect without DB in case of an error
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function select_db ( $database ) {
2011-07-19 15:58:44 +00:00
global $adminer ;
return ( $adminer -> database () == $database );
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:02:28 +00:00
function close () {
}
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
}
2013-07-05 16:04:06 +00:00
class Min_Driver extends Min_SQL {
2013-07-24 23:26:41 +00:00
2013-07-09 18:34:12 +00:00
function insertUpdate ( $table , $rows , $primary ) {
2013-07-05 16:04:06 +00:00
global $connection ;
2013-07-09 18:34:12 +00:00
foreach ( $rows as $set ) {
$update = array ();
$where = array ();
foreach ( $set as $key => $val ) {
$update [] = " $key = $val " ;
if ( isset ( $primary [ idf_unescape ( $key )])) {
$where [] = " $key = $val " ;
}
}
if ( ! (( $where && queries ( " UPDATE " . table ( $table ) . " SET " . implode ( " , " , $update ) . " WHERE " . implode ( " AND " , $where )) && $connection -> affected_rows )
|| queries ( " INSERT INTO " . table ( $table ) . " ( " . implode ( " , " , array_keys ( $set )) . " ) VALUES ( " . implode ( " , " , $set ) . " ) " )
)) {
return false ;
2013-07-05 16:04:06 +00:00
}
}
2013-07-09 18:34:12 +00:00
return true ;
2013-07-05 16:04:06 +00:00
}
2013-07-24 23:26:41 +00:00
2013-07-05 16:04:06 +00:00
}
2010-04-21 12:01:32 +00:00
function idf_escape ( $idf ) {
return '"' . str_replace ( '"' , '""' , $idf ) . '"' ;
}
2010-05-11 14:45:04 +00:00
function table ( $idf ) {
return idf_escape ( $idf );
}
2010-04-21 12:01:32 +00:00
function connect () {
global $adminer ;
$connection = new Min_DB ;
$credentials = $adminer -> credentials ();
if ( $connection -> connect ( $credentials [ 0 ], $credentials [ 1 ], $credentials [ 2 ])) {
2011-08-23 12:23:48 +00:00
if ( $connection -> server_info >= 9 ) {
$connection -> query ( " SET application_name = 'Adminer' " );
}
2010-04-21 12:01:32 +00:00
return $connection ;
}
return $connection -> error ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function get_databases () {
2011-07-29 11:34:38 +00:00
return get_vals ( " SELECT datname FROM pg_database ORDER BY datname " );
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
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
}
2010-05-14 13:51:54 +00:00
function limit1 ( $query , $where ) {
return " $query $where " ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function db_collation ( $db , $collations ) {
global $connection ;
return $connection -> result ( " SHOW LC_COLLATE " ); //! respect $db
}
function engines () {
return array ();
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function logged_user () {
global $connection ;
return $connection -> result ( " SELECT user " );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function tables_list () {
2010-04-21 22:22:23 +00:00
return get_key_vals ( " SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = current_schema() ORDER BY table_name " );
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function count_tables ( $databases ) {
return array (); // would require reconnect
}
function table_status ( $name = " " ) {
$return = array ();
2013-05-24 04:05:45 +00:00
foreach ( get_rows ( " SELECT relname AS \" Name \" , CASE relkind WHEN 'r' THEN 'table' ELSE 'view' END AS \" Engine \" , pg_relation_size(oid) AS \" Data_length \" , pg_total_relation_size(oid) - pg_relation_size(oid) AS \" Index_length \" , obj_description(oid, 'pg_class') AS \" Comment \" , relhasoids::int AS \" Oid \" , reltuples as \" Rows \"
2010-05-21 13:07:59 +00:00
FROM pg_class
2010-04-21 22:22:23 +00:00
WHERE relkind IN ( 'r' , 'v' )
2013-05-28 18:12:25 +00:00
AND relnamespace = ( SELECT oid FROM pg_namespace WHERE nspname = current_schema ())
" . ( $name != " " ? " AND relname = " . q( $name ) : " ORDER BY relname " )
2010-10-13 15:53:59 +00:00
) as $row ) { //! Index_length, Auto_increment
2010-04-21 12:01:32 +00:00
$return [ $row [ " Name " ]] = $row ;
}
return ( $name != " " ? $return [ $name ] : $return );
}
2013-07-24 23:26:41 +00:00
2010-05-27 11:31:08 +00:00
function is_view ( $table_status ) {
return $table_status [ " Engine " ] == " view " ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function fk_support ( $table_status ) {
return true ;
}
2013-07-24 23:26:41 +00:00
2010-11-11 09:47:32 +00:00
function fields ( $table ) {
2010-04-21 12:01:32 +00:00
$return = array ();
2013-05-30 00:24:27 +00:00
$aliases = array (
'timestamp without time zone' => 'timestamp' ,
'timestamp with time zone' => 'timestamptz' ,
);
2013-05-13 15:39:10 +00:00
foreach ( get_rows ( " SELECT a.attname AS field, format_type(a.atttypid, a.atttypmod) AS full_type, d.adsrc AS default, a.attnotnull::int, col_description(c.oid, a.attnum) AS comment
2010-05-21 13:07:59 +00:00
FROM pg_class c
JOIN pg_namespace n ON c . relnamespace = n . oid
JOIN pg_attribute a ON c . oid = a . attrelid
LEFT JOIN pg_attrdef d ON c . oid = d . adrelid AND a . attnum = d . adnum
2010-10-13 16:04:40 +00:00
WHERE c . relname = " . q( $table ) . "
2010-05-21 13:07:59 +00:00
AND n . nspname = current_schema ()
2010-05-21 14:23:44 +00:00
AND NOT a . attisdropped
2010-11-11 09:47:32 +00:00
AND a . attnum > 0
ORDER BY a . attnum "
2010-10-13 15:53:59 +00:00
) as $row ) {
//! collation, primary
2013-08-06 22:48:45 +00:00
preg_match ( '~([^([]+)(\((.*)\))?((\[[0-9]*])*)$~' , $row [ " full_type " ], $match );
list (, $type , $length , $row [ " length " ], $array ) = $match ;
$row [ " length " ] .= $array ;
2013-05-30 00:24:27 +00:00
$row [ " type " ] = ( $aliases [ $type ] ? $aliases [ $type ] : $type );
2013-08-06 22:48:45 +00:00
$row [ " full_type " ] = $row [ " type " ] . $length . $array ;
2013-05-13 15:39:10 +00:00
$row [ " null " ] = ! $row [ " attnotnull " ];
2013-07-24 23:26:41 +00:00
$row [ " auto_increment " ] = preg_match ( '~^nextval\\(~i' , $row [ " default " ]);
2010-10-13 15:53:59 +00:00
$row [ " privileges " ] = array ( " insert " => 1 , " select " => 1 , " update " => 1 );
2013-07-02 16:20:06 +00:00
if ( preg_match ( '~(.+)::[^)]+(.*)~' , $row [ " default " ], $match )) {
$row [ " default " ] = ( $match [ 1 ][ 0 ] == " ' " ? idf_unescape ( $match [ 1 ]) : $match [ 1 ]) . $match [ 2 ];
2011-05-18 14:52:23 +00:00
}
2010-10-13 15:53:59 +00:00
$return [ $row [ " field " ]] = $row ;
2010-04-21 12:01:32 +00:00
}
return $return ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function indexes ( $table , $connection2 = null ) {
global $connection ;
if ( ! is_object ( $connection2 )) {
$connection2 = $connection ;
}
$return = array ();
2012-06-29 21:59:04 +00:00
$table_oid = $connection2 -> result ( " SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q ( $table ));
2010-04-21 12:01:32 +00:00
$columns = get_key_vals ( " SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0 " , $connection2 );
2013-06-25 16:42:47 +00:00
foreach ( get_rows ( " SELECT relname, indisunique::int, indisprimary::int, indkey, indoption FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid " , $connection2 ) as $row ) {
$relname = $row [ " relname " ];
$return [ $relname ][ " type " ] = ( $row [ " indisprimary " ] ? " PRIMARY " : ( $row [ " indisunique " ] ? " UNIQUE " : " INDEX " ));
$return [ $relname ][ " columns " ] = array ();
2010-04-21 12:01:32 +00:00
foreach ( explode ( " " , $row [ " indkey " ]) as $indkey ) {
2013-06-25 16:42:47 +00:00
$return [ $relname ][ " columns " ][] = $columns [ $indkey ];
2010-04-21 12:01:32 +00:00
}
2013-06-25 16:42:47 +00:00
$return [ $relname ][ " descs " ] = array ();
foreach ( explode ( " " , $row [ " indoption " ]) as $indoption ) {
2013-06-25 22:01:38 +00:00
$return [ $relname ][ " descs " ][] = ( $indoption & 1 ? '1' : null ); // 1 - INDOPTION_DESC
2013-06-25 16:42:47 +00:00
}
$return [ $relname ][ " lengths " ] = array ();
2010-04-21 12:01:32 +00:00
}
return $return ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function foreign_keys ( $table ) {
2011-08-02 15:34:21 +00:00
global $on_actions ;
2010-04-21 12:01:32 +00:00
$return = array ();
2011-08-02 15:36:12 +00:00
foreach ( get_rows ( " SELECT conname, pg_get_constraintdef(oid) AS definition
2011-08-01 08:47:45 +00:00
FROM pg_constraint
2011-12-22 05:59:24 +00:00
WHERE conrelid = ( SELECT pc . oid FROM pg_class AS pc INNER JOIN pg_namespace AS pn ON ( pn . oid = pc . relnamespace ) WHERE pc . relname = " . q( $table ) . " AND pn . nspname = current_schema ())
2011-08-01 08:47:45 +00:00
AND contype = 'f' :: char
ORDER BY conkey , conname " ) as $row ) {
if ( preg_match ( '~FOREIGN KEY\s*\((.+)\)\s*REFERENCES (.+)\((.+)\)(.*)$~iA' , $row [ 'definition' ], $match )) {
$row [ 'source' ] = array_map ( 'trim' , explode ( ',' , $match [ 1 ]));
$row [ 'table' ] = $match [ 2 ];
2011-08-02 15:36:12 +00:00
if ( preg_match ( '~(.+)\.(.+)~' , $match [ 2 ], $match2 )) {
$row [ 'ns' ] = $match2 [ 1 ];
$row [ 'table' ] = $match2 [ 2 ];
}
2011-08-01 08:47:45 +00:00
$row [ 'target' ] = array_map ( 'trim' , explode ( ',' , $match [ 3 ]));
2011-08-29 11:21:02 +00:00
$row [ 'on_delete' ] = ( preg_match ( " ~ON DELETE ( $on_actions )~ " , $match [ 4 ], $match2 ) ? $match2 [ 1 ] : 'NO ACTION' );
$row [ 'on_update' ] = ( preg_match ( " ~ON UPDATE ( $on_actions )~ " , $match [ 4 ], $match2 ) ? $match2 [ 1 ] : 'NO ACTION' );
2011-08-01 08:47:45 +00:00
$return [ $row [ 'conname' ]] = $row ;
2010-04-21 12:01:32 +00:00
}
}
return $return ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function view ( $name ) {
global $connection ;
2010-10-13 16:04:40 +00:00
return array ( " select " => $connection -> result ( " SELECT pg_get_viewdef( " . q ( $name ) . " ) " ));
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function collations () {
//! supported in CREATE DATABASE
return array ();
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function information_schema ( $db ) {
return ( $db == " information_schema " );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
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 );
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:02:28 +00:00
function create_database ( $db , $collation ) {
return queries ( " CREATE DATABASE " . idf_escape ( $db ) . ( $collation ? " ENCODING " . idf_escape ( $collation ) : " " ));
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:02:28 +00:00
function drop_databases ( $databases ) {
global $connection ;
$connection -> close ();
2010-05-17 16:18:32 +00:00
return apply_queries ( " DROP DATABASE " , $databases , 'idf_escape' );
2010-04-22 23:02:28 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function rename_database ( $name , $collation ) {
//! current database cannot be renamed
return queries ( " ALTER DATABASE " . idf_escape ( DB ) . " RENAME TO " . idf_escape ( $name ));
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function auto_increment () {
2010-05-05 20:42:25 +00:00
return " " ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function alter_table ( $table , $name , $fields , $foreign , $comment , $engine , $collation , $auto_increment , $partitioning ) {
$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 ]);
2010-05-05 20:42:25 +00:00
if ( isset ( $val [ 6 ]) && $field [ 0 ] == " " ) { // auto_increment
$val [ 1 ] = ( $val [ 1 ] == " bigint " ? " big " : " " ) . " serial " ;
2010-04-21 12:01:32 +00:00
}
if ( $field [ 0 ] == " " ) {
2010-05-07 16:10:35 +00:00
$alter [] = ( $table != " " ? " ADD " : " " ) . implode ( $val );
2010-04-21 12:01:32 +00:00
} else {
if ( $column != $val [ 0 ]) {
2010-05-11 14:45:04 +00:00
$queries [] = " ALTER TABLE " . table ( $table ) . " RENAME $column TO $val[0] " ;
2010-04-21 12:01:32 +00:00
}
2010-05-05 20:42:25 +00:00
$alter [] = " ALTER $column TYPE $val[1] " ;
2010-04-21 12:01:32 +00:00
if ( ! $val [ 6 ]) {
2013-07-02 16:20:06 +00:00
$alter [] = " ALTER $column " . ( $val [ 3 ] ? " SET $val[3] " : " DROP DEFAULT " );
2010-04-21 12:01:32 +00:00
$alter [] = " ALTER $column " . ( $val [ 2 ] == " NULL " ? " DROP NOT " : " SET " ) . $val [ 2 ];
}
}
2010-05-05 20:42:25 +00:00
if ( $field [ 0 ] != " " || $val5 != " " ) {
2010-05-11 14:45:04 +00:00
$queries [] = " COMMENT ON COLUMN " . table ( $table ) . " . $val[0] IS " . ( $val5 != " " ? substr ( $val5 , 9 ) : " '' " );
2010-04-21 12:01:32 +00:00
}
}
}
$alter = array_merge ( $alter , $foreign );
if ( $table == " " ) {
2010-05-11 14:45:04 +00:00
array_unshift ( $queries , " CREATE TABLE " . table ( $name ) . " ( \n " . implode ( " , \n " , $alter ) . " \n ) " );
2010-04-21 12:01:32 +00:00
} elseif ( $alter ) {
2010-05-11 14:45:04 +00:00
array_unshift ( $queries , " ALTER TABLE " . table ( $table ) . " \n " . implode ( " , \n " , $alter ));
2010-04-21 12:01:32 +00:00
}
if ( $table != " " && $table != $name ) {
2010-05-11 14:45:04 +00:00
$queries [] = " ALTER TABLE " . table ( $table ) . " RENAME TO " . table ( $name );
2010-04-21 12:01:32 +00:00
}
if ( $table != " " || $comment != " " ) {
2010-10-13 16:04:40 +00:00
$queries [] = " COMMENT ON TABLE " . table ( $name ) . " IS " . q ( $comment );
2010-04-21 12:01:32 +00:00
}
if ( $auto_increment != " " ) {
2010-10-13 16:04:40 +00:00
//! $queries[] = "SELECT setval(pg_get_serial_sequence(" . q($name) . ", ), $auto_increment)";
2010-04-21 12:01:32 +00:00
}
foreach ( $queries as $query ) {
if ( ! queries ( $query )) {
return false ;
}
}
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function alter_indexes ( $table , $alter ) {
$create = array ();
$drop = array ();
2013-06-25 00:37:59 +00:00
$queries = array ();
2010-04-21 12:01:32 +00:00
foreach ( $alter as $val ) {
if ( $val [ 0 ] != " INDEX " ) {
2013-06-25 16:42:47 +00:00
//! descending UNIQUE indexes results in syntax error
2011-07-13 13:13:00 +00:00
$create [] = ( $val [ 2 ] == " DROP "
? " \n DROP CONSTRAINT " . idf_escape ( $val [ 1 ])
2013-06-25 00:37:59 +00:00
: " \n ADD " . ( $val [ 1 ] != " " ? " CONSTRAINT " . idf_escape ( $val [ 1 ]) : " " ) . " $val[0] " . ( $val [ 0 ] == " PRIMARY " ? " KEY " : " " ) . $val [ 2 ]
2011-07-13 13:13:00 +00:00
);
} elseif ( $val [ 2 ] == " DROP " ) {
$drop [] = idf_escape ( $val [ 1 ]);
2013-06-25 00:37:59 +00:00
} else {
$queries [] = " CREATE INDEX " . idf_escape ( $val [ 1 ] != " " ? $val [ 1 ] : uniqid ( $table . " _ " )) . " ON " . table ( $table ) . " $val[2] " ;
}
}
if ( $create ) {
array_unshift ( $queries , " ALTER TABLE " . table ( $table ) . implode ( " , " , $create ));
}
if ( $drop ) {
array_unshift ( $queries , " DROP INDEX " . implode ( " , " , $drop ));
}
foreach ( $queries as $query ) {
if ( ! queries ( $query )) {
2010-04-21 12:01:32 +00:00
return false ;
}
}
2013-06-25 00:37:59 +00:00
return true ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function truncate_tables ( $tables ) {
2010-05-11 14:45:04 +00:00
return queries ( " TRUNCATE " . implode ( " , " , array_map ( 'table' , $tables )));
2010-04-21 12:01:32 +00:00
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
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
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
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
}
2013-07-24 23:26:41 +00:00
2010-05-05 20:11:24 +00:00
function move_tables ( $tables , $views , $target ) {
foreach ( $tables as $table ) {
2010-05-11 14:45:04 +00:00
if ( ! queries ( " ALTER TABLE " . table ( $table ) . " SET SCHEMA " . idf_escape ( $target ))) {
2010-05-05 20:11:24 +00:00
return false ;
}
}
foreach ( $views as $table ) {
2010-05-11 14:45:04 +00:00
if ( ! queries ( " ALTER VIEW " . table ( $table ) . " SET SCHEMA " . idf_escape ( $target ))) {
2010-05-05 20:11:24 +00:00
return false ;
}
}
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function trigger ( $name ) {
2011-08-08 16:18:16 +00:00
if ( $name == " " ) {
return array ( " Statement " => " EXECUTE PROCEDURE () " );
}
2010-10-13 16:04:40 +00:00
$rows = get_rows ( 'SELECT trigger_name AS "Trigger", condition_timing AS "Timing", event_manipulation AS "Event", \'FOR EACH \' || action_orientation AS "Type", action_statement AS "Statement" FROM information_schema.triggers WHERE event_object_table = ' . q ( $_GET [ " trigger " ]) . ' AND trigger_name = ' . q ( $name ));
2010-10-13 15:53:59 +00:00
return reset ( $rows );
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function triggers ( $table ) {
$return = array ();
2010-10-13 16:04:40 +00:00
foreach ( get_rows ( " SELECT * FROM information_schema.triggers WHERE event_object_table = " . q ( $table )) as $row ) {
2010-04-21 12:01:32 +00:00
$return [ $row [ " trigger_name " ]] = array ( $row [ " condition_timing " ], $row [ " event_manipulation " ]);
}
return $return ;
}
2013-07-24 23:26:41 +00:00
2010-04-22 15:53:42 +00:00
function trigger_options () {
return array (
" Timing " => array ( " BEFORE " , " AFTER " ),
2010-04-22 19:43:36 +00:00
" Type " => array ( " FOR EACH ROW " , " FOR EACH STATEMENT " ),
2010-04-22 15:53:42 +00:00
);
}
2013-07-24 23:26:41 +00:00
2011-06-03 13:52:55 +00:00
/*
function routine ( $name , $type ) {
//! there can be more functions with the same name differing only in parameters, it must be also passed to DROP FUNCTION
//! no procedures, only functions
//! different syntax of CREATE FUNCTION
$rows = get_rows ( ' SELECT pg_catalog . format_type ( p . prorettype , NULL ) AS " returns " , p . prosrc AS " definition "
FROM pg_catalog . pg_namespace n
JOIN pg_catalog . pg_proc p ON p . pronamespace = n . oid
WHERE n . nspname = current_schema () AND p . proname = ' . q ( $name ));
$rows [ 0 ][ " fields " ] = array (); //!
return $rows [ 0 ];
}
*/
2013-07-24 23:26:41 +00:00
2011-06-03 13:52:55 +00:00
function routines () {
return get_rows ( ' SELECT p . proname AS " ROUTINE_NAME " , p . proargtypes AS " ROUTINE_TYPE " , pg_catalog . format_type ( p . prorettype , NULL ) AS " DTD_IDENTIFIER "
FROM pg_catalog . pg_namespace n
JOIN pg_catalog . pg_proc p ON p . pronamespace = n . oid
WHERE n . nspname = current_schema ()
ORDER BY p . proname ' );
}
2013-07-24 23:26:41 +00:00
2011-06-03 13:52:55 +00:00
function routine_languages () {
return get_vals ( " SELECT langname FROM pg_catalog.pg_language " );
}
2013-07-24 23:26:41 +00:00
2010-05-12 16:07:46 +00:00
function last_id () {
return 0 ; // there can be several sequences
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function explain ( $connection , $query ) {
return $connection -> query ( " EXPLAIN $query " );
}
2013-07-24 23:26:41 +00:00
2011-07-29 15:08:06 +00:00
function found_rows ( $table_status , $where ) {
global $connection ;
2013-07-24 23:26:41 +00:00
if ( preg_match (
" ~ rows=([0-9]+)~ " ,
2011-07-29 15:08:06 +00:00
$connection -> result ( " EXPLAIN SELECT * FROM " . idf_escape ( $table_status [ " Name " ]) . ( $where ? " WHERE " . implode ( " AND " , $where ) : " " )),
$regs
)) {
return $regs [ 1 ];
}
return false ;
}
2013-07-24 23:26:41 +00:00
2010-05-21 14:07:22 +00:00
function types () {
return get_vals ( " SELECT typname
FROM pg_type
WHERE typnamespace = ( SELECT oid FROM pg_namespace WHERE nspname = current_schema ())
AND typtype IN ( 'b' , 'd' , 'e' )
AND typelem = 0 "
);
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:30:55 +00:00
function schemas () {
2011-07-29 15:59:14 +00:00
return get_vals ( " SELECT nspname FROM pg_namespace ORDER BY nspname " );
2010-05-05 16:30:55 +00:00
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:30:55 +00:00
function get_schema () {
global $connection ;
return $connection -> result ( " SELECT current_schema() " );
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:30:55 +00:00
function set_schema ( $schema ) {
2010-05-21 13:07:59 +00:00
global $connection , $types , $structured_types ;
2010-05-21 14:07:22 +00:00
$return = $connection -> query ( " SET search_path TO " . idf_escape ( $schema ));
foreach ( types () as $type ) { //! get types from current_schemas('t')
2010-05-21 13:07:59 +00:00
if ( ! isset ( $types [ $type ])) {
$types [ $type ] = 0 ;
$structured_types [ lang ( 'User types' )][] = $type ;
}
}
2010-05-21 14:07:22 +00:00
return $return ;
2010-05-05 16:30:55 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 22:37:16 +00:00
function use_sql ( $database ) {
return " \ connect " . idf_escape ( $database );
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:31:39 +00:00
function show_variables () {
return get_key_vals ( " SHOW ALL " );
}
2011-05-11 09:48:51 +00:00
function process_list () {
2012-10-20 16:58:56 +00:00
global $connection ;
return get_rows ( " SELECT * FROM pg_stat_activity ORDER BY " . ( $connection -> server_info < 9.2 ? " procpid " : " pid " ));
2011-05-11 09:48:51 +00:00
}
2013-07-24 23:26:41 +00:00
2010-08-03 15:15:45 +00:00
function show_status () {
}
2013-07-24 23:26:41 +00:00
2012-09-09 05:56:34 +00:00
function convert_field ( $field ) {
}
2013-07-24 23:26:41 +00:00
2012-09-09 05:56:34 +00:00
function unconvert_field ( $field , $return ) {
return $return ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function support ( $feature ) {
2013-07-24 23:26:41 +00:00
return preg_match ( '~^(database|table|sql|indexes|comment|view|scheme|processlist|sequence|trigger|type|variables|drop_col)$~' , $feature ); //! routine|
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-05-07 13:44:22 +00:00
$jush = " pgsql " ;
2010-04-21 12:01:32 +00:00
$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 ),
2012-08-30 04:13:30 +00:00
lang ( 'Date and time' ) => array ( " date " => 13 , " time " => 17 , " timestamp " => 20 , " timestamptz " => 21 , " interval " => 0 ),
2010-04-21 12:01:32 +00:00
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 ),
2010-05-21 13:07:59 +00:00
) as $key => $val ) { //! can be retrieved from pg_type
2010-04-21 12:01:32 +00:00
$types += $val ;
$structured_types [ $key ] = array_keys ( $val );
}
$unsigned = array ();
2013-04-26 19:04:28 +00:00
$operators = array ( " = " , " < " , " > " , " <= " , " >= " , " != " , " ~ " , " !~ " , " LIKE " , " LIKE %% " , " IN " , " IS NULL " , " NOT LIKE " , " NOT IN " , " IS NOT NULL " ); // no "SQL" to avoid SQL injection
2010-04-21 12:01:32 +00:00
$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 " => " || " ,
)
);
}