2010-04-21 12:01:32 +00:00
< ? php
2010-10-29 13:24:06 +00:00
$drivers [ " sqlite " ] = " SQLite 3 " ;
$drivers [ " sqlite2 " ] = " SQLite 2 " ;
2010-04-21 12:01:32 +00:00
if ( isset ( $_GET [ " sqlite " ]) || isset ( $_GET [ " sqlite2 " ])) {
2010-10-29 13:24:06 +00:00
$possible_drivers = array (( isset ( $_GET [ " sqlite " ]) ? " SQLite3 " : " SQLite " ), " PDO_SQLite " );
2010-04-21 12:01:32 +00:00
define ( " DRIVER " , ( isset ( $_GET [ " sqlite " ]) ? " sqlite " : " sqlite2 " ));
2013-03-28 04:11:14 +00:00
if ( class_exists ( isset ( $_GET [ " sqlite " ]) ? " SQLite3 " : " SQLiteDatabase " )) {
2010-10-29 13:24:06 +00:00
if ( isset ( $_GET [ " sqlite " ])) {
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
class Min_SQLite {
2013-01-10 06:19:38 +00:00
var $extension = " SQLite3 " , $server_info , $affected_rows , $errno , $error , $_link ;
2013-07-24 23:26:41 +00:00
2015-08-15 15:04:21 +00:00
function __construct ( $filename ) {
2010-10-29 13:24:06 +00:00
$this -> _link = new SQLite3 ( $filename );
$version = $this -> _link -> version ();
$this -> server_info = $version [ " versionString " ];
2010-04-22 23:05:16 +00:00
}
2013-07-24 23:26:41 +00:00
2010-10-29 13:24:06 +00:00
function query ( $query ) {
$result = @ $this -> _link -> query ( $query );
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
if ( ! $result ) {
2013-01-10 06:19:38 +00:00
$this -> errno = $this -> _link -> lastErrorCode ();
2010-10-29 13:24:06 +00:00
$this -> error = $this -> _link -> lastErrorMsg ();
2010-04-21 12:01:32 +00:00
return false ;
2010-10-29 13:24:06 +00:00
} elseif ( $result -> numColumns ()) {
return new Min_Result ( $result );
2010-04-21 12:01:32 +00:00
}
2010-10-29 13:24:06 +00:00
$this -> affected_rows = $this -> _link -> changes ();
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 quote ( $string ) {
2012-05-14 06:20:47 +00:00
return ( is_utf8 ( $string )
? " ' " . $this -> _link -> escapeString ( $string ) . " ' "
: " x' " . reset ( unpack ( 'H*' , $string )) . " ' "
);
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-05-27 14:10:17 +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 result ( $query , $field = 0 ) {
$result = $this -> query ( $query );
2010-04-21 15:09:52 +00:00
if ( ! is_object ( $result )) {
2010-04-21 12:01:32 +00:00
return false ;
}
2010-10-29 13:24:06 +00:00
$row = $result -> _result -> fetchArray ();
2010-04-21 12:01:32 +00:00
return $row [ $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
2015-08-15 15:04:21 +00:00
function __construct ( $result ) {
2010-04-21 12:01:32 +00:00
$this -> _result = $result ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function fetch_assoc () {
2010-10-29 13:24:06 +00:00
return $this -> _result -> fetchArray ( SQLITE3_ASSOC );
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 fetch_row () {
2010-10-29 13:24:06 +00:00
return $this -> _result -> fetchArray ( SQLITE3_NUM );
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 fetch_field () {
2010-10-29 13:24:06 +00:00
$column = $this -> _offset ++ ;
$type = $this -> _result -> columnType ( $column );
2010-04-21 12:01:32 +00:00
return ( object ) array (
2010-10-29 13:24:06 +00:00
" name " => $this -> _result -> columnName ( $column ),
" type " => $type ,
" charsetnr " => ( $type == SQLITE3_BLOB ? 63 : 0 ), // 63 - binary
2010-04-21 12:01:32 +00:00
);
}
2013-07-24 23:26:41 +00:00
2010-10-29 13:24:06 +00:00
function __desctruct () {
return $this -> _result -> finalize ();
}
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
} else {
2013-07-24 23:26:41 +00:00
2010-04-21 15:09:52 +00:00
class Min_SQLite {
2010-10-29 13:24:06 +00:00
var $extension = " SQLite " , $server_info , $affected_rows , $error , $_link ;
2013-07-24 23:26:41 +00:00
2015-08-15 15:04:21 +00:00
function __construct ( $filename ) {
2010-10-29 13:24:06 +00:00
$this -> server_info = sqlite_libversion ();
$this -> _link = new SQLiteDatabase ( $filename );
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-10-29 13:24:06 +00:00
function query ( $query , $unbuffered = false ) {
$method = ( $unbuffered ? " unbufferedQuery " : " query " );
$result = @ $this -> _link -> $method ( $query , SQLITE_BOTH , $error );
2012-07-15 16:21:22 +00:00
$this -> error = " " ;
2010-04-21 12:01:32 +00:00
if ( ! $result ) {
2010-10-29 13:24:06 +00:00
$this -> error = $error ;
2010-04-21 12:01:32 +00:00
return false ;
2010-10-29 13:24:06 +00:00
} elseif ( $result === true ) {
$this -> affected_rows = $this -> changes ();
return true ;
2010-04-21 12:01:32 +00:00
}
2010-10-29 13:24:06 +00:00
return new Min_Result ( $result );
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 quote ( $string ) {
2010-10-29 13:24:06 +00:00
return " ' " . sqlite_escape_string ( $string ) . " ' " ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-05-27 14:10:17 +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 result ( $query , $field = 0 ) {
$result = $this -> query ( $query );
2010-04-21 15:09:52 +00:00
if ( ! is_object ( $result )) {
2010-04-21 12:01:32 +00:00
return false ;
}
2010-10-29 13:24:06 +00:00
$row = $result -> _result -> fetch ();
2010-04-21 12:01:32 +00:00
return $row [ $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
2015-08-15 15:04:21 +00:00
function __construct ( $result ) {
2010-04-21 12:01:32 +00:00
$this -> _result = $result ;
2010-10-29 13:24:06 +00:00
if ( method_exists ( $result , 'numRows' )) { // not available in unbuffered query
$this -> num_rows = $result -> numRows ();
}
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 fetch_assoc () {
2010-10-29 13:24:06 +00:00
$row = $this -> _result -> fetch ( SQLITE_ASSOC );
if ( ! $row ) {
return false ;
}
$return = array ();
foreach ( $row as $key => $val ) {
$return [( $key [ 0 ] == '"' ? idf_unescape ( $key ) : $key )] = $val ;
}
return $return ;
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 fetch_row () {
2010-10-29 13:24:06 +00:00
return $this -> _result -> fetch ( SQLITE_NUM );
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 fetch_field () {
2010-10-29 13:24:06 +00:00
$name = $this -> _result -> fieldName ( $this -> _offset ++ );
$pattern = '(\\[.*]|"(?:[^"]|"")*"|(.+))' ;
if ( preg_match ( " ~^( $pattern\\ .)? $pattern\ $ ~ " , $name , $match )) {
$table = ( $match [ 3 ] != " " ? $match [ 3 ] : idf_unescape ( $match [ 2 ]));
$name = ( $match [ 5 ] != " " ? $match [ 5 ] : idf_unescape ( $match [ 4 ]));
}
2010-04-21 12:01:32 +00:00
return ( object ) array (
2010-10-29 13:24:06 +00:00
" name " => $name ,
" orgname " => $name ,
" orgtable " => $table ,
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-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
} elseif ( extension_loaded ( " pdo_sqlite " )) {
2010-04-22 23:05:16 +00:00
class Min_SQLite extends Min_PDO {
2010-04-21 12:01:32 +00:00
var $extension = " PDO_SQLite " ;
2013-07-24 23:26:41 +00:00
2015-08-15 15:04:21 +00:00
function __construct ( $filename ) {
2010-04-22 23:05:16 +00:00
$this -> dsn ( DRIVER . " : $filename " , " " , " " );
}
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
}
2010-12-02 08:56:10 +00:00
if ( class_exists ( " Min_SQLite " )) {
class Min_DB extends Min_SQLite {
2013-07-24 23:26:41 +00:00
2015-08-15 15:04:21 +00:00
function __construct () {
parent :: __construct ( " :memory: " );
2018-01-19 13:57:58 +00:00
$this -> query ( " PRAGMA foreign_keys = 1 " );
2010-12-02 08:56:10 +00:00
}
2013-07-24 23:26:41 +00:00
2010-12-02 08:56:10 +00:00
function select_db ( $filename ) {
2013-07-24 23:26:41 +00:00
if ( is_readable ( $filename ) && $this -> query ( " ATTACH " . $this -> quote ( preg_match ( " ~(^[/ \\ \\ ]|:)~ " , $filename ) ? $filename : dirname ( $_SERVER [ " SCRIPT_FILENAME " ]) . " / $filename " ) . " AS a " )) { // is_readable - SQLite 3
2015-08-15 15:04:21 +00:00
parent :: __construct ( $filename );
2018-01-19 13:57:58 +00:00
$this -> query ( " PRAGMA foreign_keys = 1 " );
2010-12-02 08:56:10 +00:00
return true ;
}
return false ;
}
2013-07-24 23:26:41 +00:00
2010-12-02 08:56:10 +00:00
function multi_query ( $query ) {
return $this -> _result = $this -> query ( $query );
}
2013-07-24 23:26:41 +00:00
2010-12-02 08:56:10 +00:00
function next_result () {
return false ;
2010-04-22 23:05:16 +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 ) {
$values = array ();
foreach ( $rows as $set ) {
$values [] = " ( " . implode ( " , " , $set ) . " ) " ;
}
return queries ( " REPLACE INTO " . table ( $table ) . " ( " . implode ( " , " , array_keys ( reset ( $rows ))) . " ) VALUES \n " . implode ( " , \n " , $values ));
2013-07-05 16:04:06 +00:00
}
2013-07-24 23:26:41 +00:00
2018-02-08 10:21:33 +00:00
function tableHelp ( $name ) {
if ( $name == " sqlite_sequence " ) {
return " fileformat2.html#seqtab " ;
}
if ( $name == " sqlite_master " ) {
return " fileformat2.html# $name " ;
}
}
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 () {
return new Min_DB ;
}
function get_databases () {
return array ();
}
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
}
2018-02-01 17:53:53 +00:00
function limit1 ( $table , $query , $where , $separator = " \n " ) {
2010-04-21 12:01:32 +00:00
global $connection ;
2018-02-01 17:47:57 +00:00
return ( preg_match ( '~^INTO~' , $query ) || $connection -> result ( " SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT') " )
2018-02-01 17:53:53 +00:00
? limit ( $query , $where , 1 , 0 , $separator )
2018-02-05 10:21:19 +00:00
: " $query WHERE rowid = (SELECT rowid FROM " . table ( $table ) . $where . $separator . " LIMIT 1) " //! use primary key in tables with WITHOUT rowid
2018-02-01 17:47:57 +00:00
);
2010-04-21 12:01:32 +00:00
}
function db_collation ( $db , $collations ) {
2010-04-22 23:05:16 +00:00
global $connection ;
return $connection -> result ( " PRAGMA encoding " ); // there is no database list so $db == DB
2010-04-21 12:01:32 +00:00
}
function engines () {
return array ();
}
function logged_user () {
2010-04-21 16:26:16 +00:00
return get_current_user (); // should return effective user
2010-04-21 12:01:32 +00:00
}
function tables_list () {
2010-05-27 14:10:17 +00:00
return get_key_vals ( " SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view') ORDER BY (name = 'sqlite_sequence'), name " , 1 );
2010-04-21 12:01:32 +00:00
}
function count_tables ( $databases ) {
return array ();
}
function table_status ( $name = " " ) {
2012-07-29 17:45:38 +00:00
global $connection ;
2010-04-21 12:01:32 +00:00
$return = array ();
2018-02-01 15:15:36 +00:00
foreach ( get_rows ( " SELECT name AS Name, type AS Engine, 'rowid' AS Oid, '' AS Auto_increment FROM sqlite_master WHERE type IN ('table', 'view') " . ( $name != " " ? " AND name = " . q ( $name ) : " ORDER BY name " )) as $row ) {
2012-07-29 17:45:38 +00:00
$row [ " Rows " ] = $connection -> result ( " SELECT COUNT(*) FROM " . idf_escape ( $row [ " Name " ]));
2010-04-21 12:01:32 +00:00
$return [ $row [ " Name " ]] = $row ;
}
2010-10-13 16:59:15 +00:00
foreach ( get_rows ( " SELECT * FROM sqlite_sequence " , null , " " ) as $row ) {
2010-10-13 15:53:59 +00:00
$return [ $row [ " name " ]][ " Auto_increment " ] = $row [ " seq " ];
2010-04-21 12:01:32 +00:00
}
return ( $name != " " ? $return [ $name ] : $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 ) {
global $connection ;
2012-07-15 21:38:45 +00:00
return ! $connection -> result ( " SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY') " );
2010-04-21 12:01:32 +00:00
}
2010-11-11 09:47:32 +00:00
function fields ( $table ) {
2013-08-28 15:54:23 +00:00
global $connection ;
2010-04-21 12:01:32 +00:00
$return = array ();
2013-08-07 22:31:15 +00:00
$primary = " " ;
2010-10-13 15:53:59 +00:00
foreach ( get_rows ( " PRAGMA table_info( " . table ( $table ) . " ) " ) as $row ) {
2013-08-07 22:31:15 +00:00
$name = $row [ " name " ];
2010-10-13 15:53:59 +00:00
$type = strtolower ( $row [ " type " ]);
$default = $row [ " dflt_value " ];
2013-08-07 22:31:15 +00:00
$return [ $name ] = array (
" field " => $name ,
2013-07-24 23:26:41 +00:00
" type " => ( preg_match ( '~int~i' , $type ) ? " integer " : ( preg_match ( '~char|clob|text~i' , $type ) ? " text " : ( preg_match ( '~blob~i' , $type ) ? " blob " : ( preg_match ( '~real|floa|doub~i' , $type ) ? " real " : " numeric " )))),
2010-10-13 15:53:59 +00:00
" full_type " => $type ,
2013-07-24 23:26:41 +00:00
" default " => ( preg_match ( " ~'(.*)'~ " , $default , $match ) ? str_replace ( " '' " , " ' " , $match [ 1 ]) : ( $default == " NULL " ? null : $default )),
2010-10-13 15:53:59 +00:00
" null " => ! $row [ " notnull " ],
" privileges " => array ( " select " => 1 , " insert " => 1 , " update " => 1 ),
" primary " => $row [ " pk " ],
);
2013-08-07 22:31:15 +00:00
if ( $row [ " pk " ]) {
if ( $primary != " " ) {
$return [ $primary ][ " auto_increment " ] = false ;
} elseif ( preg_match ( '~^integer$~i' , $type )) {
$return [ $name ][ " auto_increment " ] = true ;
}
2013-08-28 15:40:09 +00:00
$primary = $name ;
2013-08-07 22:31:15 +00:00
}
2010-04-21 12:01:32 +00:00
}
2013-08-28 15:54:23 +00:00
$sql = $connection -> result ( " SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q ( $table ));
preg_match_all ( '~(("[^"]*+")+|[a-z0-9_]+)\s+text\s+COLLATE\s+(\'[^\']+\'|\S+)~i' , $sql , $matches , PREG_SET_ORDER );
foreach ( $matches as $match ) {
$name = str_replace ( '""' , '"' , preg_replace ( '~^"|"$~' , '' , $match [ 1 ]));
if ( $return [ $name ]) {
$return [ $name ][ " collation " ] = trim ( $match [ 3 ], " ' " );
}
}
2010-04-21 12:01:32 +00:00
return $return ;
}
function indexes ( $table , $connection2 = null ) {
2013-08-07 23:00:37 +00:00
global $connection ;
if ( ! is_object ( $connection2 )) {
$connection2 = $connection ;
}
2010-04-21 12:01:32 +00:00
$return = array ();
2013-08-07 23:00:37 +00:00
$sql = $connection2 -> result ( " SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q ( $table ));
2018-02-07 15:43:21 +00:00
if ( preg_match ( '~\bPRIMARY\s+KEY\s*\((([^)"]+|"[^"]*"|`[^`]*`)++)~i' , $sql , $match )) {
2013-08-08 22:32:36 +00:00
$return [ " " ] = array ( " type " => " PRIMARY " , " columns " => array (), " lengths " => array (), " descs " => array ());
2018-02-07 15:43:21 +00:00
preg_match_all ( '~((("[^"]*+")+|(?:`[^`]*+`)+)|(\S+))(\s+(ASC|DESC))?(,\s*|$)~i' , $match [ 1 ], $matches , PREG_SET_ORDER );
2013-08-07 23:00:37 +00:00
foreach ( $matches as $match ) {
$return [ " " ][ " columns " ][] = idf_unescape ( $match [ 2 ]) . $match [ 4 ];
$return [ " " ][ " descs " ][] = ( preg_match ( '~DESC~i' , $match [ 5 ]) ? '1' : null );
2010-04-21 12:01:32 +00:00
}
}
2013-08-09 02:09:43 +00:00
if ( ! $return ) {
foreach ( fields ( $table ) as $name => $field ) {
if ( $field [ " primary " ]) {
2013-08-09 02:20:27 +00:00
$return [ " " ] = array ( " type " => " PRIMARY " , " columns " => array ( $name ), " lengths " => array (), " descs " => array ( null ));
2013-08-09 02:09:43 +00:00
}
}
}
2013-08-07 23:00:37 +00:00
$sqls = get_key_vals ( " SELECT name, sql FROM sqlite_master WHERE type = 'index' AND tbl_name = " . q ( $table ), $connection2 );
foreach ( get_rows ( " PRAGMA index_list( " . table ( $table ) . " ) " , $connection2 ) as $row ) {
2013-06-25 16:42:47 +00:00
$name = $row [ " name " ];
2014-02-04 17:50:31 +00:00
$index = array ( " type " => ( $row [ " unique " ] ? " UNIQUE " : " INDEX " ));
$index [ " lengths " ] = array ();
$index [ " descs " ] = array ();
foreach ( get_rows ( " PRAGMA index_info( " . idf_escape ( $name ) . " ) " , $connection2 ) as $row1 ) {
$index [ " columns " ][] = $row1 [ " name " ];
$index [ " descs " ][] = null ;
}
if ( preg_match ( '~^CREATE( UNIQUE)? INDEX ' . preg_quote ( idf_escape ( $name ) . ' ON ' . idf_escape ( $table ), '~' ) . ' \((.*)\)$~i' , $sqls [ $name ], $regs )) {
preg_match_all ( '/("[^"]*+")+( DESC)?/' , $regs [ 2 ], $matches );
foreach ( $matches [ 2 ] as $key => $val ) {
if ( $val ) {
$index [ " descs " ][ $key ] = '1' ;
2013-06-25 22:28:57 +00:00
}
2012-07-15 19:24:20 +00:00
}
2010-04-21 12:01:32 +00:00
}
2014-02-04 17:50:31 +00:00
if ( ! $return [ " " ] || $index [ " type " ] != " UNIQUE " || $index [ " columns " ] != $return [ " " ][ " columns " ] || $index [ " descs " ] != $return [ " " ][ " descs " ] || ! preg_match ( " ~^sqlite_~ " , $name )) {
$return [ $name ] = $index ;
}
2010-04-21 12:01:32 +00:00
}
return $return ;
}
function foreign_keys ( $table ) {
$return = array ();
2010-10-13 15:53:59 +00:00
foreach ( get_rows ( " PRAGMA foreign_key_list( " . table ( $table ) . " ) " ) as $row ) {
$foreign_key = & $return [ $row [ " id " ]];
//! idf_unescape in SQLite2
if ( ! $foreign_key ) {
$foreign_key = $row ;
2010-04-21 12:01:32 +00:00
}
2010-10-13 15:53:59 +00:00
$foreign_key [ " source " ][] = $row [ " from " ];
$foreign_key [ " target " ][] = $row [ " to " ];
2010-04-21 12:01:32 +00:00
}
return $return ;
}
function view ( $name ) {
global $connection ;
2010-10-13 16:04:40 +00:00
return array ( " select " => preg_replace ( '~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\\s+~iU' , '' , $connection -> result ( " SELECT sql FROM sqlite_master WHERE name = " . q ( $name )))); //! identifiers may be inside []
2010-04-21 12:01:32 +00:00
}
function collations () {
2010-04-22 23:05:16 +00:00
return ( isset ( $_GET [ " create " ]) ? get_vals ( " PRAGMA collation_list " , 1 ) : array ());
2010-04-21 12:01:32 +00:00
}
function information_schema ( $db ) {
return false ;
}
function error () {
global $connection ;
return h ( $connection -> error );
}
2013-07-24 23:26:41 +00:00
2010-10-17 06:22:36 +00:00
function check_sqlite_name ( $name ) {
// avoid creating PHP files on unsecured servers
global $connection ;
$extensions = " db|sdb|sqlite " ;
if ( ! preg_match ( " ~^[^ \\ 0]* \\ .( $extensions ) \$ ~ " , $name )) {
$connection -> error = lang ( 'Please use one of the extensions %s.' , str_replace ( " | " , " , " , $extensions ));
return false ;
}
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:05:16 +00:00
function create_database ( $db , $collation ) {
global $connection ;
2010-04-23 00:26:34 +00:00
if ( file_exists ( $db )) {
$connection -> error = lang ( 'File exists.' );
return false ;
2010-04-22 23:05:16 +00:00
}
2010-10-17 06:22:36 +00:00
if ( ! check_sqlite_name ( $db )) {
return false ;
}
2013-12-20 23:37:39 +00:00
try {
$link = new Min_SQLite ( $db );
} catch ( Exception $ex ) {
$connection -> error = $ex -> getMessage ();
return false ;
}
2010-04-23 00:26:34 +00:00
$link -> query ( 'PRAGMA encoding = "UTF-8"' );
$link -> query ( 'CREATE TABLE adminer (i)' ); // otherwise creates empty file
$link -> query ( 'DROP TABLE adminer' );
return true ;
2010-04-22 23:05:16 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-22 23:05:16 +00:00
function drop_databases ( $databases ) {
global $connection ;
2015-08-15 15:04:21 +00:00
$connection -> __construct ( " :memory: " ); // to unlock file, doesn't work in PDO on Windows
2010-04-22 23:05:16 +00:00
foreach ( $databases as $db ) {
2010-04-23 00:26:34 +00:00
if ( !@ unlink ( $db )) {
$connection -> error = lang ( 'File exists.' );
2010-04-22 23:05:16 +00:00
return false ;
}
}
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function rename_database ( $name , $collation ) {
global $connection ;
2010-10-17 06:22:36 +00:00
if ( ! check_sqlite_name ( $name )) {
return false ;
}
2015-08-15 15:04:21 +00:00
$connection -> __construct ( " :memory: " );
2010-04-23 00:26:34 +00:00
$connection -> error = lang ( 'File exists.' );
return @ rename ( DB , $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 auto_increment () {
return " PRIMARY KEY " . ( DRIVER == " sqlite " ? " AUTOINCREMENT " : " " );
}
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 ) {
2012-07-15 21:38:45 +00:00
$use_all_fields = ( $table == " " || $foreign );
foreach ( $fields as $field ) {
if ( $field [ 0 ] != " " || ! $field [ 1 ] || $field [ 2 ]) {
$use_all_fields = true ;
break ;
}
}
2010-04-21 12:01:32 +00:00
$alter = array ();
2012-07-15 21:38:45 +00:00
$originals = array ();
2010-04-21 12:01:32 +00:00
foreach ( $fields as $field ) {
2010-05-05 16:27:39 +00:00
if ( $field [ 1 ]) {
2013-08-09 02:07:18 +00:00
$alter [] = ( $use_all_fields ? $field [ 1 ] : " ADD " . implode ( $field [ 1 ]));
2012-07-15 21:38:45 +00:00
if ( $field [ 0 ] != " " ) {
$originals [ $field [ 0 ]] = $field [ 1 ][ 0 ];
}
2010-05-05 16:27:39 +00:00
}
2010-04-21 12:01:32 +00:00
}
2013-08-09 02:07:18 +00:00
if ( ! $use_all_fields ) {
2010-04-21 12:01:32 +00:00
foreach ( $alter as $val ) {
2010-05-11 14:45:04 +00:00
if ( ! queries ( " ALTER TABLE " . table ( $table ) . " $val " )) {
2010-04-21 12:01:32 +00:00
return false ;
}
}
2010-05-11 14:45:04 +00:00
if ( $table != $name && ! queries ( " ALTER TABLE " . table ( $table ) . " RENAME TO " . table ( $name ))) {
2010-04-21 12:01:32 +00:00
return false ;
}
2013-08-09 02:07:18 +00:00
} elseif ( ! recreate_table ( $table , $name , $alter , $originals , $foreign )) {
return false ;
2010-04-21 12:01:32 +00:00
}
if ( $auto_increment ) {
2010-10-13 16:04:40 +00:00
queries ( " UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . q ( $name )); // ignores error
2010-04-21 12:01:32 +00:00
}
return true ;
}
2013-07-24 23:26:41 +00:00
2013-08-09 22:16:15 +00:00
function recreate_table ( $table , $name , $fields , $originals , $foreign , $indexes = array ()) {
2013-08-08 22:32:36 +00:00
if ( $table != " " ) {
2013-08-09 22:16:15 +00:00
if ( ! $fields ) {
foreach ( fields ( $table ) as $key => $field ) {
2018-02-07 13:47:29 +00:00
if ( $indexes ) {
$field [ " auto_increment " ] = 0 ;
}
2013-08-09 22:16:15 +00:00
$fields [] = process_field ( $field , $field );
$originals [ $key ] = idf_escape ( $key );
}
}
2013-08-09 02:07:18 +00:00
$primary_key = false ;
2014-01-30 17:35:17 +00:00
foreach ( $fields as $field ) {
2013-08-09 02:07:18 +00:00
if ( $field [ 6 ]) {
$primary_key = true ;
}
}
$drop_indexes = array ();
foreach ( $indexes as $key => $val ) {
if ( $val [ 2 ] == " DROP " ) {
$drop_indexes [ $val [ 1 ]] = true ;
unset ( $indexes [ $key ]);
}
}
foreach ( indexes ( $table ) as $key_name => $index ) {
$columns = array ();
foreach ( $index [ " columns " ] as $key => $column ) {
if ( ! $originals [ $column ]) {
continue 2 ;
}
$columns [] = $originals [ $column ] . ( $index [ " descs " ][ $key ] ? " DESC " : " " );
}
if ( ! $drop_indexes [ $key_name ]) {
2013-08-09 02:20:27 +00:00
if ( $index [ " type " ] != " PRIMARY " || ! $primary_key ) {
2013-08-09 02:07:18 +00:00
$indexes [] = array ( $index [ " type " ], $key_name , $columns );
}
}
}
2013-08-09 02:20:27 +00:00
foreach ( $indexes as $key => $val ) {
if ( $val [ 0 ] == " PRIMARY " ) {
unset ( $indexes [ $key ]);
2014-01-30 17:35:17 +00:00
$foreign [] = " PRIMARY KEY ( " . implode ( " , " , $val [ 2 ]) . " ) " ;
2013-08-09 02:20:27 +00:00
}
}
2013-08-09 22:16:15 +00:00
foreach ( foreign_keys ( $table ) as $key_name => $foreign_key ) {
foreach ( $foreign_key [ " source " ] as $key => $column ) {
2013-08-08 22:32:36 +00:00
if ( ! $originals [ $column ]) {
continue 2 ;
}
2013-08-09 22:16:15 +00:00
$foreign_key [ " source " ][ $key ] = idf_unescape ( $originals [ $column ]);
}
if ( ! isset ( $foreign [ " $key_name " ])) {
$foreign [] = " " . format_foreign_key ( $foreign_key );
2013-08-08 22:32:36 +00:00
}
}
2014-01-30 17:35:17 +00:00
queries ( " BEGIN " );
}
foreach ( $fields as $key => $field ) {
$fields [ $key ] = " " . implode ( $field );
2013-08-08 22:32:36 +00:00
}
2013-08-09 22:16:15 +00:00
$fields = array_merge ( $fields , array_filter ( $foreign ));
if ( ! queries ( " CREATE TABLE " . table ( $table != " " ? " adminer_ $name " : $name ) . " ( \n " . implode ( " , \n " , $fields ) . " \n ) " )) {
2013-08-08 22:32:36 +00:00
// implicit ROLLBACK to not overwrite $connection->error
return false ;
}
if ( $table != " " ) {
if ( $originals && ! queries ( " INSERT INTO " . table ( " adminer_ $name " ) . " ( " . implode ( " , " , $originals ) . " ) SELECT " . implode ( " , " , array_map ( 'idf_escape' , array_keys ( $originals ))) . " FROM " . table ( $table ))) {
return false ;
}
$triggers = array ();
foreach ( triggers ( $table ) as $trigger_name => $timing_event ) {
$trigger = trigger ( $trigger_name );
$triggers [] = " CREATE TRIGGER " . idf_escape ( $trigger_name ) . " " . implode ( " " , $timing_event ) . " ON " . table ( $name ) . " \n $trigger[Statement] " ;
}
if ( ! queries ( " DROP TABLE " . table ( $table ))) { // drop before creating indexes and triggers to allow using old names
return false ;
}
queries ( " ALTER TABLE " . table ( " adminer_ $name " ) . " RENAME TO " . table ( $name ));
if ( ! alter_indexes ( $name , $indexes )) {
return false ;
}
foreach ( $triggers as $trigger ) {
if ( ! queries ( $trigger )) {
return false ;
}
}
queries ( " COMMIT " );
}
return true ;
}
2013-04-03 17:46:51 +00:00
function index_sql ( $table , $type , $name , $columns ) {
return " CREATE $type " . ( $type != " INDEX " ? " INDEX " : " " )
. idf_escape ( $name != " " ? $name : uniqid ( $table . " _ " ))
. " ON " . table ( $table )
. " $columns "
;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function alter_indexes ( $table , $alter ) {
2013-08-08 22:32:36 +00:00
foreach ( $alter as $primary ) {
if ( $primary [ 0 ] == " PRIMARY " ) {
2013-08-09 22:16:15 +00:00
return recreate_table ( $table , $table , array (), array (), array (), $alter );
2013-08-08 22:32:36 +00:00
}
}
2013-06-24 17:04:07 +00:00
foreach ( array_reverse ( $alter ) as $val ) {
2011-07-13 13:13:00 +00:00
if ( ! queries ( $val [ 2 ] == " DROP "
? " DROP INDEX " . idf_escape ( $val [ 1 ])
2014-01-12 03:22:44 +00:00
: index_sql ( $table , $val [ 0 ], $val [ 1 ], " ( " . implode ( " , " , $val [ 2 ]) . " ) " )
2011-07-13 13:13:00 +00:00
)) {
2010-04-21 12:01:32 +00:00
return false ;
}
}
return true ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function truncate_tables ( $tables ) {
2010-05-17 16:18:32 +00:00
return apply_queries ( " DELETE FROM " , $tables );
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_views ( $views ) {
2010-05-17 16:18:32 +00:00
return apply_queries ( " DROP VIEW " , $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-17 16:18:32 +00:00
return apply_queries ( " DROP 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 ) {
return false ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function trigger ( $name ) {
global $connection ;
2011-08-08 16:18:16 +00:00
if ( $name == " " ) {
2011-08-10 16:14:27 +00:00
return array ( " Statement " => " BEGIN \n \t ; \n END " );
2011-08-08 16:18:16 +00:00
}
2014-03-15 17:58:24 +00:00
$idf = '(?:[^`"\\s]+|`[^`]*`|"[^"]*")+' ;
$trigger_options = trigger_options ();
2013-12-21 00:12:26 +00:00
preg_match (
2014-03-15 17:58:24 +00:00
" ~^CREATE \\ s+TRIGGER \\ s* $idf\\s *( " . implode ( " | " , $trigger_options [ " Timing " ]) . " ) \\ s+([a-z]+)(?: \\ s+OF \\ s+( $idf ))? \\ s+ON \\ s* $idf\\s *(?:FOR \\ s+EACH \\ s+ROW \\ s)?(.*)~is " ,
2013-12-21 00:12:26 +00:00
$connection -> result ( " SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = " . q ( $name )),
$match
);
2014-03-15 20:13:18 +00:00
$of = $match [ 3 ];
return array (
" Timing " => strtoupper ( $match [ 1 ]),
" Event " => strtoupper ( $match [ 2 ]) . ( $of ? " OF " : " " ),
" Of " => ( $of [ 0 ] == '`' || $of [ 0 ] == '"' ? idf_unescape ( $of ) : $of ),
" Trigger " => $name ,
" Statement " => $match [ 4 ],
);
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 ();
2014-03-15 17:58:24 +00:00
$trigger_options = trigger_options ();
2010-10-13 16:04:40 +00:00
foreach ( get_rows ( " SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . q ( $table )) as $row ) {
2014-03-15 17:58:24 +00:00
preg_match ( '~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*(' . implode ( " | " , $trigger_options [ " Timing " ]) . ')\\s*(.*)\\s+ON\\b~iU' , $row [ " sql " ], $match );
2010-04-21 12:01:32 +00:00
$return [ $row [ " name " ]] = array ( $match [ 1 ], $match [ 2 ]);
}
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 " , " INSTEAD OF " ),
2014-03-15 17:58:24 +00:00
" Event " => array ( " INSERT " , " UPDATE " , " UPDATE OF " , " DELETE " ),
2010-04-22 15:53:42 +00:00
" Type " => array ( " FOR EACH ROW " ),
);
}
2013-07-24 23:26:41 +00:00
2010-04-23 23:49:21 +00:00
function begin () {
return queries ( " BEGIN " );
}
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 LAST_INSERT_ROWID() " );
}
2013-07-24 23:26:41 +00:00
2010-04-21 12:01:32 +00:00
function explain ( $connection , $query ) {
2015-03-06 18:02:45 +00:00
return $connection -> query ( " EXPLAIN QUERY PLAN $query " );
2010-04-21 12:01:32 +00:00
}
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-05-27 14:10:17 +00:00
function types () {
return array ();
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:30:55 +00:00
function schemas () {
return array ();
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:30:55 +00:00
function get_schema () {
return " " ;
}
2013-07-24 23:26:41 +00:00
2010-05-05 16:30:55 +00:00
function set_schema ( $scheme ) {
return true ;
}
2013-07-24 23:26:41 +00:00
2018-01-22 13:33:21 +00:00
function create_sql ( $table , $auto_increment , $style ) {
2010-04-21 12:01:32 +00:00
global $connection ;
2013-04-29 21:46:06 +00:00
$return = $connection -> result ( " SELECT sql FROM sqlite_master WHERE type IN ('table', 'view') AND name = " . q ( $table ));
2013-04-03 17:46:51 +00:00
foreach ( indexes ( $table ) as $name => $index ) {
if ( $name == '' ) {
continue ;
}
$return .= " ; \n \n " . index_sql ( $table , $index [ 'type' ], $name , " ( " . implode ( " , " , array_map ( 'idf_escape' , $index [ 'columns' ])) . " ) " );
}
return $return ;
2010-04-21 12:01:32 +00:00
}
2013-07-24 23:26:41 +00:00
2010-05-27 14:10:17 +00:00
function truncate_sql ( $table ) {
return " DELETE FROM " . table ( $table );
}
2013-07-24 23:26:41 +00:00
2010-04-21 22:37:16 +00:00
function use_sql ( $database ) {
}
2013-07-24 23:26:41 +00:00
2018-01-22 13:14:42 +00:00
function trigger_sql ( $table ) {
2011-08-08 15:56:20 +00:00
return implode ( get_vals ( " SELECT sql || ';; \n ' FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . q ( $table )));
2010-05-05 16:28:37 +00:00
}
2013-07-24 23:26:41 +00:00
2010-04-21 15:09:52 +00:00
function show_variables () {
global $connection ;
$return = array ();
2010-04-21 23:06:32 +00:00
foreach ( array ( " auto_vacuum " , " cache_size " , " count_changes " , " default_cache_size " , " empty_result_callbacks " , " encoding " , " foreign_keys " , " full_column_names " , " fullfsync " , " journal_mode " , " journal_size_limit " , " legacy_file_format " , " locking_mode " , " page_size " , " max_page_count " , " read_uncommitted " , " recursive_triggers " , " reverse_unordered_selects " , " secure_delete " , " short_column_names " , " synchronous " , " temp_store " , " temp_store_directory " , " schema_version " , " integrity_check " , " quick_check " ) as $key ) {
2010-04-21 15:09:52 +00:00
$return [ $key ] = $connection -> result ( " PRAGMA $key " );
}
return $return ;
}
2013-07-24 23:26:41 +00:00
2010-04-21 15:09:52 +00:00
function show_status () {
2010-04-21 23:06:32 +00:00
$return = array ();
foreach ( get_vals ( " PRAGMA compile_options " ) as $option ) {
list ( $key , $val ) = explode ( " = " , $option , 2 );
$return [ $key ] = $val ;
}
return $return ;
2010-04-21 15:09:52 +00:00
}
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-12-21 00:30:22 +00:00
return preg_match ( '~^(columns|database|drop_col|dump|indexes|move_col|sql|status|table|trigger|variables|view|view_trigger)$~' , $feature );
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 = " sqlite " ;
2010-04-21 12:01:32 +00:00
$types = array ( " integer " => 0 , " real " => 0 , " numeric " => 0 , " text " => 0 , " blob " => 0 );
$structured_types = array_keys ( $types );
$unsigned = array ();
2013-04-26 19:04:28 +00:00
$operators = array ( " = " , " < " , " > " , " <= " , " >= " , " != " , " LIKE " , " LIKE %% " , " IN " , " IS NULL " , " NOT LIKE " , " NOT IN " , " IS NOT NULL " , " SQL " ); // REGEXP can be user defined function
2010-04-21 12:01:32 +00:00
$functions = array ( " hex " , " length " , " lower " , " round " , " unixepoch " , " upper " );
$grouping = array ( " avg " , " count " , " count distinct " , " group_concat " , " max " , " min " , " sum " );
$edit_functions = array (
array (
// "text" => "date('now')/time('now')/datetime('now')",
), array (
" integer|real|numeric " => " +/- " ,
// "text" => "date/time/datetime",
" text " => " || " ,
)
);
}