Skip to content

Skip partial indexes and conditional validators in uniqueness checkers#277

Merged
djezzzl merged 6 commits intomasterfrom
copilot/add-unique-index-checker
Feb 22, 2026
Merged

Skip partial indexes and conditional validators in uniqueness checkers#277
djezzzl merged 6 commits intomasterfrom
copilot/add-unique-index-checker

Conversation

Copy link
Contributor

Copilot AI commented Feb 21, 2026

  • Explore codebase to understand the issue
  • Fix UniqueIndexChecker to skip partial indexes (indexes with WHERE clause)
  • Fix MissingUniqueIndexChecker to skip validators with conditions: option
  • Move conditions test into main missing_unique_index_checker_spec.rb
  • Extract partial index test to spec/checkers/unique_index_checker/sqlite_spec.rb and spec/checkers/unique_index_checker/postgresql_spec.rb
  • All 22 SQLite tests pass
  • Update CHANGELOG with Unreleased section
Original prompt

This section details on the original issue you should resolve

<issue_title>UniqueIndexChecker and postgresql partial indexes</issue_title>
<issue_description>In postgresql you can create partial indexes that allow you specify a where condition.
I was able to add a uniqueness validation that enforces these, using a combination of scope and conditions, e.g. validates_uniqueness_of :account_id, scope: :default, condition: -> { where(default: true}. This example enforces a single default per account. It would be awesome if the gem could identify these so that they aren't being flagged.</issue_description>

<agent_instructions>Investigate and provide a proof of concept to correctly identify indexes for scoped uniqueness validations and has_one/has_many associations.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@djezzzl Hi @tconst,

Thank you for the suggestion! Indeed, it would be cool to have such. Would you like to investigate and contribute?


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits February 21, 2026 15:16
…artial indexes

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>
Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>
Copilot AI changed the title [WIP] Add support for PostgreSQL partial indexes in UniqueIndexChecker Skip partial indexes and conditional validators in uniqueness checkers Feb 21, 2026
Copilot AI requested a review from djezzzl February 21, 2026 15:17
@djezzzl
Copy link
Owner

djezzzl commented Feb 21, 2026

@copilot fix PR so that CI is green.

…est specs

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 21, 2026

@copilot fix PR so that CI is green.

Fixed in 6d71c10. The CI failures were caused by default being a reserved keyword in PostgreSQL — it can't be used as a column name in a WHERE clause. Renamed the test column to is_default in both spec files.

Copy link
Owner

@djezzzl djezzzl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address comments

Also, update the changelog with Unreleased changes in the beginning.

let(:attribute) { :account_id }
let(:klass) do
define_class do |klass|
klass.validates :account_id, uniqueness: { scope: :is_default, conditions: -> { where(is_default: true) } }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove passing scope. Keep only conditions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in dcb7ecd — removed scope:, kept only conditions:.

Comment on lines +114 to +139
context 'when partial unique index is provided' do
before do
define_database_with_entity do |table|
table.integer :account_id
table.boolean :is_default
table.index %i[account_id], unique: true, where: 'is_default = true'
end
end

specify do
expect(checker.report).to be_nil
end
end

context 'when no index is provided' do
before do
define_database_with_entity do |table|
table.integer :account_id
table.boolean :is_default
end
end

specify do
expect(checker.report).to be_nil
end
end
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep only a single specify where expect(checker.report).to be_nil because it doesn't rely on the actual index presence anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in dcb7ecd — collapsed to a single specify with expect(checker.report).to be_nil.

@@ -0,0 +1,41 @@
# frozen_string_literal: true

RSpec.describe DatabaseConsistency::Checkers::UniqueIndexChecker, :postgresql do
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this spec file. Instead, adjust unique_index_checker_spec.rb.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in dcb7ecd — deleted the file and added a :postgresql-tagged context directly in unique_index_checker_spec.rb.

end
end

context 'when uniqueness validation has conditions option' do
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this test to checker/missing_unique_index_checker_spec.rb

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in dcb7ecd — moved to spec/checkers/missing_unique_index_checker_spec.rb.

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 22, 2026

@copilot address comments

Also, update the changelog with Unreleased changes in the beginning.

Done in dcb7ecd — addressed all review comments and added an [Unreleased] section to the CHANGELOG.

Copilot AI requested a review from djezzzl February 22, 2026 07:33
Copy link
Owner

@djezzzl djezzzl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address comments

Comment on lines +160 to +174
context 'when unique partial index exists', :postgresql do
before do
define_database_with_entity do |table|
table.integer :account_id
table.boolean :is_default
table.index %i[account_id], unique: true, name: index_name, where: 'is_default = true'
end
end

let(:klass) { define_class }

specify do
expect(checker.report).to be_nil
end
end
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right. This test is only supported by PostgreSQL, but maybe also SQLite?

Therefore, please extract it to a separate file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in a705f4b. SQLite does support partial indexes with WHERE clauses (confirmed by existing tests in redundant_index_checker/sqlite_spec.rb). Extracted the test to separate files: spec/checkers/unique_index_checker/sqlite_spec.rb (using is_default = 1 for SQLite boolean syntax) and spec/checkers/unique_index_checker/postgresql_spec.rb, following the same pattern as redundant_unique_index_checker/.

…spec.rb files

Co-authored-by: djezzzl <9407725+djezzzl@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 22, 2026

@copilot address comments

Done in a705f4b — extracted the partial index test from unique_index_checker_spec.rb to separate spec/checkers/unique_index_checker/sqlite_spec.rb and spec/checkers/unique_index_checker/postgresql_spec.rb files.

Copilot AI requested a review from djezzzl February 22, 2026 10:08
@djezzzl djezzzl marked this pull request as ready for review February 22, 2026 14:33
@djezzzl djezzzl merged commit e15b46c into master Feb 22, 2026
13 checks passed
@djezzzl djezzzl deleted the copilot/add-unique-index-checker branch February 22, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UniqueIndexChecker and postgresql partial indexes

2 participants