Skip to content

Add support for annotating check constraints #868

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 29, 2023

Conversation

lovro-bikic
Copy link
Contributor

Rails added support for check constraints (rails/rails#31323), so I thought it would be nice if we could annotate them in models.

This PR adds annotation of check constraints with an option to disable/enable annotation. Most of the work done in this PR is based off of existing implementation for annotating indexes and foreign keys.

@Eusebius1920
Copy link

Thanks for sharing. This should get merged!

@deecewan
Copy link

deecewan commented Nov 8, 2021

@ctran any change we can get this merged?

@bruno-
Copy link

bruno- commented Jan 7, 2022

Here's a 2022 bump to this issue.

check_constraints are great and it would be great having them in the annotations.

@dtcristo
Copy link

dtcristo commented Apr 28, 2022

Hi @lovro-bikic,

First of all, I love the new feature ❤️.

We've started using your implementation and noticed it has issues with check constraints that go across multiple lines.

For example, say I have the following constraint:

CONSTRAINT foo_not_null_when_active CHECK (
CASE
    WHEN ((status)::text = 'active'::text) THEN (foo IS NOT NULL)
    ELSE true
END)

Currently this results in the following annotation:

# Check Constraints
#
#  foo_not_null_when_active  ()
#

Not sure how we'd want this to be formatted in the annotation? Perhaps we can keep the wrapping. Maybe something like this?

# Check Constraints
#
#  foo_not_null_when_active  (CASE
#                                WHEN ((status)::text = 'active'::text) THEN (foo IS NOT NULL)
#                                ELSE true
#                            END)
#

Alternatively could .squish it and print:

# Check Constraints
#
#  foo_not_null_when_active  (CASE WHEN ((status)::text = 'active'::text) THEN (foo IS NOT NULL) ELSE true END)
#

@lovro-bikic lovro-bikic force-pushed the develop branch 2 times, most recently from 23d6d42 to b0507b1 Compare May 4, 2022 14:24
@lovro-bikic
Copy link
Contributor Author

@dtcristo, thanks for the feedback!

I would go with multiline expressions squished into a single line, to be consistent with the rest of the annotations. I pushed a commit for it: b850e9b.

Side note: CI is failing, though the failures are unrelated to this branch. develop branch currently has the same failures.

@dtcristo
Copy link

dtcristo commented May 5, 2022

Hi @lovro-bikic 👋, I've had a play with your .squish changes in my Rails 6.1 application and running in to some issues.

So it turns out there is a bug in Rails 6.1 (since fixed here for Rails 7 only). The bug means that multi-line constraints are coming through as nil from the connection for PostgreSQL.

So your line:

check_constraint.expression.squish

Will error because check_constraint.expression is nil for these multi-line constraints. So at the very least we might want &.squish so we don't raise an exception in this case and keep the behaviour of printing nothing for users with older versions of Rails (like me).

However, something else I noticed with the change here, is that it will introduce an extra later of parenthesis around the check constraint for normal (one line) constraints.

So a constraint that was previously printing as:

alive    (age < 150)

Will now print

alive    ((age < 150))

However with this change a multi-line constraint will correctly print with only one layer of parenthesis.

Not sure if this is an issue, but I just wanted to point it out? Potentially if you see wrapping parenthesis you could strip them?

@lovro-bikic
Copy link
Contributor Author

Thanks for pointing out the issue regarding missing expressions, it should be fixed with this commit: 6449e7d.

However, something else I noticed with the change rails/rails#43963, is that it will introduce an extra later of parenthesis around the check constraint for normal (one line) constraints.

I couldn't reproduce this. I tried it out on Rails versions 6.1.5.1 and 7.0.2.4, and Rails in both cases output the constraint expression without the wrapping parentheses, so the annotation would always correctly have a single pair of them.

@lparry
Copy link

lparry commented Oct 13, 2022

It would be really helpful to get this merged. Is there anything we might to to help this along @ctran ?

@ctran ctran self-assigned this Oct 13, 2022
@ctran ctran added the feature label Oct 13, 2022
@ctran ctran added this to the v3.2.1 milestone Oct 13, 2022
@ctran
Copy link
Owner

ctran commented Oct 13, 2022

I need to take a look to see why the CI is failing.

@rjherrera
Copy link

@ctran hi there! have you been able to look at this? We found ourselves needing to annotate constraints, and found out about this pull request, it looks like what we need 😄, anything we can do to help get this merged?

@ctran
Copy link
Owner

ctran commented Mar 3, 2023

@ctran hi there! have you been able to look at this? We found ourselves needing to annotate constraints, and found out about this pull request, it looks like what we need 😄, anything we can do to help get this merged?

I just need help getting the CI build to pass :-)

@lovro-bikic
Copy link
Contributor Author

@ctran I rebased the branch but the CI is still failing due to this error:

  1) AnnotateModels annotating a file frozen option should abort without existing annotation when frozen: true 
     Failure/Error: expect { annotate_one_file frozen: true }.to raise_error SystemExit, /user.rb needs to be updated, but annotate was run with `--frozen`./
       expected SystemExit with message matching /user.rb needs to be updated, but annotate was run with `--frozen`./ but nothing was raised
     # ./spec/lib/annotate/annotate_models_spec.rb:2914:in `block (4 levels) in <top (required)>'

It seems that the test suite is non-deterministic because when I run bundle exec rspec locally sometimes it passes and sometimes it fails (either with the above error or some other errors), depending on the RSpec seed. I found that running with the seed 43289 (bundle exec rspec --seed 43289) makes the suite pass.

I'm not sure how to proceed here because these errors fall outside the scope of this PR, please advise.

@lovro-bikic
Copy link
Contributor Author

@ctran I invested a bit of time in researching the flaky test suite and found what causes these issues. Here is the PR which should fix all of them: #980. After we merge that, I will rebase this branch.

@ctran
Copy link
Owner

ctran commented Mar 29, 2023

@lovro-bikic I merged #980

Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>
Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>
Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>
Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>
Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>
@lovro-bikic
Copy link
Contributor Author

Thanks! I rebased the branch, but the CI failed because of Rubocop. I disabled these offenses but let me know if you want me to fix them in a different way.

Copy link
Owner

@ctran ctran left a comment

Choose a reason for hiding this comment

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

LGTM (we'll deal with the rubocop issues later)

@ctran ctran merged commit ea4cd00 into ctran:develop Mar 29, 2023
matteolc pushed a commit to matteolc/annotate_models that referenced this pull request Mar 31, 2023
commit 22ab676
Author: Cuong Tran <ctran@users.noreply.github.com>
Date:   Thu Mar 30 15:17:37 2023 -0700

    chore: remove broken badges from README.md

commit 10a7a76
Author: Takumi KAGIYAMA <694547+kg8m@users.noreply.github.com>
Date:   Fri Mar 31 07:15:07 2023 +0900

    Support `--frozen` option for routing annotations (ctran#979)

    The `--frozen` option previously deal only model annotations.  This change will support route annotations as well.

    ---------

    Signed-off-by: kg8m <takumi.kagiyama@gmail.com>
    Co-authored-by: Cuong Tran <ctran@users.noreply.github.com>

commit a28fef3
Author: Jim Jowdy <jjowdy@gmail.com>
Date:   Wed Mar 29 15:09:11 2023 -0700

    Fix retrieve_indexes_from_table when indexes is empty and base table does not exist. (ctran#849)

    Some tables may have a table_name_prefix but no indexes. Previous versions of
    the code would strip the prefix and look for indexes on the resulting table
    which likely would not exist. This causes DB errors, at least in MySQL. So now
    check if the new table exists first before trying to show its indexes.

commit 13b532d
Author: Cuong Tran <ctran@users.noreply.github.com>
Date:   Wed Mar 29 01:51:15 2023 -0700

    Update codeql-analysis.yml

commit ea4cd00
Author: Lovro Bikić <lovro.bikic@infinum.hr>
Date:   Wed Mar 29 10:31:01 2023 +0200

    Add support for annotating check constraints (ctran#868)

    This adds annotation of check constraints with an option to disable/enable annotation. Most of the work done in this PR is based off of existing implementation for annotating indexes and foreign keys.

    Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>

commit 76a1804
Author: Lovro Bikić <lovro.bikic@gmail.com>
Date:   Wed Mar 29 10:18:24 2023 +0200

    Fix flaky specs (ctran#980)

    Signed-off-by: Lovro Bikic <lovro.bikic@infinum.hr>
drwl added a commit to drwl/annotaterb that referenced this pull request Apr 10, 2024
drwl added a commit to drwl/annotaterb that referenced this pull request Apr 12, 2024
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants