diff --git a/ChangeLog b/ChangeLog index d270903..251009a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2014-10-01 KOJIMA Toshiyasu + + * pdoengine.class.php: revised pdoengine class constructor definition + in order to reuse the PDO instance. + + * pdodb.class.php, pdoengine.class.php: moved the foreign key check + from PDODB class to PDOEngine class init() method. + + * functions.php, functions-5-2.php: check if PDO instance is not null + to avoid displaying Zend debugger/Xdebug messages. If null, constructor + executes wp_die() function. + + * query_create.class.php: changed the data type rewriting method. + When a field name is the same as data type, e.g. "date" or "timestamp", + add a single quote to the field name and avoid to be rewritten. + This works only if the field name is on the top of the line, according + to the rule of dbDelta() function. + + Added the new function to quote illegal field name, e.g. "default" or + "values", for SQLite. This is for the plugins that use those names to + create tables without errors. + 2014-09-05 KOJIMA Toshiyasu * version 1.7 release. diff --git a/functions-5-2.php b/functions-5-2.php index ed12dea..9e80f84 100644 --- a/functions-5-2.php +++ b/functions-5-2.php @@ -34,6 +34,9 @@ class PDOSQLiteUDFS { * @param reference to PDO object $pdo */ public function __construct(&$pdo){ + if (!$pdo) { + wp_die('Database is not initialized.', 'Database Error'); + } foreach ($this->functions as $f=>$t) { $pdo->sqliteCreateFunction($f, array($this, $t)); } diff --git a/functions.php b/functions.php index c491116..d542a00 100644 --- a/functions.php +++ b/functions.php @@ -34,6 +34,9 @@ class PDOSQLiteUDFS { * @param reference to PDO object $pdo */ public function __construct(&$pdo){ + if (!$pdo) { + wp_die('Database is not initialized.', 'Database Error'); + } foreach ($this->functions as $f=>$t) { $pdo->sqliteCreateFunction($f, array($this, $t)); } diff --git a/install.php b/install.php index 56efbdb..af737cf 100644 --- a/install.php +++ b/install.php @@ -68,7 +68,7 @@ function wp_install($blog_title, $user_name, $user_email, $public, $deprecated = ;// Your server is Apache. Nothing to do more. } else { $server_message = sprintf('Your webserver doesn\'t seem to be Apache. So the database directory access restriction by the .htaccess file may not function. We strongly recommend that you should restrict the access to the directory %s in some other way.', FQDBDIR); - echo '

'; + echo '

'; echo $server_message; echo '

'; } diff --git a/pdodb.class.php b/pdodb.class.php index 3765197..791e3e8 100644 --- a/pdodb.class.php +++ b/pdodb.class.php @@ -211,8 +211,6 @@ class PDODB extends wpdb { $this->bail(sprintf(__("

Error establlishing a database connection

We have been unable to connect to the specified database.
The error message received was %s"), $this->dbh->errorInfo())); return; } - $is_enabled_foreign_keys = @$this->get_var('PRAGMA foreign_keys'); - if ($is_enabled_foreign_keys == '0') @$this->query('PRAGMA foreign_keys = ON'); $this->has_connected = true; $this->ready = true; } diff --git a/pdoengine.class.php b/pdoengine.class.php index 84a9d28..013fabc 100644 --- a/pdoengine.class.php +++ b/pdoengine.class.php @@ -160,10 +160,44 @@ class PDOEngine extends PDO { /** * Constructor * + * Create PDO object, set user defined functions and initialize other settings. + * Don't use parent::__construct() because this class does not only returns + * PDO instance but many others jobs. + * + * Constructor definition is changed since version 1.7.1. + * * @param none */ function __construct() { register_shutdown_function(array($this, '__destruct')); + $dsn = 'sqlite' . FQDB; + if (isset($GLOBALS['@pdo'])) { + $this->pdo = $GLOBALS['@pdo']; + } else { + $locked = false; + $status = 0; + do { + try { + $this->pdo = new PDO($dsn, null, null, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + require_once UDF_FILE; + new PDOSQLiteUDFS($this->pdo); + $GLOBALS['@pdo'] = $this->pdo; + } catch (PDOException $ex) { + $status = $ex->getCode(); + if ($status == 5 || $status == 6) { + $locked = true; + } else { + $err_message = $ex->getMessage(); + } + } + } while ($locked); + if ($status > 0) { + $message = 'Database initialization error!
' . + 'Code: ' . $status . '
Error Message: ' . $err_message; + $this->set_error(__LINE__, __FILE__, $message); + return false; + } + } $this->init(); } /** @@ -172,6 +206,8 @@ class PDOEngine extends PDO { * If SQLITE_MEM_DEBUG constant is defined, append information about * memory usage into database/mem_debug.txt. * + * This definition is changed since version 1.7. + * * @return boolean */ function __destruct() { @@ -199,63 +235,27 @@ class PDOEngine extends PDO { /** * Method to initialize database, executed in the contructor. * - * It checks if there's a database directory and database file, creates the tables, - * and binds the user defined function to the pdo object. + * It checks if WordPress is in the installing process and does the required + * jobs. SQLite library version specific settings are also in this function. + * + * Some developers use WP_INSTALLING constant for other purposes, if so, this + * function will do no harms. * * @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!
'; - $message .= sprintf("Error message is: %s", $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 initialization error!
'; - $message .= sprintf("Error message is: %s", $err->getMessage()); - $this->set_error(__LINE__, __FUNCTION__, $message); - return false; - } - $this->make_sqlite_tables(); + if (defined('WP_INSTALLING') && WP_INSTALLING) { + $this->prepare_directory(); + $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(); } + if (version_compare($this->get_sqlite_version(), '3.7.11', '>=')) { + $this->can_insert_multiple_rows = true; + } + $statement = $this->pdo->query('PRAGMA foreign_keys'); + if ($statement->fetchColumn(0) == '0') $this->pdo->query('PRAGMA foreign_keys = ON'); } /** diff --git a/query_create.class.php b/query_create.class.php index 6cf9ece..4e63e33 100644 --- a/query_create.class.php +++ b/query_create.class.php @@ -71,6 +71,7 @@ class CreateQuery{ return $this->_query; } $this->strip_backticks(); + $this->quote_illegal_field(); $this->get_table_name(); $this->rewrite_comments(); $this->rewrite_field_types(); @@ -106,6 +107,10 @@ class CreateQuery{ /** * Method to change the MySQL field types to SQLite compatible types. * + * If column name is the same as the key value, e.g. "date" or "timestamp", + * and the column is on the top of the line, we add a single quote and avoid + * to be replaced. But this doesn't work if that column name is in the middle + * of the line. * Order of the key value is important. Don't change it. * * @access private @@ -129,7 +134,13 @@ class CreateQuery{ 'mediumblob' => 'blob', 'mediumtext' => 'text', 'longblob' => 'blob', 'longtext' => 'text' ); - foreach ($array_types as $o=>$r){ + foreach ($array_types as $o => $r){ + if (preg_match("/^\\s*(?_query, $match)) { + $ptrn = "/$match[1]/im"; + $replaced = str_ireplace($ptrn, '#placeholder#', $this->_query); + $replaced = str_ireplace($o, "'{$o}'", $replaced); + $this->_query = str_replace('#placeholder#', $ptrn, $replaced); + } $pattern = "/\\b(?_query)) { ; @@ -393,5 +404,13 @@ class CreateQuery{ $patterns = array($pattern_charset, $pattern_collate1, $pattern_collate2); $this->_query = preg_replace($patterns, '', $this->_query); } + /** + * Method to quote illegal field name for SQLite + * + * @access private + */ + private function quote_illegal_field() { + $this->_query = preg_replace("/^\\s*(?_query); + } } ?> \ No newline at end of file