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

Fix sqlite3 dependency constraint #477

Closed

Conversation

rmacklin
Copy link

@rmacklin rmacklin commented Jul 26, 2021

Fixes #476

As of c887904 (released in mailcatcher v0.8.0), MailCatcher::Mail#db relies on SQLite3::Database responding to the foreign_keys= method:
c887904#diff-ba6f65d5c04d1ccc77ea172c1d1769c73d099580585d07dff7496e4401298e35R39
That method was introduced in:
sparklemotion/sqlite3-ruby@ee010db#diff-b01a6d9c63594012b75b704f2489342135f4f32924b02494d3236c8337c70167R264 (from sparklemotion/sqlite3-ruby#136) which was released in sqlite3 v1.3.12.

However, mailcatcher's gemspec was previously declared to work with sqlite3 ~> 1.3, which includes v1.3.0 to v1.3.11. This meant that using mailcatcher v0.8.0 with one of those versions of sqlite3 would result in the following error:

NoMethodError - undefined method `foreign_keys=' for # Did you mean? foreign_key_list:
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:39:in `block in db'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:11:in `tap'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:11:in `db'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:76:in `messages'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/web/application.rb:81:in `block in <class:Application>'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1611:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1611:in `block in compile!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:975:in `block (3 levels) in route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:994:in `route_eval'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:975:in `block (2 levels) in route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1015:in `block in process_route'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1013:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1013:in `process_route'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:973:in `block in route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:972:in `each'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:972:in `route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1085:in `block in dispatch!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `block in invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1082:in `dispatch!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:907:in `block in call!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `block in invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:907:in `call!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:895:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/xss_header.rb:18:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/path_traversal.rb:16:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/json_csrf.rb:18:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/base.rb:49:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/base.rb:49:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/frame_options.rb:31:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/nulllogger.rb:9:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/head.rb:13:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:182:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:2013:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1487:in `block in call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1787:in `synchronize'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1487:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/urlmap.rb:66:in `block in call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/urlmap.rb:50:in `each'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/urlmap.rb:50:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/builder.rb:153:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/web.rb:26:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:81:in `block in pre_process'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:79:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:79:in `pre_process'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:54:in `process'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:39:in `receive_data'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/eventmachine-1.0.9.1/lib/eventmachine.rb:193:in `run_machine'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/eventmachine-1.0.9.1/lib/eventmachine.rb:193:in `run'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher.rb:180:in `run!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/bin/mailcatcher:6:in `<top (required)>'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/mailcatcher:23:in `load'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/mailcatcher:23:in `<main>'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/ruby_executable_hooks:24:in `eval'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/ruby_executable_hooks:24:in `<main>'

To fix this, we should explicitly require sqlite3 >= 1.3.12. That will force a compatible version of sqlite3 to be installed when mailcatcher is installed, and the compatible version will be used when mailcatcher is run.

As of c887904, `MailCatcher::Mail#db`
relies on `SQLite3::Database` responding to the `foreign_keys=` method:
sj26@c887904#diff-ba6f65d5c04d1ccc77ea172c1d1769c73d099580585d07dff7496e4401298e35R39
That method was introduced in:
sparklemotion/sqlite3-ruby@ee010db#diff-b01a6d9c63594012b75b704f2489342135f4f32924b02494d3236c8337c70167R264
which was released in sqlite3 v1.3.12

However, our gemspec was previously declared to work with
`sqlite3 ~> 1.3`, which includes v1.3.0 to v1.3.11. This meant that using
mailcatcher v0.8.0 with one of those versions of sqlite3 would result in
the following error:
```
NoMethodError - undefined method `foreign_keys=' for #<SQLite3::Database:0x00007fdba21f3d28>
Did you mean?  foreign_key_list:
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:39:in `block in db'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:11:in `tap'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:11:in `db'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/mail.rb:76:in `messages'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/web/application.rb:81:in `block in <class:Application>'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1611:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1611:in `block in compile!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:975:in `block (3 levels) in route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:994:in `route_eval'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:975:in `block (2 levels) in route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1015:in `block in process_route'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1013:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1013:in `process_route'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:973:in `block in route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:972:in `each'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:972:in `route!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1085:in `block in dispatch!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `block in invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1082:in `dispatch!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:907:in `block in call!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `block in invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1067:in `invoke'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:907:in `call!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:895:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/xss_header.rb:18:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/path_traversal.rb:16:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/json_csrf.rb:18:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/base.rb:49:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/base.rb:49:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-protection-1.5.5/lib/rack/protection/frame_options.rb:31:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/nulllogger.rb:9:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/head.rb:13:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:182:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:2013:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1487:in `block in call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1787:in `synchronize'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/sinatra-1.4.8/lib/sinatra/base.rb:1487:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/urlmap.rb:66:in `block in call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/urlmap.rb:50:in `each'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/urlmap.rb:50:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/rack-1.6.13/lib/rack/builder.rb:153:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher/web.rb:26:in `call'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:81:in `block in pre_process'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:79:in `catch'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:79:in `pre_process'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:54:in `process'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/thin-1.5.1/lib/thin/connection.rb:39:in `receive_data'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/eventmachine-1.0.9.1/lib/eventmachine.rb:193:in `run_machine'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/eventmachine-1.0.9.1/lib/eventmachine.rb:193:in `run'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/lib/mail_catcher.rb:180:in `run!'
	/Users/richard/.rvm/gems/ruby-2.6.6/gems/mailcatcher-0.8.0/bin/mailcatcher:6:in `<top (required)>'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/mailcatcher:23:in `load'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/mailcatcher:23:in `<main>'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/ruby_executable_hooks:24:in `eval'
	/Users/richard/.rvm/gems/ruby-2.6.6/bin/ruby_executable_hooks:24:in `<main>'
```

To fix this, we should explicitly require sqlite3 >= 1.3.12. That will
force a compatible version of sqlite3 to be installed when mailcatcher
is installed, and the compatible version will be used when mailcatcher
is run.
@sj26
Copy link
Owner

sj26 commented Jul 27, 2021

Oh whoops, sorry! I didn't expect a new method to have been introduced in a patch release.

Thanks for the PR. I'll merge and then release a v0.8.1.

@sj26
Copy link
Owner

sj26 commented Jul 27, 2021

Looking under the covers, it's a helper that was introduced to run the pragma command. If the helper isn't always available then it may be less disruptive to run the pragma command directly, closer to what you originally proposed in #451, but when opening the connection per where the helper is used.

@sj26 sj26 closed this in 87fdd4e Jul 27, 2021
@sj26
Copy link
Owner

sj26 commented Jul 27, 2021

I've switched to the straight PRAGMA command and shipped v0.8.1. Please try it out, and thanks!

@rmacklin
Copy link
Author

If the helper isn't always available then it may be less disruptive to run the pragma command directly

Yeah, that approach makes sense!

closer to what you originally proposed in #451

For the record, I don't deserve credit for that - #451 was opened by another user

I've switched to the straight PRAGMA command and shipped v0.8.1. Please try it out

Thanks! I can confirm that the error no longer occurs with mailcatcher v0.8.1 and older versions of sqlite3 👍

@rmacklin rmacklin deleted the fix-sqlite3-dependency-constraint branch July 27, 2021 20:37
@sj26
Copy link
Owner

sj26 commented Jul 27, 2021

Whoops, I got confused by the comment on the end of that PR!

Thanks for confirming, and for the report.

nadrooJ pushed a commit to nadrooJ/mailcatcher that referenced this pull request Jan 17, 2022
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.

v0.8.0 includes changes that require a stricter sqlite3 version constraint
2 participants