2010-04-21 12:01:32 +00:00
< ? php
$possible_drivers [] = " SQLite " ;
$possible_drivers [] = " SQLite3 " ;
$possible_drivers [] = " PDO_SQLite " ;
if ( extension_loaded ( " sqlite3 " ) || extension_loaded ( " pdo_sqlite " )) {
$drivers [ " sqlite " ] = " SQLite 3 " ;
}
if ( extension_loaded ( " sqlite " ) || extension_loaded ( " pdo_sqlite " )) {
$drivers [ " sqlite2 " ] = " SQLite 2 " ;
}
if ( isset ( $_GET [ " sqlite " ]) || isset ( $_GET [ " sqlite2 " ])) {
define ( " DRIVER " , ( isset ( $_GET [ " sqlite " ]) ? " sqlite " : " sqlite2 " ));
if ( extension_loaded ( isset ( $_GET [ " sqlite2 " ]) ? " sqlite " : " sqlite3 " )) {
if ( isset ( $_GET [ " sqlite2 " ])) {
class Min_SQLite {
2010-04-22 23:05:16 +00:00
var $extension = " SQLite " , $server_info , $affected_rows , $error , $_link ;
2010-04-21 12:01:32 +00:00
function __construct () {
$this -> server_info = sqlite_libversion ();
2010-04-22 23:05:16 +00:00
$this -> _link = new SQLiteDatabase ( " :memory: " );
2010-04-21 12:01:32 +00:00
}
function open ( $filename ) {
2010-04-22 23:05:16 +00:00
$this -> _link = new SQLiteDatabase ( $filename );
}
function close () {
$this -> _link = null ;
2010-04-21 12:01:32 +00:00
}
function query ( $query , $unbuffered = false ) {
$method = ( $unbuffered ? " unbufferedQuery " : " query " );
2010-04-22 23:05:16 +00:00
$result = @ $this -> _link -> $method ( $query , SQLITE_BOTH , $error );
2010-04-21 12:01:32 +00:00
if ( ! $result ) {
$this -> error = $error ;
return false ;
} elseif ( $result === true ) {
$this -> affected_rows = $this -> changes ();
return true ;
}
return new Min_Result ( $result );
}
function quote ( $string ) {
return " ' " . sqlite_escape_string ( $string ) . " ' " ;
}
function result ( $query , $field = 0 ) {
$result = $this -> query ( $query );
2010-04-21 15:09:52 +00:00
if ( ! is_object ( $result )) {
2010-04-21 12:01:32 +00:00
return false ;
}
$row = $result -> _result -> fetch ();
return $row [ $field ];
}
}
class Min_Result {
var $_result , $_offset = 0 , $num_rows ;
function __construct ( $result ) {
$this -> _result = $result ;
if ( method_exists ( $result , 'numRows' )) { // not available in unbuffered query
$this -> num_rows = $result -> numRows ();
}
}
function fetch_assoc () {
$row = $this -> _result -> fetch ( SQLITE_ASSOC );
if ( ! $row ) {
return false ;
}
$return = array ();
foreach ( $row as $key => $val ) {
$return [( $key [ 0 ] == '"' ? idf_unescape ( $key ) : $key )] = $val ;
}
return $return ;
}
function fetch_row () {
return $this -> _result -> fetch ( SQLITE_NUM );
}
function fetch_field () {
2010-04-21 22:22:23 +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-04-21 22:22:23 +00:00
" name " => $name ,
" orgname " => $name ,
" orgtable " => $table ,
2010-04-21 12:01:32 +00:00
);
}
}
} else {
2010-04-21 15:09:52 +00:00
class Min_SQLite {
2010-04-22 23:05:16 +00:00
var $extension = " SQLite3 " , $server_info , $affected_rows , $error , $_link ;
2010-04-21 12:01:32 +00:00
function __construct () {
2010-04-22 23:05:16 +00:00
$this -> _link = new SQLite3 ( " :memory: " ); // required to display variables
$version = $this -> _link -> version ();
2010-04-21 12:01:32 +00:00
$this -> server_info = $version [ " versionString " ];
}
function open ( $filename ) {
2010-04-22 23:05:16 +00:00
$this -> _link = new SQLite3 ( $filename );
}
function close () {
$this -> _link -> close ();
2010-04-21 12:01:32 +00:00
}
function query ( $query ) {
2010-04-22 23:05:16 +00:00
$result = @ $this -> _link -> query ( $query );
2010-04-21 12:01:32 +00:00
if ( ! $result ) {
2010-04-22 23:05:16 +00:00
$this -> error = $this -> _link -> lastErrorMsg ();
2010-04-21 12:01:32 +00:00
return false ;
} elseif ( $result -> numColumns ()) {
return new Min_Result ( $result );
}
2010-04-22 23:05:16 +00:00
$this -> affected_rows = $this -> _link -> changes ();
2010-04-21 12:01:32 +00:00
return true ;
}
function quote ( $string ) {
2010-04-22 23:05:16 +00:00
return " ' " . $this -> _link -> escapeString ( $string ) . " ' " ;
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 ;
}
$row = $result -> _result -> fetchArray ();
return $row [ $field ];
}
}
class Min_Result {
var $_result , $_offset = 0 , $num_rows ;
function __construct ( $result ) {
$this -> _result = $result ;
$this -> num_rows = 1 ; //!
}
function fetch_assoc () {
return $this -> _result -> fetchArray ( SQLITE3_ASSOC );
}
function fetch_row () {
return $this -> _result -> fetchArray ( SQLITE3_NUM );
}
function fetch_field () {
$column = $this -> _offset ++ ;
2010-04-21 22:22:23 +00:00
$type = $this -> _result -> columnType ( $column );
2010-04-21 12:01:32 +00:00
return ( object ) array (
" name " => $this -> _result -> columnName ( $column ),
2010-04-21 22:22:23 +00:00
" type " => $type ,
" charsetnr " => ( $type == SQLITE3_BLOB ? 63 : 0 ), // 63 - binary
2010-04-21 12:01:32 +00:00
);
}
function __desctruct () {
return $this -> _result -> finalize ();
}
}
}
} 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 " ;
2010-04-22 23:05:16 +00:00
function __construct () {
$this -> dsn ( DRIVER . " ::memory: " , " " , " " );
}
function open ( $filename ) {
2010-04-21 12:01:32 +00:00
static $connected = false ;
if ( $connected ) {
return true ;
}
$connected = true ;
2010-04-22 23:05:16 +00:00
$this -> dsn ( DRIVER . " : $filename " , " " , " " );
2010-04-21 12:01:32 +00:00
return true ;
}
2010-04-22 23:05:16 +00:00
function close () {
// no known way
}
2010-04-21 12:01:32 +00:00
}
}
2010-04-22 23:05:16 +00:00
class Min_DB extends Min_SQLite {
function select_db ( $filename ) {
if ( ! is_readable ( $filename )) { //! verify database format
return false ;
}
set_exception_handler ( 'connect_error' ); // try/catch is not compatible with PHP 4
$this -> open ( $filename );
restore_exception_handler ();
return true ;
}
function multi_query ( $query ) {
return $this -> _result = $this -> query ( $query );
}
function store_result () {
return $this -> _result ;
}
function next_result () {
return false ;
}
}
2010-04-21 12:01:32 +00:00
function idf_escape ( $idf ) {
return '"' . str_replace ( '"' , '""' , $idf ) . '"' ;
}
function connect () {
global $connection ;
if ( $connection ) {
return $connection ; // can connect only once, function to get number of rows doesn't exist anyway
}
return new Min_DB ;
}
function get_databases () {
return array ();
}
function limit ( $query , $limit , $offset = 0 ) {
return " $query " . ( isset ( $limit ) ? " \n LIMIT $limit " . ( $offset ? " OFFSET $offset " : " " ) : " " );
}
function limit1 ( $query ) {
global $connection ;
return ( $connection -> result ( " SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT') " ) ? limit ( $query , 1 ) : " $query " );
}
function db_collation ( $db , $collations ) {
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 () {
return get_key_vals ( " SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view') " , 1 );
}
function count_tables ( $databases ) {
return array ();
}
function table_status ( $name = " " ) {
global $connection ;
$return = array ();
$result = $connection -> query ( " SELECT name AS Name, type AS Engine FROM sqlite_master WHERE type IN ('table', 'view') " . ( $name != " " ? " AND name = " . $connection -> quote ( $name ) : " " ));
while ( $row = $result -> fetch_assoc ()) {
2010-04-21 15:09:52 +00:00
$row [ " Auto_increment " ] = " " ;
2010-04-21 12:01:32 +00:00
$return [ $row [ " Name " ]] = $row ;
}
$result = $connection -> query ( " SELECT * FROM sqlite_sequence " );
if ( $result ) {
while ( $row = $result -> fetch_assoc ()) {
$return [ $row [ " name " ]][ " Auto_increment " ] = $row [ " seq " ];
}
}
return ( $name != " " ? $return [ $name ] : $return );
}
function fk_support ( $table_status ) {
global $connection ;
return ! $connection -> result ( " SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY') " );
}
function fields ( $table ) {
global $connection ;
$return = array ();
$result = $connection -> query ( " PRAGMA table_info( " . idf_escape ( $table ) . " ) " );
if ( is_object ( $result )) {
while ( $row = $result -> fetch_assoc ()) {
$type = strtolower ( $row [ " type " ]);
$return [ $row [ " name " ]] = array (
" field " => $row [ " name " ],
" type " => ( eregi ( " int " , $type ) ? " integer " : ( eregi ( " char|clob|text " , $type ) ? " text " : ( eregi ( " blob " , $type ) ? " blob " : ( eregi ( " real|floa|doub " , $type ) ? " real " : " numeric " )))),
" full_type " => $type ,
" default " => $row [ " dflt_value " ],
" null " => ! $row [ " notnull " ],
" auto_increment " => eregi ( '^integer$' , $type ) && $row [ " pk " ], //! possible false positive
" collation " => null , //!
" privileges " => array ( " select " => 1 , " insert " => 1 , " update " => 1 ),
" primary " => $row [ " pk " ],
);
}
}
return $return ;
}
function indexes ( $table , $connection2 = null ) {
global $connection ;
$return = array ();
$primary = array ();
foreach ( fields ( $table ) as $field ) {
if ( $field [ " primary " ]) {
$primary [] = $field [ " field " ];
}
}
if ( $primary ) {
$return [ " " ] = array ( " type " => " PRIMARY " , " columns " => $primary , " lengths " => array ());
}
$result = $connection -> query ( " PRAGMA index_list( " . idf_escape ( $table ) . " ) " );
if ( is_object ( $result )) {
while ( $row = $result -> fetch_assoc ()) {
$return [ $row [ " name " ]][ " type " ] = ( $row [ " unique " ] ? " UNIQUE " : " INDEX " );
$return [ $row [ " name " ]][ " lengths " ] = array ();
$result1 = $connection -> query ( " PRAGMA index_info( " . idf_escape ( $row [ " name " ]) . " ) " );
while ( $row1 = $result1 -> fetch_assoc ()) {
$return [ $row [ " name " ]][ " columns " ][] = $row1 [ " name " ];
}
}
}
return $return ;
}
function foreign_keys ( $table ) {
global $connection ;
$return = array ();
$result = $connection -> query ( " PRAGMA foreign_key_list( " . idf_escape ( $table ) . " ) " );
if ( is_object ( $result )) {
while ( $row = $result -> fetch_assoc ()) {
$foreign_key = & $return [ $row [ " id " ]];
2010-04-22 23:05:16 +00:00
//! idf_unescape in SQLite2
2010-04-21 12:01:32 +00:00
if ( ! $foreign_key ) {
$foreign_key = $row ;
}
$foreign_key [ " source " ][] = $row [ " from " ];
$foreign_key [ " target " ][] = $row [ " to " ];
}
}
return $return ;
}
function view ( $name ) {
global $connection ;
return array ( " select " => preg_replace ( '~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\\s+~iU' , '' , $connection -> result ( " SELECT sql FROM sqlite_master WHERE name = " . $connection -> quote ( $name )))); //! identifiers may be inside []
}
function collations () {
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 );
}
function exact_value ( $val ) {
global $connection ;
return $connection -> quote ( $val );
}
2010-04-22 23:05:16 +00:00
function create_database ( $db , $collation ) {
global $connection ;
// SQLITE3_OPEN_CREATE is not respected
// PRAGMA encoding = "UTF-8" is not respected
if ( ! file_exists ( $db ) && touch ( $db )) {
return true ;
}
$connection -> error = lang ( 'File can not be created.' );
return false ;
}
function drop_databases ( $databases ) {
global $connection ;
$connection -> close ();
foreach ( $databases as $db ) {
if ( ! unlink ( $db )) {
return false ;
}
}
return true ;
}
2010-04-21 12:01:32 +00:00
function rename_database ( $name , $collation ) {
global $connection ;
2010-04-22 23:05:16 +00:00
$connection -> close ();
2010-04-21 12:01:32 +00:00
return rename ( DB , $name );
}
function auto_increment () {
return " PRIMARY KEY " . ( DRIVER == " sqlite " ? " AUTOINCREMENT " : " " );
}
function alter_table ( $table , $name , $fields , $foreign , $comment , $engine , $collation , $auto_increment , $partitioning ) {
global $connection ;
$alter = array ();
foreach ( $fields as $field ) {
$alter [] = ( $table != " " && $field [ 0 ] == " " ? " ADD " : " " ) . implode ( " " , $field [ 1 ]);
}
$alter = array_merge ( $alter , $foreign );
if ( $table != " " ) {
foreach ( $alter as $val ) {
if ( ! queries ( " ALTER TABLE " . idf_escape ( $table ) . " $val " )) {
return false ;
}
}
if ( $table != $name && ! queries ( " ALTER TABLE " . idf_escape ( $table ) . " RENAME TO " . idf_escape ( $name ))) {
return false ;
}
} elseif ( ! queries ( " CREATE TABLE " . idf_escape ( $name ) . " ( \n " . implode ( " , \n " , $alter ) . " \n ) " )) {
return false ;
}
if ( $auto_increment ) {
2010-04-22 23:05:16 +00:00
queries ( " UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . $connection -> quote ( $name )); // ignores error
2010-04-21 12:01:32 +00:00
}
return true ;
}
function alter_indexes ( $table , $alter ) {
foreach ( $alter as $val ) {
if ( ! queries (( $val [ 2 ] ? " DROP INDEX " : " CREATE " . ( $val [ 0 ] != " INDEX " ? " UNIQUE " : " " ) . " INDEX " . idf_escape ( uniqid ( $table . " _ " )) . " ON " . idf_escape ( $table )) . " $val[1] " )) { //! primary key must be created in CREATE TABLE
return false ;
}
}
return true ;
}
function truncate_tables ( $tables ) {
foreach ( $tables as $table ) {
if ( ! queries ( " DELETE FROM " . idf_escape ( $table ))) {
return false ;
}
}
return true ;
}
function drop_views ( $views ) {
foreach ( $views as $view ) {
if ( ! queries ( " DROP VIEW " . idf_escape ( $view ))) {
return false ;
}
}
return true ;
}
function drop_tables ( $tables ) {
foreach ( $tables as $table ) {
if ( ! queries ( " DROP TABLE " . idf_escape ( $table ))) {
return false ;
}
}
return true ;
}
function trigger ( $name ) {
global $connection ;
preg_match ( '~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s+([a-z]+)\\s+ON\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*(?:FOR\\s*EACH\\s*ROW\\s)?(.*)~is' , $connection -> result ( " SELECT sql FROM sqlite_master WHERE name = " . $connection -> quote ( $name )), $match );
return array ( " Timing " => strtoupper ( $match [ 1 ]), " Event " => strtoupper ( $match [ 2 ]), " Trigger " => $name , " Statement " => $match [ 3 ]);
}
function triggers ( $table ) {
global $connection ;
$return = array ();
$result = $connection -> query ( " SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . $connection -> quote ( $table ));
while ( $row = $result -> fetch_assoc ()) {
preg_match ( '~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s*([a-z]+)~i' , $row [ " sql " ], $match );
$return [ $row [ " name " ]] = array ( $match [ 1 ], $match [ 2 ]);
}
return $return ;
}
2010-04-22 15:53:42 +00:00
function trigger_options () {
return array (
" Timing " => array ( " BEFORE " , " AFTER " , " INSTEAD OF " ),
" Type " => array ( " FOR EACH ROW " ),
);
}
2010-04-21 12:01:32 +00:00
function explain ( $connection , $query ) {
return $connection -> query ( " EXPLAIN $query " );
}
function create_sql ( $table ) {
global $connection ;
return $connection -> result ( " SELECT sql FROM sqlite_master WHERE name = " . $connection -> quote ( $table ));
}
2010-04-21 22:37:16 +00:00
function use_sql ( $database ) {
global $connection ;
return " ATTACH " . $connection -> quote ( $database ) . " AS " . idf_escape ( $database );
}
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 ;
}
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
}
2010-04-21 12:01:32 +00:00
function support ( $feature ) {
2010-04-21 23:06:32 +00:00
return ereg ( '^(view|trigger|variables|status)$' , $feature );
2010-04-21 12:01:32 +00:00
}
$driver = " sqlite " ;
$types = array ( " integer " => 0 , " real " => 0 , " numeric " => 0 , " text " => 0 , " blob " => 0 );
$structured_types = array_keys ( $types );
$unsigned = array ();
$operators = array ( " = " , " < " , " > " , " <= " , " >= " , " != " , " LIKE " , " LIKE %% " , " IN " , " IS NULL " , " NOT LIKE " , " NOT IN " , " IS NOT NULL " ); // REGEXP can be user defined function
$functions = array ( " hex " , " length " , " lower " , " round " , " unixepoch " , " upper " );
$grouping = array ( " avg " , " count " , " count distinct " , " group_concat " , " max " , " min " , " sum " );
$edit_functions = array (
array (
// "text" => "date('now')/time('now')/datetime('now')",
), array (
" integer|real|numeric " => " +/- " ,
// "text" => "date/time/datetime",
" text " => " || " ,
)
);
}