[DB-SIG] URI syntax for database

Ian Bicking ianb at colorstudy.com
Mon Apr 4 22:56:02 CEST 2005


Andy Dustman wrote:
> I vote for:
> 
> pydbapi-<dbms>://[<user>[:<password>]]@[<host>[:<port>]]/[<database>][?param1=...&param2=...]
> 
> Where:
> 
> dbms: Name of the database server implementation (mysql, postgresql,
> oracle, etc.); map server implementation names to callables (factory
> functions) that should be passed a mapping of all the above parameters
> and return a DB API connection object.
> 
> database: database name
> 
> paramX: optional implementation-dependent parameters
> 
> user, password, host, port, database: all obvious, standard meaning as
> in PEP-249 guidelines for connect()

The connection also should have some opportunity to parse the URI.  At 
least for SQLite it won't be quite the same (though it actually would 
fit the pattern).  How the rest gets parsed it kind of up to the driver. 
  I think Firebird actually uses a combination of a full path and a 
hostname.  Which fits fine too.  Anyway, there's some diversity, though 
of course I'd always prefer as much consistency as possible.

At the same time, it's important to me that I be able to parse a URI 
without actually connecting to the database.  So while I'd like the 
database drivers to have the opportunity to do their own parsing, I'd 
also like to invoke the constructor manually (or at least be able to do so).

Incidentally, I'd also like access to any extra parameters that the 
parser doesn't know about, so I can use them if I wish.

I guess I'll try to code up an strawman library with this basic feel, 
since there has to be a library for backward compatibility anyway.

> For MySQLdb, the factory function would look like this:
> 
> def MySQLdb_Connection(kwargs):
>     from MySQLdb import connect
>     kwargs2 = kwargs.copy()
>     try:
>         del kwargs2['database']
>         kwargs2['db'] = kwargs['database']
>     except KeyError:
>         pass
>     try:
>         del kwargs2['password']
>         kwargs2['passwd'] = kwargs['password']
>     except KeyError:
>         pass
>     return connect(**kwargs2)
> 
> Of course, if you use db instead of database, and passwd instead of
> password, this reduces to:
> 
> def MySQLdb_Connection(kwargs):
>     from MySQLdb import connect
>     return connect(**kwargs)
> 
> The factory functions should be fairly trivial for most database modules.
> 
> It might also be possible to (ab)use urllib2 by registering an Opener
> for each database of interest which returns an DB API connection
> object instead of a file-like object, and then using urllib2.urlopen()
> to open connections. But it's probably better to have a seperate
> module for this, i.e. dburllib.urlopen(url) -> connection. urlparse
> does a good bit of the work already:
> 
> 
>>>>import urlparse
>>>>urlparse.uses_netloc.append("pydbapi-mysql")
>>>>urlparse.uses_query.append("pydbapi-mysql")
>>>>urlparse.urlparse('pydbapi-mysql://user:password@host:port/database?compress=1')
> 
> ('pydbapi-mysql', 'user:password at host:port', '/database', '', 'compress=1', '')

urllib also seems to have a lot of undocumented functions that do the 
necessary parsing.


-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org


More information about the DB-SIG mailing list