aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB
diff options
context:
space:
mode:
authorMeik Sievertsen <acydburn@phpbb.com>2008-12-05 11:21:01 +0000
committerMeik Sievertsen <acydburn@phpbb.com>2008-12-05 11:21:01 +0000
commita39e87930000de5e21dae1656c15c4267e39c2ac (patch)
treee7c1799580449997e6b3a84a089ac080a155f00b /phpBB
parenta0c9705bb7d3e203324d777782a6915bf5eee1d1 (diff)
downloadforums-a39e87930000de5e21dae1656c15c4267e39c2ac.tar
forums-a39e87930000de5e21dae1656c15c4267e39c2ac.tar.gz
forums-a39e87930000de5e21dae1656c15c4267e39c2ac.tar.bz2
forums-a39e87930000de5e21dae1656c15c4267e39c2ac.tar.xz
forums-a39e87930000de5e21dae1656c15c4267e39c2ac.zip
fix postcount resync for situations where low and high post ids are higher than step value, resulting in users having 0 posts. (Bug #38195)
Enforce a requirement for some DBMS (Oracle, PostgreSQL, MSSQL) where the table order is quite important in some situations. ;) Since this does not affect the operation of the other DBMS the code is placed into dbal.php. git-svn-id: file:///svn/phpbb/trunk@9176 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB')
-rw-r--r--phpBB/includes/acp/acp_main.php39
-rw-r--r--phpBB/includes/db/dbal.php47
-rw-r--r--phpBB/includes/db/oracle.php2
3 files changed, 76 insertions, 12 deletions
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index 3e66f49afa..c79625ee39 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -184,12 +184,36 @@ class acp_main
}
// Resync post counts
- $start = 0;
- $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000;
+ $start = $max_post_id = 0;
+
+ // Find the maximum post ID, we can only stop the cycle when we've reached it
+ $sql = 'SELECT MAX(forum_last_post_id) as max_post_id
+ FROM ' . FORUMS_TABLE;
+ $result = $db->sql_query($sql);
+ $max_post_id = (int) $db->sql_fetchfield('max_post_id');
+ $db->sql_freeresult($result);
+
+ // No maximum post id? :o
+ if (!$max_post_id)
+ {
+ $sql = 'SELECT MAX(post_id)
+ FROM ' . POSTS_TABLE;
+ $result = $db->sql_query($sql);
+ $max_post_id = (int) $db->sql_fetchfield('max_post_id');
+ $db->sql_freeresult($result);
+ }
+ // Still no maximum post id? Then we are finished
+ if (!$max_post_id)
+ {
+ add_log('admin', 'LOG_RESYNC_POSTCOUNTS');
+ break;
+ }
+
+ $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000;
$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_posts = 0');
- do
+ while ($start < $max_post_id)
{
$sql = 'SELECT COUNT(post_id) AS num_posts, poster_id
FROM ' . POSTS_TABLE . '
@@ -206,16 +230,11 @@ class acp_main
$db->sql_query($sql);
}
while ($row = $db->sql_fetchrow($result));
-
- $start += $step;
- }
- else
- {
- $start = 0;
}
$db->sql_freeresult($result);
+
+ $start += $step;
}
- while ($start);
add_log('admin', 'LOG_RESYNC_POSTCOUNTS');
diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php
index f3dbae804a..885ae5a0cb 100644
--- a/phpBB/includes/db/dbal.php
+++ b/phpBB/includes/db/dbal.php
@@ -503,7 +503,8 @@ class dbal
$sql = str_replace('_', ' ', $query) . ' ' . $array['SELECT'] . ' FROM ';
- $table_array = array();
+ // Build table array. We also build an alias array for later checks.
+ $table_array = $aliases = array();
foreach ($array['FROM'] as $table_name => $alias)
{
if (is_array($alias))
@@ -511,14 +512,58 @@ class dbal
foreach ($alias as $multi_alias)
{
$table_array[] = $table_name . ' ' . $multi_alias;
+ $aliases[] = $multi_alias;
}
}
else
{
$table_array[] = $table_name . ' ' . $alias;
+ $aliases[] = $alias;
}
}
+ // We run the following code to determine if we need to re-order the table array. ;)
+ // The reason for this is that for multiple tables in the FROM statement the last table need to match the first LEFT JOIN'ed table.
+ // DBMS who rely on this (at the moment i only spotted it on multi-aliases): Oracle, PostgreSQL and MSSQL
+ $first_join_match = false;
+
+ if (!empty($array['LEFT_JOIN']) && sizeof($array['FROM']) > 1)
+ {
+ // Take first LEFT JOIN
+ $join = current($array['LEFT_JOIN']);
+
+ // Determine the table used there (even if there are more than one used, we only want to have one
+ preg_match('/(' . implode('|', $aliases) . ')\.[^\s]+/U', str_replace(array('(', ')', 'AND', 'OR', ' '), '', $join['ON']), $matches);
+
+ if (!empty($matches[1]))
+ {
+ $first_join_match = trim($matches[1]);
+ }
+ }
+
+ // If there is a first join match, we need to make sure the table order is correct
+ if ($first_join_match !== false)
+ {
+ $table_array = $last = array();
+
+ foreach ($array['FROM'] as $table_name => $alias)
+ {
+ if (is_array($alias))
+ {
+ foreach ($alias as $multi_alias)
+ {
+ ($multi_alias === $first_join_match) ? $last[] = $table_name . ' ' . $multi_alias : $table_array[] = $table_name . ' ' . $multi_alias;
+ }
+ }
+ else
+ {
+ ($alias === $first_join_match) ? $last[] = $table_name . ' ' . $alias : $table_array[] = $table_name . ' ' . $alias;
+ }
+ }
+
+ $table_array = array_merge($table_array, $last);
+ }
+
$sql .= $this->_sql_custom_build('FROM', implode(', ', $table_array));
if (!empty($array['LEFT_JOIN']))
diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php
index 6329652f96..91abc77780 100644
--- a/phpBB/includes/db/oracle.php
+++ b/phpBB/includes/db/oracle.php
@@ -191,7 +191,7 @@ class dbal_oracle extends dbal
$out .= ' ' . $val[1] . '(';
$in_array = array();
- // constuct each IN() clause
+ // constuct each IN() clause
foreach ($in_clause as $in_values)
{
$in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')';