Commit 28bae04d authored by Nigel McNie's avatar Nigel McNie
Browse files

[#3349] Prevent race condition in profile view creation.

The only reliable way to prevent it is a condition on the database. In postgres, we add a unique constraint on views with type = 'profile'. MySQL doesn't support this, so we do nothing.
(cherry picked from commit ac7b45c3)

Conflicts:

	htdocs/lib/db/upgrade.php
	htdocs/lib/upgrade.php
parent 0280714c
......@@ -1123,6 +1123,48 @@ function xmldb_core_upgrade($oldversion=0) {
drop_field($table, $field);
}
if ($oldversion < 2009080600) {
// Delete duplicate profile views if there are any, then add an index
// that will prevent it happening again - but only on postgres, as it's
// the only db that supports partial indexes
if ($viewdata = get_records_sql_array("
SELECT owner, id
FROM {view}
WHERE owner IN (
SELECT owner
FROM {view}
WHERE type = 'profile'
GROUP BY owner
HAVING COUNT(*) > 1
)
AND type = 'profile'
ORDER BY owner, id", array())) {
require_once('view.php');
$seen = array();
foreach ($viewdata as $record) {
$seen[$record->owner][] = $record->id;
}
foreach ($seen as $owner => $views) {
// Remove the first one, which is their real profile view
array_shift($views);
foreach ($views as $viewid) {
$view = new View($viewid);
if ($view->get('type') == 'profile') {
$view->delete();
}
else {
log_info("Odd: upgrade to delete duplicate profile views tried to delete a normal view? (id=$viewid)");
}
}
}
}
if (is_postgres()) {
execute_sql("CREATE UNIQUE INDEX {view_own_type_uix} ON {view}(owner) WHERE type = 'profile'");
}
}
return $status;
}
......
......@@ -560,12 +560,15 @@ function core_postinst() {
set_config('lang', 'en.utf8');
set_config('installation_key', get_random_key());
// PostgreSQL supports indexes over functions of columns, MySQL does not.
// So we can improve the index on the username field of the usr table for
// Postgres
// PostgreSQL supports indexes over functions of columns, MySQL does not.
// We make use if this if we can
if (is_postgres()) {
// Improve the username index
execute_sql('DROP INDEX {usr_use_uix}');
execute_sql('CREATE UNIQUE INDEX {usr_use_uix} ON {usr}(LOWER(username))');
// Only one profile view per user
execute_sql("CREATE UNIQUE INDEX {view_own_type_uix} ON {view}(owner) WHERE type = 'profile'");
}
// Some more advanced constraints. XMLDB can't handle this in its xml file format
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment