2010-04-21 12:01:32 +00:00
< ? php
/**
* @ author Jakub Cernohuby
* @ author Vladimir Stastka
* @ author Jakub Vrana
*/
2018-02-09 23:09:07 +00:00
$drivers [ " mssql " ] = " MS SQL (beta) " ;
2010-04-21 12:01:32 +00:00
if ( isset ( $_GET [ " mssql " ])) {
2016-10-10 23:47:16 +00:00
$possible_drivers = array ( " SQLSRV " , " MSSQL " , " PDO_DBLIB " );
2010-04-21 12:01:32 +00:00
define ( " DRIVER " , " mssql " );
if ( extension_loaded ( " sqlsrv " )) {
class Min_DB {
2013-01-10 06:19:38 +00:00
var $extension = " sqlsrv " , $_link , $_result , $server_info , $affected_rows , $errno , $error ;
2010-04-21 12:01:32 +00:00
function _get_error () {
$this -> error = " " ;
foreach ( sqlsrv_errors () as $error ) {
2013-01-10 06:19:38 +00:00
$this -> errno = $error [ " code " ];
2010-04-21 12:01:32 +00:00
$this -> error .= " $error[message] \n " ;
}
$this -> error = rtrim ( $this -> error );
}
function connect ( $server , $username , $password ) {
2018-07-18 08:41:12 +00:00
global $adminer ;
$db = $adminer -> database ();
$connection_info = array ( " UID " => $username , " PWD " => $password , " CharacterSet " => " UTF-8 " );
if ( $db != " " ) {
$connection_info [ " Database " ] = $db ;
}
$this -> _link = @ sqlsrv_connect ( preg_replace ( '~:~' , ',' , $server ), $connection_info );
2010-04-21 12:01:32 +00:00
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 ) {
2012-12-01 23:11:01 +00:00
return $this -> query ( " USE " . idf_escape ( $database ));
2010-04-21 12:01:32 +00:00
}
function query ( $query , $unbuffered = false ) {
$result = sqlsrv_query ( $this -> _link , $query ); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
if ( ! $result ) {
$this -> _get_error ();
return false ;
}
return $this -> store_result ( $result );
}
function multi_query ( $query ) {
$this -> _result = sqlsrv_query ( $this -> _link , $query );
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
if ( ! $this -> _result ) {
$this -> _get_error ();
return false ;
}
return true ;
}
function store_result ( $result = null ) {
if ( ! $result ) {
$result = $this -> _result ;
}
2014-09-19 12:41:45 +00:00
if ( ! $result ) {
return false ;
}
2010-04-21 12:01:32 +00:00
if ( sqlsrv_field_metadata ( $result )) {
return new Min_Result ( $result );
}
$this -> affected_rows = sqlsrv_rows_affected ( $result );
return true ;
}
function next_result () {
2014-09-19 12:41:45 +00:00
return $this -> _result ? sqlsrv_next_result ( $this -> _result ) : null ;
2010-04-21 12:01:32 +00:00
}
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 ;
2015-08-15 15:04:21 +00:00
function __construct ( $result ) {
2010-04-21 12:01:32 +00:00
$this -> _result = $result ;
2010-05-27 14:10:17 +00:00
// $this->num_rows = sqlsrv_num_rows($result); // available only in scrollable results
2010-04-21 12:01:32 +00:00
}
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 ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function fetch_assoc () {
2016-11-15 13:54:01 +00:00
return $this -> _convert ( sqlsrv_fetch_array ( $this -> _result , SQLSRV_FETCH_ASSOC ));
2010-04-21 12:01:32 +00:00
}
function fetch_row () {
2016-11-15 13:54:01 +00:00
return $this -> _convert ( sqlsrv_fetch_array ( $this -> _result , SQLSRV_FETCH_NUMERIC ));
2010-04-21 12:01:32 +00:00
}
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 ;
}
2013-07-24 23:26:41 +00:00
2010-04-23 09:04:05 +00:00
function seek ( $offset ) {
for ( $i = 0 ; $i < $offset ; $i ++ ) {
sqlsrv_fetch ( $this -> _result ); // SQLSRV_SCROLL_ABSOLUTE added in sqlsrv 1.1
}
}
2010-04-21 12:01:32 +00:00
function __destruct () {
sqlsrv_free_stmt ( $this -> _result );
}
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
} 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') " );
2018-05-09 13:43:01 +00:00
if ( $result ) {
$row = $result -> fetch_row ();
$this -> server_info = $this -> result ( " sp_server_info 2 " , 2 ) . " [ $row[0] ] $row[1] " ;
}
2010-04-21 12:01:32 +00:00
} 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 ) {
2014-12-30 15:54:28 +00:00
$result = @ mssql_query ( $query , $this -> _link ); //! $unbuffered
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
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 () {
2014-12-30 15:54:28 +00:00
return mssql_next_result ( $this -> _result -> _result );
2010-04-21 12:01:32 +00:00
}
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 ;
2015-08-15 15:04:21 +00:00
function __construct ( $result ) {
2010-04-21 12:01:32 +00:00
$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 ;
}
2010-04-23 09:04:05 +00:00
function seek ( $offset ) {
mssql_data_seek ( $this -> _result , $offset );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function __destruct () {
mssql_free_result ( $this -> _result );
}
}
2013-07-24 23:26:41 +00:00
2016-10-10 23:47:16 +00:00
} elseif ( extension_loaded ( " pdo_dblib " )) {
class Min_DB extends Min_PDO {
var $extension = " PDO_DBLIB " ;
function connect ( $server , $username , $password ) {
2018-02-20 15:27:40 +00:00
$this -> dsn ( " dblib:charset=utf8;host= " . str_replace ( " : " , " ;unix_socket= " , preg_replace ( '~:(\d)~' , ';port=\1' , $server )), $username , $password );
2016-10-10 23:47:16 +00:00
return true ;
}
2010-04-21 12:01:32 +00:00
2016-10-10 23:47:16 +00:00
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 ));
}
}
}
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 ) {
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 " ;
}
}
//! can use only one query for all rows
if ( ! queries ( " MERGE " . table ( $table ) . " USING (VALUES( " . implode ( " , " , $set ) . " )) AS source (c " . implode ( " , c " , range ( 1 , count ( $set ))) . " ) ON " . implode ( " AND " , $where ) //! source, c1 - possible conflict
. " WHEN MATCHED THEN UPDATE SET " . implode ( " , " , $update )
. " WHEN NOT MATCHED THEN INSERT ( " . implode ( " , " , array_keys ( $set )) . " ) VALUES ( " . implode ( " , " , $set ) . " ); " // ; is mandatory
)) {
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-09 18:43:01 +00:00
function begin () {
return queries ( " BEGIN TRANSACTION " );
}
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 ( $_GET [ " ns " ] != " " ? idf_escape ( $_GET [ " ns " ]) . " . " : " " ) . 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 ])) {
return $connection ;
}
return $connection -> error ;
}
function get_databases () {
2016-11-15 13:54:01 +00:00
return get_vals ( " SELECT name FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb') " );
2010-04-21 12:01:32 +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 ( $limit !== null ? " TOP ( " . ( $limit + $offset ) . " ) " : " " ) . " $query $where " ; // seek later
2010-04-21 12:01:32 +00:00
}
2018-02-01 17:53:53 +00:00
function limit1 ( $table , $query , $where , $separator = " \n " ) {
return limit ( $query , $where , 1 , 0 , $separator );
2010-04-21 12:01:32 +00:00
}
function db_collation ( $db , $collations ) {
global $connection ;
2018-01-22 12:51:47 +00:00
return $connection -> result ( " SELECT collation_name FROM sys.databases WHERE name = " . q ( $db ));
2010-04-21 12:01:32 +00:00
}
function engines () {
return array ();
}
function logged_user () {
global $connection ;
return $connection -> result ( " SELECT SUSER_NAME() " );
}
function tables_list () {
2010-10-13 16:04:40 +00:00
return get_key_vals ( " SELECT name, type_desc FROM sys.all_objects WHERE schema_id = SCHEMA_ID( " . q ( get_schema ()) . " ) AND type IN ('S', 'U', 'V') ORDER BY name " );
2010-04-21 12:01:32 +00:00
}
function count_tables ( $databases ) {
global $connection ;
$return = array ();
foreach ( $databases as $db ) {
$connection -> select_db ( $db );
2010-10-16 14:38:20 +00:00
$return [ $db ] = $connection -> result ( " SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES " );
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 table_status ( $name = " " ) {
$return = array ();
2019-06-11 23:03:07 +00:00
foreach ( get_rows ( " SELECT ao.name AS Name, ao.type_desc AS Engine, (SELECT value FROM fn_listextendedproperty(default, 'SCHEMA', schema_name(schema_id), 'TABLE', ao.name, null, null)) AS Comment FROM sys.all_objects AS ao WHERE schema_id = SCHEMA_ID( " . q ( get_schema ()) . " ) AND type IN ('S', 'U', 'V') " . ( $name != " " ? " AND name = " . q ( $name ) : " ORDER BY name " )) as $row ) {
2010-04-21 12:01:32 +00:00
if ( $name != " " ) {
return $row ;
}
$return [ $row [ " Name " ]] = $row ;
}
return $return ;
}
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 ;
}
2010-11-11 09:47:32 +00:00
function fields ( $table ) {
2020-03-18 16:26:50 +00:00
$comments = get_key_vals ( " SELECT objname, cast(value as varchar(max)) FROM fn_listextendedproperty('MS_DESCRIPTION', 'schema', " . q ( get_schema ()) . " , 'table', " . q ( $table ) . " , 'column', NULL) " );
2010-04-21 12:01:32 +00:00
$return = array ();
2017-12-18 20:59:05 +00:00
foreach ( get_rows ( " SELECT c.max_length, c.precision, c.scale, c.name, c.is_nullable, c.is_identity, c.collation_name, t.name type, CAST(d.definition as text) [default]
2010-05-11 15:41:42 +00:00
FROM sys . all_columns c
JOIN sys . all_objects o ON c . object_id = o . object_id
JOIN sys . types t ON c . user_type_id = t . user_type_id
LEFT JOIN sys . default_constraints d ON c . default_object_id = d . parent_column_id
2010-10-13 16:04:40 +00:00
WHERE o . schema_id = SCHEMA_ID ( " . q(get_schema()) . " ) AND o . type IN ( 'S' , 'U' , 'V' ) AND o . name = " . q( $table )
2010-10-13 15:53:59 +00:00
) as $row ) {
2010-05-26 14:10:09 +00:00
$type = $row [ " type " ];
2013-07-24 23:26:41 +00:00
$length = ( preg_match ( " ~char|binary~ " , $type ) ? $row [ " max_length " ] : ( $type == " decimal " ? " $row[precision] , $row[scale] " : " " ));
2010-05-11 15:41:42 +00:00
$return [ $row [ " name " ]] = array (
" field " => $row [ " name " ],
2010-05-26 14:10:09 +00:00
" full_type " => $type . ( $length ? " ( $length ) " : " " ),
" type " => $type ,
2010-05-11 21:17:11 +00:00
" length " => $length ,
2010-05-11 15:41:42 +00:00
" default " => $row [ " default " ],
" null " => $row [ " is_nullable " ],
2010-04-23 09:04:05 +00:00
" auto_increment " => $row [ " is_identity " ],
2010-05-11 15:41:42 +00:00
" collation " => $row [ " collation_name " ],
2010-04-21 12:01:32 +00:00
" privileges " => array ( " insert " => 1 , " select " => 1 , " update " => 1 ),
2010-04-23 09:04:05 +00:00
" primary " => $row [ " is_identity " ], //! or indexes.is_primary_key
2019-06-11 23:03:07 +00:00
" comment " => $comments [ $row [ " name " ]],
2010-04-21 12:01:32 +00:00
);
}
return $return ;
}
function indexes ( $table , $connection2 = null ) {
$return = array ();
// sp_statistics doesn't return information about primary key
2013-06-25 16:42:47 +00:00
foreach ( get_rows ( " SELECT i.name, key_ordinal, is_unique, is_primary_key, c.name AS column_name, is_descending_key
2010-10-16 06:23:34 +00:00
FROM sys . indexes i
INNER JOIN sys . index_columns ic ON i . object_id = ic . object_id AND i . index_id = ic . index_id
INNER JOIN sys . columns c ON ic . object_id = c . object_id AND ic . column_id = c . column_id
WHERE OBJECT_NAME ( i . object_id ) = " . q( $table )
2010-10-13 16:59:15 +00:00
, $connection2 ) as $row ) {
2013-06-25 16:42:47 +00:00
$name = $row [ " name " ];
$return [ $name ][ " type " ] = ( $row [ " is_primary_key " ] ? " PRIMARY " : ( $row [ " is_unique " ] ? " UNIQUE " : " INDEX " ));
$return [ $name ][ " lengths " ] = array ();
$return [ $name ][ " columns " ][ $row [ " key_ordinal " ]] = $row [ " column_name " ];
$return [ $name ][ " descs " ][ $row [ " key_ordinal " ]] = ( $row [ " is_descending_key " ] ? '1' : null );
2010-04-21 12:01:32 +00:00
}
return $return ;
}
2010-05-27 11:25:04 +00:00
function view ( $name ) {
global $connection ;
2018-02-20 15:27:40 +00:00
return array ( " select " => preg_replace ( '~^(?:[^[]|\[[^]]*])*\s+AS\s+~isU' , '' , $connection -> result ( " SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = SCHEMA_NAME() AND TABLE_NAME = " . q ( $name ))));
2010-05-27 11:25:04 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function collations () {
$return = array ();
foreach ( get_vals ( " SELECT name FROM fn_helpcollations() " ) as $collation ) {
2013-07-24 23:26:41 +00:00
$return [ preg_replace ( '~_.*~' , '' , $collation )][] = $collation ;
2010-04-21 12:01:32 +00:00
}
return $return ;
}
function information_schema ( $db ) {
return false ;
}
function error () {
global $connection ;
2018-02-20 15:27:40 +00:00
return nl_br ( h ( preg_replace ( '~^(\[[^]]*])+~m' , '' , $connection -> error )));
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 create_database ( $db , $collation ) {
2013-07-24 23:26:41 +00:00
return queries ( " CREATE DATABASE " . idf_escape ( $db ) . ( preg_match ( '~^[a-z0-9_]+$~i' , $collation ) ? " COLLATE $collation " : " " ));
2010-04-22 23:02:28 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:02:28 +00:00
function drop_databases ( $databases ) {
return queries ( " DROP DATABASE " . implode ( " , " , array_map ( 'idf_escape' , $databases )));
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function rename_database ( $name , $collation ) {
2013-07-24 23:26:41 +00:00
if ( preg_match ( '~^[a-z0-9_]+$~i' , $collation )) {
2010-10-16 13:31:25 +00:00
queries ( " ALTER DATABASE " . idf_escape ( DB ) . " COLLATE $collation " );
2010-04-21 12:01:32 +00:00
}
2010-04-23 09:04:05 +00:00
queries ( " ALTER DATABASE " . idf_escape ( DB ) . " MODIFY NAME = " . idf_escape ( $name ));
return true ; //! false negative "The database name 'test2' has been set."
2010-04-21 12:01:32 +00:00
}
function auto_increment () {
2014-11-25 02:17:43 +00:00
return " IDENTITY " . ( $_POST [ " Auto_increment " ] != " " ? " ( " . number ( $_POST [ " Auto_increment " ]) . " ,1) " : " " ) . " PRIMARY KEY " ;
2010-05-26 14:00:21 +00:00
}
2013-07-24 23:26:41 +00:00
2010-05-26 14:00:21 +00:00
function alter_table ( $table , $name , $fields , $foreign , $comment , $engine , $collation , $auto_increment , $partitioning ) {
$alter = array ();
2019-06-11 23:03:07 +00:00
$comments = array ();
2010-05-26 14:00:21 +00:00
foreach ( $fields as $field ) {
$column = idf_escape ( $field [ 0 ]);
$val = $field [ 1 ];
if ( ! $val ) {
2010-11-28 16:39:07 +00:00
$alter [ " DROP " ][] = " COLUMN $column " ;
2010-05-26 14:00:21 +00:00
} else {
2018-02-20 15:27:40 +00:00
$val [ 1 ] = preg_replace ( " ~( COLLATE )'( \\ w+)'~ " , '\1\2' , $val [ 1 ]);
2019-06-11 23:03:07 +00:00
$comments [ $field [ 0 ]] = $val [ 5 ];
unset ( $val [ 5 ]);
2010-05-26 14:00:21 +00:00
if ( $field [ 0 ] == " " ) {
2010-11-28 16:39:07 +00:00
$alter [ " ADD " ][] = " \n " . implode ( " " , $val ) . ( $table == " " ? substr ( $foreign [ $val [ 0 ]], 16 + strlen ( $val [ 0 ])) : " " ); // 16 - strlen(" FOREIGN KEY ()")
2010-05-26 14:00:21 +00:00
} else {
unset ( $val [ 6 ]); //! identity can't be removed
if ( $column != $val [ 0 ]) {
2010-10-13 16:04:40 +00:00
queries ( " EXEC sp_rename " . q ( table ( $table ) . " . $column " ) . " , " . q ( idf_unescape ( $val [ 0 ])) . " , 'COLUMN' " );
2010-05-26 14:00:21 +00:00
}
$alter [ " ALTER COLUMN " . implode ( " " , $val )][] = " " ;
}
}
}
if ( $table == " " ) {
return queries ( " CREATE TABLE " . table ( $name ) . " ( " . implode ( " , " , ( array ) $alter [ " ADD " ]) . " \n ) " );
}
if ( $table != $name ) {
2010-10-13 16:04:40 +00:00
queries ( " EXEC sp_rename " . q ( table ( $table )) . " , " . q ( $name ));
2010-05-26 14:00:21 +00:00
}
2010-11-28 15:28:15 +00:00
if ( $foreign ) {
$alter [ " " ] = $foreign ;
}
2010-05-26 14:00:21 +00:00
foreach ( $alter as $key => $val ) {
if ( ! queries ( " ALTER TABLE " . idf_escape ( $name ) . " $key " . implode ( " , " , $val ))) {
return false ;
}
}
2019-06-11 23:03:07 +00:00
foreach ( $comments as $key => $val ) {
$comment = substr ( $val , 9 ); // 9 - strlen(" COMMENT ")
queries ( " EXEC sp_dropextendedproperty @name = N'MS_Description', @level0type = N'Schema', @level0name = " . q ( get_schema ()) . " , @level1type = N'Table', @level1name = " . q ( $name ) . " , @level2type = N'Column', @level2name = " . q ( $key ));
queries ( " EXEC sp_addextendedproperty @name = N'MS_Description', @value = " . $comment . " , @level0type = N'Schema', @level0name = " . q ( get_schema ()) . " , @level1type = N'Table', @level1name = " . q ( $name ) . " , @level2type = N'Column', @level2name = " . q ( $key ));
}
2010-05-26 14:00:21 +00:00
return true ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-07-14 14:18:12 +00:00
function alter_indexes ( $table , $alter ) {
$index = array ();
$drop = array ();
foreach ( $alter as $val ) {
2011-07-13 13:13:00 +00:00
if ( $val [ 2 ] == " DROP " ) {
2010-07-14 14:18:12 +00:00
if ( $val [ 0 ] == " PRIMARY " ) { //! sometimes used also for UNIQUE
2011-07-13 13:13:00 +00:00
$drop [] = idf_escape ( $val [ 1 ]);
2010-07-14 14:18:12 +00:00
} else {
2011-07-13 13:13:00 +00:00
$index [] = idf_escape ( $val [ 1 ]) . " ON " . table ( $table );
2010-07-14 14:18:12 +00:00
}
} elseif ( ! queries (( $val [ 0 ] != " PRIMARY "
2011-07-13 13:13:00 +00:00
? " CREATE $val[0] " . ( $val [ 0 ] != " INDEX " ? " INDEX " : " " ) . idf_escape ( $val [ 1 ] != " " ? $val [ 1 ] : uniqid ( $table . " _ " )) . " ON " . table ( $table )
2010-07-14 14:18:12 +00:00
: " ALTER TABLE " . table ( $table ) . " ADD PRIMARY KEY "
2014-01-12 03:22:44 +00:00
) . " ( " . implode ( " , " , $val [ 2 ]) . " ) " )) {
2010-07-14 14:18:12 +00:00
return false ;
}
}
return ( ! $index || queries ( " DROP INDEX " . implode ( " , " , $index )))
&& ( ! $drop || queries ( " ALTER TABLE " . table ( $table ) . " DROP " . implode ( " , " , $drop )))
;
}
2013-07-24 23:26:41 +00:00
2010-05-12 16:07:46 +00:00
function last_id () {
global $connection ;
return $connection -> result ( " SELECT SCOPE_IDENTITY() " ); // @@IDENTITY can return trigger INSERT
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
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 ;
}
2013-07-24 23:26:41 +00:00
2011-07-29 15:08:06 +00:00
function found_rows ( $table_status , $where ) {
}
2013-07-24 23:26:41 +00:00
2010-04-22 14:38:05 +00:00
function foreign_keys ( $table ) {
$return = array ();
2010-10-13 16:04:40 +00:00
foreach ( get_rows ( " EXEC sp_fkeys @fktable_name = " . q ( $table )) as $row ) {
2010-04-22 14:38:05 +00:00
$foreign_key = & $return [ $row [ " FK_NAME " ]];
2019-08-21 12:33:12 +00:00
$foreign_key [ " db " ] = $row [ " PKTABLE_QUALIFIER " ];
2010-04-22 14:38:05 +00:00
$foreign_key [ " table " ] = $row [ " PKTABLE_NAME " ];
$foreign_key [ " source " ][] = $row [ " FKCOLUMN_NAME " ];
$foreign_key [ " target " ][] = $row [ " PKCOLUMN_NAME " ];
}
return $return ;
}
function truncate_tables ( $tables ) {
2010-05-17 16:18:32 +00:00
return apply_queries ( " TRUNCATE TABLE " , $tables );
2010-04-22 14:38:05 +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-22 14:38:05 +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-22 14:38:05 +00:00
}
2010-05-11 14:45:04 +00:00
function move_tables ( $tables , $views , $target ) {
2010-05-17 16:18:32 +00:00
return apply_queries ( " ALTER SCHEMA " . idf_escape ( $target ) . " TRANSFER " , array_merge ( $tables , $views ));
2010-05-11 14:45:04 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-22 14:38:05 +00:00
function trigger ( $name ) {
2011-08-08 16:18:16 +00:00
if ( $name == " " ) {
return array ();
}
2010-10-13 15:53:59 +00:00
$rows = get_rows ( " SELECT s.name [Trigger],
2010-04-22 14:38:05 +00:00
CASE WHEN OBJECTPROPERTY ( s . id , 'ExecIsInsertTrigger' ) = 1 THEN 'INSERT' WHEN OBJECTPROPERTY ( s . id , 'ExecIsUpdateTrigger' ) = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY ( s . id , 'ExecIsDeleteTrigger' ) = 1 THEN 'DELETE' END [ Event ],
CASE WHEN OBJECTPROPERTY ( s . id , 'ExecIsInsteadOfTrigger' ) = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END [ Timing ],
2010-04-22 15:53:42 +00:00
c . text
2010-04-22 14:38:05 +00:00
FROM sysobjects s
JOIN syscomments c ON s . id = c . id
2010-10-13 16:04:40 +00:00
WHERE s . xtype = 'TR' AND s . name = " . q( $name )
2010-05-11 14:45:04 +00:00
); // triggers are not schema-scoped
2010-10-13 15:53:59 +00:00
$return = reset ( $rows );
if ( $return ) {
2018-02-20 15:27:40 +00:00
$return [ " Statement " ] = preg_replace ( '~^.+\s+AS\s+~isU' , '' , $return [ " text " ]); //! identifiers, comments
2010-10-13 15:53:59 +00:00
}
return $return ;
2010-04-22 14:38:05 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-22 14:38:05 +00:00
function triggers ( $table ) {
$return = array ();
2010-10-13 15:53:59 +00:00
foreach ( get_rows ( " SELECT sys1.name,
2010-04-22 14:38:05 +00:00
CASE WHEN OBJECTPROPERTY ( sys1 . id , 'ExecIsInsertTrigger' ) = 1 THEN 'INSERT' WHEN OBJECTPROPERTY ( sys1 . id , 'ExecIsUpdateTrigger' ) = 1 THEN 'UPDATE' WHEN OBJECTPROPERTY ( sys1 . id , 'ExecIsDeleteTrigger' ) = 1 THEN 'DELETE' END [ Event ],
CASE WHEN OBJECTPROPERTY ( sys1 . id , 'ExecIsInsteadOfTrigger' ) = 1 THEN 'INSTEAD OF' ELSE 'AFTER' END [ Timing ]
FROM sysobjects sys1
JOIN sysobjects sys2 ON sys1 . parent_obj = sys2 . id
2010-10-13 16:04:40 +00:00
WHERE sys1 . xtype = 'TR' AND sys2 . name = " . q( $table )
2010-10-13 15:53:59 +00:00
) as $row ) { // triggers are not schema-scoped
2010-04-22 14:38:05 +00:00
$return [ $row [ " name " ]] = array ( $row [ " Timing " ], $row [ " Event " ]);
}
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 ( " AFTER " , " INSTEAD OF " ),
2014-03-15 17:58:24 +00:00
" Event " => array ( " INSERT " , " UPDATE " , " DELETE " ),
2010-04-22 15:53:42 +00:00
" Type " => array ( " AS " ),
);
}
2013-07-24 23:26:41 +00:00
2010-05-11 14:45:04 +00:00
function schemas () {
return get_vals ( " SELECT name FROM sys.schemas " );
}
2013-07-24 23:26:41 +00:00
2010-05-11 14:45:04 +00:00
function get_schema () {
global $connection ;
if ( $_GET [ " ns " ] != " " ) {
return $_GET [ " ns " ];
}
return $connection -> result ( " SELECT SCHEMA_NAME() " );
}
2013-07-24 23:26:41 +00:00
2010-05-11 14:45:04 +00:00
function set_schema ( $schema ) {
return true ; // ALTER USER is permanent
}
2013-07-24 23:26:41 +00:00
2010-05-05 11:11:33 +00:00
function use_sql ( $database ) {
return " USE " . idf_escape ( $database );
}
2013-07-24 23:26:41 +00:00
2010-05-05 11:11:33 +00:00
function show_variables () {
return array ();
}
2013-07-24 23:26:41 +00:00
2010-05-05 11:11:33 +00:00
function show_status () {
return array ();
}
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 ) {
2019-06-11 23:03:07 +00:00
return preg_match ( '~^(comment|columns|database|drop_col|indexes|descidx|scheme|sql|table|trigger|view|view_trigger)$~' , $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 = " mssql " ;
2010-04-21 12:01:32 +00:00
$types = array ();
$structured_types = array ();
2010-05-11 15:41:42 +00:00
foreach ( array ( //! use sys.types
2010-04-21 12:01:32 +00:00
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 ();
2011-08-09 09:32:11 +00:00
$operators = array ( " = " , " < " , " > " , " <= " , " >= " , " != " , " LIKE " , " LIKE %% " , " IN " , " IS NULL " , " NOT LIKE " , " NOT IN " , " IS NOT NULL " );
2010-04-21 12:01:32 +00:00
$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 " => " + " ,
)
);
}