aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/functions_tricky_update.php
blob: a5b9fdacd0ac810871ee67ecb5d4c6b3ee597707 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/

/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
	exit;
}

/**
* Updates rows in given table from a set of values to a new value.
* If this results in rows violating uniqueness constraints, the duplicate
* rows are eliminated.
*
* The only supported tables are bookmarks and topics_watch.
*
* @param dbal $db Database object
* @param string $table Table on which to perform the update
* @param string $column Column whose values to change
* @param array $from_values An array of values that should be changed
* @param int $to_value The new value
* @return null
*/
function phpbb_update_rows_avoiding_duplicates($db, $table, $column, $from_values, $to_value)
{
	$sql = "SELECT $column, user_id
		FROM $table
		WHERE " . $db->sql_in_set($column, $from_values);
	$result = $db->sql_query($sql);

	$old_user_ids = array();
	while ($row = $db->sql_fetchrow($result))
	{
		$old_user_ids[$row[$column]][] = $row['user_id'];
	}
	$db->sql_freeresult($result);

	$sql = "SELECT $column, user_id
		FROM $table
		WHERE $column = '" . (int) $to_value . "'";
	$result = $db->sql_query($sql);

	$new_user_ids = array();
	while ($row = $db->sql_fetchrow($result))
	{
		$new_user_ids[$row[$column]][] = $row['user_id'];
	}
	$db->sql_freeresult($result);

	$queries = array();
	$any_found = false;
	foreach ($from_values as $from_value)
	{
		if (!isset($old_user_ids[$from_value]))
		{
			continue;
		}
		$any_found = true;
		if (empty($new_user_ids))
		{
			$sql = "UPDATE $table
				SET $column = " . (int) $to_value. "
				WHERE $column = '" . $db->sql_escape($from_value) . "'";
			$queries[] = $sql;
		}
		else
		{
			$different_user_ids = array_diff($old_user_ids[$from_value], $new_user_ids[$to_value]);
			if (!empty($different_user_ids))
			{
				$sql = "UPDATE $table
					SET $column = " . (int) $to_value. "
					WHERE $column = '" . $db->sql_escape($from_value) . "'
					AND " . $db->sql_in_set('user_id', $different_user_ids);
				$queries[] = $sql;
			}
		}
	}

	if ($any_found)
	{
		$db->sql_transaction('begin');

		foreach ($queries as $sql)
		{
			$db->sql_query($sql);
		}

		$sql = "DELETE FROM $table
			WHERE " . $db->sql_in_set($column, $from_values);
		$db->sql_query($sql);

		$db->sql_transaction('commit');
	}
}