felix-starman
So, I’m using MySQL, and having a table where I’m restricting the ability to insert/update records to have overlaps, but end_date is allowed to be NULL.
Since MySQL doesn’t have extensions around this, the easiest way to do it is with a trigger.
I have the following triggers:
CREATE TRIGGER memberships_insert_overlap
BEFORE INSERT
ON team_memberships FOR EACH ROW
BEGIN
DECLARE rowcount INT;
SELECT COUNT(*) INTO rowcount FROM team_memberships
WHERE person_id = NEW.person_id
AND (NEW.start_date <= COALESCE(end_date, '9999-12-31')) and (COALESCE(NEW.end_date, '9999-12-31') >= start_date)
AND (NEW.start_date <= COALESCE(NEW.end_date, '9999-12-31')) and (start_date <= COALESCE(end_date, '9999-12-31'));
IF rowcount > 0 THEN
signal sqlstate '45000' set message_text = 'overlap not allowed team_memberships.no_overlap';
END IF;
END;
CREATE TRIGGER memberships_update_overlap
BEFORE UPDATE
ON team_memberships FOR EACH ROW
BEGIN
DECLARE rowcount INT;
SELECT COUNT(*) INTO rowcount FROM team_memberships
WHERE person_id = NEW.person_id AND id != OLD.id
AND (NEW.start_date <= COALESCE(end_date, '9999-12-31')) and (COALESCE(NEW.end_date, '9999-12-31') >= start_date)
AND (NEW.start_date <= COALESCE(NEW.end_date, '9999-12-31')) and (start_date <= COALESCE(end_date, '9999-12-31'));
IF rowcount > 0 THEN
signal sqlstate '45000' set message_text = 'overlap not allowed team_memberships.no_overlap';
END IF;
END;
I’m getting the typical/expected (MyXQL.Error) (1644) overlap not allowed team_memberships.no_overlap
I feel like there’s probably something I’m missing with what sqlstate should be set to for “emulating” a constraint, or that there’s some place in MyXQL where I can register a custom handler.
Anyone have any ideas?
I’d rather not litter my code w/ error-catching statements wherever we do inserts/updates.
EDIT: I should note, I’m not concerned about the trigger logic itself. That works fine. I’m wondering if there’s a better way to wrap up this interface.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #security











Showing Posts 1 to 3- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
felix-starman
It’s looks like I should be able to use the MySQL error number and
:extra_error_codeson the MyXQL config.I’ll see if that works reasonably. I haven’t found where in ecto_sql that it handles other types than ER_DUP_ENTRY and a couple others
felix-starman
For anyone who comes across this in the future,
extra_error_codescurrently only allows the raised error to include a name: i.e.** (MyXQL.Error) (1644) (ER_SIGNAL_EXCEPTION) overlap not allowedinstead of just** (MyXQL.Error) (1644) overlap not allowed.I’m not sure what follows was the “right” way to do it and I’m sure MySQL DBAs would be shaking their heads, but it’s what I did.
Since it’s still similar enough to a duplicate entry/unique constraint if you turn your head sideways and squint at it, I just updated the
SQLSTATEto23000, andMYSQL_ERRNOto1062, which maps toER_DUP_ENTRY(used for unique constaints).For completeness, here’s the migration.
This basically rejects any insert/update that is overlapping on date ranges, including nulls on the
end_date.I wouldn’t say it’s “good”. But it gets the job done.
I may open a proposal thread for discussion about the
ecto_sqladapters to allow custom handling of error codes through something like anmfatuple from config.felix-starman
If someone comes across this in the future, I added
constraintmigration support, andcheck_constraintChangeset support toecto_sqlandmyxqlso that’s another option.In MySQL the check constraint error number is 3819, and the name, and message can be gotten by calling
perror 3819If a check constraint makes sense for you, you can do the solution above, and just construct your message to match that message string, and signal that error.
I’m going to try and make a demo PR for ecto_sql to implement an overriding mechanism for
to_constraintsin the adapter behaviours as well, so custom errors can have custom messages, and be handled by changesets “like normal”