mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-07-25 16:03:48 +00:00
Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
@ -15,6 +15,7 @@ module Gitlab
|
|||||||
FIND_DUPLICATE_SETS_SQL = <<~SQL
|
FIND_DUPLICATE_SETS_SQL = <<~SQL
|
||||||
SELECT ARRAY_AGG(id ORDER BY id ASC) as ids
|
SELECT ARRAY_AGG(id ORDER BY id ASC) as ids
|
||||||
FROM %{table_name}
|
FROM %{table_name}
|
||||||
|
WHERE %{not_null_conditions}
|
||||||
GROUP BY %{column_list}
|
GROUP BY %{column_list}
|
||||||
HAVING COUNT(*) > 1
|
HAVING COUNT(*) > 1
|
||||||
SQL
|
SQL
|
||||||
@ -323,10 +324,15 @@ module Gitlab
|
|||||||
def find_duplicate_sets(table_name, columns)
|
def find_duplicate_sets(table_name, columns)
|
||||||
logger.info("Checking for duplicates in '#{table_name}' for columns: #{columns.join(',')}...")
|
logger.info("Checking for duplicates in '#{table_name}' for columns: #{columns.join(',')}...")
|
||||||
|
|
||||||
|
not_null_conditions = columns.map do |col|
|
||||||
|
"#{connection.quote_column_name(col)} IS NOT NULL"
|
||||||
|
end.join(' AND ')
|
||||||
|
|
||||||
sql = format(
|
sql = format(
|
||||||
FIND_DUPLICATE_SETS_SQL,
|
FIND_DUPLICATE_SETS_SQL,
|
||||||
table_name: connection.quote_table_name(table_name),
|
table_name: connection.quote_table_name(table_name),
|
||||||
column_list: columns.map { |col| connection.quote_column_name(col) }.join(', ')
|
column_list: columns.map { |col| connection.quote_column_name(col) }.join(', '),
|
||||||
|
not_null_conditions: not_null_conditions
|
||||||
)
|
)
|
||||||
|
|
||||||
execute_local(sql, read_only: true) do
|
execute_local(sql, read_only: true) do
|
||||||
|
@ -74,8 +74,8 @@ RSpec.describe Gitlab::Database::RepairIndex, feature_category: :database do
|
|||||||
connection.execute(<<~SQL)
|
connection.execute(<<~SQL)
|
||||||
CREATE TABLE #{test_table} (
|
CREATE TABLE #{test_table} (
|
||||||
id serial PRIMARY KEY,
|
id serial PRIMARY KEY,
|
||||||
name varchar(255) NOT NULL,
|
name varchar(255) NULL,
|
||||||
email varchar(255) NOT NULL
|
email varchar(255) NULL
|
||||||
);
|
);
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
@ -184,7 +184,9 @@ RSpec.describe Gitlab::Database::RepairIndex, feature_category: :database do
|
|||||||
INSERT INTO #{test_table} (name, email) VALUES
|
INSERT INTO #{test_table} (name, email) VALUES
|
||||||
('test_user', 'test@example.com'), -- ID 1
|
('test_user', 'test@example.com'), -- ID 1
|
||||||
('test_user', 'test@example.com'), -- ID 2 (duplicate)
|
('test_user', 'test@example.com'), -- ID 2 (duplicate)
|
||||||
('other_user', 'other@example.com'); -- ID 3
|
('test_user', NULL), -- ID 3, email NULL, should be preserved
|
||||||
|
(NULL, 'other@example.com'), -- ID 4, name NULL, should be preserved
|
||||||
|
('other_user', 'other@example.com'); -- ID 5
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
# Create standard references (no entity column)
|
# Create standard references (no entity column)
|
||||||
@ -217,7 +219,7 @@ RSpec.describe Gitlab::Database::RepairIndex, feature_category: :database do
|
|||||||
it 'handles all reference types correctly' do
|
it 'handles all reference types correctly' do
|
||||||
# before: 3 users, various references
|
# before: 3 users, various references
|
||||||
user_count_before = connection.select_value("SELECT COUNT(*) FROM #{test_table}")
|
user_count_before = connection.select_value("SELECT COUNT(*) FROM #{test_table}")
|
||||||
expect(user_count_before).to eq(3)
|
expect(user_count_before).to eq(5)
|
||||||
|
|
||||||
# unique index doesn't exist yet
|
# unique index doesn't exist yet
|
||||||
index_exists_before = connection.select_value(<<~SQL).present?
|
index_exists_before = connection.select_value(<<~SQL).present?
|
||||||
@ -230,9 +232,16 @@ RSpec.describe Gitlab::Database::RepairIndex, feature_category: :database do
|
|||||||
|
|
||||||
repairer.run
|
repairer.run
|
||||||
|
|
||||||
# after: 2 users (duplicate removed)
|
# after: 4 users (only true duplicate ID 2 removed)
|
||||||
|
# ID 3 with NULL value preserved
|
||||||
user_count_after = connection.select_value("SELECT COUNT(*) FROM #{test_table}")
|
user_count_after = connection.select_value("SELECT COUNT(*) FROM #{test_table}")
|
||||||
expect(user_count_after).to eq(2)
|
expect(user_count_after).to eq(4)
|
||||||
|
|
||||||
|
# Verify NULL values are preserved
|
||||||
|
null_records = connection.select_value(
|
||||||
|
"SELECT COUNT(*) FROM #{test_table} WHERE email IS NULL or name is NULL"
|
||||||
|
)
|
||||||
|
expect(null_records).to eq(2)
|
||||||
|
|
||||||
# standard reference updated to good ID
|
# standard reference updated to good ID
|
||||||
standard_ref = connection.select_value(
|
standard_ref = connection.select_value(
|
||||||
|
Reference in New Issue
Block a user