diff --git a/db.php b/db.php new file mode 100644 index 0000000..d108dfc --- /dev/null +++ b/db.php @@ -0,0 +1,96 @@ + + +
+$message
+$data
+ + + +HTML +); +} + +if (version_compare( PHP_VERSION, '5.2.4', '<')) { + pdo_log_erro(__('PHP version on this server is too old.'), sprinf(__("Your server is running PHP version %d but this version of WordPress requires at least 5.2.4"), phpversion())); +} + +if (!extension_loaded('pdo')) { + pdo_log_erro(__('PHP PDO Extension is not loaded.'), __('Your PHP installation appears to be missing the PDO extension which is required for this version of WordPress.')); +} + +if (!extension_loaded('pdo_sqlite')) { + pdo_log_erro(__('PDO Driver for SQLite is missing.'), __('Your PHP installtion appears not to have the right PDO drivers loaded. These are required for this version of WordPress and the type of database you have specified.')); +} + +/** + * Notice: + * Your scripts have the permission to create directories or files on your server. + * If you write in your wp-config.php like below, we take these definitions. + * define('DB_DIR', '/full_path_to_the_database_directory/'); + * define('DB_FILE', 'database_file_name'); + */ +if (defined('WP_PLUGIN_DIR')) { + define('PDODIR', WP_PLUGIN_DIR . '/sqlite-integration/'); +} else { + if (defined('WP_CONTENT_DIR')) { + define('PDODIR', WP_CONTENT_DIR . '/plugins/sqlite-integration/'); + } else { + define('PDODIR', ABSPATH . 'wp-content/plugins/sqlite-integration/'); + } +} + +if (defined('DB_DIR')) { + if (substr(DB_DIR, -1, 1) != '/') { + define('FQDBDIR', DB_DIR . '/'); + } else { + define('FQDBDIR', DB_DIR); + } +} else { + if (defined('WP_CONTENT_DIR')) { + define('FQDBDIR', WP_CONTENT_DIR . '/database/'); + } else { + define('FQDBDIR', ABSPATH . 'wp-content/database/'); + } +} + +if ( defined('DB_FILE' )) { + define('FQDB', FQDBDIR . DB_FILE); +} else { + define('FQDB', FQDBDIR . '.ht.sqlite'); +} + +if (version_compare(PHP_VERSION, '5.3', '<')) { + define('UDF_FILE', PDODIR . 'functions-5-2.php'); +} elseif (version_compare(PHP_VERSION, '5.3', '>=')) { + define('UDF_FILE', PDODIR . 'functions.php'); +} + +require_once PDODIR . 'pdodb.class.php'; +?> \ No newline at end of file diff --git a/functions-5-2.php b/functions-5-2.php new file mode 100644 index 0000000..545b653 --- /dev/null +++ b/functions-5-2.php @@ -0,0 +1,370 @@ +functions as $f=>$t) { + $pdo->sqliteCreateFunction($f, array($this, $t)); + } + } + + private $functions = array( + 'month' => 'month', + 'year' => 'year', + 'day' => 'day', + 'unix_timestamp' => 'unix_timestamp', + 'now' => 'now', + 'char_length' => 'char_length', + 'md5' => 'md5', + 'curdate' => 'curdate', + 'rand' => 'rand', + 'substring' => 'substring', + 'dayofmonth' => 'day', + 'second' => 'second', + 'minute' => 'minute', + 'hour' => 'hour', + 'date_format' => 'dateformat', + 'from_unixtime' => 'from_unixtime', + 'date_add' => 'date_add', + 'date_sub' => 'date_sub', + 'adddate' => 'date_add', + 'subdate' => 'date_sub', + 'localtime' => 'now', + 'localtimestamp' => 'now', + //'date'=>'date', + 'isnull' => 'isnull', + 'if' => '_if', + 'regexpp' => 'regexp', + 'concat' => 'concat', + 'field' => 'field', + 'log' => 'log', + 'least' => 'least', + 'get_lock' => 'get_lock', + 'release_lock' => 'release_lock', + 'ucase' => 'ucase', + 'lcase' => 'lcase', + 'inet_ntoa' => 'inet_ntoa', + 'inet_aton' => 'inet_aton', + 'datediff' => 'datediff' + ); + + public function month($field){ + $t = strtotime($field); + return date('n', $t); + } + public function year($field){ + $t = strtotime($field); + return date('Y', $t); + } + public function day($field){ + $t = strtotime($field); + return date('j', $t); + } + public function unix_timestamp($field = null){ + return is_null($field) ? time() : strtotime($field); + } + public function second($field){ + $t = strtotime($field); + return intval( date("s", $t) ); + } + public function minute($field){ + $t = strtotime($field); + return intval(date("i", $t)); + } + public function hour($time){ + list($hours, $minutes, $seconds) = explode(":", $time); + return intval($hours); + } + public function from_unixtime($field, $format=null){ + // $field is a timestamp + //convert to ISO time + $date = date("Y-m-d H:i:s", $field); + //now submit to dateformat + + return is_null($format) ? $date : $self->dateformat($date, $format); + } + public function now(){ + return date("Y-m-d H:i:s"); + } + public function curdate() { + return date("Y-m-d"); + } + public function char_length($field){ + return strlen($field); + } + public function md5($field){ + return md5($field); + } + public function rand(){ + return rand(0,1); + } + public function substring($text, $pos, $len=null){ + if (is_null($len)) return substr($text, $pos-1); + else return substr($text, $pos-1, $len); + } + public function dateformat($date, $format){ + $mysql_php_dateformats = array ( '%a' => 'D', '%b' => 'M', '%c' => 'n', '%D' => 'jS', '%d' => 'd', '%e' => 'j', '%H' => 'H', '%h' => 'h', '%I' => 'h', '%i' => 'i', '%j' => 'z', '%k' => 'G', '%l' => 'g', '%M' => 'F', '%m' => 'm', '%p' => 'A', '%r' => 'h:i:s A', '%S' => 's', '%s' => 's', '%T' => 'H:i:s', '%U' => 'W', '%u' => 'W', '%V' => 'W', '%v' => 'W', '%W' => 'l', '%w' => 'w', '%X' => 'Y', '%x' => 'o', '%Y' => 'Y', '%y' => 'y', ); + $t = strtotime($date); + $format = strtr($format, $mysql_php_dateformats); + $output = date($format, $t); + return $output; + } + public function date_add($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + public function date_sub($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + + private function deriveInterval($interval){ + $interval = trim(substr(trim($interval), 8)); + $parts = explode(' ', $interval); + foreach($parts as $part){ + if (!empty($part)){ + $_parts[] = $part; + } + } + $type = strtolower(end($_parts)); + switch ($type){ + case "second": + case "minute": + case "hour": + case "day": + case "week": + case "month": + case "year": + if (intval($_parts[0]) > 1){ + $type .= 's'; + } + return "$_parts[0] $_parts[1]"; + break; + case "minute_second": + list($minutes, $seconds) = explode (':', $_parts[0]); + $minutes = intval($minutes); + $seconds = intval($seconds); + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + $seconds = ($seconds > 1) ? "$seconds seconds" : "$seconds second"; + return "$minutes $seconds"; + break; + + case "hour_second": + list($hours, $minutes, $seconds) = explode (':', $_parts[0]); + $hours = intval($hours); + $minutes = intval($minutes); + $seconds = intval($seconds); + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + $seconds = ($seconds > 1) ? "$seconds seconds" : "$seconds second"; + return "$hours $minutes $seconds"; + break; + case "hour_minute": + list($hours, $minutes) = explode (':', $_parts[0]); + $hours = intval($hours); + $minutes = intval($minutes); + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + return "$hours $minutes"; + break; + case "day_second": + $days = intval($_parts[0]); + list($hours, $minutes, $seconds) = explode (':', $_parts[1]); + $hours = intval($hours); + $minutes = intval($minutes); + $seconds = intval($seconds); + $days = $days > 1 ? "$days days" : "$days day"; + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + $seconds = ($seconds > 1) ? "$seconds seconds" : "$seconds second"; + return "$days $hours $minutes $seconds"; + break; + case "day_minute": + $days = intval($_parts[0]); + list($hours, $minutes) = explode (':', $_parts[1]); + $hours = intval($hours); + $minutes = intval($minutes); + $days = $days > 1 ? "$days days" : "$days day"; + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + $minutes = ($minutes > 1) ? "$minutes minutes" : "$minutes minute"; + return "$days $hours $minutes"; + break; + case "day_hour": + $days = intval($_parts[0]); + $hours = intval($_parts[1]); + $days = $days > 1 ? "$days days" : "$days day"; + $hours = ($hours > 1) ? "$hours hours" : "$hours hour"; + return "$days $hours"; + break; + case "year_month": + list($years, $months) = explode ('-', $_parts[0]); + $years = intval($years); + $months = intval($months); + $years = ($years > 1) ? "$years years" : "$years year"; + $months = ($months > 1) ? "$months months": "$months month"; + return "$years $months"; + break; + default: + return false; + } + } + + public function date($date){ + return date("Y-m-d", strtotime($date)); + } + + public function isnull($field){ + return is_null($field); + } + + public function _if($expression, $true, $false){ + return ($expression == true) ? $true : $false; + } + + public function regexp($field, $pattern){ + $pattern = str_replace('/', '\/', $pattern); + $pattern = "/" . $pattern ."/i"; + return preg_match ($pattern, $field); + } + + public function concat() { + $returnValue = ""; + $argsNum = func_num_args(); + $argsList = func_get_args(); + for ($i = 0; $i < $argsNum; $i++) { + if (is_null($argsList[$i])) { + return null; + } + $returnValue .= $argsList[$i]; + } + return $returnValue; + } + + public function field() { + $numArgs = func_num_args(); + if ($numArgs < 2 or is_null(func_get_arg(0))) { + return null; + } + $arr = func_get_args(); + $searchString = strtolower(array_shift($arr)); + for ($i = 0; $i < $numArgs-1; $i++) { + if ($searchString === strtolower($arr[$i])) return $i + 1; + } + return null; + } + + public function log() { + $numArgs = func_num_args(); + if ($numArgs == 1) { + $arg1 = func_get_arg(0); + return log($arg1); + } else if ($numArgs == 2) { + $arg1 = func_get_arg(0); + $arg2 = func_get_arg(1); + return log($arg1)/log($arg2); + } else { + return false; + } + } + + public function least() { + $arr = func_get_args(); + return min($arr); + } + + /** + * These two functions are meaningless in SQLite + * So we return meaningless statement and do nothing + * @param string $name + * @param integer $timeout + * @return string + */ + public function get_lock($name, $timeout) { + return '1=1'; + } + public function release_lock($name) { + return '1=1'; + } + + /** + * MySQL aliases for upper and lower functions + * @param unknown $string + * @return string + */ + public function ucase($string) { + return "upper($string)"; + } + public function lcase($string) { + return "lower($string)"; + } + + /** + * MySQL aliases for INET_NTOA and INET_ATON functions + * @param unsigned integer, string respectively + * @return string, unsigned integer respectively + */ + public function inet_ntoa($num) { + return long2ip($num); + } + public function inet_aton($addr) { + $int_data = ip2long($addr); + $unsigned_int_data = sprintf('%u', $address); + return $unsigned_int_data; + } + + /** + * MySQL aliase for DATEDIFF function + * @param string, string + * @return string + */ + public function datediff($start, $end) { + $start_date = strtotime($start); + $end_date = strtotime($end); + $interval = floor(($end_date - $start_date)/(3600*24)); + return $interval; + } +} +?> \ No newline at end of file diff --git a/functions.php b/functions.php new file mode 100644 index 0000000..5f7af23 --- /dev/null +++ b/functions.php @@ -0,0 +1,344 @@ +functions as $f=>$t) { + $pdo->sqliteCreateFunction($f, array($this, $t)); + } + } + + private $functions = array( + 'month' => 'month', + 'year' => 'year', + 'day' => 'day', + 'unix_timestamp' => 'unix_timestamp', + 'now' => 'now', + 'char_length' => 'char_length', + 'md5' => 'md5', + 'curdate' => 'curdate', + 'rand' => 'rand', + 'substring' => 'substring', + 'dayofmonth' => 'day', + 'second' => 'second', + 'minute' => 'minute', + 'hour' => 'hour', + 'date_format' => 'dateformat', + 'from_unixtime' => 'from_unixtime', + 'date_add' => 'date_add', + 'date_sub' => 'date_sub', + 'adddate' => 'date_add', + 'subdate' => 'date_sub', + 'localtime' => 'now', + 'localtimestamp' => 'now', + //'date'=>'date', + 'isnull' => 'isnull', + 'if' => '_if', + 'regexpp' => 'regexp', + 'concat' => 'concat', + 'field' => 'field', + 'log' => 'log', + 'least' => 'least', + 'replace' => 'replace', + 'get_lock' => 'get_lock', + 'release_lock' => 'release_lock', + 'ucase' => 'ucase', + 'lcase' => 'lcase', + 'inet_ntoa' => 'inet_ntoa', + 'inet_aton' => 'inet_aton', + 'datediff' => 'datediff' + ); + + public function month($field){ + $t = strtotime($field); + return date('n', $t); + } + public function year($field){ + $t = strtotime($field); + return date('Y', $t); + } + public function day($field){ + $t = strtotime($field); + return date('j', $t); + } + public function unix_timestamp($field = null){ + return is_null($field) ? time() : strtotime($field); + } + public function second($field){ + $t = strtotime($field); + return intval( date("s", $t) ); + } + public function minute($field){ + $t = strtotime($field); + return intval(date("i", $t)); + } + public function hour($time){ + list($hours, $minutes, $seconds) = explode(":", $time); + return intval($hours); + } + public function from_unixtime($field, $format=null){ + // $field is a timestamp + //convert to ISO time + $date = date("Y-m-d H:i:s", $field); + //now submit to dateformat + + return is_null($format) ? $date : $self->dateformat($date, $format); + } + public function now(){ + return date("Y-m-d H:i:s"); + } + public function curdate() { + return date("Y-m-d"); + } + public function char_length($field){ + return strlen($field); + } + public function md5($field){ + return md5($field); + } + public function rand(){ + return rand(0,1); + } + public function substring($text, $pos, $len=null){ + if (is_null($len)) return substr($text, $pos-1); + else return substr($text, $pos-1, $len); + } + public function dateformat($date, $format){ + $mysql_php_dateformats = array ( '%a' => 'D', '%b' => 'M', '%c' => 'n', '%D' => 'jS', '%d' => 'd', '%e' => 'j', '%H' => 'H', '%h' => 'h', '%I' => 'h', '%i' => 'i', '%j' => 'z', '%k' => 'G', '%l' => 'g', '%M' => 'F', '%m' => 'm', '%p' => 'A', '%r' => 'h:i:s A', '%S' => 's', '%s' => 's', '%T' => 'H:i:s', '%U' => 'W', '%u' => 'W', '%V' => 'W', '%v' => 'W', '%W' => 'l', '%w' => 'w', '%X' => 'Y', '%x' => 'o', '%Y' => 'Y', '%y' => 'y', ); + $t = strtotime($date); + $format = strtr($format, $mysql_php_dateformats); + $output = date($format, $t); + return $output; + } + public function date_add($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->add(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + public function date_sub($date, $interval) { + $interval = $this->deriveInterval($interval); + switch (strtolower($date)) { + case "curdate()": + $objDate = new Datetime($this->curdate()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d"); + break; + case "now()": + $objDate = new Datetime($this->now()); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + break; + default: + $objDate = new Datetime($date); + $objDate->sub(new DateInterval($interval)); + $returnval = $objDate->format("Y-m-d H:i:s"); + } + return $returnval; + } + private function deriveInterval($interval) { + $interval = trim(substr(trim($interval), 8)); + $parts = explode(' ', $interval); + foreach ($parts as $part) { + if (!empty($part)) { + $_parts[] = $part; + } + } + $type = strtolower(end($_parts)); + switch ($type) { + case "second": $unit = 'S'; return 'PT' . $_parts[0] . $unit; break; + case "minute": $unit = 'M'; return 'PT' . $_parts[0] . $unit; break; + case "hour": $unit = 'H'; return 'PT' . $_parts[0] . $unit; break; + case "day": $unit = 'D'; return 'P' . $_parts[0] . $unit; break; + case "week": $unit = 'W'; return 'P' . $_parts[0] . $unit; break; + case "month": $unit = 'M'; return 'P' . $_parts[0] . $unit; break; + case "year": $unit = 'Y'; return 'P' . $_parts[0] . $unit; break; + case "minute_second": + list($minutes, $seconds) = explode(':', $_parts[0]); + return 'PT' . $minutes . 'M' . $seconds . 'S'; + break; + case "hour_second": + list($hours, $minutes, $seconds) = explode (':', $_parts[0]); + return 'PT' . $hours . 'H' . $minutes . 'M' . $seconds . 'S'; + break; + case "hour_minute": + list($hours, $minutes) = explode (':', $_parts[0]); + return 'PT' . $hours . 'H' . $minutes . 'M'; + break; + case "day_second": + $days = intval($_parts[0]); + list($hours, $minutes, $seconds) = explode (':', $_parts[1]); + return 'P' . $days . 'D' . 'T' . $hours . 'H' . $minutes . 'M' . $seconds . 'S'; + break; + case "day_minute": + $days = intval($_parts[0]); + list($hours, $minutes) = explode(':', $parts[1]); + return 'P' . $days . 'D' . 'T' . $hours . 'H' . $minutes . 'M'; + break; + case "day_hour": + $days = intval($_parts[0]); + $hours = intval($_parts[1]); + return 'P' . $days . 'D' . 'T' . $hours . 'H'; + break; + case "year_month": + list($years, $months) = explode ('-', $_parts[0]); + return 'P' . $years . 'Y' . $months . 'M'; + break; + } + } + + public function date($date){ + return date("Y-m-d", strtotime($date)); + } + + public function isnull($field){ + return is_null($field); + } + + public function _if($expression, $true, $false){ + return ($expression == true) ? $true : $false; + } + + public function regexp($field, $pattern){ + $pattern = str_replace('/', '\/', $pattern); + $pattern = "/" . $pattern ."/i"; + return preg_match ($pattern, $field); + } + + public function concat() { + $returnValue = ""; + $argsNum = func_num_args(); + $argsList = func_get_args(); + for ($i = 0; $i < $argsNum; $i++) { + if (is_null($argsList[$i])) { + return null; + } + $returnValue .= $argsList[$i]; + } + return $returnValue; + } + + public function field() { + $numArgs = func_num_args(); + if ($numArgs < 2 or is_null(func_get_arg(0))) { + return null; + } + $arr = func_get_args(); + $searchString = strtolower(array_shift($arr)); + for ($i = 0; $i < $numArgs-1; $i++) { + if ($searchString === strtolower($arr[$i])) return $i + 1; + } + return null; + } + + public function log() { + $numArgs = func_num_args(); + if ($numArgs == 1) { + $arg1 = func_get_arg(0); + return log($arg1); + } else if ($numArgs == 2) { + $arg1 = func_get_arg(0); + $arg2 = func_get_arg(1); + return log($arg1)/log($arg2); + } else { + return false; + } + } + + public function least() { + $arr = func_get_args(); + return min($arr); + } + + public function replace($haystack, $needle, $replace) { + return str_replace($needle, $replace, $haystack); + } + + /** + * These two functions are meaningless in SQLite + * So we return meaningless statement and do nothing + * @param string $name + * @param integer $timeout + * @return string + */ + public function get_lock($name, $timeout) { + return '1=1'; + } + public function release_lock($name) { + return '1=1'; + } + + /** + * MySQL aliases for upper and lower functions + * @param $string + * @return string + */ + public function ucase($string) { + return "upper($string)"; + } + public function lcase($string) { + return "lower($string)"; + } + + /** + * MySQL aliases for INET_NTOA and INET_ATON functions + * @param unsigned integer, string respectively + * @return string, unsigned integer respectively + */ + public function inet_ntoa($num) { + return long2ip($num); + } + public function inet_aton($addr) { + $int_data = ip2long($addr); + $unsigned_int_data = sprintf('%u', $address); + return $unsigned_int_data; + } + + /** + * MySQL aliase for DATEDIFF function + * @param string, string + * @return string + */ + public function datediff($start, $end) { + /* PHP 5.3.2 has a serious bug in DateTime::diff() + * see https://bugs.php.net/bug.php?id=51184 + */ + if (version_compare(PHP_VERSION, '5.3.2', '==')) { + $start_date = strtotime($start); + $end_date = strtotime($end); + $interval = floor(($start_date - $end_date)/(3600*24)); + return $interval; + } else { + $start_date = new DateTime($start); + $end_date = new DateTime($end); + $interval = $end_date->diff($start_date, false); + return $interval->format('%r%a'); + } + } +} +?> \ No newline at end of file diff --git a/install.php b/install.php new file mode 100644 index 0000000..6a0dfe4 --- /dev/null +++ b/install.php @@ -0,0 +1,63 @@ +Note that password carefully! It is a random password that was generated just for you.'); + $user_id = wp_create_user($user_name, $user_password, $user_email); + update_user_option($user_id, 'default_password_nag', true, true); + $email_password = true; + } else if (!$user_id) { + $message = ''.__('Your chosen password.').''; + $user_id = wp_create_user($user_name, $user_password, $user_email); + } + + $user = new WP_User($user_id); + $user->set_role('administrator'); + + wp_install_defaults($user_id); + + flush_rewrite_rules(); + + wp_new_blog_notification($blog_title, $guessurl, $user_id, ($email_password ? $user_password : __('The password you chose during the install.'))); + + wp_cache_flush(); + + return array('url' => $guessurl, 'user_id' => $user_id, 'password' => $user_password, 'password_message' => $message); +} +?> \ No newline at end of file diff --git a/js/sqlite.js b/js/sqlite.js new file mode 100644 index 0000000..140eae7 --- /dev/null +++ b/js/sqlite.js @@ -0,0 +1,101 @@ +/* + * script for SQLite Integration + * this file is only included on the documentation page and the utilities page + */ +jQuery(document).ready(function($) { + var $table = null; + var $headers = null; + if (document.getElementById("sqlite-table") != null) { + $table = $('#sqlite-table'); + $headers = $table.find('thead th').slice(0,2); + } else if (document.getElementById("plugins-table") != null) { + $table = $('#plugins-table'); + $headers = $table.find('thead th').slice(0); + } else if (document.getElementById("patch-files") != null) { + $table = $('#patch-files'); + $headers = $table.find('thead th').slice(1); + } + $headers + .wrapInner('') + .addClass('sort'); + var rows = $table.find('tbody > tr').get(); + $headers.bind('click', function(event) { + event.preventDefault(); + var $header = $(this), + sortKey = $header.data('sort').key, + sortDirection = 1; + if ($header.hasClass('sorted-asc')) { + sortDirection = -1; + } + rows.sort(function(a, b) { + var keyA = $(a).data('table')[sortKey]; + var keyB = $(b).data('table')[sortKey]; + if (keyA < keyB) return -sortDirection; + if (keyA > keyB) return sortDirection; + return 0; + }); + $headers.removeClass('sorted-asc sortd-desc'); + $headers.addClass(sortDirection == 1 ? 'sorted-asc' : 'sorted-desc'); + $.each(rows, function(index, row) { + $table.children('tbody').append(row); + }); + stripe('#plugins-table'); + stripe('#sqlite-table'); + stripe('#patch-files'); + }); + function stripe(arg) { + $(arg).find('tr.alt').removeClass('alt'); + var $args = arg + ' tbody'; + $($args).each(function() { + $(this).children(':visible').has('td').filter(function(index) { + return (index % 2) == 1; + }).addClass('alt'); + }); + } + stripe('#plugins-table'); + stripe('#sys-info'); + stripe('#sqlite-table'); + stripe('#status'); + stripe('#patch-files'); +}); + +jQuery(document).ready(function($) { + var $table = $('#plugins-info'); + var $headers = $table.find('thead th').slice(0); + $headers + .wrapInner('') + .addClass('sort'); + var rows = $table.find('tbody > tr').get(); + $headers.bind('click', function(event) { + event.preventDefault(); + var $header = $(this), + sortKey = $header.data('sort').key, + sortDirection = 1; + if ($header.hasClass('sorted-asc')) { + sortDirection = -1; + } + rows.sort(function(a, b) { + var keyA = $(a).data('table')[sortKey]; + var keyB = $(b).data('table')[sortKey]; + if (keyA < keyB) return -sortDirection; + if (keyA > keyB) return sortDirection; + return 0; + }); + $headers.removeClass('sorted-asc sortd-desc'); + $headers.addClass(sortDirection == 1 ? 'sorted-asc' : 'sorted-desc'); + $.each(rows, function(index, row) { + $table.children('tbody').append(row); + }); + stripe('#plugins-info'); + }); + function stripe(arg) { + $(arg).find('tr.alt').removeClass('alt'); + var $args = arg + ' tbody'; + $($args).each(function() { + $(this).children(':visible').has('td').filter(function(index) { + return (index % 2) == 1; + }).addClass('alt'); + }); + } + stripe('#plugins-info'); +}); diff --git a/languages/sqlite-integration-ja.mo b/languages/sqlite-integration-ja.mo new file mode 100644 index 0000000..a5db75e Binary files /dev/null and b/languages/sqlite-integration-ja.mo differ diff --git a/languages/sqlite-integration-ja.po b/languages/sqlite-integration-ja.po new file mode 100644 index 0000000..2c6c093 --- /dev/null +++ b/languages/sqlite-integration-ja.po @@ -0,0 +1,1198 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2013 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Kojima ToshiyasuWe have been unable to "
+"connect to the specified database.
The error message received was %s"
+msgstr ""
+"
データベースに接続できませんでした。
エラーメッセージは、%sです。"
+
+#: pdoengine.class.php:80 pdoengine.class.php:96 schema.php:26
+msgid "Database connection error!
"
+msgstr "データベース接続エラー!
"
+
+#: pdoengine.class.php:81 pdoengine.class.php:97 schema.php:27 schema.php:81
+msgid "Error message is: %s"
+msgstr "エラーメッセージは: "
+
+#: pdoengine.class.php:115
+msgid ""
+"Unable to create the required directory! Please check your server settings."
+msgstr ""
+"必要なディレクトリが作成できませんでした。サーバ設定を確認してください。"
+
+#: pdoengine.class.php:120 pdoengine.class.php:126
+msgid ""
+"Unable to create a file in the directory! Please check your server settings."
+msgstr ""
+"ディレクトリにファイルを作成できませんでした。サーバ設定を確認してください。"
+
+#: pdoengine.class.php:148
+#, php-format
+msgid ""
+"
Sorry, we cannot determine the type of query " +"that is requested.
The query is %s
" +msgstr "" +"申し訳ありません、要求されたクエリのタイプを決定できません。
クエリは%s" +"です。
" + +#: pdoengine.class.php:294 +#, php-format +msgid "Problem preparing the PDO SQL Statement. Error was: %s" +msgstr "SQLステートメントの準備中に問題。エラーは: %s" + +#: pdoengine.class.php:327 +#, php-format +msgid "Error while executing query! Error message was: %s" +msgstr "クエリの実行中にエラー! エラーメッセージは: %s" + +#: pdoengine.class.php:381 +msgid "The query is too big to parse properly" +msgstr "クエリが長すぎて解析できません" + +#: pdoengine.class.php:583 +#, php-format +msgid "Problem in creating table or index. Error was: %s" +msgstr "テーブルまたはインデックスを作成中に問題発生。エラーは: %s" + +#: pdoengine.class.php:626 +#, php-format +msgid "Problem in executing alter query. Error was: %s" +msgstr "ALTERクエリを実行中に問題発生。エラーは: %s" + +#: schema.php:80 +#, php-format +msgid "" +"Error occured while creating tables or indexes...We have been unable to "
+"connect to the specified database.
The error message received was %s"
+msgstr ""
+
+#: pdoengine.class.php:80 pdoengine.class.php:96 schema.php:26
+msgid "Database connection error!
"
+msgstr ""
+
+#: pdoengine.class.php:81 pdoengine.class.php:97 schema.php:27 schema.php:81
+msgid "Error message is: %s"
+msgstr ""
+
+#: pdoengine.class.php:115
+msgid ""
+"Unable to create the required directory! Please check your server settings."
+msgstr ""
+
+#: pdoengine.class.php:120 pdoengine.class.php:126
+msgid ""
+"Unable to create a file in the directory! Please check your server settings."
+msgstr ""
+
+#: pdoengine.class.php:148
+#, php-format
+msgid ""
+"
Sorry, we cannot determine the type of query " +"that is requested.
The query is %s
" +msgstr "" + +#: pdoengine.class.php:294 +#, php-format +msgid "Problem preparing the PDO SQL Statement. Error was: %s" +msgstr "" + +#: pdoengine.class.php:327 +#, php-format +msgid "Error while executing query! Error message was: %s" +msgstr "" + +#: pdoengine.class.php:381 +msgid "The query is too big to parse properly" +msgstr "" + +#: pdoengine.class.php:583 +#, php-format +msgid "Problem in creating table or index. Error was: %s" +msgstr "" + +#: pdoengine.class.php:626 +#, php-format +msgid "Problem in executing alter query. Error was: %s" +msgstr "" + +#: schema.php:80 +#, php-format +msgid "" +"Error occured while creating tables or indexes...WordPress database error: [$str]
+ $query
We have been unable to connect to the specified database.
The error message received was %s"), $this->dbh->errorInfo()));
+ return;
+ }
+ $this->ready = true;
+ }
+
+ /**
+ * overrides wpdb::query()
+ * @see wpdb::query()
+ */
+ function query($query) {
+ if (!$this->ready)
+ return false;
+
+ $query = apply_filters('query', $query);
+
+ $return_val = 0;
+ $this->flush();
+
+ $this->func_call = "\$db->query(\"$query\")";
+
+ $this->last_query = $query;
+
+ if (defined('SAVEQUERIES') && SAVEQUERIES)
+ $this->timer_start();
+
+ $this->result = $this->dbh->query($query);
+ $this->num_queries++;
+
+ if (defined('SAVEQUERIES') && SAVEQUERIES)
+ $this->queries[] = array($query, $this->timer_stop(), $this->get_caller());
+
+ if ($this->last_error = $this->dbh->get_error_message()) {
+ if (defined('WP_INSTALLING') && WP_INSTALLING) {
+ //$this->suppress_errors();
+ } else {
+ $this->print_error($this->last_error);
+ return false;
+ }
+ }
+
+ if (preg_match('/^\\s*(create|alter|truncate|drop|optimize)\\s*/i', $query)) {
+// $return_val = $this->result;
+ $return_val = $this->dbh->get_return_value();
+ } elseif (preg_match('/^\\s*(insert|delete|update|replace)\s/i', $query)) {
+ $this->rows_affected = $this->dbh->get_affected_rows();
+ if (preg_match('/^\s*(insert|replace)\s/i', $query)) {
+ $this->insert_id = $this->dbh->get_insert_id();
+ }
+ $return_val = $this->rows_affected;
+ } else {
+ $this->last_result = $this->dbh->get_query_results();
+ $this->num_rows = $this->dbh->get_num_rows();
+ $return_val = $this->num_rows;
+ }
+ return $return_val;
+ }
+
+ /**
+ * overrides wpdb::load_col_info(), which uses a mysql function.
+ * @see wpdb::load_col_info()
+ */
+ function load_col_info() {
+ if ($this->col_info)
+ return;
+ $this->col_info = $this->dbh->get_columns();
+ }
+
+ /**
+ * overrides wpdb::has_cap()
+ * We don't support collation, group_concat, set_charset
+ * @see wpdb::has_cap()
+ */
+ function has_cap($db_cap) {
+ switch(strtolower($db_cap)) {
+ case 'collation':
+ case 'group_concat':
+ case 'set_charset':
+ return false;
+ case 'subqueries':
+ return true;
+ default:
+ return false;
+ }
+ }
+ /**
+ * overrides wpdb::db_version()
+ * Returns mysql version number but it means nothing for SQLite.
+ * @see wpdb::db_version()
+ */
+ function db_version() {
+ global $required_mysql_version;
+ return $required_mysql_version;
+ }
+}
+
+/**
+ * Initialize $wpdb with PDODB class
+ */
+if (!isset($wpdb)) {
+ global $wpdb;
+ $wpdb = new PDODB();
+}
+?>
\ No newline at end of file
diff --git a/pdoengine.class.php b/pdoengine.class.php
new file mode 100644
index 0000000..56f472c
--- /dev/null
+++ b/pdoengine.class.php
@@ -0,0 +1,898 @@
+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!
", 'sqlite-integration');
+ $message .= sprintf(__("Error message is: ", 'sqlite-integration'), $err->getMessage());
+ $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!
", '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);
+ $message = __('Unable to create the required directory! Please check your server settings.', 'sqlite-integration');
+ echo $message;
+ return false;
+ }
+ }
+ if (!is_writable(FQDBDIR)) {
+ umask($u);
+ $message = __('Unable to create a file in the directory! Please check your server settings.', 'sqlite-integration');
+ echo $message;
+ return false;
+ }
+ if (!is_file(FQDBDIR . '.htaccess')) {
+ $fh = fopen(FQDBDIR . '.htaccess', "w");
+ if (!$fh) {
+ umask($u);
+ $message = __('Unable to create a file in the directory! Please check your server settings.', 'sqlite-integration');
+ 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(__("
Sorry, we cannot determine the type of query that is requested.
The query is %s
", '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; + 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 = '" . ob_get_contents() . ""; + 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 = '/(? 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) { + $result = preg_match('/^\\s*(EXPLAIN|PRAGMA|SELECT\\s*FOUND_ROWS|SELECT|INSERT|UPDATE|REPLACE|DELETE|ALTER|CREATE|DROP|SHOW\\s*\\w+\\s*\\w+\\s*|DESCRIBE|DESC|TRUNCATE|OPTIMIZE)/i', $query, $match); + + 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; + } + } + 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("/(''|(?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; + } + } + } +} +?> \ No newline at end of file diff --git a/query.class.php b/query.class.php new file mode 100644 index 0000000..d773e9e --- /dev/null +++ b/query.class.php @@ -0,0 +1,526 @@ +query_type = $query_type; + $this->_query = $query; + switch ($this->query_type) { + case 'truncate': + $this->_handle_truncate_query(); + break; + case 'alter': + $this->_handle_alter_query(); + break; + case 'create': + $this->_handle_create_query(); + break; + case 'describe': + case 'desc': + $this->_handle_describe_query(); + break; + case 'show': + $this->_handle_show_query(); + break; + case 'showcolumns': + $this->_handle_show_columns_query(); + break; + case 'showindex': + $this->_handle_show_index(); + break; + case 'select': + $this->_strip_backticks(); + $this->_handle_sql_count(); + $this->_rewrite_date_sub(); + $this->_delete_index_hints(); + $this->_rewrite_regexp(); + $this->_rewrite_boolean(); + break; + case 'insert': + $this->_strip_backticks(); + $this->_execute_duplicate_key_update(); + $this->_rewrite_insert_ignore(); + $this->_rewrite_regexp(); + break; + case 'update': + $this->_strip_backticks(); + $this->_rewrite_update_ignore(); +// $this->_rewrite_date_sub(); + $this->_rewrite_limit_usage(); + $this->_rewrite_order_by_usage(); + $this->_rewrite_regexp(); + break; + case 'delete': + $this->_strip_backticks(); + $this->_rewrite_limit_usage(); + $this->_rewrite_order_by_usage(); + $this->_rewrite_date_sub(); + $this->_rewrite_regexp(); + $this->_delete_workaround(); + break; + case 'replace': + $this->_strip_backticks(); + $this->_rewrite_date_sub(); + $this->_rewrite_regexp(); + break; + case 'optimize': + $this->_rewrite_optimize(); + break; + default: + } + return $this->_query; + } + + /** + * method to dummy the SHOW TABLES query + */ + private function _handle_show_query(){ + $table_name = ''; + $pattern = '/^\\s*SHOW\\s*TABLES\\s*(LIKE\\s*(.*))$/im'; + if (preg_match($pattern, $this->_query, $matches)) { + $table_name = str_replace(array("'", ';'), '', $matches[2]); + } + if (!empty($table_name)) { + $suffix = ' AND name LIKE '. "'" . $table_name . "'"; + } else { + $suffix = ''; + } + $this->_query = "SELECT name FROM sqlite_master WHERE type='table'" . $suffix . ' ORDER BY name DESC'; + } + + /** + * method to strip all column qualifiers (backticks) from a query + */ + private function _strip_backticks(){ + $this->_query = str_replace('`', '', $this->_query); + } + + /** + * method to emulate the SQL_CALC_FOUND_ROWS placeholder for mysql + * + * this is a kind of tricky play. + * 1. remove SQL_CALC_FOUND_ROWS option, and give it to the pdo engine + * 2. make another $wpdb instance, and execute SELECT COUNT(*) query + * 3. give the returned value to the original instance variable + * + * when SQL statement contains GROUP BY option, SELECT COUNT query doesn't + * go well. So we remove the GROUP BY, which means the returned value may + * be a approximate one. + * + * this kind of statement is required for WordPress to calculate the paging. + * see also WP_Query class in wp-includes/query.php + */ + private function _handle_sql_count(){ + if (stripos($this->_query, 'SELECT SQL_CALC_FOUND_ROWS') !== false){ + global $wpdb; + // first strip the code. this is the end of rewriting process + $this->_query = str_ireplace('SQL_CALC_FOUND_ROWS', '', $this->_query); + // we make the data for next SELECE FOUND_ROWS() statement + $unlimited_query = preg_replace('/\\bLIMIT\\s*.*/imsx', '', $this->_query); +// $unlimited_query = preg_replace('/\\bFALSE\\s*.*/imsx', '0', $unlimited_query); + $unlimited_query = preg_replace('/\\bGROUP\\s*BY\\s*.*/imsx', '', $unlimited_query); + $unlimited_query = $this->__transform_to_count($unlimited_query); + $_wpdb = new PDODB(); + $result = $_wpdb->query($unlimited_query); + $wpdb->dbh->found_rows_result = $_wpdb->last_result; + } + } + + /** + * transforms a select query to a select count(*) + * + * @param string $query the query to be transformed + * @return string the transformed query + */ + private function __transform_to_count($query){ + $pattern = '/^\\s*SELECT\\s*(DISTINCT|)?.*?FROM\b/imsx'; + $_query = preg_replace($pattern, 'SELECT \\1 COUNT(*) FROM ', $query); + return $_query; + } + + /** + * rewrites the insert ignore phrase for sqlite + */ + private function _rewrite_insert_ignore(){ + $this->_query = str_ireplace('INSERT IGNORE', 'INSERT OR IGNORE ', $this->_query); + } + + /** + * rewrites the update ignore phrase for sqlite + */ + private function _rewrite_update_ignore(){ + $this->_query = str_ireplace('UPDATE IGNORE', 'UPDATE OR IGNORE ', $this->_query); + } + + + /** + * rewrites the date_add function for udf to manipulate + */ + private function _rewrite_date_add(){ + //(date,interval expression unit) + $pattern = '/\\s*date_add\\s*\(([^,]*),([^\)]*)\)/imsx'; + if (preg_match($pattern, $this->_query, $matches)) { + $expression = "'".trim($matches[2])."'"; + $this->_query = preg_replace($pattern, " date_add($matches[1], $expression) ", $this->_query); + } + } + + /** + * rewrite the data_sub function for udf to manipulate + */ + private function _rewrite_date_sub(){ + //(date,interval expression unit) + $pattern = '/\\s*date_sub\\s*\(([^,]*),([^\)]*)\)/imsx'; + if (preg_match($pattern, $this->_query, $matches)) { + $expression = "'".trim($matches[2])."'"; + $this->_query = preg_replace($pattern, " date_sub($matches[1], $expression) ", $this->_query); + } + } + + /** + * handles the create query + * this function won't be used... See PDOEngine class + */ + private function _handle_create_query(){ + require_once PDODIR.'query_create.class.php'; + $engine = new CreateQuery(); + $this->_query = $engine->rewrite_query($this->_query); + $engine = null; + } + + /** + * handles the ALTER query + * this function won't be used... See PDOEngine class + */ + private function _handle_alter_query(){ + require_once PDODIR . 'query_alter.class.php'; + $engine = new AlterQuery(); + $this->_query = $engine->rewrite_query($this->_query, 'alter'); + $engine = null; + } + + /** + * handles DESCRIBE or DESC query + * this is required in the WordPress install process + */ + private function _handle_describe_query(){ + // $this->_query = "select 1=1"; + $pattern = '/^\\s*(DESCRIBE|DESC)\\s*(.*)/i'; + if (preg_match($pattern, $this->_query, $match)) { + $tablename = preg_replace('/[\';]/', '', $match[2]); + $this->_query = "PRAGMA table_info($tablename)"; + } + } + + /** + * The author of the original 'PDO for WordPress' says update method of wpdb + * insists on adding LIMIT. But the newest version of WordPress doesn't do that. + * Nevertheless some plugins use DELETE with LIMIT, UPDATE with LIMIT. + * We need to exclude sub query's LIMIT. + */ + private function _rewrite_limit_usage(){ + if (stripos($this->_query, '(select') === false) { + $this->_query = preg_replace('/\\s*LIMIT\\s*[0-9]$/i', '', $this->_query); + } + } + /** + * SQLite compiled without SQLITE_ENABLE_UPDATE_DELETE_LIMIT option can't + * execute UPDATE with ORDER BY, DELETE with GROUP BY. + * We need to exclude sub query's GROUP BY. + */ + private function _rewrite_order_by_usage() { + if (stripos($this->_query, '(select') === false) { + $this->_query = preg_replace('/\\s*ORDER\\s*BY\\s*.*$/i', '', $this->_query); + } + } + + private function _handle_truncate_query(){ + $pattern = '/TRUNCATE TABLE (.*)/im'; + $this->_query = preg_replace($pattern, 'DELETE FROM $1', $this->_query); + } + /** + * rewrites use of Optimize queries in mysql for sqlite. + * table name is ignored. + */ + private function _rewrite_optimize(){ + $this->_query ="VACUUM"; + } + + /** + * Jusitn Adie says: some wp UI interfaces (notably the post interface) + * badly composes the day part of the date leading to problems in sqlite + * sort ordering etc. + * + * I don't understand that... + * + * @return void + */ + private function _rewrite_badly_formed_dates(){ + $pattern = '/([12]\d{3,}-\d{2}-)(\d )/ims'; + $this->_query = preg_replace($pattern, '${1}0$2', $this->_query); + } + + /** + * function to remove unsupported index hinting from mysql queries + * + * @return void + */ + private function _delete_index_hints(){ + $pattern = '/use\s+index\s*\(.*?\)/i'; + $this->_query = preg_replace($pattern, '', $this->_query); + } + + /** + * Justin Adie says: + * method to fix inconsistent use of quoted, unquoted etc date values in query function + * this is ironic, given the above rewrite badlyformed dates method + * examples + * where month(fieldname)=08 becomes month(fieldname)='8' + * where month(fieldname)='08' becomes month(fieldname)='8' + * + * I don't understand... + * + * @return void + */ + private function _fix_date_quoting(){ + $pattern = '/(month|year|second|day|minute|hour|dayofmonth)\s*\((.*?)\)\s*=\s*["\']?(\d{1,4})[\'"]?\s*/ei'; + $this->_query = preg_replace($pattern, "'\\1(\\2)=\'' . intval('\\3') . '\' ' ", $this->_query); + } + + private function _rewrite_regexp(){ + $pattern = '/\s([^\s]*)\s*regexp\s*(\'.*?\')/im'; + $this->_query = preg_replace($pattern, ' regexpp(\1, \2)', $this->_query); + } + + /** + * rewrites boolean to numeral + * SQLite doesn't support true/false type + */ + private function _rewrite_boolean() { + $query = str_ireplace('TRUE', "1", $this->_query); + $query = str_ireplace('FALSE', "0", $query); + $this->_query = $query; + } + + /** + * method to execute SHOW COLUMNS query + */ + private function _handle_show_columns_query() { + $pattern_like = '/^\\s*SHOW\\s*(COLUMNS|FIELDS)\\s*FROM\\s*(.*)?\\s*LIKE\\s*(.*)?/i'; + $pattern = '/^\\s*SHOW\\s*(COLUMNS|FIELDS)\\s*FROM\\s*(.*)?/i'; + if (preg_match($pattern_like, $this->_query, $matches)) { + $table_name = str_replace("'", "", trim($matches[2])); + $column_name = str_replace("'", "", trim($matches[3])); + $query_string = "SELECT sql FROM sqlite_master WHERE tbl_name='$table_name' AND sql LIKE '%$column_name%'"; + $this->_query = $query_string; + } elseif (preg_match($pattern, $this->_query, $matches)) { + $table_name = $matches[2]; + $query_string = preg_replace($pattern, "PRAGMA table_info($table_name)", $this->_query); + $this->_query = $query_string; + } + } + + /** + * method to execute SHOW INDEX query + */ + private function _handle_show_index() { + $_columns = array(// No, you'll get no meaningful information.. + 'Key_name' => 'name', + ); + $pattern_0 = '/^\\s*SHOW\\s*(?:INDEX|INDEXES|KEYS)\\s*FROM\\s*(\\w+)?\\s*WHERE\\s*(.*)$/im'; + $pattern_1 = '/^\\s*SHOW\\s*(?:INDEX|INDEXES|KEYS)\\s*FROM\\s*(\\w+)?/im'; + if (preg_match($pattern_0, $this->_query, $match_0)) { + $table_name = str_replace("'", '', $match_0[1]); + list($key, $value) = explode('=', $match_0[2]); + $key = trim($key); + $value = preg_replace("/[\';]/", '', $value); + $value = trim($value); + if (array_key_exists($key, $_columns)) { + $key = $_columns[$key]; + $where_clause = 'AND ' . $key . ' LIKE ' . "'" . $value . "%'"; + } else { + $where_clause = ''; + } + $this->_query = "SELECT * FROM sqlite_master WHERE tbl_name='$table_name' $where_clause"; + } elseif (preg_match($pattern_1, $this->_query, $match_1)) { + $table_name = preg_replace("/[\';]/", '', $match_1[1]); + $table_name = trim($table_name); + $this->_query = "SELECT * FROM sqlite_master WHERE tbl_name='$table_name'"; + } + } + + /** + * function to rewrite ON DUPLICATE KEY UPDATE statement + * I use SELECT query and check if INSERT is allowed or not + * Rewriting procedure looks like a detour, but I've got another way. + * + * @return void + */ + private function _execute_duplicate_key_update() { + $update = false; + $unique_keys_for_cond = array(); + $unique_keys_for_check = array(); + $pattern = '/^\\s*INSERT\\s*INTO\\s*(\\w+)?\\s*(.*)\\s*ON\\s*DUPLICATE\\s*KEY\\s*UPDATE\\s*(.*)$/ims'; + if (preg_match($pattern, $this->_query, $match_0)) { + $table_name = trim($match_0[1]); + $insert_data = trim($match_0[2]); + $update_data = trim($match_0[3]); + // prepare two unique key data for the table + // 1. array('col1', 'col2, col3', etc) 2. array('col1', 'col2', 'col3', etc) + $_wpdb = new PDODB(); + $indexes = $_wpdb->get_results("SHOW INDEX FROM {$table_name}"); + if (!empty($indexes)) { + foreach ($indexes as $index) { + if ($index->Non_unique == 0) { + $unique_keys_for_cond[] = $index->Column_name; + if (strpos($index->Column_name, ',') !== false) { + $unique_keys_for_check = array_merge($unique_keys_for_check, explode(',', $index->Column_name)); + } else { + $unique_keys_for_check[] = $index->Column_name; + } + } + } + $unique_keys_for_check = array_map('trim', $unique_keys_for_check); + } else { + // Without unique key or primary key, UPDATE statement will affect all the rows! + $query = 'INSERT INTO '.$table_name.' '.$insert_data; + $this->_query = $query; + $_wpdb = null; + return; + } + // data check + if (preg_match('/^\((.*)\)\\s*VALUES\\s*\((.*)\)$/im', $insert_data, $match_1)) { + $col_array = explode(',', $match_1[1]); + $ins_data_array = explode(',', $match_1[2]); + foreach ($col_array as $col) { + $val = trim(array_shift($ins_data_array)); + $ins_data_assoc[trim($col)] = $val; + } +// $ins_data_assoc = array_combine($col_array, $ins_array); + $condition = ''; + foreach ($unique_keys_for_cond as $unique_key) { + if (strpos($unique_key, ',') !== false) { + $unique_key_array = explode(',', $unique_key); + $counter = count($unique_key_array); + for ($i = 0; $i < $counter; ++$i) { + $col = trim($unique_key_array[$i]); + if (isset($ins_data_assoc[$col]) && $i == $counter - 1) { + $condition .= $col . '=' . $ins_data_assoc[$col] . ' OR '; + } elseif (isset($ins_data_assoc[$col])) { + $condition .= $col . '=' . $ins_data_assoc[$col] . ' AND '; + } else { + continue; + } + } +// $condition = rtrim($condition, ' AND '); + } else { + $col = trim($unique_key); + if (isset($ins_data_assoc[$col])) { + $condition .= $col . '=' . $ins_data_assoc[$col] . ' OR '; + } else { + continue; + } + } + } + $condition = rtrim($condition, ' OR '); + $test_query = "SELECT * FROM {$table_name} WHERE {$condition}"; + $results = $_wpdb->query($test_query); + $_wpdb = null; + if ($results == 0) { + $this->_query = 'INSERT INTO '.$table_name.' '.$insert_data; + return; + } else { + // change (col, col...) values (data, data...) to array(col=>data, col=>data...) + if (preg_match('/^\((.*)\)\\s*VALUES\\s*\((.*)\)$/im', $insert_data, $match_2)) { + $col_array = explode(',', $match_2[1]); + $ins_array = explode(',', $match_2[2]); + $count = count($col_array); + for ($i = 0; $i < $count; $i++) { + $col = trim($col_array[$i]); + $val = trim($ins_array[$i]); + $ins_array_assoc[$col] = $val; + } + } + // change col = data, col = data to array(col=>data, col=>data) + // some plugins have semi-colon at the end of the query + $update_data = rtrim($update_data, ';'); + $tmp_array = explode(',', $update_data); + foreach ($tmp_array as $pair) { + list($col, $value) = explode('=', $pair); + $col = trim($col); + $value = trim($value); + $update_array_assoc[$col] = $value; + } + // change array(col=>values(col)) to array(col=>data) + foreach ($update_array_assoc as $key => &$value) { + if (preg_match('/^VALUES\\s*\((.*)\)$/im', $value, $match_3)) { + $col = trim($match_3[1]); + $value = $ins_array_assoc[$col]; + } + } + foreach ($ins_array_assoc as $key => $val) { + if (in_array($key, $unique_keys_for_check)) { + $where_array[] = $key . '=' . $val; + } + } + $update_strings = ''; + foreach ($update_array_assoc as $key => $val) { + if (in_array($key, $unique_keys_for_check)) { + $where_array[] = $key . '=' . $val; + } else { + $update_strings .= $key . '=' . $val . ','; + } + } + $update_strings = rtrim($update_strings, ','); + $unique_where = array_unique($where_array, SORT_REGULAR); + $where_string = ' WHERE ' . implode(' AND ', $unique_where); + // $where_string = ' WHERE ' . rtrim($where_string, ','); + $update_query = 'UPDATE ' . $table_name . ' SET ' . $update_strings . $where_string; + $this->_query = $update_query; + } + } + } else { + // wordaround... + $pattern = '/ ON DUPLICATE KEY UPDATE.*$/im'; + $replace_query = preg_replace($pattern, '', $this->_query); + $replace_query = str_ireplace('INSERT ', 'INSERT OR REPLACE ', $replace_query); + $this->_query = $replace_query; + } + } + + /** + * workaround function to avoid DELETE with JOIN + * wp-admin/includes/upgrade.php contains 'DELETE ... JOIN' statement. + * This query can't be replaced with regular expression or udf, so we + * replace all the statement with another. + */ + private function _delete_workaround() { + global $wpdb; +// $pattern = "DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2 USING (option_name) WHERE o2.option_id > o1.option_id"; + $pattern = "DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2"; + $rewritten = "DELETE FROM $wpdb->options WHERE option_id IN (SELECT MIN(option_id) FROM $wpdb->options GROUP BY option_name HAVING COUNT(*) > 1)"; + if (stripos($this->_query, $pattern) !== false) { + $this->_query = $rewritten; + } + } +} +?> \ No newline at end of file diff --git a/query_alter.class.php b/query_alter.class.php new file mode 100644 index 0000000..0b410a6 --- /dev/null +++ b/query_alter.class.php @@ -0,0 +1,453 @@ +split_multiple($command); + foreach ($command_array as $single_command) { + $command_tokens = $this->command_tokenizer($single_command); + if (!empty($command_tokens)) { + $tokens[] = array_merge($tmp_tokens, $command_tokens); + } else { + $this->_query = 'SELECT 1=1'; + } + } + foreach ($tokens as $token) { + $command_name = $token['command']; + switch ($command_name) { + case 'add column': case 'rename to': case 'add index': case 'drop index': + $this->_query = $this->handle_single_command($token); + break; + case 'add primary key': + $this->_query = $this->handle_add_primary_key($token); + break; + case 'drop primary key': + $this->_query = $this->handle_drop_primary_key($token); + break; + case 'modify column': + $this->_query = $this->handle_modify_command($token); + break; + case 'change column': + $this->_query = $this->handle_change_command($token); + break; + case 'alter column': + $this->_query = $this->handle_alter_command($token); + break; + default: + break; + } + } + } else { + $this->_query = 'SELECT 1=1'; + } + return $this->_query; + } + + private function command_tokenizer($command) { + $tokens = array(); + if (preg_match('/^(ADD|DROP|RENAME|MODIFY|CHANGE|ALTER)\\s*(\\w+)?\\s*(\\w+)?\\s*/ims', $command, $match)) { + $the_rest = str_ireplace($match[0], '', $command); + $match_1 = strtolower(trim($match[1])); + $match_2 = strtolower(trim($match[2])); + $match_3 = isset($match[3]) ? strtolower(trim($match[3])) : ''; + switch ($match_1) { + case 'add': + if (in_array($match_2, array('fulltext', 'constraint', 'foreign'))) { + break; + } elseif ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + $tokens['column_def'] = trim($the_rest); + } elseif ($match_2 == 'primary') { + $tokens['command'] = $match_1.' '.$match_2.' '.$match_3; + $tokens['column_name'] = $the_rest; + } elseif ($match_2 == 'unique') { + list($index_name, $col_name) = preg_split('/[\(\)]/s', trim($the_rest), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens['unique'] = true; + $tokens['command'] = $match_1.' '.$match_3; + $tokens['index_name'] = trim($index_name); + $tokens['column_name'] = '('.trim($col_name).')'; + } elseif (in_array($match_2, array('index', 'key'))) { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['index_name'] = $match_3; + $tokens['column_name'] = trim($the_rest); + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + $tokens['column_def'] = $match_3.' '.$the_rest; + } + break; + case 'drop': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = trim($match_3); + } elseif ($match_2 == 'primary') { + $tokens['command'] = $match_1.' '.$match_2.' '.$match_3; + } elseif (in_array($match_2, array('index', 'key'))) { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['index_name'] = $match_3; + } elseif ($match_2 == 'primary') { + $tokens['command'] = $match_1.' '.$match_2.' '.$match_3; + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + } + break; + case 'rename': + if ($match_2 == 'to') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + } else { + $tokens['command'] = $match_1.' to'; + $tokens['column_name'] = $match_2; + } + break; + case 'modify': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + $tokens['column_def'] = trim($the_rest); + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + $tokens['column_def'] = $match_3.' '.trim($the_rest); + } + break; + case 'change': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['old_column'] = $match_3; + list($new_col) = preg_split('/\s/s', trim($the_rest), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens['new_column'] = $new_col; + $col_def = str_ireplace($new_col, '', $the_rest); + $tokens['column_def'] = trim($col_def); + } else { + $tokens['command'] = $match_1.' column'; + $tokens['old_column'] = $match_2; + $tokens['new_column'] = $match_3; + $tokens['column_def'] = trim($the_rest); + } + break; + case 'alter': + if ($match_2 == 'column') { + $tokens['command'] = $match_1.' '.$match_2; + $tokens['column_name'] = $match_3; + list($set_or_drop) = explode(' ', $the_rest); + if ($set_or_drop == 'set') { + $tokens['default_command'] = 'set default'; + $default_value = str_ireplace('set default', '', $the_rest); + $tokens['default_value'] = trim($default_value); + } else { + $tokens['default_command'] = 'drop default'; + } + } else { + $tokens['command'] = $match_1.' column'; + $tokens['column_name'] = $match_2; + if ($match_3 == 'set') { + $tokens['default_command'] = 'set default'; + $default_value = str_ireplace('default', '', $the_rest); + $tokens['default_value'] = trim($default_value); + } else { + $tokens['default_command'] = 'drop default'; + } + } + break; + default: + break; + } + return $tokens; + } + } + + private function split_multiple($command) { + $out = true; + $command_array = array(); + $command_string = ''; + $tokens = preg_split('/\b/s', $command, -1, PREG_SPLIT_DELIM_CAPTURE); + foreach ($tokens as $token) { + switch (trim($token)) { + case ';': + break; + case '(': + $command_string .= $token; + $out = false; + break; + case ')': + $command_string .= $token; + $out = true; + break; + case '),': + $command_array[] = $command_string; + $command_string = ''; + $out = true; + break; + case ',': + if ($out) { + $command_array[] = $command_string; + $command_string = ''; + } else { + $command_string .= $token; + } + break; + default: + $command_string .= $token; + break; + } + } + if (!empty($command_string)) { + $command_array[] = $command_string; + } + return $command_array; + } + + private function handle_single_command($queries) { + $tokenized_query = $queries; + if (stripos($tokenized_query['command'], 'add column') !== false) { + $column_def = $this->convert_field_types($tokenized_query['column_name'], $tokenized_query['column_def']); + $query = "ALTER TABLE {$tokenized_query['table_name']} ADD COLUMN {$tokenized_query['column_name']} $column_def"; + } elseif (stripos($tokenized_query['command'], 'rename') !== false) { + $query = "ALTER TABLE {$tokenized_query['table_name']} RENAME TO {$tokenized_query['column_name']}"; + } elseif (stripos($tokenized_query['command'], 'add index') !== false) { + $unique = isset($tokenized_query['unique']) ? 'UNIQUE' : ''; + $query = "CREATE $unique INDEX IF NOT EXISTS {$tokenized_query['index_name']} ON {$tokenized_query['table_name']} {$tokenized_query['column_name']}"; + } elseif (stripos($tokenized_query['command'], 'drop index') !== false) { + $query = "DROP INDEX IF EXISTS {$tokenized_query['index_name']}"; + } else { + $query = 'SELECT 1=1'; + } + return $query; + } + + private function handle_add_primary_key($queries) { + $tokenized_query = $queries; + $tbl_name = $tokenized_query['table_name']; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='$tbl_name'"); + $_wpdb = null; + for ($i = 0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $table_query = array_shift($index_queries); + $table_query = str_replace($tokenized_query['table_name'], $temp_table, $table_query); + $table_query = rtrim($table_query, ')'); + $table_query = ", PRIMARY KEY {$tokenized_query['column_name']}"; + $query[] = $table_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_drop_primary_key($queries) { + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i = 0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $table_query = array_shift($index_queries); + $pattern1 = '/^\\s*PRIMARY\\s*KEY\\s*\(.*\)/im'; + $pattern2 = '/^\\s*.*(PRIMARY\\s*KEY\\s*(:?AUTOINCREMENT|))\\s*(?!\()/im'; + if (preg_match($pattern1, $table_query, $match)) { + $table_query = str_replace($match[0], '', $table_query); + } elseif (preg_match($pattern2, $table_query, $match)) { + $table_query = str_replace($match[1], '', $table_query); + } + $table_query = str_replace($tokenized_query['table_name'], $temp_table, $table_query); + $query[] = $table_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_modify_command($queries) { + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $column_def = $this->convert_field_types($tokenized_query['column_name'], $tokenized_query['column_def']); + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i =0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $create_query = array_shift($index_queries); + if (stripos($create_query, $tokenized_query['column_name']) === false) { + return 'SELECT 1=1'; + } elseif (preg_match("/{$tokenized_query['column_name']}\\s*{$tokenized_query['column_def']}\\s*[,)]/i", $create_query)) { + return 'SELECT 1=1'; + } + $create_query = preg_replace("/{$tokenized_query['table_name']}/i", $temp_table, $create_query); + if (preg_match("/\\b{$tokenized_query['column_name']}\\s*.*(?=,)/ims", $create_query)) { + $create_query = preg_replace("/\\b{$tokenized_query['column_name']}\\s*.*(?=,)/ims", "{$tokenized_query['column_name']} {$tokenized_query['column_def']}", $create_query); + } elseif (preg_match("/\\b{$tokenized_query['column_name']}\\s*.*(?=\))/ims", $create_query)) { + $create_query = preg_replace("/\\b{$tokenized_query['column_name']}\\s*.*(?=\))/ims", "{$tokenized_query['column_name']} {$tokenized_query['column_def']}", $create_query); + } + $query[] = $create_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_change_command($queries) { + $col_check = false; + $old_fields = ''; + $new_fields = ''; + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + $column_def = $this->convert_field_types($tokenized_query['new_column'], $tokenized_query['column_def']); + $_wpdb = new PDODB(); + $col_obj = $_wpdb->get_results("SHOW COLUMNS FROM {$tokenized_query['table_name']}"); + foreach ($col_obj as $col) { + if ($col->Field == $tokenized_query['old_column']) $col_check = true; + $old_fields .= $col->Field . ','; + } + if ($col_check == false) { + $_wpdb = null; + return 'SELECT 1=1'; + } + $old_fields = rtrim($old_fields, ','); + $new_fields = str_replace($tokenized_query['old_column'], $tokenized_query['new_column'], $old_fields); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i = 0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $create_query = array_shift($index_queries); + $create_query = preg_replace("/{$tokenized_query['table_name']}/i", $temp_table, $create_query); + if (preg_match("/\\b{$tokenized_query['old_column']}\\s*(.+?)(?=,)/ims", $create_query, $match)) { + if ($tokenized_query['column_def'] == trim($match[1])) { + return 'SELECT 1=1'; + } else { + $create_query = preg_replace("/\\b{$tokenized_query['old_column']}\\s*.*?(?=,)/ims", "{$tokenized_query['new_column']} {$tokenized_query['column_def']}", $create_query); + } + } elseif (preg_match("/\\b{$tokenized_query['old_column']}\\s*(.+?)(?=\))/ims", $create_query, $match)) { + if ($tokenized_query['column_def'] == trim($match[1])) { + return 'SELECT 1=1'; + } else { + $create_query = preg_replace("/\\b{$tokenized_query['old_column']}\\s*.*?(?=\))/ims", "{$tokenized_query['new_column']} {$tokenized_query['column_def']}", $create_query); + } + } + $query[] = $create_query; + $query[] = "INSERT INTO $temp_table ($new_fields) SELECT $old_fields FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + + private function handle_alter_command($queries) { + $tokenized_query = $queries; + $temp_table = 'temp_'.$tokenized_query['table_name']; + if (stripos($tokenized_query['default_command'], 'set') !== false) { + $def_value = $this->convert_field_types($tokenized_query['column_name'], $tokenized_query['default_value']); + $def_value = 'DEFAULT '.$def_value; + } else { + $def_value = ''; + } + $_wpdb = new PDODB(); + $query_obj = $_wpdb->get_results("SELECT sql FROM sqlite_master WHERE tbl_name='{$tokenized_query['table_name']}'"); + $_wpdb = null; + for ($i =0; $i < count($query_obj); $i++) { + $index_queries[$i] = $query_obj[$i]->sql; + } + $create_query = array_shift($index_queries); + if (stripos($create_query, $tokenized_query['column_name']) === false) { + return 'SELECT 1=1'; + } + if (preg_match("/\\s*({$tokenized_query['column_name']}\\s*.*?)\\s*(DEFAULT\\s*.*)[,)]/im", $create_query, $match)) { + $col_def = trim($match[1]); + $old_default = trim($match[2]); + $create_query = preg_replace("/($col_def)\\s*$old_default/im", "\\1 $def_value", $create_query); + $create_query = str_ireplace($tokenized_query['table_name'], $temp_table, $create_query); + } else { + return 'SELECT 1=1'; + } + $query[] = $create_query; + $query[] = "INSERT INTO $temp_table SELECT * FROM {$tokenized_query['table_name']}"; + $query[] = "DROP TABLE IF EXISTS {$tokenized_query['table_name']}"; + $query[] = "ALTER TABLE $temp_table RENAME TO {$tokenized_query['table_name']}"; + foreach ($index_queries as $index) { + $query[] = $index; + } + return $query; + } + /** + * Change the field definition to SQLite compatible data type. + * @param string $col_name + * @param string $col_def + * @return string + */ + private function convert_field_types($col_name, $col_def){ + $array_types = array( + 'bit' => 'INTEGER', 'bool' => 'INTEGER', + 'boolean' => 'INTEGER', 'tinyint' => 'INTEGER', + 'smallint' => 'INTEGER', 'mediumint' => 'INTEGER', + 'int' => 'INTEGER', 'integer' => 'INTEGER', + 'bigint' => 'INTEGER', 'float' => 'REAL', + 'double' => 'REAL', 'decimal' => 'REAL', + 'dec' => 'REAL', 'numeric' => 'REAL', + 'fixed' => 'REAL', 'date' => 'TEXT', + 'datetime' => 'TEXT', 'timestamp' => 'TEXT', + 'time' => 'TEXT', 'year' => 'TEXT', + 'char' => 'TEXT', 'varchar' => 'TEXT', + 'binary' => 'INTEGER', 'varbinary' => 'BLOB', + 'tinyblob' => 'BLOB', 'tinytext' => 'TEXT', + 'blob' => 'BLOB', 'text' => 'TEXT', + 'mediumblob' => 'BLOB', 'mediumtext' => 'TEXT', + 'longblob' => 'BLOB', 'longtext' => 'TEXT' + ); + $array_curtime = array('current_timestamp', 'current_time', 'current_date'); + $array_reptime = array("'0000-00-00 00:00:00'", "'0000-00-00 00:00:00'", "'0000-00-00'"); + $def_string = str_replace('`', '', $col_def); + foreach ($array_types as $o=>$r){ + $pattern = "/\\b" . $o . "\\s*(\([^\)]*\))?\\s*/imsx"; + if (preg_match($pattern, $def_string)) { + $def_string = preg_replace($pattern, "$r ", $def_string); + break; + } + } + $def_string = preg_replace('/unsigned/im', '', $def_string); + $def_string = preg_replace('/auto_increment/im', 'PRIMARY KEY AUTOINCREMENT', $def_string); + // when you use ALTER TABLE ADD, you can't use current_*. so we replace + $def_string = str_ireplace($array_curtime, $array_reptime, $def_string); + // colDef is enum + $pattern_enum = '/enum\((.*?)\)([^,\)]*)/ims'; + if (preg_match($pattern_enum, $col_def, $matches)) { + $def_string = 'TEXT' . $matches[2] . ' CHECK (' . $col_name . ' IN (' . $matches[1] . '))'; + } + return $def_string; + } +} +?> \ No newline at end of file diff --git a/query_create.class.php b/query_create.class.php new file mode 100644 index 0000000..35b5df0 --- /dev/null +++ b/query_create.class.php @@ -0,0 +1,285 @@ +_query = $query; + $this->_errors [] = ''; + $this->strip_backticks(); + $this->get_table_name(); + $this->rewrite_comments(); + $this->rewrite_field_types(); + $this->rewrite_character_set(); + $this->rewrite_engine_info(); + $this->rewrite_unsigned(); + $this->rewrite_autoincrement(); + $this->rewrite_primary_key(); + $this->rewrite_unique_key(); + $this->rewrite_enum(); + $this->rewrite_set(); + $this->rewrite_key(); + $this->add_if_not_exists(); + + return $this->post_process(); + } + + /** + * Method for getting the table name from the create query. + * taken from PDO for WordPress + * we don't need 'IF NOT EXISTS', so we changed the pattern. + */ + private function get_table_name(){ + // $pattern = '/^\\s*CREATE\\s*(TEMP|TEMPORARY)?\\s*TABLE\\s*(IF NOT EXISTS)?\\s*([^\(]*)/imsx'; + $pattern = '/^\\s*CREATE\\s*(?:TEMP|TEMPORARY)?\\s*TABLE\\s*(?:IF\\s*NOT\\s*EXISTS)?\\s*([^\(]*)/imsx'; + if (preg_match($pattern, $this->_query, $matches)) { + $this->table_name = trim($matches[1]); + } + } + + /** + * Method for changing the field type to SQLite compatible type. + */ + private function rewrite_field_types(){ + $array_types = array ( + 'bit' => 'integer', 'bool' => 'integer', + 'boolean' => 'integer', 'tinyint' => 'integer', + 'smallint' => 'integer', 'mediumint' => 'integer', + 'int' => 'integer', 'integer' => 'integer', + 'bigint' => 'integer', 'float' => 'real', + 'double' => 'real', 'decimal' => 'real', + 'dec' => 'real', 'numeric' => 'real', + 'fixed' => 'real', 'date' => 'text', + 'datetime' => 'text', 'timestamp' => 'text', + 'time' => 'text', 'year' => 'text', + 'char' => 'text', 'varchar' => 'text', + 'binary' => 'integer', 'varbinary' => 'blob', + 'tinyblob' => 'blob', 'tinytext' => 'text', + 'blob' => 'blob', 'text' => 'text', + 'mediumblob' => 'blob', 'mediumtext' => 'text', + 'longblob' => 'blob', 'longtext' => 'text' + ); + foreach ($array_types as $o=>$r){ + $pattern = '/\\b(?_query = preg_replace($pattern, " $r ", $this->_query); + } + } + + /** + * Method for stripping the comments from the SQL statement + */ + private function rewrite_comments(){ + $this->_query = preg_replace("/# --------------------------------------------------------/","-- ******************************************************",$this->_query); + $this->_query = preg_replace("/#/","--",$this->_query); + } + + /** + * Method for stripping the engine and other stuffs + */ + private function rewrite_engine_info(){ + $this->_query = preg_replace("/\\s*(TYPE|ENGINE)\\s*=\\s*.*(?_query); + $this->_query = preg_replace("/ AUTO_INCREMENT\\s*=\\s*[0-9]*/ims",'',$this->_query); + } + + /** + * Method for stripping unsigned + */ + private function rewrite_unsigned(){ + $this->_query = preg_replace('/\\bunsigned\\b/ims', ' ', $this->_query); + } + + /** + * Method for rewriting auto_increment + * if the field type is 'integer primary key', it is automatically autoincremented + */ + private function rewrite_autoincrement(){ + $this->_query = preg_replace('/\\bauto_increment\\s*primary\\s*key\\s*(,)?/ims', ' PRIMARY KEY AUTOINCREMENT \\1', $this->_query, -1, $count); + $this->_query = preg_replace('/\\bauto_increment\\b\\s*(,)?/ims', ' PRIMARY KEY AUTOINCREMENT $1', $this->_query, -1, $count); + if ($count > 0){ + $this->has_primary_key = true; + } + } + + /** + * Method for rewriting primary key + */ + private function rewrite_primary_key(){ + if ($this->has_primary_key) { + $this->_query = preg_replace('/\\bprimary key\\s*\([^\)]*\)/ims', ' ', $this->_query); + } else { + // If primary key has an index name, we remove that name. + $this->_query = preg_replace('/\\bprimary\\s*key\\s*.*?\\s*(\(.*?\))/im', 'PRIMARY KEY \\1', $this->_query); + } + } + + /** + * Method for rewriting unique key + */ + private function rewrite_unique_key(){ + $this->_query = preg_replace_callback('/\\bunique key\\b([^\(]*)(\([^\)]*\))/ims', array($this, '_rewrite_unique_key'), $this->_query); + } + + /** + * Callback method for rewrite_unique_key + * @param array $matches an array of matches from the Regex + */ + private function _rewrite_unique_key($matches){ + $index_name = trim($matches[1]); + $col_name = trim($matches[2]); + $tbl_name = $this->table_name; + $_wpdb = new PDODB(); + $results = $_wpdb->get_results("SELECT name FROM sqlite_master WHERE type='index'"); + $_wpdb = null; + if ($results) { + foreach ($results as $result) { + if ($result->name == $index_name) { + $r = rand(0, 50); + $index_name = $index_name . "_$r"; + break; + } + } + } + $index_name = str_replace(' ', '', $index_name); + $this->index_queries[] = "CREATE UNIQUE INDEX $index_name ON " . $tbl_name .$col_name; + return ''; + } + + /** + * Method for handling ENUM fields + * SQLite doesn't support enum, so we change it to check constraint + */ + private function rewrite_enum(){ + $pattern = '/(,|\))([^,]*)enum\((.*?)\)([^,\)]*)/ims'; + $this->_query = preg_replace_callback($pattern, array($this, '_rewrite_enum'), $this->_query); + } + + /** + * Method for the callback function rewrite_enum and rewrite_set + */ + private function _rewrite_enum($matches){ + $output = $matches[1] . ' ' . $matches[2]. ' TEXT '. $matches[4].' CHECK ('.$matches[2].' IN ('.$matches[3].')) '; + return $output; + } + + /** + * Method for rewriting usage of set + * whilst not identical to enum, they are similar and sqlite does not + * support either. + */ + private function rewrite_set(){ + $pattern = '/\b(\w)*\bset\\s*\((.*?)\)\\s*(.*?)(,)*/ims'; + $this->_query = preg_replace_callback($pattern, array($this, '_rewrite_enum'), $this->_query); + } + + /** + * Method for rewriting usage of key to create an index + * sqlite cannot create non-unique indices as part of the create query + * so we need to create an index by hand and append it to the create query + */ + private function rewrite_key(){ + $this->_query = preg_replace_callback('/,\\s*(KEY|INDEX)\\s*(\\w+)?\\s*(\(.*(?_query); + } + + /** + * Callback method for rewrite_key + * @param array $matches an array of matches from the Regex + */ + private function _rewrite_key($matches){ + $index_name = trim($matches[2]); + $col_name = trim($matches[3]); + if (preg_match('/\([0-9]+?\)/', $col_name, $match)) { + $col_name = preg_replace_callback('/\([0-9]+?\)/', array($this, '_remove_length'), $col_name); + } + $tbl_name = $this->table_name; + $_wpdb = new PDODB(); + $results = $_wpdb->get_results("SELECT name FROM sqlite_master WHERE type='index'"); + $_wpdb = null; + if ($results) { + foreach ($results as $result) { + if ($result->name == $index_name) { + $r = rand(0, 50); + $index_name = $index_name . "_$r"; + break; + } + } + } + $this->index_queries[] = 'CREATE INDEX '. $index_name . ' ON ' . $tbl_name . $col_name ; + return ''; + } + private function _remove_length($match) { + return ''; + } + /** + * Method to assemble the main query and index queries into an array + * to be returned to the base class + * @return array + */ + private function post_process(){ + $mainquery = $this->_query; + do{ + $count = 0; + $mainquery = preg_replace('/,\\s*\)/imsx',')', $mainquery, -1, $count); + } while ($count > 0); + do { + $count = 0; + $mainquery = preg_replace('/\(\\s*?,/imsx', '(', $mainquery, -1, $count); + } while ($count > 0); + $return_val[] = $mainquery; + $return_val = array_merge($return_val, $this->index_queries); + return $return_val; + } + /** + * Method to add IF NOT EXISTS to query defs + * sometimes, if upgrade.php is being called, wordpress seems to want to run + * new create queries. this stops the query from throwing an error and halting + * output + */ + private function add_if_not_exists(){ + $pattern_table = '/^\\s*CREATE\\s*(TEMP|TEMPORARY)?\\s*TABLE\\s*(IF NOT EXISTS)?\\s*/ims'; + $this->_query = preg_replace($pattern_table, 'CREATE $1 TABLE IF NOT EXISTS ', $this->_query); + $pattern_index = '/^\\s*CREATE\\s*(UNIQUE)?\\s*INDEX\\s*(IF NOT EXISTS)?\\s*/ims'; + for ($i = 0; $i < count($this->index_queries); $i++) { + $this->index_queries[$i] = preg_replace($pattern_index, 'CREATE $1 INDEX IF NOT EXISTS ', $this->index_queries[$i]); + } + } + + /** + * Method to strip back ticks + */ + private function strip_backticks(){ + $this->_query = str_replace('`', '', $this->_query); + foreach ($this->index_queries as &$query) { + $query = str_replace('`', '', $query); + } + } + + /** + * Method to remove the character set information from within mysql queries + */ + private function rewrite_character_set(){ + $pattern_charset = '/\\b(default\\s*character\\s*set|default\\s*charset|character\\s*set)\\s*(?_query = preg_replace($patterns, '', $this->_query); + } +} \ No newline at end of file diff --git a/readme-ja.txt b/readme-ja.txt new file mode 100644 index 0000000..d8ceb27 --- /dev/null +++ b/readme-ja.txt @@ -0,0 +1,170 @@ +=== SQLite Integration === +Contributors: kjmtsh +Plugin Name: SQLite Integration +Plugin URI: http://dogwood.skr.jp/wordpress/sqlite-integration-ja/ +Tags: database, SQLite, PDO +Author: Kojima Toshiyasu +Author URI: http://dogwood.skr.jp/ +Requires at least: 3.3 +Tested up to: 3.5.2 +Stable tag: 1.0 +License: GPLv2 +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +SQLite IntegrationはSQLiteでWordPressを使えるようにするプラグインです。 + +== Description == + +このプラグインは[SQLite](http://www.sqlite.org/)を使ってWordPressを運用するためのものです。MySQLデータベース・サーバを用意する必要はありません。SQLiteは自己完結的で、サーバを必要とせず、トランザクションをサポートしたデータベース・エンジンです。MySQLのようにたくさんの拡張機能を持たないかわりに、小規模から中規模のトラフィックがあるウェブサイトに適しています。 + +SQLite Integrationはラッパ・プログラムです。WordPressとSQLiteの間に入って、やり取りを中継し、次のように動作します。 + +1. WordPressからMySQLに発行されるSQLステートメントをインターセプトします +2. それをSQLiteが実行できる形に書き換えます +3. SQLiteに渡します +4. SQLiteから結果を受け取ります +5. 必要なら、WordPressが望む形式にフォーマットしなおします +6. WordPressに結果を返します + +WordPressはMySQLと話していると思っていて、背後で何が起こっているかは知りません。実際にはSQLiteと話しているのですが、WordPressはいつもの通り仕事をします。 + +SQLite Integrationは[PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress)プラグインの後継です。後者は残念なことに、もうメンテナンスされていないようです。SQLite IntegrationはPDO for WordPressの基本的なアイディアと構造を借りて、より多くの機能とユーティリティを追加しました。 + += Features = + +SQLite Integrationは普通の「プラグイン」ではありません。WordPressをインストールするときに使います。そのため、少し準備が必要です。インストールのセクションを参照してください。[SQLite Integration Page](http://dogwood.skr.jp/wordpress/sqlite-integration/)をご覧になると、もっと詳しい説明を読むことができます。 + +インストールに成功したら、MySQLを使う他のWordPressと同じように使うことができます。オプションとして、管理パネルでこのプラグインを有効化することができます。有効化すると有益な情報と説明を見ることができます。これは必須ではありませんが、お勧めします。 + += Backward Compatibility = + +現在[PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress)をお使いの場合は、データベースを移行することができます。インストールのセクションをご覧ください。 + += Support = + +下の方法でコンタクトを取ってください。 + +[Support Forum](http://wordpress.org/support/plugin/sqlite-integration)にポストする。 + +注意: WordPress.orgはMySQL以外のデータベースを正式にサポートしていません。だから、WordPress.orgからのサポートは得られません。フォーラムに投稿しても、回答を得ることはまずないでしょう。また、パッチをあてたプラグインを使う場合は、そのプラグインの作者からのサポートはないものと思ってください。自分でリスクを負う必要があります。 + += Translation = + +ドキュメントは英語で書かれています。日本語のカタログファイルと、.potファイルがアーカイブに含まれています。もしあなたの言語に翻訳をしたら、知らせてください。 + +== Installation == + +このプラグインは他のプラグインとはちがいます。管理パネルのプラグイン・ページでインストールすることはできません。 + +まず、WordPressのインストールを準備しなければなりません。Codexの[Installing Wordpress ](http://codex.wordpress.org/Installing_WordPress)をご覧ください。 + +必要要件をチェックし、WordPressのアーカイブを展開したら、wp-config-sample.phpをwp-config.phpにリネームして、[Codex page](http://codex.wordpress.org/Editing_wp-config.php)に書いてあるように、少し編集する必要があります。データベースの設定*以外*の部分を設定してください。 + +終わったら、オプションの設定を書き加えることができます。次の説明に従ってください。 + +* デフォルト(wp-content/database)とは違うディレクトリにSQLiteデータベース・ファイルを置きたい場合は、次の行を追加してください(最後のスラッシュを忘れずに)。 + + `define('DB_DIR', '/home/youraccount/database_directory/');` + + 注意: PHPスクリプトがこのディレクトリを作ったり、中にファイルを書き込んだりする権限を持っていることが必要です。 + +* デフォルト(.ht.sqlite)とは違うデータベース・ファイル名を使いたい場合は、次の行を追加してください。 + + `define('DB_FILE', 'database_file_name');` + + 注意: PDO for WordPressをお使いの方は、「データベースを移行する」のセクションをご覧ください。 + + よくわからない場合は、何も追加する必要はありません。 + +wp-config.phpの準備が終わったら、次のステップに進みます。 + +1. プラグインのアーカイブを展開します。 + +2. アーカイブに含まれるdb.phpファイルをwp-contentディレクトリに移動(またはコピー)してください。 + +3. sqlite-wordpressディレクトリをwp-content/plugin/ディレクトリの下に移動してください。 + + `wordpress/wp-contents/db.php` + + と、 + + `wordpress/wp-contents/sqlite-integration` + + のようになります。 + +さあ、これでお終いです。ディレクトリの構造をそのままに、あなたのサーバにアップロードして、お好きなブラウザでwp-admin/install.phpにアクセスしてください。WordPressのインストールが始まります。Enjoy blogging! + += Migrate your database to SQLite Integration = + +一番よい方法は、次のようにすることです。 + +1. データをエクスポートする。 + +2. 最新のWordPressを、SQLite Integrationを使って新規インストールする。 + +3. WordPress Importerを使って以前のデータをインポートする。 + +何らかの理由で、データがエクスポートできない場合は、次の方法を試すことができます。 + +1. あなたのMyBlog.sqliteがWordPressの必要とするテーブルを全て含んでいるかどうかチェックしてください。[SQLite Manager Mozilla Addon](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/)のようなユーティリティが必要かもしれません。また、Codexの[Database Description](http://codex.wordpress.org/Database_Description)を参照してください。 + +2. MyBlog.sqliteとdb.phpファイルをバックアップしてください。 + +3. あなたのMyBlog.sqliteを.ht.sqliteにリネームするか、または、wp-config.phpに次の行を追加してください。 + + `define('FQDB', 'MyBlog.sqlite');` + +4. wp-content/db.phpをSQLite Integrationに含まれている同名のファイルと入れ替えてください。 + +これでおしまいです。忘れずに必要要件とWordPressのバージョンをチェックしてください。*SQLite IntegrationはWordPress 3.2.x以前のものでは動作しません。* + +== Frequently Asked Questions == + += データベース・ファイルが作られません = + +ディレクトリやファイルを作るのに失敗するのは、多くの場合、PHPにその権限がないことが原因です。サーバの設定を確認するか、管理者に聞いてみてください。 + += あれこれのプラグインが有効化できません、あるいはちゃんと動作しません = + +ある種のプラグイン、特にキャッシュ系のプラグインやデータベース管理系のプラグインはこのプラグインと一緒に使えません。SQLite Integrationを有効化して、ドキュメントの「プラグイン互換性」のセクションをご覧ください。あるいは、[SQLite Integration Plugin Page](http://dogwood.skr.jp/wordpress/plugins/)をご覧ください。 + += 管理画面のドキュメントは必要ないのですが = + +無効化すればすぐに消えます。有効化と無効化は管理画面の表示・非表示だけで、本体には影響を与えません。プラグインを削除したい場合は、単に削除すれば消えます。 + +== Screenshots == + +1. システム情報の画面ではデータベースの状態やプラグインの対応状況を見ることができます。 + +== Requirements == + +* PHP 5.2 以上で PDO extension が必要です(PHP 5.3 以上をお勧めします)。 +* PDO SQLite ドライバがロードされている必要があります。 + +== Known Limitations == + +多くのプラグインはちゃんと動作するはずです。が、中にはそうでないものもあります。一般的には、WordPressの関数を通さず、PHPのMysqlあるいはMysqliライブラリの関数を使ってデータベースを操作しようとするプラグインは問題を起こすでしょう。 + +他には下のようなものがあります。 + += これらのプラグインを使うことはできません。SQLite Integrationと同じファイルを使おうとするからです。 = + +* [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/) +* [DB Cache Reloaded Fix](http://wordpress.org/extend/plugins/db-cache-reloaded-fix/) +* [HyperDB](http://wordpress.org/extend/plugins/hyperdb/) + += これらのプラグインも使えません。SQLiteがエミュレートできないMySQL独自の拡張機能を使っているからです。 = + +* [Yet Another Related Posts](http://wordpress.org/extend/plugins/yet-another-related-posts-plugin/) +* [Better Related Posts](http://wordpress.org/extend/plugins/better-related/) + +たぶん、もっとあるでしょう。 + +== Changelog == + += 1.0 (2013-07-07) = +最初のリリース。 + +== Upgrade Notice == + +SQLite Integrationのアップグレードに失敗するようなら、FTPを使っての手動アップグレードを試してみてください。 diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..967e6d9 --- /dev/null +++ b/readme.txt @@ -0,0 +1,162 @@ +=== SQLite Integration === +Contributors: kjmtsh +Plugin Name: SQLite Integration +Plugin URI: http://dogwood.skr.jp/wordpress/sqlite-integration/ +Tags: database, SQLite, PDO +Author: Kojima Toshiyasu +Author URI: http://dogwood.skr.jp/ +Requires at least: 3.3 +Tested up to: 3.5.2 +Stable tag: 1.0 +License: GPLv2 +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +SQLite Integration is the plugin that enables WordPress to use SQLite. If you want to build a WordPress website with it, this plugin is for you. + +== Description == + +This plugin enables WordPress to work with [SQLite](http://www.sqlite.org/). You don't have to prepare MySQL database server and its configuration. SQLite is a self-contained, serverless, transactional SQL database engine. It is not a full-featured database system like MySQL or PostgreSQL, but it best fits for low to medium traffic websites. + +SQLite Integration is a kind of wrapper program, which is placed between WordPress and SQLite database and works as a mediator. It works as follows: + +1. Intercepts the SQL statement for MySQL from WordPress +2. Rewrites it for SQLite to execute +3. Give it to SQLite +4. Gets the results from SQLite +5. Formats the results as WordPress wants, if necessary +6. Give the results back to WordPress + +WordPress thinks she talks with MySQL and doesn't know what has happened in the background. She really talks with SQLite and will be happy with it. + +SQLite Integration is a successor to [PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress) plugin, which unfortunately enough, doesn't seem to be maintained any more. SQLite Integration uses the basic idea and structures of that plugin and adds some more features or some utilities. + += Features = + +SQLite Integration is not an ordinary 'plugin'. It is used to install WordPress itself. You need to do some preparations. Please read the install section. And see more detailed instruction in the [SQLite Integration Page](http://dogwood.skr.jp/wordpress/sqlite-integration). + +Once you succeeded in installing WordPress, you can use it just like the others using MySQL. Optionally, you can activate this plugin in the installed plugins panel of the adimn dashboard, and you can see the useful information and instructions. It is not required but I recommend it. + += Backward Compatibility = + +If you are using [PDO for WordPress](http://wordpress.org/extend/plugins/pdo-for-wordpress), you can migrate your database. See install section. + += Support = + +Please contact us with the methods below: + +Post to [Support Forum](http://wordpress.org/support/plugin/sqlite-integration/). + +Notes: WordPress.org doesn't officially support using any other database than MySQL. So there will be no supports from WordPress.org. Even if you post to the general Forum, you have few chances to get the answer. And if you use patched plugins, you will have be no support from the plugin authors, eithter. + += Translation = + +Documentation is written in English. Japanese catalog file and .pot file are included in the archive. If you translate it into your language, please let me know. + +== Installation == + +This plugin is *not* like the other plugins. You can't install and activate it on the plugin administration panel. + +First of all, you've got to prepare WordPress installation. See [Installing Wordpress ](http://codex.wordpress.org/Installing_WordPress) section in the Codex. + +After checking the prerequisites and unzipping the WordPress archive file, you must rename wp-contig-sample.php file to wp-config.php and do some editting as the [Codex page](http://codex.wordpress.org/Editing_wp-config.php) says. Please follow the instructions *except* the database settings. + +When you finish, you can add optional settings. Follow the steps below: + +* If you want to put the SQLite database file to the directory different from the default setting (wp-content/database), you can add the line below (don't forget to add a trailing slash): + + `define('DB_DIR', '/home/youraccount/database_directory/');` + + Note: Your PHP scripts must be able to create that directory and files in it. + +* If you want to change the database file name to the one different from the default (.ht.sqlite), you can add the line below: + + `define('DB_FILE', 'database_file_name');` + + Note: If you are using 'PDO for WordPress' plugin, see also 'Migrating your database' section. + + If you don't understand well, you don't have to add any of the lines above. + +After you finish preparing wp-config.php, follow the next steps: + +1. Unzip the plugin archive file. + +2. Move db.php file contained in the archive to wp-content directory. + +3. Move the sqlite-integration directory to wp-content/plugin/ directory. + + `wordpress/wp-contents/db.php` + + and + + `wordpress/wp-contents/sqlite-integration` + + respectively. + +OK. This is all. Upload everything (keeping the directory structure) to your server and access the wp-admin/install.php with your favorite browser, and WordPress installation process will begin. Enjoy your blogging! + += Migrate your database to SQLite Integration = + +If you are using PDO for WordPress now, you can migrate your database to SQLite Integration. You don't have to reinstall WordPress. Please follow the next steps: + +1. Check if your MyBlog.sqlite file contains all the tables required by WordPress. You have to use a utility software like [SQLite Manager Mozilla Addon](https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/). See also [Database Description](http://codex.wordpress.org/Database_Description) in Codex. + +2. Backup your MyBlog.sqlite and db.php files. + +3. EITHER rename your MyBlog.sqlite to .ht.sqlite OR add the next line in wp-config.php file. + + `define('FQDB', 'MyBlog.sqlite');` + +4. Overwrite your wp-content/db.php with the db.php file contained in SQLite Integration archive. + +That's all. Don't forget to check the requirement and your WordPress version. *SQLite Integration doesn't work with WordPress version 3.2.x or lesser*. + +== Frequently Asked Questions == + += Database file is not created = + +The reason of failure in creating directory or files is often that PHP is not allowed to craete them. Please check your server setting or ask the administrator. + += Such and such plugins can't be activated or doesn't seem to work properly = + +Some of the plugins, especially cache plugins or database maintenace plugins, are not compatible with this plugin. Please activate SQLite Integration and see the plugin comatibility section in the documentation or visit the [SQLite Integration Page](http://dogwood.skr.jp/wordpress/sqlite-integration/). + += I don't want the admin menu and documentation = + +Just deactivate the plugin, and you can remove them. Activation and deactivation affect only admin menu. If you want to remove all the plugin files, just delete it. + +== Screenshots == + +1. System Information tells you your database status and installed plugins compatibility. + +== Requirements == + +* PHP 5.2 or newer with PDO extension (PHP 5.3 or newer is better). +* PDO SQLite driver must be loaded. + +== Known Limitations == + +Many of the other plugins will work fine with this plugin. But there are some you can't use. Generally speaking, the plugins that manipulate database not with WordPress functions but with Mysql or Mysqli native drivers from PHP might cause the problem. + +These are other examples: + += You can't use these plugins because they create the same file that this plugin uses: = + +* [W3 Total Cache](http://wordpress.org/extend/plugins/w3-total-cache/) +* [DB Cache Reloaded Fix](http://wordpress.org/extend/plugins/db-cache-reloaded-fix/) +* [HyperDB](http://wordpress.org/extend/plugins/hyperdb/) + += You can't use some of the plugins, because they are using MySQL specific features that SQLite can't emulate. For example: = + +* [Yet Another Related Posts](http://wordpress.org/extend/plugins/yet-another-related-posts-plugin/) +* [Better Related Posts](http://wordpress.org/extend/plugins/better-related/) + +Probably there are more, I'm afraid. + +== Changelog == + += 1.0 (2013-07-07) = +First release version of the plugin. + +== Upgrade Notice == + +When you fail in upgrading SQLite Integration, I recommend that you should try manual upgrade via FTP. diff --git a/schema.php b/schema.php new file mode 100644 index 0000000..dec5a59 --- /dev/null +++ b/schema.php @@ -0,0 +1,91 @@ + PDO::ERRMODE_EXCEPTION)); + } catch (PDOException $err) { + $err_data = $err->errorInfo; + $message = __("Database connection error!
+ Plugin Page.', $domain);?> +
++ +
+ + ++ PDO for WordPress, which enabled WordPress to use SQLite for its database. But PDO for WordPress doesn\'t seem to be maintained any more only to be outdated. SQLite Integration makes use of the basic ideas and framework of PDO for WordPress, adds some new features and updates it to be able to work with the newest version of WordPress(3.5.1 and 3.6 beta).', $domain); ?> +
++ SQLite Web Page says — SQLite is a "software library that implements selfcontained, serverless, zero-configuration, transactional SQL database engine". It is "a good choice for small to medium size websites". It\'s small and portable, and you don\'t need any database server system.', $domain); ?> +
++ +
++ +
++ +
+ + ++ +
++ Support Forum.', $domain);?> +
+ ++ +
++ +
+ + ++ +
++ +
++ +
++ System Info page. To see more details, please visit the Plugin Page.', $domain), $utils->show_parent());?> +
+ ++ | + | + | ||
---|---|---|---|---|
name;?> | + compat, 'patch') !== false) :?> ++ compat, 'probably no')) :?> + | + + | + + | reason;?> | + +
+ +
++ My recommendation is not to use caching plugins. Even so, if you want a caching plugin, you could try WP Super Cache, which doesn\'t use db.php file. But no warranty, try at your own risk.', $domain);?> +
++ +
+ ++ +
++ +
++$postRes = mysql_query($sql,$wpdb->dbh); ++
+ +
++if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) { ++
+ +
++ +
++$postRes = $wpdb->query($sql); ++
+if ( version_compare($wpdb->db_version(), '4.1.0', '>=') ) { ++
+ +
+ ++ +
++ WordPress Related Posts or Related Posts or others. They are working fine with SQLite Integration!', $domain);?> +
++ Plugin Page about how to apply a patch file to the plugin. But the command line interface sometimes embarrasses some people, especially newbies.', $domain);?> +
++ +
++ +
++ +
++ +
+ + ++ +
++ | + + | +
---|---|
+ | + + | +
+++ +
+
+ | + |
---|---|
+ | + |
+ | + |
+ | get_module_setting('PDO', 'PDO support');?> | +
+ | get_module_setting('PDO', 'PDO drivers');?> | +
+ | get_module_setting('pdo_sqlite', 'PDO Driver for SQLite 3.x');?> | +
+ | get_module_setting('pdo_sqlite', 'SQLite Library');?> + |
+ | + |
---|---|
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + |
+ | + '; + echo ($i+1).'. '.$col; + $i++; + } + ?> + | +
+ | + '; + echo ($i+1).'. '.$op; + $i++; + } + ?> + | +
+ +
++ | + | + |
---|---|---|
' . $tbl_name . ' | '; + echo '' . $which_table . ' table | ';?> +';} ?> | +
+ +
++ | + | + |
---|
+ +
+ + ++ +
+ + + ++ If you don\'t understand well, please don\'t edit this file.', $domain)?> +
+ + +