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

db: adding multi database support #1446

Merged
merged 2 commits into from
May 12, 2019
Merged

Conversation

RustyBower
Copy link
Contributor

@RustyBower RustyBower commented Jan 13, 2019

This should fix #736.

This PR migrates from direct SQLite SQL statements to using the SQLAlchemy ORM. This will allow users to choose whether they want to stick with SQLite (Default), or leverage another database engine.

I've added a few more variables to core to handle non-SQLite databases: db_type, db_user, db_pass, db_host, and db_name. If db_type is not specified, or is specified with sqlite, the other values do not need to be specified. If db_type is specified with MySQL, users will need to specify the other parameters.

We could probably move the Models into their own model.py to clean things up a bit, but I will leave that to your discretion @dgw

@RustyBower RustyBower force-pushed the multi_db_support branch 5 times, most recently from 0890294 to 80cab9e Compare January 13, 2019 07:31
@dgw dgw added this to the 7.0.0 milestone Jan 13, 2019
@dgw dgw added the Feature label Jan 13, 2019
Copy link
Contributor

@cerealcable cerealcable left a comment

Choose a reason for hiding this comment

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

Thanks for the work @RustyBower, just a few comments ;)

sopel/db.py Outdated Show resolved Hide resolved
sopel/db.py Outdated Show resolved Hide resolved
@@ -96,8 +96,23 @@ class CoreSection(StaticSection):
channels = ListAttribute('channels')
"""List of channels for the bot to join when it connects"""

db_type = ValidatedAttribute('db_type')
"""The type of database to use for Sopel's database. (SQLite or MySQL)"""
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we simply refer to sqlalchemy docs instead of limiting choices?

Copy link
Member

Choose a reason for hiding this comment

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

I'd love for this to be a ChoiceAttribute, for the automatic error message Sopel would spit out if configured to an unknown value, but that would certainly wind up biting us at some point when SQLAlchemy adds support for some newfangled database type that Sopel doesn't know about…

Copy link
Contributor

Choose a reason for hiding this comment

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

That's probably going to be infrequent though and a minor PR to address, that seems like a reasonable choice. Downside to this is that it limits usability in non-standard databases. There are some that ship supported in SQLAlchemy and others that are through external packages.

The docs for what Dialects (databases) SQLAlchemy supports (as in listed on their website): https://docs.sqlalchemy.org/en/latest/dialects/index.html

After thinking about it, given that SQLAlchemy could have any database plugin written and then consumed since anyone could write a new Dialect for SQLAlchemy, it'd probably be best to not limit this by using a ChoiceAttribute. I think warning when a connection couldn't be made instead is best.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've made this a ChoiceAttribute for now. It looks like there aren't that many dialects to deal with (7), and honestly people only probably use 4 of those (sqlite, mysql, postgres, and mssql).

The biggest question is how we are going to handle dependencies for these, since mysql requires pymysql, etc. Is that something that should be documented or should the PyMySQL dependency be included in requirements (which would also need to include the dependencies for all other database dialects, and that feels bad)

Copy link
Member

Choose a reason for hiding this comment

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

Dependencies for the various dialects should be left to documentation, IMO. Adding them all to requirements would partially defeat the purpose of making the backend a choice, because the point is to use SQLite (from Python's standard library) unless the user specifically sets it up otherwise. And to do that, they should need to read some documentation. 😸

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like it. I've added some of the basic stuff into coretasks, but I will definitely update README with some more of the different db backend requirements.

@RustyBower RustyBower force-pushed the multi_db_support branch 4 times, most recently from c4a576d to 4b8ddc5 Compare January 14, 2019 02:35
@RustyBower
Copy link
Contributor Author

RustyBower commented Jan 14, 2019

Just finished testing. MSSQL, MySQL, Postgres, and SQLite all work.

I am unable to test Oracle because apparently you need to pay for a license. I haven't tested the last 2 (firebird or sybase).

I don't love having String(255) everywhere, but I'm unable to just have String, since it causes MySQL to explode. I'm still looking at other options.

dgw
dgw previously requested changes Feb 8, 2019
Copy link
Member

@dgw dgw left a comment

Choose a reason for hiding this comment

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

Gave this a preliminary once-over. Nothing major, but a few things did jump out.

(Some stuff was already fixed after @cerealcable's review, so 👍 for that!)

sopel/db.py Outdated Show resolved Hide resolved
sopel/config/core_section.py Outdated Show resolved Hide resolved
sopel/db.py Outdated Show resolved Hide resolved
@dgw dgw dismissed their stale review February 8, 2019 12:41

All addressed; need to re-review after testing for real.

@dgw
Copy link
Member

dgw commented Mar 21, 2019

@RustyBower I think you messed up this PR the other day, like you did with the reddit plugin one. Review conversations that were marked as resolved are missing their resolutions in the current PR state.

Looks like 2c0b884 was the last good state.

@dgw
Copy link
Member

dgw commented Mar 22, 2019

@RustyBower Still broken compared to before. A lot of issues that were fixed as of 2c0b884 are present again in the current state, because some commits are missing.

Merging upstream into a feature branch is a bad idea. I suggest doing a git reset --hard 2c0b884 and rebasing that onto master, fixing the conflicts manually. (Something I can obviously do myself, but if you learn about rebasing yourself it's a helpful skill to have. 😸)

@RustyBower RustyBower force-pushed the multi_db_support branch 2 times, most recently from e57aa7f to 2c0b884 Compare March 22, 2019 01:56
@RustyBower
Copy link
Contributor Author

This should be all set. I just triple checked with various databases, and it all works 👍

Copy link
Contributor

@Exirel Exirel left a comment

Choose a reason for hiding this comment

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

Damn, naming things is really hard.

sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/config/core_section.py Show resolved Hide resolved
sopel/config/core_section.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
sopel/db.py Show resolved Hide resolved
@Exirel
Copy link
Contributor

Exirel commented Mar 25, 2019

@RustyBower almost done! There is this generic Exception raised that I would like to see replaced by a more-specific one.

Copy link
Contributor

@Exirel Exirel left a comment

Choose a reason for hiding this comment

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

In sopel.db, it appears that you did not import sopel.config.

While you are at it, could you replace from sopel.tools import Identifier by this:

from sopel import config, tools

and then use tools.Identifier and config.ConfigurationError when needed?

sopel/db.py Outdated Show resolved Hide resolved
sopel/db.py Outdated Show resolved Hide resolved
@RustyBower
Copy link
Contributor Author

Squashed all the commits, should be ready for the big show now

@dgw
Copy link
Member

dgw commented Mar 28, 2019

Well, I approuve, as long as everything's green. 😛

Too bad everything's not green. There's an undefined name, that DatabaseConfigurationError you wanted so much… (Not that I disagree about making the exception specific!)

Copy link
Member

@dgw dgw left a comment

Choose a reason for hiding this comment

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

The good news is, my comments fall squarely in the "nitpick" category. 😃

Bad news is, you're still not done force-pushing this PR, because at least a couple of them are actually important nitpicks. 😦

(But I suggest you address these in new commits and rebase after the PR is approved—sound good?)

sopel/db.py Show resolved Hide resolved
sopel/db.py Outdated Show resolved Hide resolved
sopel/db.py Outdated Show resolved Hide resolved
sopel/config/core_section.py Show resolved Hide resolved
sopel/config/core_section.py Show resolved Hide resolved
Copy link
Member

@dgw dgw left a comment

Choose a reason for hiding this comment

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

This is 👍 pending me getting a chance to put it through some paces on an actual instance (though I shouldn't need to if the DB tests pass, right? 😛)

Future plans: Documentation updates to the README, and possibly adding setuptools extras for the different DB options.

@dgw dgw self-assigned this Apr 10, 2019
@deathbybandaid
Copy link
Contributor

Very excited for this, will bot owners have any way to migrate existing sqlite content to another database?

@RustyBower
Copy link
Contributor Author

RustyBower commented Apr 18, 2019

Not currently, but there exist some tools like https://github.com/seanharr11/etlalchemy that can do the migrations between any of the now supported DBs

@dgw
Copy link
Member

dgw commented Apr 18, 2019

Not currently

Or ever, probably. I don't think it's Sopel's responsibility to offer migration from one database back-end to another. Existing users have numerous options from which to choose if they want to move away from SQLite, just like they had their choice of tools for moving to SQLite when Willie 5.0 came out.

If it "wasn't our problem" when dropping support for other database engines, it certainly "isn't our problem" when adding (back) support for engines other than SQLite while still keeping SQLite support.

@deathbybandaid
Copy link
Contributor

It's still good to note that there is a solution though.

@Exirel
Copy link
Contributor

Exirel commented May 8, 2019

I think this PR is ready to be merged. We should then improve the following points:

  • documentation,
  • driver support,
  • tests,

which can be all done in future PR.

@dgw
Copy link
Member

dgw commented May 10, 2019

Assigning to @RustyBower as a reminder. We agreed on IRC that I'll merge this once some rudimentary documentation on the more popular drivers is in place.

Basic docs (in the readme here and in a section at https://sopel.chat/usage/installing/ — a separate PR to sopel-irc/sopel.chat) should cover sqlite, mysql, and pgsql at minimum. Anything more obscure can wait, I think. Not many of us would want to buy, say, an Oracle license just to document it. 😁

README.rst Outdated Show resolved Hide resolved
@RustyBower
Copy link
Contributor Author

Should be all set with README configuration

@dgw dgw merged commit adc2fe7 into sopel-irc:master May 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

OperationalError: database is locked
5 participants