2013-07-07 06:49:38 +00:00
< ? php
/**
* @ package SQLite Integration
* @ author Kojima Toshiyasu , Justin Adie
*
*/
/**
* This class does the real work
* accepts a request from wpdb class , initialize PDO instance ,
* execute SQL statement , and returns the results to wpdb class .
*/
class PDOEngine extends PDO {
public $is_error = false ;
public $found_rows_result ;
private $rewritten_query ;
private $query_type ;
private $results = null ;
private $_results = null ;
private $pdo ;
private $prepared_query ;
private $extracted_variables = array ();
private $error_messages = array ();
private $errors ;
public $queries = array ();
private $last_insert_id ;
private $affected_rows ;
private $column_names ;
private $num_rows ;
private $return_value ;
private $can_insert_multiple_rows = false ;
private $param_num ;
protected $has_active_transaction = false ;
/**
* Constructor
* @ param array $DatabaseParams
*/
function __construct () {
$this -> init ();
}
function __destruct () {
$this -> pdo = null ;
return true ;
}
/**
* Function to initialize database
* checks if there ' s a database directory and database file , creates the tables ,
* and binds the user defined function to the pdo object
* @ return boolean
*/
private function init () {
$dsn = 'sqlite:' . FQDB ;
$result = $this -> prepare_directory ();
if ( ! $result ) return false ;
if ( is_file ( FQDB )) {
$locked = false ;
do {
try {
if ( $locked ) $locked = false ;
$this -> pdo = new PDO (
$dsn , // data source name
null , // user name
null , // user password
array ( // PDO options
PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION
));
$statement = $this -> pdo -> query ( " SELECT COUNT(*) FROM sqlite_master WHERE type='table' " );
$number_of_tables = $statement -> fetchColumn ( 0 );
$statement = null ;
if ( $number_of_tables == 0 ) {
$this -> make_sqlite_tables ();
}
} catch ( PDOException $err ) {
$status = $err -> getCode ();
// code 5 => The database file is locked
// code 6 => A table in the database is locked
if ( $status == 5 || $status == 6 ) {
$locked = true ;
} else {
$message = __ ( " Database connection error!<br /> " , 'sqlite-integration' );
2013-07-24 02:31:01 +00:00
$message .= sprintf ( __ ( " Error message is: %s " , 'sqlite-integration' ), $err -> getMessage ());
2013-07-07 06:49:38 +00:00
$this -> set_error ( __LINE__ , __FUNCTION__ , $message );
return false ;
}
}
} while ( $locked );
require_once UDF_FILE ;
new PDOSQLiteUDFS ( $this -> pdo );
if ( version_compare ( $this -> get_sqlite_version (), '3.7.11' , '>=' )) {
$this -> can_insert_multiple_rows = true ;
}
} else { // database file is not found, so we make it and create tables...
try {
$this -> pdo = new PDO ( $dsn , null , null , array ( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION ));
} catch ( PDOException $err ) {
$message = __ ( " Database connection error!<br /> " , 'sqlite-integration' );
$message .= sprintf ( __ ( " Error message is: %s " , 'sqlite-integration' ), $err -> getMessage ());
$this -> set_error ( __LINE__ , __FUNCTION__ , $message );
return false ;
}
$this -> make_sqlite_tables ();
}
}
/**
* Make database direcotry and . htaccess file
* executed once while installation process
*/
private function prepare_directory () {
global $wpdb ;
$u = umask ( 0000 );
if ( ! is_dir ( FQDBDIR )) {
if ( !@ mkdir ( FQDBDIR , 0777 , true )) {
umask ( $u );
2013-08-13 00:34:40 +00:00
$message = 'Unable to create the required directory! Please check your server settings.' ;
2013-07-07 06:49:38 +00:00
echo $message ;
return false ;
}
}
if ( ! is_writable ( FQDBDIR )) {
umask ( $u );
2013-08-13 00:34:40 +00:00
$message = 'Unable to create a file in the directory! Please check your server settings.' ;
2013-07-07 06:49:38 +00:00
echo $message ;
return false ;
}
if ( ! is_file ( FQDBDIR . '.htaccess' )) {
$fh = fopen ( FQDBDIR . '.htaccess' , " w " );
if ( ! $fh ) {
umask ( $u );
2013-08-13 00:34:40 +00:00
$message = 'Unable to create a file in the directory! Please check your server settings.' ;
2013-07-07 06:49:38 +00:00
echo $message ;
return false ;
}
fwrite ( $fh , " DENY FROM ALL " );
fclose ( $fh );
}
umask ( $u );
return true ;
}
/**
* Make database file itself and WordPress tables
* executed once while installation process
*/
private function make_sqlite_tables () {
require_once PDODIR . " install.php " ;
}
public function query ( $query ) {
$this -> flush ();
$this -> queries [] = " Raw query: \t $query " ;
$res = $this -> determine_query_type ( $query );
if ( ! $res ) {
$bailoutString = sprintf ( __ ( " <h1>Unknown query type</h1><p>Sorry, we cannot determine the type of query that is requested.</p><p>The query is %s</p> " , 'sqlite-integration' ), $query );
$this -> set_error ( __LINE__ , __FUNCTION__ , $bailoutString );
}
switch ( strtolower ( $this -> query_type )) {
case 'foundrows' :
$this -> results = $this -> found_rows_result ;
$this -> num_rows = count ( $this -> results );
$this -> found_rows_result = null ;
break ;
case 'insert' :
if ( $this -> can_insert_multiple_rows ) {
$this -> execute_insert_query_new ( $query );
} else {
$this -> execute_insert_query ( $query );
}
break ;
case 'create' :
$result = $this -> execute_create_query ( $query );
$this -> return_value = $result ;
break ;
case 'alter' :
$result = $this -> execute_alter_query ( $query );
$this -> return_value = $result ;
break ;
case 'show_variables' :
$result = $this -> show_variables_workaround ( $query );
break ;
2013-07-24 02:31:01 +00:00
case 'drop_index' :
$pattern = '/^\\s*(DROP\\s*INDEX\\s*.*?)\\s*ON\\s*(.*)/im' ;
if ( preg_match ( $pattern , $query , $match )) {
$drop_query = 'ALTER TABLE ' . trim ( $match [ 2 ]) . ' ' . trim ( $match [ 1 ]);
$this -> query_type = 'alter' ;
$result = $this -> execute_alter_query ( $drop_query );
$this -> return_value = $result ;
} else {
$this -> return_value = false ;
}
break ;
2013-07-07 06:49:38 +00:00
default :
$engine = $this -> prepare_engine ( $this -> query_type );
$this -> rewritten_query = $engine -> rewrite_query ( $query , $this -> query_type );
$this -> queries [] = " Rewritten: $this->rewritten_query " ;
$this -> extract_variables ();
$statement = $this -> prepare_query ();
$this -> execute_query ( $statement );
if ( ! $this -> is_error ) {
$this -> process_results ( $engine );
} else { // Error
;
}
break ;
}
if ( defined ( 'PDO_DEBUG' ) && PDO_DEBUG === true ) {
file_put_contents ( FQDBDIR . 'debug.txt' , $this -> get_debug_info (), FLIE_APPEND );
}
return $this -> return_value ;
}
public function get_insert_id () {
return $this -> last_insert_id ;
}
public function get_affected_rows () {
return $this -> affected_rows ;
}
public function get_columns () {
return $this -> column_names ;
}
public function get_query_results () {
return $this -> results ;
}
public function get_num_rows () {
return $this -> num_rows ;
}
public function get_return_value () {
return $this -> return_value ;
}
public function get_error_message (){
if ( count ( $this -> error_messages ) === 0 ){
$this -> is_error = false ;
$this -> error_messages = array ();
return '' ;
}
$output = '<div style="clear:both"> </div>' ;
if ( $this -> is_error === false ){
// return $output;
return '' ;
}
$output .= " <div class= \" queries \" style= \" clear:both; margin_bottom:2px; border: red dotted thin; \" >Queries made or created this session were<br/> \r \n \t <ol> \r \n " ;
foreach ( $this -> queries as $q ){
$output .= " \t \t <li> " . $q . " </li> \r \n " ;
}
$output .= " \t </ol> \r \n </div> " ;
foreach ( $this -> error_messages as $num => $m ){
$output .= " <div style= \" clear:both; margin_bottom:2px; border: red dotted thin; \" class= \" error_message \" style= \" border-bottom:dotted blue thin; \" >Error occurred at line { $this -> errors [ $num ][ 'line' ] } in Function { $this -> errors [ $num ][ 'function' ] } . <br/> Error message was: $m </div> " ;
}
ob_start ();
debug_print_backtrace ();
$output .= " <pre> " . ob_get_contents () . " </pre> " ;
ob_end_clean ();
return $output ;
}
private function get_debug_info (){
$output = '' ;
foreach ( $this -> queries as $q ){
$output .= $q . " \r \n " ;
}
return $output ;
}
private function flush (){
$this -> rewritten_query = '' ;
$this -> query_type = '' ;
$this -> results = null ;
$this -> _results = null ;
$this -> last_insert_id = null ;
$this -> affected_rows = null ;
$this -> column_names = array ();
$this -> num_rows = null ;
$this -> return_value = null ;
$this -> extracted_variables = array ();
$this -> error_messages = array ();
$this -> is_error = false ;
$this -> queries = array ();
$this -> param_num = 0 ;
}
private function prepare_engine ( $query_type = null ) {
if ( stripos ( $query_type , 'create' ) !== false ) {
require_once PDODIR . 'query_create.class.php' ;
$engine = new CreateQuery ();
} elseif ( stripos ( $query_type , 'alter' ) !== false ) {
require_once PDODIR . 'query_alter.class.php' ;
$engine = new AlterQuery ();
} else {
require_once PDODIR . 'query.class.php' ;
$engine = new PDOSQLiteDriver ();
}
return $engine ;
}
private function prepare_query (){
$this -> queries [] = " Prepare: \t " . $this -> prepared_query ;
$reason = 0 ;
$message = '' ;
$statement = null ;
do {
try {
$statement = $this -> pdo -> prepare ( $this -> prepared_query );
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
}
} while ( 5 == $reason || 6 == $reason );
if ( $reason > 0 ){
$err_message = sprintf ( __ ( " Problem preparing the PDO SQL Statement. Error was: %s " , 'sqlite-integration' ), $message );
$this -> set_error ( __LINE__ , __FUNCTION__ , $err_message );
}
return $statement ;
}
private function execute_query ( $statement ) {
$reason = 0 ;
$message = '' ;
if ( ! is_object ( $statement ))
return ;
if ( count ( $this -> extracted_variables ) > 0 ) {
$this -> queries [] = " Executing: " . var_export ( $this -> extracted_variables , true );
do {
if ( $this -> query_type == 'update' || $this -> query_type == 'replace' ) {
try {
$this -> beginTransaction ();
$statement -> execute ( $this -> extracted_variables );
$this -> commit ();
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
$this -> rollBack ();
}
} else {
try {
$statement -> execute ( $this -> extracted_variables );
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
}
}
} while ( 5 == $reason || 6 == $reason );
} else {
$this -> queries [] = " Executing: (no parameters) \t " ;
do {
if ( $this -> query_type == 'update' || $this -> query_type == 'replace' ) {
try {
$this -> beginTransaction ();
$statement -> execute ();
$this -> commit ();
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
$this -> rollBack ();
}
} else {
try {
$statement -> execute ();
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
}
}
} while ( 5 == $reason || 6 == $reason );
}
if ( $reason > 0 ) {
$err_message = sprintf ( __ ( " Error while executing query! Error message was: %s " , 'sqlite-integration' ), $message );
$this -> set_error ( __LINE__ , __FUNCTION__ , $err_message );
return false ;
} else {
$this -> _results = $statement -> fetchAll ( PDO :: FETCH_OBJ );
}
//generate the results that $wpdb will want to see
switch ( $this -> query_type ) {
case " insert " :
case " update " :
case " replace " :
$this -> last_insert_id = $this -> pdo -> lastInsertId ();
$this -> affected_rows = $statement -> rowCount ();
$this -> return_value = $this -> affected_rows ;
break ;
case " select " :
case " show " :
case " showcolumns " :
case " showindex " :
case " describe " :
case " desc " :
// case "foundrows":
$this -> num_rows = count ( $this -> _results );
$this -> return_value = $this -> num_rows ;
break ;
case " delete " :
$this -> affected_rows = $statement -> rowCount ();
$this -> return_value = $this -> affected_rows ;
break ;
case " alter " :
case " drop " :
case " create " :
case " optimize " :
case " truncate " :
if ( $this -> is_error ) {
$this -> return_value = false ;
} else {
$this -> return_value = true ;
}
break ;
}
}
private function extract_variables () {
if ( $this -> query_type == 'create' ) {
$this -> prepared_query = $this -> rewritten_query ;
return ;
}
//long queries can really kill this
$pattern = '/(?<!\\\\)([\'"])(.*?)(?<!\\\\)\\1/imsx' ;
$_limit = $limit = ini_get ( 'pcre.backtrack_limit' );
do {
if ( $limit > 10000000 ) {
$message = __ ( " The query is too big to parse properly " , 'sqlite-integration' );
$this -> set_error ( __LINE__ , __FUNCTION__ , $message );
break ; //no point in continuing execution, would get into a loop
} else {
ini_set ( 'pcre.backtrack_limit' , $limit );
$query = preg_replace_callback ( $pattern , array ( $this , 'replace_variables_with_placeholders' ), $this -> rewritten_query );
}
$limit = $limit * 10 ;
} while ( empty ( $query ));
//reset the pcre.backtrack_limist
ini_set ( 'pcre.backtrack_limit' , $_limit );
$this -> queries [] = " With Placeholders: $query " ;
$this -> prepared_query = $query ;
}
private function replace_variables_with_placeholders ( $matches ) {
//remove the wordpress escaping mechanism
$param = stripslashes ( $matches [ 0 ]);
//remove trailing spaces
$param = trim ( $param );
//remove the quotes at the end and the beginning
if ( in_array ( $param { strlen ( $param ) - 1 }, array ( " ' " , '"' ))) {
$param = substr ( $param , 0 , - 1 ) ; //end
}
if ( in_array ( $param { 0 }, array ( " ' " , '"' ))) {
$param = substr ( $param , 1 ); //start
}
//$this->extracted_variables[] = $param;
$key = ':param_' . $this -> param_num ++ ;
$this -> extracted_variables [] = $param ;
//return the placeholder
//return ' ? ';
return ' ' . $key . ' ' ;
}
/**
* takes the query string , determines the type and returns the type string
* if the query is the type PDO for Wordpress can ' t executes , returns false
* @ param string $query
* @ return boolean | string
*/
private function determine_query_type ( $query ) {
2013-07-24 02:31:01 +00:00
$result = preg_match ( '/^\\s*(EXPLAIN|PRAGMA|SELECT\\s*FOUND_ROWS|SELECT|INSERT|UPDATE|REPLACE|DELETE|ALTER|CREATE|DROP\\s*INDEX|DROP|SHOW\\s*\\w+\\s*\\w+\\s*|DESCRIBE|DESC|TRUNCATE|OPTIMIZE)/i' , $query , $match );
2013-07-07 06:49:38 +00:00
if ( ! $result ) {
return false ;
}
$this -> query_type = strtolower ( $match [ 1 ]);
if ( stripos ( $this -> query_type , 'found' ) !== false ) {
$this -> query_type = 'foundrows' ;
}
if ( stripos ( $this -> query_type , 'show' ) !== false ) {
if ( stripos ( $this -> query_type , 'show tables' ) !== false ) {
$this -> query_type = 'show' ;
} elseif ( stripos ( $this -> query_type , 'show columns' ) !== false || stripos ( $this -> query_type , 'show fields' ) !== false ) {
$this -> query_type = 'showcolumns' ;
} elseif ( stripos ( $this -> query_type , 'show index' ) !== false || stripos ( $this -> query_type , 'show indexes' ) !== false || stripos ( $this -> query_type , 'show keys' ) !== false ) {
$this -> query_type = 'showindex' ;
} elseif ( stripos ( $this -> query_type , 'show variables' ) !== false || stripos ( $this -> query_type , 'show global variables' ) !== false || stripos ( $this -> query_type , 'show session variables' ) !== false ) {
$this -> query_type = 'show_variables' ;
} else {
return false ;
}
}
2013-07-24 02:31:01 +00:00
if ( stripos ( $this -> query_type , 'drop index' ) !== false ) {
$this -> query_type = 'drop_index' ;
}
2013-07-07 06:49:38 +00:00
return true ;
}
/**
* SQLite version 3.7 . 11 began support multiple rows insert with values
* clause . This is for that version or later .
* @ param string $query
*/
private function execute_insert_query_new ( $query ) {
$engine = $this -> prepare_engine ( $this -> query_type );
$this -> rewritten_query = $engine -> rewrite_query ( $query , $this -> query_type );
$this -> queries [] = " Rewritten: $this->rewritten_query " ;
$this -> extract_variables ();
$statement = $this -> prepare_query ();
$this -> execute_query ( $statement );
}
/**
* executes the INSERT query for SQLite version 3.7 . 10 or lesser
* @ param string $query
*/
private function execute_insert_query ( $query ) {
global $wpdb ;
$multi_insert = false ;
$statement = null ;
$engine = $this -> prepare_engine ( $this -> query_type );
if ( preg_match ( '/(INSERT.*?VALUES\\s*)(\(.*\))/imsx' , $query , $matched )) {
$query_prefix = $matched [ 1 ];
$values_data = $matched [ 2 ];
if ( stripos ( $values_data , 'ON DUPLICATE KEY' ) !== false ) {
$exploded_parts = $values_data ;
} elseif ( stripos ( $query_prefix , " INSERT INTO $wpdb->comments " ) !== false ) {
$exploded_parts = $values_data ;
} else {
$exploded_parts = $this -> parse_multiple_inserts ( $values_data );
}
$count = count ( $exploded_parts );
if ( $count > 1 ) {
$multi_insert = true ;
}
}
if ( $multi_insert ) {
$first = true ;
foreach ( $exploded_parts as $value ) {
if ( substr ( $value , - 1 , 1 ) === ')' ) {
$suffix = '' ;
} else {
$suffix = ')' ;
}
$query_string = $query_prefix . ' ' . $value . $suffix ;
$this -> rewritten_query = $engine -> rewrite_query ( $query_string , $this -> query_type );
$this -> queries [] = " Rewritten: $this->rewritten_query " ;
$this -> extracted_variables = array ();
$this -> extract_variables ();
if ( $first ) {
$statement = $this -> prepare_query ();
$this -> execute_query ( $statement );
$first = false ;
} else {
$this -> execute_query ( $statement );
}
}
} else {
$this -> rewritten_query = $engine -> rewrite_query ( $query , $this -> query_type );
$this -> queries [] = " Rewritten: $this->rewritten_query " ;
$this -> extract_variables ();
$statement = $this -> prepare_query ();
$this -> execute_query ( $statement );
}
}
/**
* helper function for execute_insert_query ()
* @ param string $values
* @ return array
*/
private function parse_multiple_inserts ( $values ) {
$tokens = preg_split ( " /(''|(?<! \\ \\ )'|(?<! \ () \ ),(?= \ s* \ ())/s " , $values , - 1 , PREG_SPLIT_DELIM_CAPTURE );
$exploded_parts = array ();
$part = '' ;
$literal = false ;
foreach ( $tokens as $token ) {
switch ( $token ) {
case " ), " :
if ( ! $literal ) {
$exploded_parts [] = $part ;
$part = '' ;
} else {
$part .= $token ;
}
break ;
case " ' " :
if ( $literal ) {
$literal = false ;
} else {
$literal = true ;
}
$part .= $token ;
break ;
default :
$part .= $token ;
break ;
}
}
if ( ! empty ( $part )) {
$exploded_parts [] = $part ;
}
return $exploded_parts ;
}
/**
* function to execute CREATE query
* @ param string
* @ return boolean
*/
private function execute_create_query ( $query ) {
$engine = $this -> prepare_engine ( $this -> query_type );
$rewritten_query = $engine -> rewrite_query ( $query );
$reason = 0 ;
$message = '' ;
// $queries = explode(";", $this->rewritten_query);
try {
$this -> beginTransaction ();
foreach ( $rewritten_query as $single_query ) {
$this -> queries [] = " Executing: \t " . $single_query ;
$single_query = trim ( $single_query );
if ( empty ( $single_query )) continue ;
$this -> pdo -> exec ( $single_query );
}
$this -> commit ();
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
if ( 5 == $reason || 6 == $reason ) {
$this -> commit ();
} else {
$this -> rollBack ();
}
}
if ( $reason > 0 ) {
$err_message = sprintf ( __ ( " Problem in creating table or index. Error was: %s " , 'sqlite-integration' ), $message );
$this -> set_error ( __LINE__ , __FUNCTION__ , $err_message );
return false ;
}
return true ;
}
/**
* function to execute ALTER TABLE query
* @ param string
* @ return boolean
*/
private function execute_alter_query ( $query ) {
$engine = $this -> prepare_engine ( $this -> query_type );
$reason = 0 ;
$message = '' ;
$rewritten_query = $engine -> rewrite_query ( $query , $this -> query_type );
try {
$this -> beginTransaction ();
if ( is_array ( $rewritten_query )) {
foreach ( $rewritten_query as $single_query ) {
$this -> queries [] = " Executing: \t " . $single_query ;
$single_query = trim ( $single_query );
if ( empty ( $single_query )) continue ;
$this -> pdo -> exec ( $single_query );
}
} else {
$this -> queries [] = " Executing: \t " . $rewritten_query ;
$rewritten_query = trim ( $rewritten_query );
$this -> pdo -> exec ( $rewritten_query );
}
$this -> commit ();
} catch ( PDOException $err ) {
$reason = $err -> getCode ();
$message = $err -> getMessage ();
if ( 5 == $reason || 6 == $reason ) {
$this -> commit ();
usleep ( 10000 );
} else {
$this -> rollBack ();
}
}
if ( $reason > 0 ) {
$err_message = sprintf ( __ ( " Problem in executing alter query. Error was: %s " , 'sqlite-integration' ), $message );
$this -> set_error ( __LINE__ , __FUNCTION__ , $err_message );
return false ;
}
return true ;
}
/**
* function to execute SHOW VARIABLES query
*
* This query is meaningless for SQLite . This function returns null data and
* avoid the error message .
*
* @ param string
* @ return ObjectArray
*/
private function show_variables_workaround ( $query ) {
$dummy_data = array ( 'Variable_name' => '' , 'Value' => null );
$pattern = '/SHOW\\s*VARIABLES\\s*LIKE\\s*(.*)?$/im' ;
if ( preg_match ( $pattern , $query , $match )) {
$value = str_replace ( " ' " , '' , $match [ 1 ]);
$dummy_data [ 'Variable_name' ] = trim ( $value );
// this is set for Wordfence Security Plugin
if ( $value == 'max_allowed_packet' ) $dummy_data [ 'Value' ] = 1047552 ;
}
$_results [] = new ObjectArray ( $dummy_data );
$this -> results = $_results ;
$this -> num_rows = count ( $this -> results );
$this -> return_value = $this -> num_rows ;
return true ;
}
private function process_results ( $engine ) {
if ( in_array ( $this -> query_type , array ( 'describe' , 'desc' , 'showcolumns' ))) {
$this -> convert_to_columns_object ();
} elseif ( 'showindex' === $this -> query_type ){
$this -> convert_to_index_object ();
} else {
$this -> results = $this -> _results ;
}
}
private function set_error ( $line , $function , $message ){
global $wpdb ;
$this -> errors [] = array ( " line " => $line , " function " => $function );
$this -> error_messages [] = $message ;
$this -> is_error = true ;
if ( $wpdb -> suppress_errors ) return false ;
if ( ! $wpdb -> show_errors ) return false ;
file_put_contents ( FQDBDIR . 'debug.txt' , " Line $line , Function: $function , Message: $message \n " , FILE_APPEND );
}
/**
* method that takes the associative array of query results and creates a numeric array of anonymous objects
*/
private function convert_to_object (){
$_results = array ();
if ( count ( $this -> results ) === 0 ){
echo $this -> get_error_message ();
} else {
foreach ( $this -> results as $row ){
$_results [] = new ObjectArray ( $row );
}
}
$this -> results = $_results ;
}
/**
* method to rewrite pragma results to mysql compatible array
* when query_type is describe , we use sqlite pragma function .
* see pdo_sqlite_driver . php
*/
private function convert_to_columns_object () {
$_results = array ();
$_columns = array ( //Field names MySQL SHOW COLUMNS returns
'Field' => " " ,
'Type' => " " ,
'Null' => " " ,
'Key' => " " ,
'Default' => " " ,
'Extra' => " "
);
if ( count ( $this -> _results ) === 0 ) {
echo $this -> get_error_message ();
} else {
foreach ( $this -> _results as $row ) {
$_columns [ 'Field' ] = $row -> name ;
$_columns [ 'Type' ] = $row -> type ;
$_columns [ 'Null' ] = $row -> notnull ? " NO " : " YES " ;
$_columns [ 'Key' ] = $row -> pk ? " PRI " : " " ;
$_columns [ 'Default' ] = $row -> dflt_value ;
$_results [] = new ObjectArray ( $_columns );
}
}
$this -> results = $_results ;
}
/**
* rewrites the result of SHOW INDEX to the Object compatible with MySQL
*/
private function convert_to_index_object () {
$_results = array ();
$_columns = array (
'Table' => " " ,
'Non_unique' => " " , // unique -> 0, not unique -> 1
'Key_name' => " " , // the name of the index
'Seq_in_index' => " " , // column sequence number in the index. begins at 1
'Column_name' => " " ,
'Collation' => " " , //A(scend) or NULL
'Cardinality' => " " ,
'Sub_part' => " " , // set to NULL
'Packed' => " " , // How to pack key or else NULL
'Null' => " " , // If column contains null, YES. If not, NO.
'Index_type' => " " , // BTREE, FULLTEXT, HASH, RTREE
'Comment' => " "
);
if ( count ( $this -> _results ) == 0 ) {
echo $this -> get_error_message ();
} else {
foreach ( $this -> _results as $row ) {
if ( $row -> type == 'table' && ! stripos ( $row -> sql , 'primary' ))
continue ;
if ( $row -> type == 'index' && stripos ( $row -> name , 'sqlite_autoindex' ) !== false )
continue ;
switch ( $row -> type ) {
case 'table' :
$pattern1 = '/^\\s*PRIMARY.*\((.*)\)/im' ;
$pattern2 = '/^\\s*(\\w+)?\\s*.*PRIMARY.*(?!\()/im' ;
if ( preg_match ( $pattern1 , $row -> sql , $match )) {
$col_name = trim ( $match [ 1 ]);
$_columns [ 'Key_name' ] = 'PRIMARY' ;
$_columns [ 'Non_unique' ] = 0 ;
$_columns [ 'Column_name' ] = $col_name ;
} elseif ( preg_match ( $pattern2 , $row -> sql , $match )) {
$col_name = trim ( $match [ 1 ]);
$_columns [ 'Key_name' ] = 'PRIMARY' ;
$_columns [ 'Non_unique' ] = 0 ;
$_columns [ 'Column_name' ] = $col_name ;
}
break ;
case 'index' :
if ( stripos ( $row -> sql , 'unique' ) !== false ) {
$_columns [ 'Non_unique' ] = 0 ;
} else {
$_columns [ 'Non_unique' ] = 1 ;
}
if ( preg_match ( '/^.*\((.*)\)/i' , $row -> sql , $match )) {
$col_name = str_replace ( " ' " , '' , $match [ 1 ]);
$_columns [ 'Column_name' ] = trim ( $col_name );
}
$_columns [ 'Key_name' ] = $row -> name ;
break ;
default :
break ;
}
$_columns [ 'Table' ] = $row -> tbl_name ;
$_columns [ 'Collation' ] = NULL ;
$_columns [ 'Cardinality' ] = 0 ;
$_columns [ 'Sub_part' ] = NULL ;
$_columns [ 'Packed' ] = NULL ;
$_columns [ 'Null' ] = 'NO' ;
$_columns [ 'Index_type' ] = 'BTREE' ;
$_columns [ 'Comment' ] = '' ;
$_results [] = new ObjectArray ( $_columns );
}
}
$this -> results = $_results ;
}
/**
* function to get SQLite library version
* this is used for checking if SQLite can execute multiple rows insert
* @ return version number string or 0
*/
private function get_sqlite_version () {
try {
$statement = $this -> pdo -> prepare ( 'SELECT sqlite_version()' );
$statement -> execute ();
$result = $statement -> fetch ( PDO :: FETCH_NUM );
return $result [ 0 ];
} catch ( PDOException $err ) {
return '0' ;
}
}
/**
* function call to PDO :: beginTransaction ()
* @ see PDO :: beginTransaction ()
*/
public function beginTransaction () {
if ( $this -> has_active_transaction ) {
return false ;
} else {
$this -> has_active_transaction = $this -> pdo -> beginTransaction ();
return $this -> has_active_transaction ;
}
}
/**
* function call to PDO :: commit ()
* @ see PDO :: commit ()
*/
public function commit () {
$this -> pdo -> commit ();
$this -> has_active_transaction = false ;
}
/**
* function call to PDO :: rollBack ()
* @ see PDO :: rollBack ()
*/
public function rollBack () {
$this -> pdo -> rollBack ();
$this -> has_active_transaction = false ;
}
}
class ObjectArray {
function __construct ( $data = null , & $node = null ) {
foreach ( $data as $key => $value ) {
if ( is_array ( $value ) ) {
if ( ! $node ) {
$node =& $this ;
}
$node -> $key = new stdClass ();
self :: __construct ( $value , $node -> $key );
} else {
if ( ! $node ) {
$node =& $this ;
}
$node -> $key = $value ;
}
}
}
}
?>