Closed theduke closed 6 years ago
The current db-* modules are not perfect, but what they get right is that they don't use subtyping and runtime polymorphism where it's not required. Your design throws away this advantage for no good reason. Stop thinking in Java please. ;-)
What if one wants to support multiple database types at runtime?
@Araq
What they get wrong though, is that you can't switch between drivers at all without re-writing a lot of your code. Having similar interfaces for the drivers is pretty pointless when you can't switch between them.
For example, testing with sqllite, production with postgres. Which might be a bad example because it's not a good idea, but the general assumption holds. Or starting a project with SQLite, and if it gets big enough, switching to a proper database.
I've basically already written a light version of this for an ORM I'm working on. And the current design makes this really much more awkward than it needs to be.
@Varriount
That wouldn be a problem, one could just instantiate multiple Db objects for different drivers.
Also, the drivers could/should be written in a way that they can still be used standalone. So basically just the current versions of db_postgres etc.
Just with the added feature of using them wrapped with the SQL package if one cares about being able to switch the backend.
GO for example has a very similiar SQL package, and it's the defacto standard for using SQL with Go.
If this is how you want the database modules to work then by all means go ahead and implement it that way. But for now as a Nimble package.
The standard library modules are here to stay for the foreseeable future, if you can create a Nimble package that is superior then we may adopt it into the standard library.
What they get wrong though, is that you can't switch between drivers at all without re-writing a lot of your code. Having similar interfaces for the drivers is pretty pointless when you can't switch between them.
It's not similar, it is supposed to be identical. And we ported the forum from postgres to sqlite with no issues and without code rewrites, so I wonder why you had different experiences.
@theduke
standardized access to varying SQL drivers.
As @Araq has said, the modules provide a consistent interface.
It is true that the db connection identifier returned from open()
is not common, but unique to each database.
However, once you have that identifier, you use that dbConn to connect to a consistent set of procs.
Long way of saying Why does the dbConn need to be unified?
Because all the db_modules expose the same procs, you just change the import module, tweak your queries, change the database/username/password for open(), and it works to a new database type.
@Varriount
What if one wants to support multiple database types at runtime?
You can currently connect to two different database types at the same time.
import db_sqlite, db_mysql
var
m = db_mysqlite.open(....)
s = db_sqlite.open(.....)
m.exec(....)
s.exec(....)
This PR combines the db_sqlite, db_mysql and db_postres into one module. You call the initDb() with a database type to get your unique id (for mapping functions to the correct db_xxx database module), and then the procs are the same as the underlying db_xxxx modules. Maybe this accomplishes the same thing??
@theDuke
maintain a connection pool that allows concurrent/threaded code to painlessly work with the database.
I don't know how the current db_xxxx modules work with the Nim thread/spawn/...
Is this a real issue currently?
Provide a base module or import file that defines the common things like exception classes, tags, etc, so that EDb exception is globally defined, rather than having db_sqlite.EDb different to db_mysql.EDb, and likewise for tags
I suppose this never panned out. Looks like the OP went to the dark side. Closing in any case, if you're still interested in creating this then please go for it and post a link here to your awesome package :)
@dom96 haha I guess I went to the dark side, namely Rust. ;)
indeed. You're always welcome back in the light side ;)
I hereby propose a new sql package that provides a standardized access to varying SQL drivers.
The sql package would contain a Db type that is used for creating a database connection and executing queries. This type is driver independent. Different drivers register themselves to the sql package on import.
All drivers currently in the core (sqlite3, postgres, mysql, odbcsql) are moved out and into custom nimble packages.
The Db object uses the driver under the hood to create connections, execute the queries, and manages prepared statements. The Db object will, optionally, maintain a connection pool that allows concurrent/threaded code to painlessly work with the database. A pool of connections is maintained, and connections are re-used.
If the driver is capable of prepared statements, the Db object also maintains a mapping of which connections have which prepared statement available, and uses an appropriate connection if available, waits for one, or prepares the statement on a free/new connection.
The sql package provides two base types: Driver and Connection, which have base methods that must be implemented by a driver.
Some rough code to demonstrate. This is nothing too well thought out, just how I imagine it to be.
Connection
Driver
Db
Let me know what you think!