Add basic support for check constraints to database migrations#31323
Add basic support for check constraints to database migrations#31323jeremy merged 1 commit intorails:masterfrom
Conversation
|
Thanks for the pull request, and welcome! The Rails team is excited to review your changes, and you should hear from @schneems (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. This repository is being automatically checked for code quality issues using Code Climate. You can see results for this analysis in the PR status below. Newly introduced issues should be fixed before a Pull Request is considered ready to review. Please see the contribution instructions for more information. |
There was a problem hiding this comment.
Why was every line in this hash changed when you only added a single line?
There was a problem hiding this comment.
@sgrif because it's very clearly [already] aligned to the longest key?
(though it does seem to have ended up one space further over than it should be.)
There was a problem hiding this comment.
Sorry, I should have been more clear on my intent:
Do you think we could drop the visual alignment change here so we aren't changing every line in this hash? I think having the one line that is not aligned the same is fine.
sgrif
left a comment
There was a problem hiding this comment.
I don't think the tests here are sufficient. There are no tests which check that the constraint has actually been added to the table (which can only really be tested by attempting an insertion that should fail).
In particular, I don't think you've handled SQLite correctly, where check constraints are supported, but can only be added inline with the column definition. Unless I'm missing something, there's no way to add a check constraint as part of a column definition in this PR at all.
|
+1 to @sgrif's thoughts on sqlite. I also recently discovered that add_reference doesn't create foreign keys on sqlite, even though sqlite could support it. I'm working on a PR for that, and it'd great to not see sqlite fall behind farther. |
That sounds more like an additional feature than a flaw in this PR, per se. (i.e., if the PR were implementing column-level constraints and had omitted SQLite, that would be more of a problem; whereas I think only implementing table-level constraints is a perfectly reasonable self-contained feature, particularly as someone's first substantial contribution.) |
|
I'm fine with omitting SQLite support entirely for this feature to start, but I still think we need tests which actually exercise the added constraint. |
|
@matthewd you're right, that makes sense. This API makes sense in general, just not for sqlite. Totally fair to skip it. Much like how add_foreign_key can't work on sqlite, but add_reference should be doable. Would it be possible/tolerable to emit some kind of warning if a constraint (or foreign key) migration is treated as a no-op sqlite3? I spent a ton of time tracing that behavior out and I'm not sure what we do now is intuitive. The sqlite docs say they support foreign keys and foreign key migrations are "successful", so it one does not expect to end up without a foreign key in their sqlite db. |
4845759 to
ab123b4
Compare
|
Updated PR. Added missing test (suggested by @sgrif ) and support for sqlite. |
|
What's missing to move forward on this branch atm? |
|
This is a good feature. It's 2019 already, and SQL-92 standard had |
|
If core team will accept this PR, I will update it as needed. |
|
Constraints enforcement is a database system's job. In general, only DBMS is able to reliably enforce constraints in 100% of cases. If you implement checks in your app logic, there are significant chances that after one year or so they will be silently broken, because some human accessed DB directly, changing data, or because you've launched, say, API using a different language/framework, or because you've used some DB migrations bypassing your abstraction layer which tried to enforce constraints.
|
|
@matthewd Wdyt about moving this forward? |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
There was a problem hiding this comment.
🙌🏼
Method naming
Maybe remove the _constraint part from new methods names? Seems a little redundant
Comparing,
create_table :distributors do |t|
t.string :zipcode
t.check_constraint "zipchk", "char_length(zipcode) = 5"
end
remove_check_constraint :distributors, "zipchk"create_table :distributors do |t|
t.string :zipcode
t.check "zipchk", "char_length(zipcode) = 5"
end
remove_check :distributors, "zipchk"I prefer the clarity of seeing constraint mentioned. If it were a constraint on a column definition, check: "expression" would be nicer.
Naming constraints
Having to name constraints is a hassle, too. Can we name them automatically, like we do with foreign keys and indexes? For example, we could transform the check expression into name like chk_rails_#{hashed_identifier}.
activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
Outdated
Show resolved
Hide resolved
activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
Outdated
Show resolved
Hide resolved
activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
Outdated
Show resolved
Hide resolved
14b1e36 to
c19da90
Compare
|
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
jeremy
left a comment
There was a problem hiding this comment.
Ready to merge pending rebase. Thanks for your work on this @fatkodima.
b43feb3 to
ac01c4d
Compare
ac01c4d to
c3ee7da
Compare
|
@jeremy Rebased. |
|
Wow. Great news 👍 |
Active Record already supports adding `NOT VALID` foreign key constraints in PostgreSQL, but back in rails#31323 when check constraint support was initially added, the ability to add a check constraint and validate it separately was not included. This adds that functionality!
Supports annotating model check constraints, credit goes to folks who worked on ctran/annotate_models#868. Adds new option `show_check_constraints` that defaults to `false`. When enabled, it will add check constraints annotations rails/rails#31323 to the model annotations. It can be enabled also through the command line with options `-c` or `--show-check-constraints`. Resolves #104
This patch adds basic support for adding and removing check constraints using the migration DSL:
Check constraints are dumped inside
create_tablesections toschema.rb.add_check_constraintandremove_check_constraintare both reversible.Considerations
_constraintpart from new methods names? Seems a little redundantNO INHERIT(PostgreSQL)?Related #23083.