From dfe674ffa12a77468ef2663d75d67768ee219039 Mon Sep 17 00:00:00 2001 From: David M Date: Sat, 5 May 2007 04:53:43 +0000 Subject: [PATCH] - changed the way we do forum accounting in phpBB, far less intensive and much faster. sync() recalculates the number of topics and posts using just the topics table instead of having to join topics and posts together. However, even this can be avoided if we know what operation is happening and an auto sync is not in action. Since MCP operations are "known", we can provide very fast MCP operations. - changed the way we decide if a DB gets multi value support. Old method uses switch/case, new method assumes a DB can't unless the DB says it can via a property I hope nothing is broken :P git-svn-id: file:///svn/phpbb/trunk@7466 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/develop/create_schema_files.php | 1 + phpBB/includes/acp/acp_forums.php | 2 +- phpBB/includes/acp/acp_prune.php | 2 +- phpBB/includes/acp/acp_users.php | 2 +- phpBB/includes/db/dbal.php | 31 ++-- phpBB/includes/db/mysql.php | 1 + phpBB/includes/db/mysqli.php | 2 + phpBB/includes/db/postgres.php | 38 ++-- phpBB/includes/functions_admin.php | 116 ++++++++---- phpBB/includes/mcp/mcp_main.php | 215 +++++++++++----------- phpBB/install/database_update.php | 3 + phpBB/install/install_convert.php | 2 +- phpBB/install/schemas/firebird_schema.sql | 1 + phpBB/install/schemas/mssql_schema.sql | 3 + phpBB/install/schemas/mysql_40_schema.sql | 1 + phpBB/install/schemas/mysql_41_schema.sql | 1 + phpBB/install/schemas/oracle_schema.sql | 2 + phpBB/install/schemas/postgres_schema.sql | 1 + phpBB/install/schemas/sqlite_schema.sql | 1 + 19 files changed, 243 insertions(+), 182 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index b912c69a40..42b921d228 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1694,6 +1694,7 @@ function get_schema_struct() 'forum_id_type' => array('INDEX', array('forum_id', 'topic_type')), 'last_post_time' => array('INDEX', 'topic_last_post_time'), 'topic_approved' => array('INDEX', 'topic_approved'), + 'forum_appr_last' => array('INDEX', array('forum_id', 'topic_approved', 'topic_last_post_id')), 'fid_time_moved' => array('INDEX', array('forum_id', 'topic_last_post_time', 'topic_moved_id')), ), ); diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 7ae04848d6..0c9e93540d 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -1309,7 +1309,7 @@ class acp_forums { // Delete ghost topics that link back to the same forum then resync counters sync('topic_moved'); - sync('forum', 'forum_id', $to_id); + sync('forum', 'forum_id', $to_id, false, true); } return array(); diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index a516a8b194..97d452a400 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -142,7 +142,7 @@ class acp_prune while ($row = $db->sql_fetchrow($result)); // Sync all pruned forums at once - sync('forum', 'forum_id', $prune_ids, true); + sync('forum', 'forum_id', $prune_ids, true, true); add_log('admin', 'LOG_PRUNE', $log_data); } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 2dca5fa7b6..13e21bd86b 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -584,7 +584,7 @@ class acp_users if (sizeof($forum_id_ary)) { - sync('forum', 'forum_id', $forum_id_ary); + sync('forum', 'forum_id', $forum_id_ary, false, true); } diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index dbc0859733..cfd13fd118 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -38,6 +38,9 @@ class dbal // Holding the last sql query on sql error var $sql_error_sql = ''; + // Supports multi inserts? + var $multi_insert = false; + /** * Current sql layer */ @@ -364,25 +367,21 @@ class dbal return false; } - switch ($this->sql_layer) + if ($this->multi_insert) { - case 'mysql': - case 'mysql4': - case 'mysqli': - $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('MULTI_INSERT', $sql_ary)); - break; - - default: - foreach ($sql_ary as $ary) + $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('MULTI_INSERT', $sql_ary)); + } + else + { + foreach ($sql_ary as $ary) + { + if (!is_array($ary)) { - if (!is_array($ary)) - { - return false; - } - - $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary)); + return false; } - break; + + $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary)); + } } return true; diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php index dfa4823a87..c20e73315a 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -30,6 +30,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); class dbal_mysql extends dbal { var $mysql_version; + var $multi_insert = true; /** * Connect to server diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index c03c117085..6f54b5c8b3 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -26,6 +26,8 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); */ class dbal_mysqli extends dbal { + var $multi_insert = true; + /** * Connect to server */ diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php index bdaab439ea..94bc70fa6a 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/postgres.php @@ -26,6 +26,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); class dbal_postgres extends dbal { var $last_query_text = ''; + var $pgsql_version; /** * Connect to server @@ -80,6 +81,28 @@ class dbal_postgres extends dbal if ($this->db_connect_id) { + // determine what version of PostgreSQL is running, we can be more efficient if they are running 8.2+ + if (version_compare(PHP_VERSION, '5.0.0', '>=')) + { + $this->pgsql_version = @pg_parameter_status($this->db_connect_id, 'server_version'); + } + else + { + $query_id = @pg_query($this->db_connect_id, 'SELECT VERSION()'); + $row = @pg_fetch_assoc($query_id, null); + @pg_free_result($query_id); + + if (!empty($row['version'])) + { + $this->pgsql_version = substr($row['version'], 10); + } + } + + if (!empty($this->pgsql_version) && $this->pgsql_version[0] >= '8' && $this->pgsql_version[2] >= '2') + { + $this->multi_insert = true; + } + if ($schema !== '') { @pg_query($this->db_connect_id, 'SET search_path TO ' . $schema); @@ -95,20 +118,7 @@ class dbal_postgres extends dbal */ function sql_server_info() { - if (version_compare(PHP_VERSION, '5.0.0', '>=')) - { - $version = @pg_version($this->db_connect_id); - return 'PostgreSQL' . ((!empty($version)) ? ' ' . $version['client'] : ''); - } - else - { - $query_id = @pg_query($this->db_connect_id, 'select version()'); - $row = @pg_fetch_assoc($query_id, null); - @pg_free_result($query_id); - - $version = $row['version']; - return ((!empty($version)) ? ' ' . $version : ''); - } + return 'PostgreSQL ' . $this->pgsql_version; } /** diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 8c57a986db..7e6e097571 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -424,7 +424,7 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true) if ($auto_sync) { - sync('forum', 'forum_id', $forum_ids, true); + sync('forum', 'forum_id', $forum_ids, true, true); unset($forum_ids); } } @@ -485,7 +485,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) sync('topic_reported', 'topic_id', $topic_ids); sync('topic_attachment', 'topic_id', $topic_ids); sync('topic', 'topic_id', $topic_ids, true); - sync('forum', 'forum_id', $forum_ids, true); + sync('forum', 'forum_id', $forum_ids, true, true); } // Update posted information @@ -567,7 +567,7 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s if ($auto_sync) { - sync('forum', 'forum_id', $forum_ids, true); + sync('forum', 'forum_id', $forum_ids, true, true); sync('topic_reported', $where_type, $where_ids); } @@ -718,7 +718,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = { sync('topic_reported', 'topic_id', $topic_ids); sync('topic', 'topic_id', $topic_ids, true); - sync('forum', 'forum_id', $forum_ids, true); + sync('forum', 'forum_id', $forum_ids, true, true); } if ($approved_posts) @@ -991,7 +991,7 @@ function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true) if ($auto_sync) { $where_type = ($forum_id) ? 'forum_id' : ''; - sync('forum', $where_type, $forum_id, true); + sync('forum', $where_type, $forum_id, true, true); } } @@ -1441,9 +1441,12 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $forum_ids[$forum_id] = $forum_id; $forum_data[$forum_id] = $row; - $forum_data[$forum_id]['posts'] = 0; - $forum_data[$forum_id]['topics'] = 0; - $forum_data[$forum_id]['topics_real'] = 0; + if ($sync_extra) + { + $forum_data[$forum_id]['posts'] = 0; + $forum_data[$forum_id]['topics'] = 0; + $forum_data[$forum_id]['topics_real'] = 0; + } $forum_data[$forum_id]['last_post_id'] = 0; $forum_data[$forum_id]['last_post_subject'] = ''; $forum_data[$forum_id]['last_post_time'] = 0; @@ -1460,43 +1463,72 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $forum_ids = array_values($forum_ids); - // 2: Get topic counts for each forum - $sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics - FROM ' . TOPICS_TABLE . ' - WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' - GROUP BY forum_id, topic_approved'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) + // 2: Get topic counts for each forum (optional) + if ($sync_extra) { - $forum_id = (int) $row['forum_id']; - $forum_data[$forum_id]['topics_real'] += $row['forum_topics']; + $sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' + GROUP BY forum_id, topic_approved'; + $result = $db->sql_query($sql); - if ($row['topic_approved']) + while ($row = $db->sql_fetchrow($result)) { - $forum_data[$forum_id]['topics'] = $row['forum_topics']; - } - } - $db->sql_freeresult($result); + $forum_id = (int) $row['forum_id']; + $forum_data[$forum_id]['topics_real'] += $row['forum_topics']; - // 3: Get post count and last_post_id for each forum + if ($row['topic_approved']) + { + $forum_data[$forum_id]['topics'] = $row['forum_topics']; + } + } + $db->sql_freeresult($result); + } + + // 3: Get post count for each forum (optional) + if ($sync_extra) + { + if (sizeof($forum_ids) == 1) + { + $sql = 'SELECT SUM(topic_replies + 1) AS forum_posts + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' + AND t.topic_approved = 1'; + } + else + { + $sql = 'SELECT p.forum_id, SUM(topic_replies + 1) AS forum_posts + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' + AND t.topic_approved = 1 + GROUP BY p.forum_id'; + } + + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; + + $forum_data[$forum_id]['posts'] = (int) $row['forum_posts']; + } + $db->sql_freeresult($result); + } + + // 4: Get last_post_id for each forum if (sizeof($forum_ids) == 1) { - $sql = 'SELECT COUNT(p.post_id) AS forum_posts, MAX(p.post_id) AS last_post_id - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t - WHERE ' . $db->sql_in_set('p.forum_id', $forum_ids) . ' - AND p.topic_id = t.topic_id - AND t.topic_approved = 1 - AND p.post_approved = 1'; + $sql = 'SELECT MAX(t.topic_last_post_id) as last_post_id + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' + AND t.topic_approved = 1'; } else { - $sql = 'SELECT p.forum_id, COUNT(p.post_id) AS forum_posts, MAX(p.post_id) AS last_post_id - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t - WHERE ' . $db->sql_in_set('p.forum_id', $forum_ids) . ' - AND p.topic_id = t.topic_id + $sql = 'SELECT t.forum_id, MAX(t.topic_last_post_id) as last_post_id + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' AND t.topic_approved = 1 - AND p.post_approved = 1 GROUP BY p.forum_id'; } @@ -1506,14 +1538,13 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; - $forum_data[$forum_id]['posts'] = (int) $row['forum_posts']; $forum_data[$forum_id]['last_post_id'] = (int) $row['last_post_id']; $post_ids[] = $row['last_post_id']; } $db->sql_freeresult($result); - // 4: Retrieve last_post infos + // 5: Retrieve last_post infos if (sizeof($post_ids)) { $sql = 'SELECT p.post_id, p.poster_id, p.post_subject, p.post_time, p.post_username, u.username, u.user_colour @@ -1555,8 +1586,13 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, unset($post_info); } - // 5: Now do that thing - $fieldnames = array('posts', 'topics', 'topics_real', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); + // 6: Now do that thing + $fieldnames = array('last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); + + if ($sync_extra) + { + array_push($fieldnames, 'posts', 'topics', 'topics_real'); + } foreach ($forum_data as $forum_id => $row) { @@ -1912,7 +1948,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, // batch processing. if ($resync_parents && sizeof($resync_forums) && $where_type != 'range') { - sync('forum', 'forum_id', array_values($resync_forums), true); + sync('forum', 'forum_id', array_values($resync_forums), true, true); } break; } diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index b63af4886c..fd2f4345ed 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -351,6 +351,37 @@ function change_topic_type($action, $topic_ids) AND forum_id = 0'; $db->sql_query($sql); + // Do a little forum sync stuff + $sql = 'SELECT t.topic_replies + 1 as topic_posts, COUNT(t.topic_approved) as topics_authed + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids) . ' + GROUP BY t.topic_posts'; + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . (int) $row_data['topic_posts']; + } + + if ($row_data['topics_authed']) + { + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $row_data['topics_authed']; + } + + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) sizeof($topic_ids); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + sync('forum', 'forum_id', $to_forum_id); } } @@ -388,6 +419,37 @@ function change_topic_type($action, $topic_ids) WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); + // Do a little forum sync stuff + $sql = 'SELECT t.topic_replies + 1 as topic_posts, COUNT(t.topic_approved) as topics_authed + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids) . ' + GROUP BY t.topic_posts'; + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . (int) $row_data['topic_posts']; + } + + if ($row_data['topics_authed']) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $row_data['topics_authed']; + } + + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) sizeof($topic_ids); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + sync('forum', 'forum_id', $forum_id); } } @@ -536,25 +598,30 @@ function mcp_move_topic($topic_ids) } } - $sql = 'SELECT COUNT(p.post_id) AS topic_posts, MAX(p.post_id) AS last_post_id - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t + $db->sql_transaction('begin'); + + $sql = 'SELECT topic_replies + 1 as topic_posts + FROM ' . TOPICS_TABLE . ' t WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids) . ' - AND p.topic_id = t.topic_id - AND t.topic_approved = 1 - AND p.post_approved = 1'; + GROUP BY topic_posts'; $result = $db->sql_query($sql); $row_data = $db->sql_fetchrow($result); $db->sql_freeresult($result); - $forum_sync_data[$forum_id]['forum_posts'] -= (int) $row_data['topic_posts']; - $forum_sync_data[$forum_id]['forum_topics'] -= (int) $topics_authed_moved; - $forum_sync_data[$forum_id]['forum_topics_real'] -= (int) $topics_moved; + $sync_sql = array(); - $forum_sync_data[$to_forum_id]['forum_posts'] += (int) $row_data['topic_posts']; - $forum_sync_data[$to_forum_id]['forum_topics'] += (int) $topics_authed_moved; - $forum_sync_data[$to_forum_id]['forum_topics_real'] += (int) $topics_moved; + if ($row_data['topic_posts']) + { + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . (int) $row_data['topic_posts']; + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . (int) $row_data['topic_posts']; + } - $db->sql_transaction('begin'); + if ($topics_authed_moved) + { + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $topics_authed_moved; + } + + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) $topics_moved; // Move topics, but do not resync yet move_topics($topic_ids, $to_forum_id, false); @@ -614,114 +681,31 @@ function mcp_move_topic($topic_ids) $db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow)); - $forum_sync_data[(int) $row['forum_id']]['forum_topics']++; - $forum_sync_data[(int) $row['forum_id']]['forum_topics_real']++; + $topics_authed_moved--; + $topics_moved--; } } unset($topic_data); + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) $topics_moved; + + if ($topics_authed_moved) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $topics_authed_moved; + } + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; - // we must update the info, this post is being moved and is not the newest anymore - if ($forum_sync_data[$forum_id]['forum_last_post_id'] == $row_data['last_post_id']) + foreach ($sync_sql as $forum_id_key => $array) { - $forum_sync_data[$forum_id]['forum_last_post_id'] = 0; - $forum_sync_data[$forum_id]['forum_last_post_subject'] = ''; - $forum_sync_data[$forum_id]['forum_last_post_time'] = 0; - $forum_sync_data[$forum_id]['forum_last_poster_id'] = 0; - $forum_sync_data[$forum_id]['forum_last_poster_name'] = ''; - $forum_sync_data[$forum_id]['forum_last_poster_colour'] = ''; - - // I want the newest post that is not in the collection - // TODO: this is the last trouble maker - $sql = 'SELECT MAX(p.post_id) AS last_post_id - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t - WHERE p.topic_id = t.topic_id - AND t.topic_approved = 1 - AND p.post_approved = 1 - AND t.forum_id = ' . $forum_id; - $result = $db->sql_query($sql); - - if ($last_post_id = $db->sql_fetchfield('last_post_id', false, $result)) - { - $sql = 'SELECT p.post_subject, p.post_time, p.post_username, p.poster_id, u.username as poster_name, u.user_colour as poster_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.post_id = ' . $last_post_id . ' - AND p.poster_id = u.user_id'; - $result2 = $db->sql_query($sql); - $post_data = $db->sql_fetchrow($result2); - $db->sql_freeresult($result2); - - $post_data['post_id'] = $last_post_id; - - if ($post_data['poster_id'] == ANONYMOUS) - { - $post_data['poster_name'] = $post_data['post_username']; - } - unset($post_data['post_username']); - - foreach ($post_data as $row => $val) - { - $forum_sync_data[$forum_id]['forum_last_' . $row] = $val; - } - } - - $db->sql_freeresult($result); - } - - // we must update the info, this post is being moved and is not the newest anymore - if ($forum_sync_data[$to_forum_id]['forum_last_post_id'] < $row_data['last_post_id']) - { - $forum_sync_data[$to_forum_id]['forum_last_post_id'] = 0; - $forum_sync_data[$to_forum_id]['forum_last_post_subject'] = ''; - $forum_sync_data[$to_forum_id]['forum_last_post_time'] = 0; - $forum_sync_data[$to_forum_id]['forum_last_poster_id'] = 0; - $forum_sync_data[$to_forum_id]['forum_last_poster_name'] = ''; - $forum_sync_data[$to_forum_id]['forum_last_poster_colour'] = ''; - - // mod just moved all the posts out of the forum! - $sql = 'SELECT p.post_subject, p.post_time, p.post_username, p.poster_id, u.username as poster_name, u.user_colour as poster_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.post_id = ' . $row_data['last_post_id'] . ' - AND p.poster_id = u.user_id'; - $result2 = $db->sql_query($sql); - $post_data = $db->sql_fetchrow($result2); - $db->sql_freeresult($result2); - - if ($post_data) - { - $post_data['post_id'] = $row_data['last_post_id']; - - if ($post_data['poster_id'] == ANONYMOUS) - { - $post_data['poster_name'] = $post_data['post_username']; - } - unset($post_data['post_username']); - - foreach ($post_data as $row => $val) - { - $forum_sync_data[$to_forum_id]['forum_last_' . $row] = $val; - } - } - } - - foreach ($forum_sync_data as $forum_id_key => $sql_ary) - { - foreach ($sql_ary as $key => $value) - { - if (strpos($key, 'forum_last_') === 0 || $key === 'forum_posts' || $key === 'forum_topics' || $key === 'forum_topics_real') - { - continue; - } - unset($sql_ary[$key]); - } - $sql = 'UPDATE ' . FORUMS_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + SET ' . implode(', ', $array) . ' WHERE forum_id = ' . $forum_id_key; $db->sql_query($sql); } + sync('forum', 'forum_id', array($forum_id, $to_forum_id)); + $db->sql_transaction('commit'); } else @@ -1165,6 +1149,21 @@ function mcp_fork_topic($topic_ids) // Sync new topics, parent forums and board stats sync('topic', 'topic_id', $new_topic_id_list, true); + + $sync_sql = array(); + + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $total_posts; + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . sizeof($new_topic_id_list); + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . sizeof($new_topic_id_list); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + sync('forum', 'forum_id', $to_forum_id, true); set_config('num_topics', $config['num_topics'] + sizeof($new_topic_id_list), true); set_config('num_posts', $config['num_posts'] + $total_posts, true); diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 287379fcd8..c9b7134674 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -350,6 +350,9 @@ $database_update_info = array( ACL_ROLES_DATA_TABLE => array( 'ath_opt_id' => array('auth_option_id'), ), + TOPICS_TABLE => array( + 'forum_appr_last' => array('forum_id', 'topic_approved', 'topic_last_post_id'), + ), ), // Add the following unique indexes 'add_unique_index' => array( diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 4c406d5105..52e4d1cf14 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -1688,7 +1688,7 @@ class install_convert extends module // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics. // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing) - sync('forum'); + sync('forum', '', '', false, true); $cache->destroy('sql', FORUMS_TABLE); $template->assign_block_vars('checks', array( diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 626874474b..50a59d9c98 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -1234,6 +1234,7 @@ CREATE INDEX phpbb_topics_forum_id ON phpbb_topics(forum_id);; CREATE INDEX phpbb_topics_forum_id_type ON phpbb_topics(forum_id, topic_type);; CREATE INDEX phpbb_topics_last_post_time ON phpbb_topics(topic_last_post_time);; CREATE INDEX phpbb_topics_topic_approved ON phpbb_topics(topic_approved);; +CREATE INDEX phpbb_topics_forum_appr_last ON phpbb_topics(forum_id, topic_approved, topic_last_post_id);; CREATE INDEX phpbb_topics_fid_time_moved ON phpbb_topics(forum_id, topic_last_post_time, topic_moved_id);; CREATE GENERATOR phpbb_topics_gen;; diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index 89db3d2824..7caea395ec 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -1455,6 +1455,9 @@ GO CREATE INDEX [topic_approved] ON [phpbb_topics]([topic_approved]) ON [PRIMARY] GO +CREATE INDEX [forum_appr_last] ON [phpbb_topics]([forum_id], [topic_approved], [topic_last_post_id]) ON [PRIMARY] +GO + CREATE INDEX [fid_time_moved] ON [phpbb_topics]([forum_id], [topic_last_post_time], [topic_moved_id]) ON [PRIMARY] GO diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 17afe935ae..a5d850ca68 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -835,6 +835,7 @@ CREATE TABLE phpbb_topics ( KEY forum_id_type (forum_id, topic_type), KEY last_post_time (topic_last_post_time), KEY topic_approved (topic_approved), + KEY forum_appr_last (forum_id, topic_approved, topic_last_post_id), KEY fid_time_moved (forum_id, topic_last_post_time, topic_moved_id) ); diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index f2366835ca..6308ed0c15 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -835,6 +835,7 @@ CREATE TABLE phpbb_topics ( KEY forum_id_type (forum_id, topic_type), KEY last_post_time (topic_last_post_time), KEY topic_approved (topic_approved), + KEY forum_appr_last (forum_id, topic_approved, topic_last_post_id), KEY fid_time_moved (forum_id, topic_last_post_time, topic_moved_id) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index f185e79ff9..8ad99ea189 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -1633,6 +1633,8 @@ CREATE INDEX phpbb_topics_last_post_time ON phpbb_topics (topic_last_post_time) / CREATE INDEX phpbb_topics_topic_approved ON phpbb_topics (topic_approved) / +CREATE INDEX phpbb_topics_forum_appr_last ON phpbb_topics (forum_id, topic_approved, topic_last_post_id) +/ CREATE INDEX phpbb_topics_fid_time_moved ON phpbb_topics (forum_id, topic_last_post_time, topic_moved_id) / diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index 946526eba8..fe20316705 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -1090,6 +1090,7 @@ CREATE INDEX phpbb_topics_forum_id ON phpbb_topics (forum_id); CREATE INDEX phpbb_topics_forum_id_type ON phpbb_topics (forum_id, topic_type); CREATE INDEX phpbb_topics_last_post_time ON phpbb_topics (topic_last_post_time); CREATE INDEX phpbb_topics_topic_approved ON phpbb_topics (topic_approved); +CREATE INDEX phpbb_topics_forum_appr_last ON phpbb_topics (forum_id, topic_approved, topic_last_post_id); CREATE INDEX phpbb_topics_fid_time_moved ON phpbb_topics (forum_id, topic_last_post_time, topic_moved_id); /* diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 0b7b4e8961..fcd6a50679 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -807,6 +807,7 @@ CREATE INDEX phpbb_topics_forum_id ON phpbb_topics (forum_id); CREATE INDEX phpbb_topics_forum_id_type ON phpbb_topics (forum_id, topic_type); CREATE INDEX phpbb_topics_last_post_time ON phpbb_topics (topic_last_post_time); CREATE INDEX phpbb_topics_topic_approved ON phpbb_topics (topic_approved); +CREATE INDEX phpbb_topics_forum_appr_last ON phpbb_topics (forum_id, topic_approved, topic_last_post_id); CREATE INDEX phpbb_topics_fid_time_moved ON phpbb_topics (forum_id, topic_last_post_time, topic_moved_id); # Table: 'phpbb_topics_track'