diff options
author | Tim Almdal <tnalmdal@shaw.ca> | 2009-03-12 03:20:13 +0000 |
---|---|---|
committer | Tim Almdal <tnalmdal@shaw.ca> | 2009-03-12 03:20:13 +0000 |
commit | d1f181da08cbb747a7353bf84fbaa5d1ab82bd02 (patch) | |
tree | 5b2f3c3e6675c59db77af4699b5e4585d071af02 | |
parent | e58b955d4acc44bc2b49fffbffda42ad8b66069d (diff) |
Attempt to reduce the chance of replacing text in sql statements that
is not a table name (but contained in braces) with the database prefix
by building and maintaining a cache of database tables and prefixes.
-rw-r--r-- | core/libraries/MY_Database.php | 28 | ||||
-rw-r--r-- | core/tests/Database_Test.php | 19 |
2 files changed, 44 insertions, 3 deletions
diff --git a/core/libraries/MY_Database.php b/core/libraries/MY_Database.php index be0c2ec3..d54ac82b 100644 --- a/core/libraries/MY_Database.php +++ b/core/libraries/MY_Database.php @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class Database extends Database_Core { + protected $_table_names; + public function open_paren() { $this->where[] = "("; return $this; @@ -56,6 +58,30 @@ class Database extends Database_Core { public function add_table_prefixes($sql) { $prefix = $this->config["table_prefix"]; - return preg_replace("#{([a-zA-Z0-9_]+)}#", "{$prefix}$1", $sql); + if (strpos($sql, "SHOW TABLES") === 0) { + /* + * Don't ignore "show tables", otherwise we could have a infinite + * @todo this may have to be changed if we support more than mysql + */ + return $sql; + } else if (strpos($sql, "CREATE TABLE") === 0) { + // Creating a new table add it to the table cache. + $open_brace = strpos($sql, "{") + 1; + $close_brace = strpos($sql, "}", $open_brace); + $name = substr($sql, $open_brace, $close_brace - $open_brace); + $this->_table_names["{{$name}}"] = "{$prefix}$name"; + } + + if (!isset($this->_table_names)) { + // This should only run once on the first query + $this->_table_names =array(); + $len = strlen($prefix); + foreach($this->list_tables() as $table_name) { + $naked_name = strpos($table_name, $prefix) !== 0 ? $table_name : substr($table_name, $len); + $this->_table_names["{{$naked_name}}"] = $table_name; + } + } + + return empty($this->_table_names) ? $sql : strtr($sql, $this->_table_names); } }
\ No newline at end of file diff --git a/core/tests/Database_Test.php b/core/tests/Database_Test.php index 1e0764cc..3d3c965b 100644 --- a/core/tests/Database_Test.php +++ b/core/tests/Database_Test.php @@ -86,14 +86,28 @@ class Database_Test extends Unit_Test_Case { function prefix_replacement_test() { $db = Database_For_Test::instance(); - $sql = "UPDATE {access_caches} SET `edit_1` = 1 " . + $converted = $db->add_table_prefixes("CREATE TABLE IF NOT EXISTS {test_tables} ( + `id` int(9) NOT NULL auto_increment, + `name` varchar(32) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY(`name`)) + ENGINE=InnoDB DEFAULT CHARSET=utf8"); + $expected = "CREATE TABLE IF NOT EXISTS g3test_test_tables ( + `id` int(9) NOT NULL auto_increment, + `name` varchar(32) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY(`name`)) + ENGINE=InnoDB DEFAULT CHARSET=utf8"; + $this->assert_same($expected, $converted); + + $sql = "UPDATE {test_tables} SET `name` = '{test string}' " . "WHERE `item_id` IN " . " (SELECT `id` FROM {items} " . " WHERE `left` >= 1 " . " AND `right` <= 6)"; $sql = $db->add_table_prefixes($sql); - $expected = "UPDATE g3test_access_caches SET `edit_1` = 1 " . + $expected = "UPDATE g3test_test_tables SET `name` = '{test string}' " . "WHERE `item_id` IN " . " (SELECT `id` FROM g3test_items " . " WHERE `left` >= 1 " . @@ -113,6 +127,7 @@ class Database_Test extends Unit_Test_Case { class Database_For_Test extends Database { static function instance() { $db = new Database_For_Test(); + $db->_table_names["{items}"] = "g3test_items"; $db->config["table_prefix"] = "g3test_"; return $db; } |