Skip to content
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

Composite constraints #1146

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
Draft

Composite constraints #1146

wants to merge 15 commits into from

Conversation

dantownsend
Copy link
Member

@dantownsend dantownsend commented Jan 25, 2025

Based off this: #984

That PR is really great, but I've added the following:

  • Docs
  • Check constraints
  • I changed the module to piccolo.constraints from piccolo.constraint, because we support unique and check constraints, so plural made a bit more sense to me.

Remaining tasks:

  • Update / fix the tests

In the original PR, constraints were added like this:

from piccolo.constraints import UniqueConstraint

class Album(Table):
    name = Varchar()
    band = ForeignKey(Band)
    unique_name_band = UniqueConstraint(['name', 'band'])

Which I do quite like.

In this PR I tried this:

class Album(Table):
    name = Varchar()
    band = ForeignKey(Band)

Album.add_unique_constraint(Album.name, Album.band)

My rational is:

  • Piccolo tends to use column references instead of strings where possible, because linters can detect errors.
  • The user doesn't have to name their constraint if they don't want to. They can do this though: Album.add_unique_constraint(Album.name, Album.band, name='unique_name_band'). If no name is specified we generate a sensible one.

We could support both syntaxes - it wouldn't be that hard, but it can be confusing having multiple ways to do the same thing.

What do people think?

@dantownsend dantownsend added the enhancement New feature or request label Jan 25, 2025
@Skelmis
Copy link
Collaborator

Skelmis commented Jan 25, 2025

Thinking out loud.

I like the use of columns instead of strings, but just thinking it may be worth considering getting it on the table itself somehow. I figure something like Django's Meta model which may look like the following:

class Album(Table):
    name = Varchar()
    band = ForeignKey(Band)
  
    class Meta:
        unique_together = [Album.name, Album.band]

This could also be expanded for other configs such as

class Album(Table):
    name = Varchar()
    band = ForeignKey(Band)
  
    class Meta:
        help_text = "A music album!"
        unique_together = [Album.name, Album.band]

The reasoning behind the thought is just based more so on visual grouping and ensuring table related configs remain on the table itself. Note that I am aware TableMeta handles it all internally regardless, I was more so just thinking about developer UX.


Although ignoring the above, I like the proposed syntax and rational. I think your updated approach and method makes more sense then as table attributes. I'd be happy to use this feature in my code bases as proposed

@dantownsend
Copy link
Member Author

@Skelmis Thanks, that's great input.

I agree that having it on the table class somehow is nicer. Even if there's just a classmethod called add_constraints which you override, and it gets called automatically when the table class is ready. I'll experiment with it a bit more.

Check constraints
=================

.. automethod:: Table.add_check_constraint
Copy link
Member

Choose a reason for hiding this comment

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

@dantownsend For now, constraints are droped by simply deleting (or commenting out) the constraints from the table definition. I'm fine with that, but it should be indicated in the docs so the user knows how to use that. Another option is to create a drop_unique_constraint classmethod that will drop the constraints. As you wish, both options suit me.

Copy link
Member

@sinisaos sinisaos left a comment

Choose a reason for hiding this comment

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

@dantownsend I already wrote in @atkei PR that I agree with the changes and that they are great. Using column references instead of string is a great improvement. When you finish and merge this PR it will be great for Piccolo as many people have been asking for this feature. Great.

@dantownsend
Copy link
Member Author

@sinisaos Thanks. I've been thinking about it this morning. I'm leaning towards keeping both approaches - being able to define the constraints inline in the table if you're happy just using strings, and the new API if you want to use column references. Will have a think today.

@sinisaos
Copy link
Member

@dantownsend I think you should only use one option (one api) to create and drop unique constraints because having two ways to do the same thing could be confusing and unnecessary. That's just my opinion. You can do what you think is best.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

4 participants