1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
Database URI
============
[](http://badge.fury.io/pl/URI-db)
[](https://github.com/libwww-perl/URI-db/actions/workflows/ci.yml)
This project proposes a standard for database connection URIs and provides a
simple Perl implementation. This figure summarizes the definition syntax and
for database URIs (illustration adapted from
[RFC 3986](http://tools.ietf.org/html/rfc3986) --- STD 66, chapter 3):
db:engine://username:password@example.com:8042/widgets.db?tz=utc&charset=utf8#users
\/ \____/ \_______________/ \_________/ \__/ \________/ \/ \__/ \____/ \__/\____/
| | | | | | | | | | |
| | userinfo hostname port | key | key | |
| | \________________________________/ | | | |
| | | | value value |
| engine | | \_________________/ |
scheme | authority db name or path | |
name | \___________________________________________/ query fragment
| | |
| | hierarchical part
| |
| | db name or path query fragment
| __|_ ________|________ _____|____ ____|____
/\ / \ / \ / \/ \
db:engine:my_big_fat_database?encoding=big5#log.animals
Notes on this syntax:
* The Database URI *scheme* is `db`. Consequently, database URIs always start
with `db:`. This is the [URI scheme](http://en.wikipedia.org/wiki/URI_scheme)
that defines a database URI.
* Next comes the database *engine*. This part is a string naming the type of
database engine for the database. It must always be followed by a colon, `:`.
There is no formal list of supported engines, though certain implementations
may specify engine-specific semantics, such as a default port.
* The *authority* part is separated from the engine by a double slash, `//`,
and terminated by the next slash or end of the URI. It consists of an
optional user-information part, terminated by `@` (e.g.,
`username:password@`); a host address (e.g., domain name or IP address); and
an optional port number, preceded by a colon, `:`.
* The *path* part specifies the database name or path. It must be separated
from the authority, if the authority is present, by a single slash, `/`. If
the database name is a full path, it may start with an additional slash.
* The optional *query* part, separated by a question mark, `?`, contains
`key=value` pairs separated by a semicolon, `;`, or ampersand, `&`. These
parameters may be used to configure a database connection with parameters not
directly supported by the rest of the URI format.
* The optional *fragment* part, separted by a hash mark, `#`, contains
additional context information, such as a table or view name.
Here are some database URIs without an authority part, which is typical for
non-server engines such as [SQLite](http://sqlite.org/), where the path part
is a relative or absolute file name:
* `db:sqlite:`
* `db:sqlite:foo.db`
* `db:sqlite:../foo.db`
* `db:sqlite:/var/db/foo.sqlite`
Other engines may use a database name rather than a file name:
* `db:ingres:mydb`
* `db:postgresql:template1`
When a URI includes an authority part, it must be preceded by a double slash:
* `db:postgresql://example.com/`
* `db:mysql://root@localhost/`
* `db:pg://postgres:secr3t@example.net`
Formally, the authority part requires a host name, but some implementations,
inspired by the [file scheme](http://en.wikipedia.org/wiki/File_URI_scheme),
might allow an empty host to imply localhost.
* `db:mysql:/root@`
* `db:postgres://postgres:secr3t@`
* `db:sqlite:///`
The path part contians the database name, separated from the authority by a
single slash:
* `db:postgresql://example.com/template1`
* `db:mongodb://localhost:27017/myDatabase`
* `db:oracle://scott:tiger@foo.com/scott`
Some databases, such as Firebird, take both a host name and a file path. Just
put the relative or absolute path after that slash, as appropriate:
* `db:firebird://localhost/test.gdb` - Relative
* `db:firebird://localhost/../test.gdb` - Relative
* `db:firebird://localhost/C:/temp/test.gdb` - Absolute
* `db:firebird://localhost/%2Ftmp/test.gdb` - Absolute
Note the percent-encoded slash in the last example. Formally, an absolute path
may not start with a slash, so we use its percent-encoded representation here.
In practice, implementations may recognize a leading slash, anyway:
* `db:firebird://localhost//tmp/test.gdb`
Any URI format may optionally have a query part containing key/value pairs:
* `db:sqlite:foo.db?foreign_keys=ON;journal_mode=WAL`
* `db:pg://localhost:5433/postgres?client_encoding=utf8;connect_timeout=10`
URIs may also have a fragment that names a specific database object. Since
database URIs will generally be used for connecting, this part may be ignored.
* `db:sqlite:my.db#users`
* `db:pg://localhost/postgres#pg_catalog.pg_class`.
### URI Compliance ###
Formally, a database URI as defined here is an opaque URI starting with `db:`
followed by an embedded server-style URI. For example, this database URI:
db:pg://localhost/mydb
Is formally the URI `pg://localhost/mydb` embedded in an opaque `db:` URI. It
adheres to this formal definition because the scheme part of a URI is not
allowed to contain a sub-scheme (or subprotocol, in the
[JDBC parlance](http://docs.oracle.com/cd/B14117_01/java.101/b10979/urls.htm#BEIJFHHB)).
It is therefore a legal URI embedded in a second legal URI.
Informally, it's simpler to think of a database URI as a single URI starting
with the combination of the scheme and the engine, e.g., `db:pg`.
Some may recognize URIs as database URIs in the absence of the `db:` scheme,
provided their schemes correspond to widely-recognized database engines, such
as `postgresql`, `mysql`, `sqlite`, `mssql`, and `oracle`. These are not
formally recognized as standard schemes, though they may be recognized as
standard engines by the `db:` scheme specification.
### Inspiration ###
The format here is inspired by a lot of prior art.
* [JDBC URIs](http://docs.oracle.com/javase/6/docs/technotes/guides/jdbc/getstart/connection.html#997649)
set the precedent for an opaque URI with a second, embedded URI, as
[discussed here](https://groups.google.com/forum/#!topic/comp.lang.java.programmer/twkIYNaDS64).
* A number of database URI formats set the standard for `engine://authority/dbname`, including:
* [PostgreSQL libpq URIs](http://www.postgresql.org/docs/9.3/static/libpq-connect.html#LIBPQ-CONNSTRING)
* [SQLAlchemy URLs](http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html#database-urls)
* [Stackato database URLs](http://docs.stackato.com/3.0/user/services/data-services.html#database-url)
* [Django database URLs](https://github.com/kennethreitz/dj-database-url)
* [Rails database URLs](https://github.com/glenngillen/rails-database-url)
* [Ruby Pg URL](https://bitbucket.org/eradman/ruby-pg-url)
Author
------
[David E. Wheeler](http://theory.so/)
Contributers
------------
* [Brian T. Wightman](https://github.com/MidLifeXis)
|