URI-db-0.22000755001751000177 014603652634 12436 5ustar00runnerdocker000000000000URI-db-0.22/Build.PL000444001751000177 311514603652634 14067 0ustar00runnerdocker000000000000use strict; use warnings; use Module::Build; my $class = Module::Build->subclass( class => 'My::Builder', code => q{ sub ACTION_tarball_name { print shift->dist_dir . ".tar.gz\n" } sub ACTION_latest_changes { my $self = shift; (my $dv = $self->dist_version) =~ s/^v//; open my $in, '<:raw', 'Changes' or die "Cannot open Changes: $!\n"; open my $out, '>:raw', 'latest_changes.md' or die "Cannot open latest_changes.md: $!\n"; while (<$in>) { last if /^\Q$dv\E\b/ } print {$out} "Changes for v$dv\n"; while (<$in>) { last if /^\s*$/; chomp; if (s/^\s+-/- /) { print {$out} "\n"; } else { s/^\s+/ /; } print {$out} $_; } $self->add_to_cleanup('latest_changes.md'); } }, ); $class->new( module_name => 'URI::db', license => 'perl', configure_requires => { 'Module::Build' => '0.30', }, build_requires => { 'Module::Build' => '0.30', 'Test::More' => '0.88', }, requires => { 'perl' => 5.008001, 'URI' => '1.40', 'URI::Nested' => '0.10', }, meta_merge => { resources => { homepage => 'https://search.cpan.org/dist/URI-db/', bugtracker => 'https://github.com/theory/uri-db/issues/', repository => 'https://github.com/theory/uri-db/', } }, )->create_build_script; URI-db-0.22/Changes000444001751000177 732014603652634 14070 0ustar00runnerdocker000000000000Revision history for Perl extension URI::db. 0.22 2024-04-05T01:38:17Z - Changed Oracle database DBI parameter generation as follows: - If there is not a hostname or port, just use the raw SID or service name as the database name: `dbi:Oracle:$name`. This is way 1 in the DBD::Oracle documentation - If there is a hostname or port, use the EZCONNECT syntax. This is way 3 in the DBD::Oracle documentation. Use of a port without a host name may not be valid, but it seems most prudent to build an EZCONNECT that includes the port in this context and to let Oracle or DBD::Oracle reject it if appropriate. Thanks again to @vectro for the and diligence, testing, and patience with this issue (#22). 0.21 2023-05-09T22:18:52Z - Changed Oracle database DBI parameter name from `sid` to `service_name`. Thanks to @vectro for the report (#22). 0.20 2022-06-20T17:48:44Z - Added URI::cockroach and URI::yugabyte. 0.19 2018-07-19T15:15:04Z - Added URI::snowflake. 0.18 2017-11-03T15:01:43Z - Added URI::redshift to support db:redshift: URIs, thanks to a pull request from Steve Caldwell (PR #12). - Added URI::exasol, thanks to Johan Wärlander. 0.17 2016-02-03T18:35:33Z - Added URI::_ado, which subclasses URI::_odbc to provide a `dbi_dsn()` that returns a DSN using DBD::ADO. NOTE: This class is experimental, since I was unable to figure out the best default values for the connection string -- there are so many options! Feedback and recommendations wanted (Issue #11). - The `dbi_dsn` method of URI::mssql now supports a single argument to specify the DBI driver for which to return a DSN. Pass in "sybase" or "ado" (experimental) to get a DSN for either of those drivers, instead. Based on work by Dan Muey. 0.16 2015-09-22T00:17:07Z - Added new abstract class, URI::_odbc, for URIs that use ODBC in `dbi_dsn`. - The `dbi_dsn` method of URI::mssql now returns an ODBC DSN instead of DBD::Sybase, since the latter would require Sybase to build. - URI::sqlserver now inherits from URI::mssql rather than the other way around. - Fixed a bug where a URI with three slashes but no authority part after the first two would incorrectly think the databse name should be an absolute path. That is, in "db:sqlite:///foo.db", the `dbname` value is "foo.db", not "/foo.db". Thanks to Dan Book for the report (issue #8). 0.15 2014-09-04T00:29:46Z - Added the `canonical_engine` accessor, which returns the canonical engine name. - Added `the canonical` method, which will replace the engine name with its canonical value if it's not already canonical. 0.14 2014-09-03T00:28:37Z - The `dbi_dsn` method of URI::vertica now returns an ODBC DSN instead of DBD::Pg, since the latter apparently does not work with Verica. - Added a note to the `dbi_dsn` documentation that query params are included in the returned value. 0.13 2014-08-09T22:48:53Z - Added URI::postgresxc and URI::pgxc, which simply inherit from URI::pg. - Added URI::ldapdb, which represents LDAP databases. Patch from Brian T. Wightman. 0.12 2014-01-10T17:23:35Z - Eliminated "v-string in use/require non-portable" warning on older Perls. 0.11 2014-01-03T20:01:01Z - Fixed URI::oracle to properly generate a DBI DSN with no host name or port. - The `dbi_dsn()` method in URI::sqlserver (and its subclasses) now generates a DSN using DBD::Sybase, rather than DBD::ODBC. 0.10 2013-12-20T00:16:30Z - Initial version. URI-db-0.22/MANIFEST000444001751000177 173614603652634 13733 0ustar00runnerdocker000000000000Build.PL Changes lib/URI/_ado.pm lib/URI/_db.pm lib/URI/_odbc.pm lib/URI/cassandra.pm lib/URI/cockroach.pm lib/URI/cockroachdb.pm lib/URI/couch.pm lib/URI/couchdb.pm lib/URI/cubrid.pm lib/URI/db.pm lib/URI/db2.pm lib/URI/derby.pm lib/URI/exasol.pm lib/URI/firebird.pm lib/URI/hive.pm lib/URI/impala.pm lib/URI/informix.pm lib/URI/ingres.pm lib/URI/interbase.pm lib/URI/ldapdb.pm lib/URI/maria.pm lib/URI/mariadb.pm lib/URI/max.pm lib/URI/maxdb.pm lib/URI/monet.pm lib/URI/monetdb.pm lib/URI/mongo.pm lib/URI/mongodb.pm lib/URI/mssql.pm lib/URI/mysql.pm lib/URI/oracle.pm lib/URI/pg.pm lib/URI/pgsql.pm lib/URI/pgxc.pm lib/URI/postgres.pm lib/URI/postgresql.pm lib/URI/postgresxc.pm lib/URI/redshift.pm lib/URI/snowflake.pm lib/URI/sqlite.pm lib/URI/sqlite3.pm lib/URI/sqlserver.pm lib/URI/sybase.pm lib/URI/teradata.pm lib/URI/unify.pm lib/URI/vertica.pm lib/URI/yugabyte.pm lib/URI/yugabytedb.pm MANIFEST This list of files README README.md t/db.t t/dbi.t t/engines.t META.yml META.json URI-db-0.22/META.json000444001751000177 1322514603652634 14237 0ustar00runnerdocker000000000000{ "abstract" : "Database URIs", "author" : [ "David E. Wheeler " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4234", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "URI-db", "prereqs" : { "build" : { "requires" : { "Module::Build" : "0.30", "Test::More" : "0.88" } }, "configure" : { "requires" : { "Module::Build" : "0.30" } }, "runtime" : { "requires" : { "URI" : "1.40", "URI::Nested" : "0.10", "perl" : "5.008001" } } }, "provides" : { "URI::cassandra" : { "file" : "lib/URI/cassandra.pm", "version" : "0.22" }, "URI::cockroach" : { "file" : "lib/URI/cockroach.pm", "version" : "0.22" }, "URI::cockroachdb" : { "file" : "lib/URI/cockroachdb.pm", "version" : "0.22" }, "URI::couch" : { "file" : "lib/URI/couch.pm", "version" : "0.22" }, "URI::couchdb" : { "file" : "lib/URI/couchdb.pm", "version" : "0.22" }, "URI::cubrid" : { "file" : "lib/URI/cubrid.pm", "version" : "0.22" }, "URI::db" : { "file" : "lib/URI/db.pm", "version" : "0.22" }, "URI::db2" : { "file" : "lib/URI/db2.pm", "version" : "0.22" }, "URI::derby" : { "file" : "lib/URI/derby.pm", "version" : "0.22" }, "URI::exasol" : { "file" : "lib/URI/exasol.pm", "version" : "0.22" }, "URI::firebird" : { "file" : "lib/URI/firebird.pm", "version" : "0.22" }, "URI::hive" : { "file" : "lib/URI/hive.pm", "version" : "0.22" }, "URI::impala" : { "file" : "lib/URI/impala.pm", "version" : "0.22" }, "URI::informix" : { "file" : "lib/URI/informix.pm", "version" : "0.22" }, "URI::ingres" : { "file" : "lib/URI/ingres.pm", "version" : "0.22" }, "URI::interbase" : { "file" : "lib/URI/interbase.pm", "version" : "0.22" }, "URI::ldapdb" : { "file" : "lib/URI/ldapdb.pm", "version" : "0.22" }, "URI::maria" : { "file" : "lib/URI/maria.pm", "version" : "0.22" }, "URI::mariadb" : { "file" : "lib/URI/mariadb.pm", "version" : "0.22" }, "URI::max" : { "file" : "lib/URI/max.pm", "version" : "0.22" }, "URI::maxdb" : { "file" : "lib/URI/maxdb.pm", "version" : "0.22" }, "URI::monet" : { "file" : "lib/URI/monet.pm", "version" : "0.22" }, "URI::monetdb" : { "file" : "lib/URI/monetdb.pm", "version" : "0.22" }, "URI::mongo" : { "file" : "lib/URI/mongo.pm", "version" : "0.22" }, "URI::mongodb" : { "file" : "lib/URI/mongodb.pm", "version" : "0.22" }, "URI::mssql" : { "file" : "lib/URI/mssql.pm", "version" : "0.22" }, "URI::mysql" : { "file" : "lib/URI/mysql.pm", "version" : "0.22" }, "URI::oracle" : { "file" : "lib/URI/oracle.pm", "version" : "0.22" }, "URI::pg" : { "file" : "lib/URI/pg.pm", "version" : "0.22" }, "URI::pgsql" : { "file" : "lib/URI/pgsql.pm", "version" : "0.22" }, "URI::pgxc" : { "file" : "lib/URI/pgxc.pm", "version" : "0.22" }, "URI::postgres" : { "file" : "lib/URI/postgres.pm", "version" : "0.22" }, "URI::postgresql" : { "file" : "lib/URI/postgresql.pm", "version" : "0.22" }, "URI::postgresxc" : { "file" : "lib/URI/postgresxc.pm", "version" : "0.22" }, "URI::redshift" : { "file" : "lib/URI/redshift.pm", "version" : "0.22" }, "URI::snowflake" : { "file" : "lib/URI/snowflake.pm", "version" : "0.22" }, "URI::sqlite" : { "file" : "lib/URI/sqlite.pm", "version" : "0.22" }, "URI::sqlite3" : { "file" : "lib/URI/sqlite3.pm", "version" : "0.22" }, "URI::sqlserver" : { "file" : "lib/URI/sqlserver.pm", "version" : "0.22" }, "URI::sybase" : { "file" : "lib/URI/sybase.pm", "version" : "0.22" }, "URI::teradata" : { "file" : "lib/URI/teradata.pm", "version" : "0.22" }, "URI::unify" : { "file" : "lib/URI/unify.pm", "version" : "0.22" }, "URI::vertica" : { "file" : "lib/URI/vertica.pm", "version" : "0.22" }, "URI::yugabyte" : { "file" : "lib/URI/yugabyte.pm", "version" : "0.22" }, "URI::yugabytedb" : { "file" : "lib/URI/yugabytedb.pm", "version" : "0.22" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/theory/uri-db/issues/" }, "homepage" : "https://search.cpan.org/dist/URI-db/", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "https://github.com/theory/uri-db/" } }, "version" : "0.22", "x_serialization_backend" : "JSON::PP version 4.16" } URI-db-0.22/META.yml000444001751000177 707314603652634 14053 0ustar00runnerdocker000000000000--- abstract: 'Database URIs' author: - 'David E. Wheeler ' build_requires: Module::Build: '0.30' Test::More: '0.88' configure_requires: Module::Build: '0.30' dynamic_config: 1 generated_by: 'Module::Build version 0.4234, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: URI-db provides: URI::cassandra: file: lib/URI/cassandra.pm version: '0.22' URI::cockroach: file: lib/URI/cockroach.pm version: '0.22' URI::cockroachdb: file: lib/URI/cockroachdb.pm version: '0.22' URI::couch: file: lib/URI/couch.pm version: '0.22' URI::couchdb: file: lib/URI/couchdb.pm version: '0.22' URI::cubrid: file: lib/URI/cubrid.pm version: '0.22' URI::db: file: lib/URI/db.pm version: '0.22' URI::db2: file: lib/URI/db2.pm version: '0.22' URI::derby: file: lib/URI/derby.pm version: '0.22' URI::exasol: file: lib/URI/exasol.pm version: '0.22' URI::firebird: file: lib/URI/firebird.pm version: '0.22' URI::hive: file: lib/URI/hive.pm version: '0.22' URI::impala: file: lib/URI/impala.pm version: '0.22' URI::informix: file: lib/URI/informix.pm version: '0.22' URI::ingres: file: lib/URI/ingres.pm version: '0.22' URI::interbase: file: lib/URI/interbase.pm version: '0.22' URI::ldapdb: file: lib/URI/ldapdb.pm version: '0.22' URI::maria: file: lib/URI/maria.pm version: '0.22' URI::mariadb: file: lib/URI/mariadb.pm version: '0.22' URI::max: file: lib/URI/max.pm version: '0.22' URI::maxdb: file: lib/URI/maxdb.pm version: '0.22' URI::monet: file: lib/URI/monet.pm version: '0.22' URI::monetdb: file: lib/URI/monetdb.pm version: '0.22' URI::mongo: file: lib/URI/mongo.pm version: '0.22' URI::mongodb: file: lib/URI/mongodb.pm version: '0.22' URI::mssql: file: lib/URI/mssql.pm version: '0.22' URI::mysql: file: lib/URI/mysql.pm version: '0.22' URI::oracle: file: lib/URI/oracle.pm version: '0.22' URI::pg: file: lib/URI/pg.pm version: '0.22' URI::pgsql: file: lib/URI/pgsql.pm version: '0.22' URI::pgxc: file: lib/URI/pgxc.pm version: '0.22' URI::postgres: file: lib/URI/postgres.pm version: '0.22' URI::postgresql: file: lib/URI/postgresql.pm version: '0.22' URI::postgresxc: file: lib/URI/postgresxc.pm version: '0.22' URI::redshift: file: lib/URI/redshift.pm version: '0.22' URI::snowflake: file: lib/URI/snowflake.pm version: '0.22' URI::sqlite: file: lib/URI/sqlite.pm version: '0.22' URI::sqlite3: file: lib/URI/sqlite3.pm version: '0.22' URI::sqlserver: file: lib/URI/sqlserver.pm version: '0.22' URI::sybase: file: lib/URI/sybase.pm version: '0.22' URI::teradata: file: lib/URI/teradata.pm version: '0.22' URI::unify: file: lib/URI/unify.pm version: '0.22' URI::vertica: file: lib/URI/vertica.pm version: '0.22' URI::yugabyte: file: lib/URI/yugabyte.pm version: '0.22' URI::yugabytedb: file: lib/URI/yugabytedb.pm version: '0.22' requires: URI: '1.40' URI::Nested: '0.10' perl: '5.008001' resources: bugtracker: https://github.com/theory/uri-db/issues/ homepage: https://search.cpan.org/dist/URI-db/ license: http://dev.perl.org/licenses/ repository: https://github.com/theory/uri-db/ version: '0.22' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' URI-db-0.22/README000444001751000177 227514603652634 13461 0ustar00runnerdocker000000000000URI/db version 0.22 =================== This library implements a Perl interface for a proposed standard for database connection URIs. The basic formats are: * `db:engine://username:password@example.com:8042/over/there/widget.db?type=animal&name=narwhal` * `db:engine:my_big_fat_database?subject=Topic` This library also includes an interface to convert database URIs to [DBI](https://metacpan.org/module/DBI) DSNs. For additional information on the format, see `README.md`. **Warning:** This is an alpha release. I will do my best to preserve functionality going forward, especially as [Sqitch](http://sqitch.org/) uses this module. However, as the database URI specification moves forward, changes *may* require backwards-incompatible changes. Caveat Hackor. Installation ------------ To install this module, type the following: perl Build.PL ./Build ./Build test ./Build install Dependencies ------------ URI::db requires the following modules: * URI * URI::Nested Copyright and Licence --------------------- Copyright (c) 2013-2023 David E. Wheeler. Some Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. URI-db-0.22/README.md000444001751000177 1653214603652634 14101 0ustar00runnerdocker000000000000Database URI ============ [![CPAN version](https://badge.fury.io/pl/URI-db.svg)](http://badge.fury.io/pl/URI-db) [![Build Status](https://github.com/libwww-perl/URI-db/actions/workflows/ci.yml/badge.svg)](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) URI-db-0.22/lib000755001751000177 014603652634 13204 5ustar00runnerdocker000000000000URI-db-0.22/lib/URI000755001751000177 014603652634 13643 5ustar00runnerdocker000000000000URI-db-0.22/lib/URI/_ado.pm000444001751000177 13514603652634 15217 0ustar00runnerdocker000000000000package URI::_ado; use base 'URI::_odbc'; our $VERSION = '0.22'; sub dbi_driver { 'ADO' } URI-db-0.22/lib/URI/_db.pm000444001751000177 364714603652634 15074 0ustar00runnerdocker000000000000package URI::_db; use strict; use 5.008001; use base 'URI::_login'; our $VERSION = '0.22'; sub uri { shift } sub _no_scheme_ok { 0 } sub canonical_engine { shift->scheme } sub canonical { my $canon = shift->SUPER::canonical; my $engine = $canon->canonical_engine; return $canon if $canon->scheme eq $engine; $canon = $canon->clone; $canon->scheme($engine); return $canon; } sub engine { my $self = shift; return $self->scheme unless @_; my $old = $self->scheme(@_); bless $self => 'URI::_db' unless $self->isa('URI::_db'); return $old; } sub has_recognized_engine { ref $_[0] ne __PACKAGE__; } sub dbname { my $self = shift; my $is_full = $self->opaque =~ m{^//(?://|/?(?!/))}; return $self->path($is_full && defined $_[0] ? "/$_[0]" : shift) if @_; my @segs = $self->path_segments or return; shift @segs if $is_full; join '/' => @segs; } sub query_params { my $self = shift; require URI::QueryParam; return map { my $f = $_; map { $f => $_ } grep { defined } $self->query_param($f) } $self->query_param; } sub _dbi_param_map { my $self = shift; return ( [ host => scalar $self->host ], [ port => scalar $self->_port ], [ dbname => scalar $self->dbname ], ); } sub dbi_params { my $self = shift; return ( ( map { @{ $_ } } grep { defined $_->[1] && length $_->[1] } $self->_dbi_param_map ), $self->query_params, ); } sub dbi_driver { return undef } sub _dsn_params { my $self = shift; my @params = $self->dbi_params; my @kvpairs; while (@params) { push @kvpairs => join '=', shift @params, shift @params; } return join ';' => @kvpairs; } sub dbi_dsn { my $self = shift; my $driver = $self->dbi_driver or return $self->_dsn_params; return join ':' => 'dbi', $driver, $self->_dsn_params; } 1; URI-db-0.22/lib/URI/_odbc.pm000444001751000177 76014603652634 15367 0ustar00runnerdocker000000000000package URI::_odbc; use base 'URI::_db'; our $VERSION = '0.22'; sub dbi_driver { 'ODBC' } sub _dbi_param_map { my $self = shift; my $host = $self->host; my $port = $self->_port; # Just return the DSN if no host or port. return [ DSN => scalar $self->dbname ] unless $host || $port; return ( [ Server => $host ], [ Port => $port || $self->default_port ], [ Database => scalar $self->dbname ], ); } 1; URI-db-0.22/lib/URI/cassandra.pm000444001751000177 14314603652634 16253 0ustar00runnerdocker000000000000package URI::cassandra; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 9160 } 1; URI-db-0.22/lib/URI/cockroach.pm000444001751000177 57414603652634 16260 0ustar00runnerdocker000000000000package URI::cockroach; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 26257 } sub dbi_driver { 'Pg' } sub canonical_engine { 'cockroach' } sub _dbi_param_map { my $self = shift; return ( [ host => scalar $self->host ], [ port => scalar $self->port ], # Always pass the port [ dbname => scalar $self->dbname ], ); } URI-db-0.22/lib/URI/cockroachdb.pm000444001751000177 11414603652634 16554 0ustar00runnerdocker000000000000package URI::cockroachdb; use base 'URI::cockroach'; our $VERSION = '0.22'; URI-db-0.22/lib/URI/couch.pm000444001751000177 11014603652634 15407 0ustar00runnerdocker000000000000package URI::couch; use base 'URI::couchdb'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/couchdb.pm000444001751000177 20414603652634 15721 0ustar00runnerdocker000000000000package URI::couchdb; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 5984 } sub canonical_engine { 'couchdb' } 1; URI-db-0.22/lib/URI/cubrid.pm000444001751000177 51314603652634 15565 0ustar00runnerdocker000000000000package URI::cubrid; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 33000 } sub dbi_driver { 'cubrid' } sub _dbi_param_map { my $self = shift; return ( [ host => scalar $self->host ], [ port => scalar $self->_port ], [ database => scalar $self->dbname ], ); } 1; URI-db-0.22/lib/URI/db.pm000444001751000177 2213114603652634 14742 0ustar00runnerdocker000000000000package URI::db; # db:engine:dbname # db:engine:/path/to/some.db # db:engine://dbname # db:engine:///path/to/some.db # db:engine:../relative.db # db:engine://../relative.db # db:engine://[netloc][:port][/dbname][?param1=value1&...] # db:engine://[user[:password]@][netloc][:port][/dbname][?param1=value1&...] use strict; use 5.008001; use base 'URI::Nested'; use URI::_db; our $VERSION = '0.22'; sub prefix { 'db' } sub nested_class { 'URI::_db' } 1; __END__ =head1 Name URI::db - Database URIs =head1 Synopsis use URI; my $db_uri = URI->new('db:pg://user@localhost'); my $pg_uri = URI->new('postgres://example.com/template1'); my $sl_uri = URI->new('sqlite:/var/db/widgets.db'); =head1 Description This class provides support for database URIs. They're inspired by L and L, though they're a bit more formal. The specification for their format is documented in L|https:/github.com/theory/db-uri/>. B This is an alpha release. I will do my best to preserve functionality going forward, especially as L uses this module. However, as the database URI specification moves forward, changes I require backwards-incompatible changes. Caveat Hackor. =head3 Format A database URI is made up of these parts: db:engine:[//[user[:password]@][host][:port]/][dbname][?params][#fragment] =over =item C The literal string C is the scheme that defines a database URI. Optional for well-known engines. =item C A string identifying the database engine. =item C The user name to use when connecting to the database. =item C The password to use when connecting to the database. =item C The host address to connect to. =item C The network port to connect to. =item C The name of the database. For some engines, this will be a file name, in which case it may be a complete or local path, as appropriate. =item C A URI-standard GET query string representing additional parameters to be passed to the engine. =item C Identifies a database part, such as a table or view. =back =head3 Examples Some examples: =over =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =item * C =back =head1 Interface The following differences exist compared to the C class interface: =head2 Class Method =head3 C Returns the default port for the engine. This is a class method value defined by each recognized URI engine. =head2 Constructors =head3 C my $uri = URI::db->new($string); my $uri = URI::db->new($string, $base); Always returns a URI::db object. C<$base> may be another URI object or string. Unlike in L's C, the scheme will always be applied to the URI if it does not already have one. =head2 Accessors =head3 C my $scheme = $uri->scheme; $uri->scheme( $new_scheme ); Gets or sets the scheme part of the URI. For C URIs, the scheme cannot be changed to any value other than "db" (or any case variation thereof). For non-C URIs, the scheme may be changed to any value, though the URI object may no longer be a database URI. =head3 C my $engine = $uri->engine; $uri->engine( $new_engine ); Gets or sets the engine part of the URI, which may be any valid URI scheme value, though recognized engines provide additional context, such as the C and a driver-specific C. If called with an argument, it updates the engine, possibly changing the class of the URI, and returns the old engine value. =head3 C my $canonical_engine = $uri->canonical_engine; Returns the canonical engine. A number of engine names are aliases for other engines. This method will return the non-aliased engine name. For example, the C engine will return the canonical engine C, the C returns the canonical engine C, and C returns the canonical engine C. =head3 C my $dbname = $uri->dbname; $uri->dbname( $new_dbname ); Gets or sets the name of the database. If called with an argument, the path will also be updated. =head3 C my $host = $uri->host; $uri->host( $new_host ); Gets or sets the host to connect to. =head3 C my $port = $uri->port; $uri->port( $new_port ); Gets or sets the port to connect to. =head3 C my $user = $uri->user; $uri->user( $new_user ); Gets or sets the user name. =head3 C my $password = $uri->password; $uri->password( $new_password ); Gets or sets the password. =head3 C Returns the underlying engine URI. For URIs starting with C, this will be the URI that follows. For database URIs without C, the URI itself will be returned. =head2 Instance Methods =head3 C my $has_recognized_engine = $uri->has_recognized_engine; Returns true if the engine is recognized by URI::db, and false if it is not. A recognized engine is simply one that inherits from C. =head3 C my @params = $uri->query_params; Returns a list of key/value pairs representing all query parameters. Parameters specified more than once will be returned more than once, so avoid assigning to a hash. If you want a hash, use L's C, where duplicate keys lead to an array of values for that key: use URI::QueryParam; my $params = $uri->query_form_hash; =head3 C if ( my $driver = $uri->dbi_driver ) { eval "require DBD::$driver" or die; } Returns a string representing the L driver name for the database engine, if one is known. Returns C if no driver is known. =head3 C DBI->connect( $uri->dbi_dsn, $uri->user, $uri->password ); Returns a L DSN appropriate for use in a call to C<< DBI->connect >>. The attributes will usually be pulled from the URI host name, port, and database name, as well as the query parameters. If no driver is known for the URI, the C part of the DSN will be omitted, in which case you can use the C<$DBI_DRIVER> environment variable to identify an appropriate driver. If the URI supports multiple drivers, pass the name of the one you want to C. Currently only URI::myssql supports alternate drivers, ADO, ODBC, or Sybase. Otherwise, each database URI does its best to create a valid DBI DSN. Some examples: | URI | DSN | |--------------------------------------+--------------------------------------------------| | db:pg:try | dbi:Pg:dbname=try | | db:mysql://localhost:33/foo | dbi:mysql:host=localhost;port=33;database=foo | | db:db2://localhost:33/foo | dbi:DB2:HOSTNAME=localhost;PORT=33;DATABASE=foo | | db:vertica:dbadmin | dbi:ODBC:DSN=dbadmin | | db:mssql://foo.com/pubs?Driver=MSSQL | dbi:ODBC:Host=foo.com;Database=pubs;Driver=MSSQL | =head3 C my @params = $uri->dbi_params; Returns a list of key/value pairs used as parameters in the L DSN, including query parameters. Parameters specified more than once will be returned more than once, so avoid assigning to a hash. =head3 C my $abs = $uri->abs( $base_uri ); For C URIs, simply returns the URI::db object itself. For Non-C URIs, the behavior is the same as for L including respect for C<$URI::ABS_ALLOW_RELATIVE_SCHEME>. =head3 C my $rel = $uri->rel( $base_uri ); For C URIs, simply returns the URI::db object itself. For Non-C URIs, the behavior is the same as for L. =head3 C my $canonical_uri = $uri->canonical; Returns a normalized version of the URI. This behavior is the same for other URIs, except that the engine will be replaced with the value of C if it is not already the canonical engine. =head1 Support This module is stored in an open L. Feel free to fork and contribute! Please file bug reports via L or by sending mail to L. =head1 Author David E. Wheeler =head1 Copyright and License Copyright (c) 2013-2023 David E. Wheeler. Some Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut URI-db-0.22/lib/URI/db2.pm000444001751000177 50514603652634 14765 0ustar00runnerdocker000000000000package URI::db2; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 50000 } sub dbi_driver { 'DB2' } sub _dbi_param_map { my $self = shift; return ( [ HOSTNAME => scalar $self->host ], [ PORT => scalar $self->_port ], [ DATABASE => scalar $self->dbname ], ); } 1; URI-db-0.22/lib/URI/derby.pm000444001751000177 13714603652634 15424 0ustar00runnerdocker000000000000package URI::derby; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 1527 } 1; URI-db-0.22/lib/URI/exasol.pm000444001751000177 67514603652634 15621 0ustar00runnerdocker000000000000package URI::exasol; use base 'URI::_odbc'; our $VERSION = '0.22'; sub default_port { 8563 } sub _dbi_param_map { my $self = shift; my $host = $self->host; my $port = $self->_port; # Just return the DSN if no host or port. return [ DSN => scalar $self->dbname ] unless $host || $port; return ( [ EXAHOST => $host ], [ EXAPORT => $port || $self->default_port ], ); } 1; URI-db-0.22/lib/URI/firebird.pm000444001751000177 20214603652634 16076 0ustar00runnerdocker000000000000package URI::firebird; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 3050 } sub dbi_driver { 'Firebird' } 1; URI-db-0.22/lib/URI/hive.pm000444001751000177 13714603652634 15252 0ustar00runnerdocker000000000000package URI::hive; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 10000 } 1; URI-db-0.22/lib/URI/impala.pm000444001751000177 14114603652634 15555 0ustar00runnerdocker000000000000package URI::impala; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 21000 } 1; URI-db-0.22/lib/URI/informix.pm000444001751000177 46414603652634 16155 0ustar00runnerdocker000000000000package URI::informix; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 1526 } sub dbi_driver { 'Informix' } sub _dbi_param_map { } sub dbi_dsn { my $self = shift; return join ':' => 'dbi', $self->dbi_driver, join ';' => $self->dbname, ($self->_dsn_params || ()); } 1; URI-db-0.22/lib/URI/ingres.pm000444001751000177 46014603652634 15605 0ustar00runnerdocker000000000000package URI::ingres; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 1524 } sub dbi_driver { 'Ingres' } sub _dbi_param_map { } sub dbi_dsn { my $self = shift; return join ':' => 'dbi', $self->dbi_driver, join ';' => $self->dbname, ($self->_dsn_params || ()); } 1; URI-db-0.22/lib/URI/interbase.pm000444001751000177 20414603652634 16266 0ustar00runnerdocker000000000000package URI::interbase; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 3050 } sub dbi_driver { 'InterBase' } 1; URI-db-0.22/lib/URI/ldapdb.pm000444001751000177 111314603652634 15560 0ustar00runnerdocker000000000000package URI::ldapdb; use base 'URI::_db'; our $VERSION = '0.22'; sub dbi_driver { 'LDAP' } sub _dbi_param_map { my $self = shift; return ( [ dbname => scalar $self->dbname ], ); } sub dbi_dsn { my $self = shift; return join ':' => 'dbi', $self->dbi_driver, $self->dbname } 1; =head1 Name URI::ldapdb - LDAP database URI =head1 Description Linkage between URI::db and DBD::LDAP. I would have used L, but that was already taken for a module with slightly different intentions. =head1 Contributed By Brian T. Wightman =cut URI-db-0.22/lib/URI/maria.pm000444001751000177 10614603652634 15404 0ustar00runnerdocker000000000000package URI::maria; use base 'URI::mysql'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/mariadb.pm000444001751000177 11014603652634 15705 0ustar00runnerdocker000000000000package URI::mariadb; use base 'URI::mysql'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/max.pm000444001751000177 10414603652634 15076 0ustar00runnerdocker000000000000package URI::max; use base 'URI::maxdb'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/maxdb.pm000444001751000177 54614603652634 15416 0ustar00runnerdocker000000000000package URI::maxdb; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 7673 } sub dbi_driver { 'MaxDB' } sub canonical_engine { 'maxdb' } sub _dbi_param_map { } sub dbi_dsn { my $self = shift; return join ( ':' => 'dbi', $self->dbi_driver, grep { defined } $self->host, $self->_port, ) . $self->path_query; } 1; URI-db-0.22/lib/URI/monet.pm000444001751000177 11014603652634 15430 0ustar00runnerdocker000000000000package URI::monet; use base 'URI::monetdb'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/monetdb.pm000444001751000177 55114603652634 15747 0ustar00runnerdocker000000000000package URI::monetdb; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 50000 } sub dbi_driver { 'monetdb' } sub canonical_engine { 'monetdb' } sub _dbi_param_map { my $self = shift; # DBD::monetdb had no database name support. return ( [ host => scalar $self->host ], [ port => scalar $self->_port ], ); } 1; URI-db-0.22/lib/URI/mongo.pm000444001751000177 11014603652634 15425 0ustar00runnerdocker000000000000package URI::mongo; use base 'URI::mongodb'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/mongodb.pm000444001751000177 20514603652634 15740 0ustar00runnerdocker000000000000package URI::mongodb; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 27017 } sub canonical_engine { 'mongodb' } 1; URI-db-0.22/lib/URI/mssql.pm000444001751000177 245714603652634 15505 0ustar00runnerdocker000000000000package URI::mssql; use base 'URI::_odbc'; our $VERSION = '0.22'; sub default_port { 1433 } sub canonical_engine { 'mssql' } sub dbi_dsn { my $self = shift; my $driver = shift or return $self->SUPER::dbi_dsn; my $lcd = lc $driver; return $self->SUPER::dbi_dsn if $lcd eq 'odbc'; my $class = $lcd eq 'ado' ? 'URI::_ado' : $lcd eq 'sybase' ? 'URI::sybase' : die "Unknown driver: $driver\n"; eval "require $class" or die; # Make a copy blessed into the alternate class to get its DSN. my $alt = bless \"$self" => $class; return $alt->dbi_dsn; } 1; =head1 Name URI::mssql - Microsoft SQL Server database URI =head1 Description L format for Microsoft SQL Server. =head1 Interface The following differences exist compared to the C interface: =head2 Instance Methods =head3 C my $dsn = $uri->dbi_dsn; $dsn = $uri->dbi_dsn($driver); Extends the implementation of C to support a driver argument. By default, C returns a DSN appropriate for use with L. Pass "sybase" or "ado" to instead get a DSN appropriate to L or L, respectively. Note that DBD::ADO value is experimental and subject to change. L. =cut URI-db-0.22/lib/URI/mysql.pm000444001751000177 55114603652634 15464 0ustar00runnerdocker000000000000package URI::mysql; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 3306 } sub dbi_driver { 'mysql' } sub canonical_engine { 'mysql' } sub _dbi_param_map { my $self = shift; return ( [ host => scalar $self->host ], [ port => scalar $self->_port ], [ database => scalar $self->dbname ], ); } 1; URI-db-0.22/lib/URI/oracle.pm000444001751000177 107314603652634 15604 0ustar00runnerdocker000000000000package URI::oracle; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 1521 } sub dbi_driver { 'Oracle' } sub _dsn_params { my $self = shift; my $name = $self->dbname || ''; my $dsn = $self->host; if (my $p = $self->_port) { $dsn .= ":$p"; } return $name unless $dsn; $dsn .= "/$name"; if (my @p = $self->query_params) { my @kvpairs; while (@p) { push @kvpairs => join '=', shift @p, shift @p; } $dsn .= '?' . join '&' => @kvpairs; } return "//$dsn"; } 1; URI-db-0.22/lib/URI/pg.pm000444001751000177 22414603652634 14722 0ustar00runnerdocker000000000000package URI::pg; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 5432 } sub dbi_driver { 'Pg' } sub canonical_engine { 'pg' } 1; URI-db-0.22/lib/URI/pgsql.pm000444001751000177 10014603652634 15433 0ustar00runnerdocker000000000000package URI::pgsql; use base 'URI::pg'; our $VERSION = '0.22'; URI-db-0.22/lib/URI/pgxc.pm000444001751000177 10214603652634 15250 0ustar00runnerdocker000000000000package URI::pgxc; use base 'URI::pg'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/postgres.pm000444001751000177 10314603652634 16156 0ustar00runnerdocker000000000000package URI::postgres; use base 'URI::pg'; our $VERSION = '0.22'; URI-db-0.22/lib/URI/postgresql.pm000444001751000177 11014603652634 16511 0ustar00runnerdocker000000000000package URI::postgresql; use base 'URI::pg'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/postgresxc.pm000444001751000177 11014603652634 16507 0ustar00runnerdocker000000000000package URI::postgresxc; use base 'URI::pg'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/redshift.pm000444001751000177 10614603652634 16123 0ustar00runnerdocker000000000000package URI::redshift; use base 'URI::pg'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/snowflake.pm000444001751000177 14414603652634 16306 0ustar00runnerdocker000000000000package URI::snowflake; use base 'URI::_odbc'; our $VERSION = '0.22'; sub default_port { 443 } 1; URI-db-0.22/lib/URI/sqlite.pm000444001751000177 31214603652634 15613 0ustar00runnerdocker000000000000package URI::sqlite; use base 'URI::_db'; our $VERSION = '0.22'; sub dbi_driver { 'SQLite' } sub canonical_engine { 'sqlite' } sub _dbi_param_map { return [ dbname => scalar shift->dbname ]; } 1; URI-db-0.22/lib/URI/sqlite3.pm000444001751000177 11114603652634 15673 0ustar00runnerdocker000000000000package URI::sqlite3; use base 'URI::sqlite'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/sqlserver.pm000444001751000177 11214603652634 16336 0ustar00runnerdocker000000000000package URI::sqlserver; use base 'URI::mssql'; our $VERSION = '0.22'; 1; URI-db-0.22/lib/URI/sybase.pm000444001751000177 17614603652634 15610 0ustar00runnerdocker000000000000package URI::sybase; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 2638 } sub dbi_driver { 'Sybase' } 1; URI-db-0.22/lib/URI/teradata.pm000444001751000177 66114603652634 16106 0ustar00runnerdocker000000000000package URI::teradata; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 1025 } sub dbi_driver { 'Teradata' } sub _dbi_param_map { return [ DATABASE => scalar shift->dbname ]; } sub dbi_dsn { my $self = shift; return join ';' => ( join ( ':' => 'dbi', $self->dbi_driver, grep { defined } $self->host, $self->_port ), $self->_dsn_params || () ); } 1; URI-db-0.22/lib/URI/unify.pm000444001751000177 45714603652634 15456 0ustar00runnerdocker000000000000package URI::unify; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 27117 } sub dbi_driver { 'Unify' } sub _dbi_param_map { } sub dbi_dsn { my $self = shift; return join ':' => 'dbi', $self->dbi_driver, join ';' => $self->dbname, ($self->_dsn_params || ()); } 1; URI-db-0.22/lib/URI/vertica.pm000444001751000177 14314603652634 15751 0ustar00runnerdocker000000000000package URI::vertica; use base 'URI::_odbc'; our $VERSION = '0.22'; sub default_port { 5433 } 1; URI-db-0.22/lib/URI/yugabyte.pm000444001751000177 56714603652634 16157 0ustar00runnerdocker000000000000package URI::yugabyte; use base 'URI::_db'; our $VERSION = '0.22'; sub default_port { 5433 } sub dbi_driver { 'Pg' } sub canonical_engine { 'pg' } sub _dbi_param_map { my $self = shift; return ( [ host => scalar $self->host ], [ port => scalar $self->port ], # Always pass the port [ dbname => scalar $self->dbname ], ); } 1; URI-db-0.22/lib/URI/yugabytedb.pm000444001751000177 11614603652634 16453 0ustar00runnerdocker000000000000package URI::yugabytedb; use base 'URI::yugabyte'; our $VERSION = '0.22'; 1; URI-db-0.22/t000755001751000177 014603652634 12701 5ustar00runnerdocker000000000000URI-db-0.22/t/db.t000444001751000177 2220714603652634 13633 0ustar00runnerdocker000000000000#!/usr/bin/perl -w use strict; use Test::More; use utf8; use URI; use URI::QueryParam; isa_ok my $uri = URI->new('db:'), 'URI::db', 'Opaque DB URI'; is $uri->engine, undef, 'DB URI with no engine should have undef engine'; is $uri->scheme, 'db', 'DB URI with no engine should have scheme "db"'; ok !$uri->has_recognized_engine, 'Engineless should not have recognized engine'; # Try changing the engine. is $uri->engine('foo'), undef, 'Assign engine'; is $uri->engine, 'foo', 'Engine should now be "foo"'; is $uri->as_string, 'db:foo:', 'Engine should be included in stringified URI'; isa_ok $uri, 'URI::db', 'Updated engine URI'; isa_ok $uri->nested_uri, 'URI::_db'; # Try changing to a known engine. is $uri->engine('pg'), 'foo', 'Assign engine'; is $uri->engine, 'pg', 'Engine should now be "pg"'; is $uri->as_string, 'db:pg:', 'Engine should be included in stringified URI'; isa_ok $uri, 'URI::db', 'Pg engine URI'; isa_ok $uri->nested_uri, 'URI::pg'; # Try setting to an undefined engine. is $uri->engine(undef), 'pg', 'Assign undef engine'; is $uri->engine, 'pg', 'DB URI should not have had its engine undefined'; is $uri->scheme, 'db', 'DB URI with undef engine should have scheme "db"'; isa_ok $uri, 'URI::db', 'Undef engine URI'; isa_ok $uri->nested_uri, 'URI::_db'; # Try changing the scheme. is $uri->scheme('Db'), 'db', 'Change scheme to "Db"'; isa_ok $uri, 'URI::db'; is $uri->scheme, 'db', 'New scheme should still be "db"'; is $uri->as_string, 'Db:pg:', 'Should stringify with the new scheme'; # Change the scheme to something other than db. eval { $uri->scheme('foo') }; ok my $err = $@, 'Should get error changing to non-DB scheme'; like $err, qr/Cannot change URI::db scheme/, 'Should be the proper error'; # Now use a non-db-qalified URI. isa_ok $uri = URI->new('pg:'), 'URI::pg', 'Opaque Pg URI'; is $uri->engine, 'pg', 'Pg URI engine should be "pg"'; is $uri->scheme, 'pg', 'Pg URI scheme should be "pg"'; ok $uri->has_recognized_engine, 'Pg URI should be a recognized engine'; # Change it to another engine. is $uri->engine('vertica'), 'pg', 'Change the engine to "vertica"'; isa_ok $uri, 'URI::vertica'; is $uri->engine, 'vertica', 'Vertica URI engine should be "vertica"'; is $uri->scheme, 'vertica', 'Vertica URI scheme should be "vertica"'; ok $uri->has_recognized_engine, 'Vertica URI should be a recognized engine'; # Try using an unknown engine. is $uri->engine('foo'), 'vertica', 'Change the engine to "foo"'; isa_ok $uri, 'URI::_db'; is $uri->scheme, 'foo', 'Foo URI scheme should be "foo"'; is $uri->engine, 'foo', 'Foo URI engine should be "foo"'; ok !$uri->has_recognized_engine, 'Foo URI should not be a recognized engine'; # Try using an undefined engine. is $uri->engine(undef), 'foo', 'Change the engine to undef'; isa_ok $uri, 'URI::_db'; is $uri->scheme, 'foo', 'Foo URI scheme should still be "foo"'; is $uri->engine, 'foo', 'Foo URI engine should still be "foo"'; ok !$uri->has_recognized_engine, 'Foo URI should not be a recognized engine'; is $uri->as_string, 'foo:', 'URI string should be foo:'; # Test dbname with opaque URI. isa_ok $uri = URI->new('db:'), 'URI::db', 'Another opaque DB URI'; is $uri->dbname, undef, 'DB name should be undef'; is $uri->dbname('foo'), "", 'Assign a database name'; is $uri->dbname, 'foo', 'DB name should be "foo"'; is $uri->path, 'foo', 'Path should be "foo"'; isa_ok $uri, 'URI::db', 'Unknown engine URI'; isa_ok $uri->nested_uri, 'URI::_db'; # Pass a path. is $uri->dbname('/tmp/foo'), 'foo', 'Assign a database name path'; is $uri->dbname, '/tmp/foo', 'DB name should be "/tmp/foo"'; is $uri->path, '/tmp/foo', 'Path should be "/tmp/foo"'; # Try a Windows path. WARN: { my $msg; local $SIG{__WARN__} = sub { $msg = shift }; $uri->dbname('C:/temp/foo'); like $msg, qr{'[.]/' prepended}, 'Should warn about prepending ./ to path'; } pass 'Assign a database Windows path'; is $uri->dbname, './C:/temp/foo', 'DB name should be "./C:/temp/foo"'; is $uri->path, './C:/temp/foo', 'Path should be "./C:/temp/foo"'; # Create a full URI with authority section. isa_ok $uri = URI->new('db://localhost'), 'URI::db', 'Full DB URI'; $uri->dbname('foo'); pass 'Assign a database name'; is $uri->dbname, 'foo', 'DB name should be "foo"'; is $uri->path, '/foo', 'Path should be "/foo"'; isa_ok $uri->nested_uri, 'URI::_db'; # Pass a path. $uri->dbname('/tmp/foo'); pass 'Assign a database name full path'; is $uri->dbname, '/tmp/foo', 'DB name should be "/tmp/foo"'; is $uri->path, '//tmp/foo', 'Path should be "//tmp/foo"'; # Try a relative path. $uri->dbname('foo.db'); pass 'Assign a database name relative path'; is $uri->dbname, 'foo.db', 'DB name should be "foo.db"'; is $uri->path, '/foo.db', 'Path should be "/foo.db"'; # Try a Windows path. $uri->dbname('C:/temp/foo'); pass 'Assign a database Windows path'; is $uri->dbname, 'C:/temp/foo', 'DB name should be "C:/temp/foo"'; is $uri->path, '/C:/temp/foo', 'Path should be "/C:/temp/foo"'; # Try constructor. isa_ok $uri = URI::db->new('pg:'), 'URI::db', 'pg URI'; isa_ok $uri->nested_uri, 'URI::pg', 'pg URI URI'; is $uri->as_string, 'db:pg:', 'pg URI should be correct'; # Should convert non-db URI to a db URI. isa_ok $uri = URI::db->new('foo:'), 'URI::db', 'foo URI'; isa_ok $uri->nested_uri, 'URI::_db', 'foo URI URI'; is $uri->as_string, 'db:foo:', 'foo URI should be correct'; # Should pay attention to base URI. isa_ok $uri = URI::db->new('foo', 'pg:'), 'URI::db', 'db URI with pg base'; isa_ok $uri->nested_uri, 'URI::pg', 'db:pg URI'; is $uri->as_string, 'db:pg:foo', 'db URI with pg: base should be correct'; # Should pay attention to db: base URI. isa_ok $uri = URI::db->new('foo', 'db:'), 'URI::db', 'db URI with db base'; isa_ok $uri->nested_uri, 'URI::_db', 'db base URI'; is $uri->as_string, 'db:foo', 'db URI with db: base should be correct'; # Should pay attention to db:pg base URI. isa_ok $uri = URI::db->new('foo', 'db:pg'), 'URI::db', 'db URI with db:pg base'; isa_ok $uri->nested_uri, 'URI::pg', 'db:pg base URI'; is $uri->as_string, 'db:pg:foo', 'db URI with db:pg base should be correct'; # Try with a db:pg base. my $base = URI->new('db:pg'); isa_ok $uri = URI::db->new('foo', $base), 'URI::db', 'db URI with obj base'; isa_ok $uri->nested_uri, 'URI::pg', 'obj base URI'; is $uri->as_string, 'db:pg:foo', 'db URI with obj base should be correct'; isa_ok $base, 'URI::db', 'base URI'; # Try with a db: base. $base = URI->new('db:'); isa_ok $uri = URI::db->new('foo', $base), 'URI::db', 'db URI with db obj base'; isa_ok $uri->nested_uri, 'URI::_db', 'db obj base URI'; is $uri->as_string, 'db:foo', 'db URI with db obj base should be correct'; isa_ok $base, 'URI::db', 'base URI'; # Try db:unknown. $base = URI->new('db:unknown:'); isa_ok $uri = URI::db->new('foo', $base), 'URI::db', 'db URI with obj base'; isa_ok $uri->nested_uri, 'URI::_db', 'obj base URI'; is $uri->as_string, 'db:unknown:foo', 'db URI with obj base should be correct'; isa_ok $base, 'URI::db', 'base URI'; # Try with some other base. $base = URI->new('bar:'); isa_ok $uri = URI::db->new('foo', $base), 'URI::db', 'db URI with obj base'; isa_ok $uri->nested_uri, 'URI::_db', 'obj base URI'; is $uri->as_string, 'db:bar:foo', 'db URI with obj base should be correct'; isa_ok $base, 'URI', 'bar base URI'; # Try new_abs. isa_ok $uri = URI::db->new_abs('foo', 'pg:'), 'URI::pg'; is $uri->as_string, 'pg:/foo', 'Should have pg: URI'; isa_ok $uri = URI::db->new_abs('foo', 'db:pg:'), 'URI::db'; is $uri->as_string, 'db:pg:/foo', 'Should have db:pg: URI'; isa_ok $uri = URI::db->new_abs('foo', 'db:'), 'URI::db'; is $uri->as_string, 'db:foo', 'Should have db: URI'; isa_ok $uri = URI::db->new_abs('foo', 'bar:'), 'URI::_generic'; isa_ok $uri = URI::db->new_abs('foo', 'file::'), 'URI::file'; isa_ok $uri = URI::db->new_abs('pg:foo', 'pg:'), 'URI::pg'; is $uri->as_string, 'pg:foo', 'Should have pg:foo URI'; isa_ok $uri = URI::db->new_abs('db:foo', 'db:'), 'URI::db'; is $uri->as_string, 'db:foo', 'Should have db:foo URI'; isa_ok $uri = URI::db->new_abs('db:pg:foo', 'db:pg:'), 'URI::db'; is $uri->as_string, 'db:pg:foo', 'Should have db:pg:foo URI'; # Test abs. isa_ok $uri = URI->new('db:pg:'), 'URI::db'; is overload::StrVal( $uri->abs('file:/hi') ), overload::StrVal($uri), 'abs should return URI object itself'; # Test rel. is overload::StrVal( $uri->rel('file:/hi') ), overload::StrVal($uri), 'rel should return URI object itself'; # Test clone. is $uri->clone, $uri, 'Clone should return dupe URI'; isnt overload::StrVal( $uri->clone ), overload::StrVal($uri), 'Clone should not return self'; # Test eq. can_ok $uri, 'eq'; ok $uri->eq($uri), 'URI should equal itself'; ok $uri->eq($uri->as_string), 'URI should equal itself stringified'; ok $uri->eq(URI->new( $uri->as_string )), 'URI should equal equiv URI'; ok $uri->eq($uri->clone), 'URI should equal itself cloned'; ok !$uri->eq('pg:'), 'URI should not equal non-DB URI'; # Test dbname in hostless URI. for my $opaque ('', '//', '//foo@/') { ok my $uri = URI->new("db:sqlite:$opaque"), qq{Create URI with opaque "$opaque"}; ok !$uri->dbname, 'dbname should be empty'; $uri->dbname('foo.db'); is $uri->dbname, 'foo.db', 'dbname should be "foo.db"'; my $prefix = $opaque eq '' ? '' : '/'; is $uri->path, "${prefix}foo.db", 'path should be "${prefix}foo.db"'; } done_testing; URI-db-0.22/t/dbi.t000444001751000177 4145514603652634 14012 0ustar00runnerdocker000000000000#!/usr/bin/perl -w use strict; use Test::More; use utf8; use URI; for my $spec ( { uri => 'db:', dsn => '', dbi => [ [host => undef], ['port' => undef], [dbname => undef] ], qry => [], }, { uri => 'db:pg:', dsn => 'dbi:Pg:', dbi => [ [host => undef], [port => undef], [dbname => undef] ], qry => [], }, { uri => 'db:pg://localhost', dsn => 'dbi:Pg:host=localhost', dbi => [ [host => 'localhost'], [port => undef], [dbname => undef] ], qry => [], }, { uri => 'db:pg://localhost', dsn => 'dbi:Pg:host=localhost', dbi => [ [host => 'localhost'], [port => undef], [dbname => undef] ], qry => [], }, { uri => 'db:pg://me:secret@example.com/foodb', dsn => 'dbi:Pg:host=example.com;dbname=foodb', dbi => [ [host => 'example.com'], [port => undef], [dbname => 'foodb'] ], qry => [], }, { uri => 'db:pg://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:postgresql://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:postgres://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:postgresxc://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:pgsql://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:pgxc://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:redshift://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:sqlite:', dsn => 'dbi:SQLite:', dbi => [ [dbname => undef] ], qry => [], }, { uri => 'db:sqlite:foo.db', dsn => 'dbi:SQLite:dbname=foo.db', dbi => [ [dbname => 'foo.db'] ], qry => [], }, { uri => 'db:sqlite:/path/foo.db', dsn => 'dbi:SQLite:dbname=/path/foo.db', dbi => [ [dbname => '/path/foo.db'] ], qry => [], }, { uri => 'db:sqlite:///path/foo.db', dsn => 'dbi:SQLite:dbname=path/foo.db', dbi => [ [dbname => 'path/foo.db'] ], qry => [], }, { uri => 'db:cubrid://localhost:33/foo', dsn => 'dbi:cubrid:host=localhost;port=33;database=foo', dbi => [ [host => 'localhost'], [port => 33], [database => 'foo'] ], qry => [], }, { uri => 'db:db2://localhost:33/foo', dsn => 'dbi:DB2:HOSTNAME=localhost;PORT=33;DATABASE=foo', dbi => [ [HOSTNAME => 'localhost'], [PORT => 33], [DATABASE => 'foo'] ], qry => [], }, { uri => 'db:firebird://localhost:33/foo', dsn => 'dbi:Firebird:host=localhost;port=33;dbname=foo', dbi => [ [host => 'localhost'], [port => 33], [dbname => 'foo'] ], qry => [], }, { uri => 'db:informix:foo.db', dsn => 'dbi:Informix:foo.db', dbi => [], qry => [], }, { uri => 'db:informix:foo.db?foo=1', dsn => 'dbi:Informix:foo.db;foo=1', dbi => [], qry => [foo => 1], }, { uri => 'db:ingres:foo.db', dsn => 'dbi:Ingres:foo.db', dbi => [], qry => [], }, { uri => 'db:ingres:foo.db?foo=1', dsn => 'dbi:Ingres:foo.db;foo=1', dbi => [], qry => [foo => 1], }, { uri => 'db:interbase://localhost:33/foo', dsn => 'dbi:InterBase:host=localhost;port=33;dbname=foo', dbi => [ [host => 'localhost'], [port => 33], [dbname => 'foo'] ], qry => [], }, { uri => 'db:ldapdb://localhost:33/foo', dsn => 'dbi:LDAP:foo', dbi => [ [ dbname => 'foo' ] ], qry => [], }, { uri => 'db:ldapdb://localhost/foo', dsn => 'dbi:LDAP:foo', dbi => [ [ dbname => 'foo' ] ], qry => [], }, { uri => 'db:ldapdb://./foo', dsn => 'dbi:LDAP:foo', dbi => [ [ dbname => 'foo' ] ], qry => [], }, { uri => 'db:maxdb://localhost:33/foo', dsn => 'dbi:MaxDB:localhost:33/foo', dbi => [], qry => [], }, { uri => 'db:maxdb://localhost/foo', dsn => 'dbi:MaxDB:localhost/foo', dbi => [], qry => [], }, { uri => 'db:monetdb://localhost:1222?foo=1', dsn => 'dbi:monetdb:host=localhost;port=1222;foo=1', dbi => [ [host => 'localhost'], [port => 1222] ], qry => [foo => 1], }, { uri => 'db:monetdb://localhost/lolz', dsn => 'dbi:monetdb:host=localhost', dbi => [ [host => 'localhost'], [port => undef] ], qry => [], }, { uri => 'db:mysql://localhost:33/foo', dsn => 'dbi:mysql:host=localhost;port=33;database=foo', dbi => [ [host => 'localhost'], [port => 33], [database => 'foo'] ], qry => [], }, { uri => 'db:mariadb://localhost:33/foo', dsn => 'dbi:mysql:host=localhost;port=33;database=foo', dbi => [ [host => 'localhost'], [port => 33], [database => 'foo'] ], qry => [], }, { uri => 'db:oracle://localhost:33/foo', dsn => 'dbi:Oracle://localhost:33/foo', dbi => [ [host => 'localhost'], [port => 33], [dbname => 'foo'] ], qry => [], }, { uri => 'db:oracle://localhost/foo', dsn => 'dbi:Oracle://localhost/foo', dbi => [ [host => 'localhost'], [port => undef], [dbname => 'foo'] ], qry => [], }, { uri => 'db:oracle://:42/foo', dsn => 'dbi:Oracle://:42/foo', dbi => [ [host => ''], [port => 42], [dbname => 'foo'] ], qry => [], }, { uri => 'db:oracle:foo', dsn => 'dbi:Oracle:foo', dbi => [ [host => undef], [port => undef], [dbname => 'foo'] ], qry => [], }, { uri => 'db:oracle:///foo', dsn => 'dbi:Oracle:foo', dbi => [ [host => ''], [port => undef], [dbname => 'foo'] ], qry => [], }, { uri => 'db:oracle://:42/foo?x=y;a=b', dsn => 'dbi:Oracle://:42/foo?x=y&a=b', dbi => [ [host => ''], [port => 42], [dbname => 'foo'] ], qry => [ x => 'y', a => 'b' ], }, { uri => 'db:mssql:', dsn => 'dbi:ODBC:', dbi => [ [DSN => undef] ], qry => [], alt => { odbc => 'dbi:ODBC:', sybase => 'dbi:Sybase:' }, }, { uri => 'db:mssql:dbadmin', dsn => 'dbi:ODBC:DSN=dbadmin', dbi => [ [DSN => 'dbadmin'] ], qry => [], alt => { ado => 'dbi:ADO:DSN=dbadmin', sybase => 'dbi:Sybase:dbname=dbadmin', }, }, { uri => 'db:mssql://localhost', dsn => 'dbi:ODBC:Server=localhost;Port=1433', dbi => [ [Server => 'localhost'], [Port => 1433], [Database => undef] ], qry => [], alt => { ADO => 'dbi:ADO:Server=localhost', ODBC => 'dbi:ODBC:Server=localhost;Port=1433', SYBASE => 'dbi:Sybase:host=localhost', }, }, { uri => 'db:mssql://localhost:33', dsn => 'dbi:ODBC:Server=localhost;Port=33', dbi => [ [Server => 'localhost'], [Port => 33], [Database => undef] ], qry => [], alt => { ado => 'dbi:ADO:Server=localhost;Port=33', sybase => 'dbi:Sybase:host=localhost;port=33', }, }, { uri => 'db:mssql://foo:123/try?foo=1&foo=2&lol=yes&Driver=HPMssql', dsn => 'dbi:ODBC:Server=foo;Port=123;Database=try;foo=1;foo=2;lol=yes;Driver=HPMssql', dbi => [ [Server => 'foo'], [Port => 123], [Database => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes', Driver => 'HPMssql' ], alt => { ado => 'dbi:ADO:Server=foo;Port=123;Database=try;foo=1;foo=2;lol=yes;Driver=HPMssql', sybase => 'dbi:Sybase:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes;Driver=HPMssql', }, }, { uri => 'db:mssql://localhost:33/foo', dsn => 'dbi:ODBC:Server=localhost;Port=33;Database=foo', dbi => [ [Server => 'localhost'], [Port => 33], [Database => 'foo'] ], qry => [], alt => { ado => 'dbi:ADO:Server=localhost;Port=33;Database=foo', sybase => 'dbi:Sybase:host=localhost;port=33;dbname=foo', }, }, { uri => 'db:sqlserver://localhost:33/foo', dsn => 'dbi:ODBC:Server=localhost;Port=33;Database=foo', dbi => [ [Server => 'localhost'], [Port => 33], [Database => 'foo'] ], qry => [], alt => { Ado => 'dbi:ADO:Server=localhost;Port=33;Database=foo', Odbc => 'dbi:ODBC:Server=localhost;Port=33;Database=foo', Sybase => 'dbi:Sybase:host=localhost;port=33;dbname=foo', }, }, { uri => 'db:sybase://localhost:33/foo', dsn => 'dbi:Sybase:host=localhost;port=33;dbname=foo', dbi => [ [host => 'localhost'], [port => 33], [dbname => 'foo'] ], qry => [], }, { uri => 'db:teradata://localhost', dsn => 'dbi:Teradata:localhost', dbi => [ [DATABASE => undef] ], qry => [], }, { uri => 'db:teradata://localhost:33/foo?hi=1', dsn => 'dbi:Teradata:localhost:33;DATABASE=foo;hi=1', dbi => [ [DATABASE => 'foo'] ], qry => [ hi => 1], }, { uri => 'db:unify:foo.db', dsn => 'dbi:Unify:foo.db', dbi => [], qry => [], }, { uri => 'db:unify:', dsn => 'dbi:Unify:', dbi => [], qry => [], }, { uri => 'db:unify:?foo=1&bar=2', dsn => 'dbi:Unify:foo=1;bar=2', dbi => [], qry => [ foo => 1, bar => 2 ], }, { uri => 'db:vertica:', dsn => 'dbi:ODBC:', dbi => [ [DSN => undef] ], qry => [], }, { uri => 'db:vertica:dbadmin', dsn => 'dbi:ODBC:DSN=dbadmin', dbi => [ [DSN => 'dbadmin'] ], qry => [], }, { uri => 'db:vertica://localhost', dsn => 'dbi:ODBC:Server=localhost;Port=5433', dbi => [ [Server => 'localhost'], [Port => 5433], [Database => undef] ], qry => [], }, { uri => 'db:vertica://localhost:33', dsn => 'dbi:ODBC:Server=localhost;Port=33', dbi => [ [Server => 'localhost'], [Port => 33], [Database => undef] ], qry => [], }, { uri => 'db:vertica://foo:123/try?foo=1&foo=2&lol=yes&Driver=HPVertica', dsn => 'dbi:ODBC:Server=foo;Port=123;Database=try;foo=1;foo=2;lol=yes;Driver=HPVertica', dbi => [ [Server => 'foo'], [Port => 123], [Database => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes', Driver => 'HPVertica' ], }, { uri => 'db:exasol:', dsn => 'dbi:ODBC:', dbi => [ [DSN => undef] ], qry => [], alt => { odbc => 'dbi:ODBC:', EXASOL => 'dbi:ODBC:' }, }, { uri => 'db:exasol:', dsn => 'dbi:ODBC:', dbi => [ [DSN => undef] ], qry => [], }, { uri => 'db:exasol:dbadmin', dsn => 'dbi:ODBC:DSN=dbadmin', dbi => [ [DSN => 'dbadmin'] ], qry => [], }, { uri => 'db:exasol://localhost', dsn => 'dbi:ODBC:EXAHOST=localhost;EXAPORT=8563', dbi => [ [EXAHOST => 'localhost'], [EXAPORT => 8563] ], qry => [], }, { uri => 'db:exasol://localhost:33', dsn => 'dbi:ODBC:EXAHOST=localhost;EXAPORT=33', dbi => [ [EXAHOST => 'localhost'], [EXAPORT => 33] ], qry => [], }, { uri => 'db:exasol://foo:123/try?foo=1&foo=2&lol=yes&Driver=HPExasol', dsn => 'dbi:ODBC:EXAHOST=foo;EXAPORT=123;foo=1;foo=2;lol=yes;Driver=HPExasol', dbi => [ [EXAHOST => 'foo'], [EXAPORT => 123] ], qry => [ foo => 1, foo => 2, lol => 'yes', Driver => 'HPExasol' ], }, { uri => 'db:snowflake:', dsn => 'dbi:ODBC:', dbi => [ [DSN => undef] ], qry => [], }, { uri => 'db:snowflake:dbadmin', dsn => 'dbi:ODBC:DSN=dbadmin', dbi => [ [DSN => 'dbadmin'] ], qry => [], }, { uri => 'db:snowflake://yow', dsn => 'dbi:ODBC:Server=yow;Port=443', dbi => [ [Server => 'yow'], [Port => 443], [Database => undef] ], qry => [], }, { uri => 'db:snowflake://yow:33', dsn => 'dbi:ODBC:Server=yow;Port=33', dbi => [ [Server => 'yow'], [Port => 33], [Database => undef] ], qry => [], }, { uri => 'db:snowflake://foo:123/try?foo=1&foo=2&lol=yes&Driver=Snowflaker', dsn => 'dbi:ODBC:Server=foo;Port=123;Database=try;foo=1;foo=2;lol=yes;Driver=Snowflaker', dbi => [ [Server => 'foo'], [Port => 123], [Database => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes', Driver => 'Snowflaker' ], }, { uri => 'db:cockroach:', dsn => 'dbi:Pg:port=26257', dbi => [ [host => undef], [port => 26257], [dbname => undef] ], qry => [], }, { uri => 'db:cockroach://xxx:5432', dsn => 'dbi:Pg:host=xxx;port=5432', dbi => [ [host => 'xxx'], [port => 5432], [dbname => undef] ], qry => [], }, { uri => 'db:cockroach://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:cockroachdb:', dsn => 'dbi:Pg:port=26257', dbi => [ [host => undef], [port => 26257], [dbname => undef] ], qry => [], }, { uri => 'db:cockroachdb://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:yugabyte:', dsn => 'dbi:Pg:port=5433', dbi => [ [host => undef], [port => 5433], [dbname => undef] ], qry => [], }, { uri => 'db:yugabyte://xxx:5432', dsn => 'dbi:Pg:host=xxx;port=5432', dbi => [ [host => 'xxx'], [port => 5432], [dbname => undef] ], qry => [], }, { uri => 'db:yugabyte://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, { uri => 'db:yugabytedb:', dsn => 'dbi:Pg:port=5433', dbi => [ [host => undef], [port => 5433], [dbname => undef] ], qry => [], }, { uri => 'db:yugabytedb://foo:123/try?foo=1&foo=2&lol=yes', dsn => 'dbi:Pg:host=foo;port=123;dbname=try;foo=1;foo=2;lol=yes', dbi => [ [host => 'foo'], [port => 123], [dbname => 'try'] ], qry => [ foo => 1, foo => 2, lol => 'yes' ], }, ) { my $uri = $spec->{uri}; ok my $u = URI->new($uri), "URI $uri"; is_deeply [ $u->query_params ], $spec->{qry}, "... $uri query params"; is_deeply [ $u->_dbi_param_map ], $spec->{dbi}, "... $uri DBI param map"; is_deeply [ $u->dbi_params ], [ ( map { @{ $_ } } grep { defined $_->[1] && length $_->[1] } @{ $spec->{dbi} } ), @{ $spec->{qry} }, ], "... $uri DBI params"; is $u->dbi_dsn, $spec->{dsn}, "... $uri DSN"; if (my $alt = $spec->{alt}) { while (my ($driver, $dsn) = each %{ $alt }) { is $u->dbi_dsn($driver), $dsn, "$uri $driver DSN"; } } } done_testing; URI-db-0.22/t/engines.t000444001751000177 5710114603652634 14677 0ustar00runnerdocker000000000000#!/usr/bin/perl -w use strict; use Test::More; use utf8; use URI; use URI::QueryParam; for my $spec ( [ db => undef, undef ], [ unknown => undef, undef ], [ postgresql => 5432, 'pg' ], [ postgres => 5432, 'pg' ], [ pgsql => 5432, 'pg' ], [ pg => 5432, 'pg' ], [ pgxc => 5432, 'pg' ], [ postgresxc => 5432, 'pg' ], [ redshift => 5432, 'pg' ], [ mysql => 3306, 'mysql' ], [ mariadb => 3306, 'mysql' ], [ maria => 3306, 'mysql' ], [ sqlite => undef, 'sqlite' ], [ sqlite3 => undef, 'sqlite' ], [ oracle => 1521, 'oracle' ], [ cubrid => 33000, 'cubrid' ], # ? [ firebird => 3050, 'firebird' ], [ mssql => 1433, 'mssql' ], [ sqlserver => 1433, 'mssql' ], [ db2 => 50000, 'db2' ], # ? [ ingres => 1524, 'ingres' ], [ sybase => 2638, 'sybase' ], [ informix => 1526, 'informix' ], # ? [ teradata => 1025, 'teradata' ], [ interbase => 3050, 'interbase' ], [ unify => 27117, 'unify' ], # ? [ mongodb => 27017, 'mongodb' ], [ mongo => 27017, 'mongodb' ], [ monetdb => 50000, 'monetdb' ], # ? [ monet => 50000, 'monetdb' ], # ? [ maxdb => 7673, 'maxdb' ], # ? [ max => 7673, 'maxdb' ], # ? [ impala => 21000, 'impala' ], [ couchdb => 5984, 'couchdb' ], [ couch => 5984, 'couchdb' ], [ hive => 10000, 'hive' ], [ cassandra => 9160, 'cassandra' ], [ derby => 1527, 'derby' ], [ vertica => 5433, 'vertica' ], [ ldapdb => undef, 'ldapdb' ], [ exasol => 8563, 'exasol' ], [ snowflake => 443, 'snowflake' ], [ cockroach => 26257, 'cockroach' ], [ cockroachdb => 26257, 'cockroach' ], [ yugabyte => 5433, 'pg' ], [ yugabytedb => 5433, 'pg' ], ) { my ($engine, $port, $canon) = @{ $spec }; my $prefix = "db:$engine"; my $class = "URI::$engine"; my $label = $engine; my $clabel = $canon; if ($engine eq 'db' || $engine eq 'unknown') { $prefix = 'db'; $class = 'URI::_db'; $engine = undef; $label = ''; $canon = undef; $clabel = ''; } else { # Should work well as a direct URI. my $string = "$engine://hi:there\@foo.com:1234/blah.db"; isa_ok my $uri = URI->new($string), $class; isa_ok $uri, 'URI::_db'; isa_ok $uri->uri, $class; is $uri->scheme, $engine, qq{Non-DB scheme should be "$engine"}; is $uri->engine, $engine, qq{Non-DB URI engine should be "$label"}; is $uri->dbname, 'blah.db', 'Simple URI db name should be "blah.db"'; is $uri->host, 'foo.com', 'Non-DB URI host should be "foo.com"'; is $uri->port, 1234, 'Non-DB URI port should be 1234'; is $uri->user, 'hi', 'Non-DB URI user should be "hi"'; is $uri->password, 'there', 'Non-DB URI password should be "there"'; is_deeply $uri->query_form_hash, {}, 'Non-DB URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Non-DB URI query params should be empty'; is $uri->as_string, $string, 'Non-DB URI string should be correct'; is "$uri", $string, 'Non-DB URI should correctly strigify'; ok $uri->has_recognized_engine, "$engine should be recognized engine"; is $uri->canonical_engine, $canon, qq{Non-DB URI canonical engine should be "$clabel"}; $uri->port(undef) if $clabel eq 'sqlite' || $clabel eq 'ldapdb'; is $uri->canonical->engine, $canon, qq{Non-DB URI canonical URI engine should be "$clabel"}; } isa_ok my $uri = URI->new("$prefix:"), 'URI::db', "DB URI with $class"; if ($prefix ne 'db') { isa_ok $uri->uri, 'URI::_db'; isa_ok $uri->uri, $class; } is $uri->scheme, 'db', 'Scheme should be "db"'; is $uri->engine, $engine, qq{Simple URI engine should be "$label"}; is $uri->canonical_engine, $canon, qq{Simple URI canonical engine should be "$clabel"}; is $uri->dbname, undef, 'Simple URI db name should be undef'; is $uri->host, undef, 'Simple URI host should be undef'; is $uri->port, $port, 'Simple URI port should be undef'; is $uri->user, undef, 'Simple URI user should be undef'; is $uri->password, undef, 'Simple URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Simple URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Simple URI query params should be empty'; is $uri->as_string, "$prefix:", 'Simple URI string should be correct'; is "$uri", "$prefix:", 'Simple URI should correctly strigify'; if ($engine) { ok $uri->has_recognized_engine, "$engine should be recognized engine"; } else { ok !$uri->has_recognized_engine, "$prefix should not be recognized engine"; } isa_ok $uri = URI->new("$prefix:foo.db"), 'URI::db', "Path URI with $class"; isa_ok $uri->uri, $class, "Path URI $class URI"; is $uri->scheme, 'db', 'Scheme should be "db"'; is $uri->engine, $engine, qq{Path URI engine should be "$label"}; is $uri->canonical_engine, $canon, qq{Path URI canonical engine should be "$clabel"}; is $uri->dbname, 'foo.db', 'Path URI db name should be "foo.db"'; is $uri->host, undef, 'Path URI host should be undef'; is $uri->port, $port, 'Path URI port should be undef'; is $uri->user, undef, 'Path URI user should be undef'; is $uri->password, undef, 'Path URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Path URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Path URI query params should be empty'; is $uri->as_string, "$prefix:foo.db", 'Path URI string should be correct'; is "$uri", "$prefix:foo.db", 'Simple URI should correctly strigify'; isa_ok $uri = URI->new("$prefix:/path/to/foo.db"), 'URI::db', "Absolute Path URI with class"; isa_ok $uri->uri, $class, "Absolute Path URI $class URI"; isa_ok $uri, 'URI::db' unless $prefix eq 'db'; is $uri->scheme, 'db', 'Scheme should be "db"'; is $uri->engine, $engine, qq{Absolute Path URI engine should be "$label"}; is $uri->canonical_engine, $canon, qq{Absolute path URI canonical engine should be "$clabel"}; is $uri->dbname, '/path/to/foo.db', 'Absolute Path URI db name should be "/path/to/foo.db"'; is $uri->host, undef, 'Absolute Path URI host should be undef'; is $uri->port, $port, 'Absolute Path URI port should be undef'; is $uri->user, undef, 'Absolute Path URI user should be undef'; is $uri->password, undef, 'Absolute Path URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Absolute Path URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Absolute Path URI query params should be empty'; is $uri->as_string, "$prefix:/path/to/foo.db", 'Absolute Path URI string should be correct'; is "$uri", "$prefix:/path/to/foo.db", 'Simple URI should correctly strigify'; isa_ok $uri = URI->new("$prefix:///path/to/foo.db"), 'URI::db', "No host, full path URI with $class"; isa_ok $uri->uri, $class, "No host, full path URI $class URI"; isa_ok $uri, 'URI::db' unless $prefix eq 'db'; is $uri->scheme, 'db', 'Scheme should be "db"'; is $uri->engine, $engine, qq{No host, full path URI engine should be "$label"}; is $uri->canonical_engine, $canon, qq{No host, full path URI canonical engine should be "$clabel"}; is $uri->dbname, 'path/to/foo.db', 'No host, full path URI db name should be "path/to/foo.db"'; is $uri->host, '', 'No host, full path URI host should be empty'; is $uri->port, $port, 'No host, full path URI port should be undef'; is $uri->user, undef, 'No host, full path URI user should be undef'; is $uri->password, undef, 'No host, full path URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'No host, full path URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'No host, full path URI query params should be empty'; is $uri->as_string, "$prefix:///path/to/foo.db", 'No host, full path URI string should be correct'; is "$uri", "$prefix:///path/to/foo.db", 'Simple URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://"), 'URI::db', "Hostless URI with $class"; isa_ok $uri->uri, $class, "Hostless URI $class URI"; is $uri->engine, $engine, qq{Hostless URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Hostless URI canonical engine should be "$clabel"}; is $uri->dbname, undef, 'Hostless URI db name should be undef'; is $uri->host, '', 'Hostless URI host should be ""'; is $uri->port, $port, 'Hostless URI port should be undef'; is $uri->user, undef, 'Hostless URI user should be undef'; is $uri->password, undef, 'Hostless URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Hostless URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Hostless URI query params should be empty'; is $uri->as_string, "$prefix://", 'Hostless URI string should be correct'; is "$uri", "$prefix://", 'Hostless URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://localhost//foo.db"), 'URI::db', "Host+FullPath URI with $class"; isa_ok $uri->uri, $class, "Host+FullPath URI $class URI"; is $uri->engine, $engine, qq{Host+FullPath URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Host+FullPath URI canonical engine should be "$clabel"}; is $uri->dbname, '/foo.db', 'Host+FullPath URI db name should be "/foo.db"'; is $uri->host, 'localhost', 'Host+FullPath URI host should be "localhost"'; is $uri->port, $port, 'Host+FullPath URI port should be undef'; is $uri->user, undef, 'Host+FullPath URI user should be undef'; is $uri->password, undef, 'Host+FullPath URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Host+FullPath URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Host+FullPath URI query params should be empty'; is $uri->as_string, "$prefix://localhost//foo.db", 'Host+FullPath URI string should be correct'; is "$uri", "$prefix://localhost//foo.db", 'Host+FullPath URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://localhost/%2Ftmp/test.gdb"), 'URI::db', "Host+PcntPath URI with $class"; isa_ok $uri->uri, $class, "Host+PcntPath URI $class URI"; is $uri->engine, $engine, qq{Host+PcntPath URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Host+PcntPath URI canonical engine should be "$clabel"}; is $uri->dbname, '/tmp/test.gdb', 'Host+PcntPath URI db name should be "/tmp/test.gdb"'; is $uri->host, 'localhost', 'Host+PcntPath URI host should be "localhost"'; is $uri->port, $port, 'Host+PcntPath URI port should be undef'; is $uri->user, undef, 'Host+PcntPath URI user should be undef'; is $uri->password, undef, 'Host+PcntPath URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Host+PcntPath URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Host+PcntPath URI query params should be empty'; is $uri->as_string, "$prefix://localhost/%2Ftmp/test.gdb", 'Host+PcntPath URI string should be correct'; is "$uri", "$prefix://localhost/%2Ftmp/test.gdb", 'Host+PcntPath URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://localhost/C:/tmp/foo.db"), 'URI::db', "Host+WinPath URI with $class"; isa_ok $uri->uri, $class, "Host+WinPath URI $class URI"; is $uri->engine, $engine, qq{Host+WinPath URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Host+WinPath URI canonical engine should be "$clabel"}; is $uri->dbname, 'C:/tmp/foo.db', 'Host+WinPath URI db name should be "C:/tmp/foo.db"'; is $uri->host, 'localhost', 'Host+WinPath URI host should be "localhost"'; is $uri->port, $port, 'Host+WinPath URI port should be undef'; is $uri->user, undef, 'Host+WinPath URI user should be undef'; is $uri->password, undef, 'Host+WinPath URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Host+WinPath URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Host+WinPath URI query params should be empty'; is $uri->as_string, "$prefix://localhost/C:/tmp/foo.db", 'Host+WinPath URI string should be correct'; is "$uri", "$prefix://localhost/C:/tmp/foo.db", 'Host+WinPath URI should correctly strigify'; isa_ok $uri = URI->new("$prefix:////foo.db"), 'URI::db', "Hostless+FullPath URI with $class"; isa_ok $uri->uri, $class, "Hostless+FullPath URI $class URI"; is $uri->engine, $engine, qq{Hostless+FullPath URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Hostless+FullPath URI canonical engine should be "$clabel"}; is $uri->dbname, '/foo.db', 'Hostless+FullPath URI db name should be "/foo.db"'; is $uri->host, '', 'Hostless+FullPath URI host should be ""'; is $uri->port, $port, 'Hostless+FullPath URI port should be undef'; is $uri->user, undef, 'Hostless+FullPath URI user should be undef'; is $uri->password, undef, 'Hostless+FullPath URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Hostless+FullPath URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Hostless+FullPath URI query params should be empty'; is $uri->as_string, "$prefix:////foo.db", 'Hostless+FullPath URI string should be correct'; is "$uri", "$prefix:////foo.db", 'Hostless+FullPath URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://localhost"), 'URI::db', "Localhost URI with $class"; isa_ok $uri->uri, $class, "Localhost URI $class URI"; is $uri->engine, $engine, qq{Localhost URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Localhost URI canonical engine should be "$clabel"}; is $uri->dbname, undef, 'Localhost URI db name should be undef'; is $uri->host, 'localhost', 'Localhost URI host should be "localhost"'; is $uri->port, $port, 'Localhost URI port should be undef'; is $uri->user, undef, 'Localhost URI user should be undef'; is $uri->password, undef, 'Localhost URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Localhost URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Localhost URI query params should be empty'; is $uri->as_string, "$prefix://localhost", 'Localhost URI string should be correct'; is "$uri", "$prefix://localhost", 'Localhost URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://example.com:5433"), 'URI::db', "Host+Port DB URI with $class"; isa_ok $uri->uri, $class, "Host+Port URI $class URI"; is $uri->engine, $engine, qq{Host+Port URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Host+Port URI canonical engine should be "$clabel"}; is $uri->dbname, undef, 'Host+Port URI db name should be undef'; is $uri->host, 'example.com', 'Host+Port URI host should be "example.com"'; is $uri->port, 5433, 'Host+Port URI port should be 5433'; is $uri->user, undef, 'Host+Port URI user should be undef'; is $uri->password, undef, 'Host+Port URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'Host+Port URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Host+Port URI query params should be empty'; is $uri->as_string, "$prefix://example.com:5433", 'Host+Port URI string should be correct'; is "$uri", "$prefix://example.com:5433", 'Host+Port URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://example.com/mydb"), 'URI::db', "DB URI with $class"; isa_ok $uri->uri, $class, "DB URI $class URI"; is $uri->engine, $engine, qq{DB URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{DB URI canonical engine should be "$clabel"}; is $uri->dbname, 'mydb', 'DB URI db name should be "mydb"'; is $uri->host, 'example.com', 'DB URI host should be "example.com"'; is $uri->port, $port, 'DB URI port should be undef'; is $uri->user, undef, 'DB URI user should be undef'; is $uri->password, undef, 'DB URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'DB URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'DB URI query params should be empty'; is $uri->as_string, "$prefix://example.com/mydb", 'DB URI string should be correct'; is "$uri", "$prefix://example.com/mydb", 'DB URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://example.com/"), 'URI::db', "DBLess URI with $class"; isa_ok $uri->uri, $class, "DBLess URI $class URI"; is $uri->engine, $engine, qq{DBless URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{DBless URI canonical engine should be "$clabel"}; is $uri->dbname, '', 'DBless URI db name should be ""'; is $uri->host, 'example.com', 'DBless URI host should be "example.com"'; is $uri->port, $port, 'DBless URI port should be undef'; is $uri->user, undef, 'DBless URI user should be undef'; is $uri->password, undef, 'DBless URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'DBless URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'DBless URI query params should be empty'; is $uri->as_string, "$prefix://example.com/", 'DBless URI string should be correct'; is "$uri", "$prefix://example.com/", 'DBless URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://user\@localhost//fullpathdb"), 'URI::db', "User URI with $class"; isa_ok $uri->uri, $class, "User URI $class URI"; is $uri->engine, $engine, qq{User URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{User URI canonical engine should be "$clabel"}; is $uri->dbname, '/fullpathdb', 'User URI db name should be "/fullpathdb"'; is $uri->host, 'localhost', 'User URI host should be "localhost"'; is $uri->port, $port, 'User URI port should be undef'; is $uri->user, 'user', 'User URI user should be "user"'; is $uri->password, undef, 'User URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'User URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'User URI query params should be empty'; is $uri->as_string, "$prefix://user\@localhost//fullpathdb", 'User URI string should be correct'; is "$uri", "$prefix://user\@localhost//fullpathdb", 'User URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://user\@//fullpathdb"), 'URI::db', "User w/o host URI with $class"; isa_ok $uri->uri, $class, "User w/o host URI $class URI"; is $uri->engine, $engine, qq{User w/o host URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{User w/o host URI canonical engine should be "$clabel"}; is $uri->dbname, '/fullpathdb', 'User w/o host URI db name should be "/fullpathdb"'; is $uri->host, '', 'User w/o host URI host should be ""'; is $uri->port, $port, 'User w/o host URI port should be undef'; is $uri->user, 'user', 'User w/o host URI user should be "user"'; is $uri->password, undef, 'User w/o host URI password should be undef'; is_deeply $uri->query_form_hash, {}, 'User w/o host URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'User w/o host URI query params should be empty'; is $uri->as_string, "$prefix://user\@//fullpathdb", 'User w/o host URI string should be correct'; is "$uri", "$prefix://user\@//fullpathdb", 'User w/o host URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://user:secret\@localhost"), 'URI::db', "Password URI with $class"; isa_ok $uri->uri, $class, "Password URI $class URI"; is $uri->engine, $engine, qq{Password URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Password URI canonical engine should be "$clabel"}; is $uri->dbname, undef, 'Password URI db name should be undef'; is $uri->host, 'localhost', 'Password URI host should be "localhost"'; is $uri->port, $port, 'Password URI port should be undef'; is $uri->user, 'user', 'Password URI user should be "user"'; is $uri->password, 'secret', 'Password URI password should be "secret"'; is_deeply $uri->query_form_hash, {}, 'Password URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Password URI query params should be empty'; is $uri->as_string, "$prefix://user:secret\@localhost", 'Password URI string should be correct'; is "$uri", "$prefix://user:secret\@localhost", 'Password URI should correctly strigify'; isa_ok $uri = URI->new("$prefix://other\@localhost/otherdb?foo=bar&foo=baz&baz=yow"), 'URI::db', "Query URI with $class"; isa_ok $uri->uri, $class, "Query URI $class URI"; is $uri->engine, $engine, qq{Query URI engine should be "label"}; is $uri->canonical_engine, $canon, qq{Query URI canonical engine should be "$clabel"}; is $uri->dbname, 'otherdb', 'Query URI db name should be "otherdb"'; is $uri->host, 'localhost', 'Query URI host should be "localhost"'; is $uri->port, $port, 'Query URI port should be undef'; is $uri->user, 'other', 'Query URI user should be "other"'; is $uri->password, undef, 'Query URI password should be undef'; is_deeply $uri->query_form_hash, { foo => [qw(bar baz)], baz => 'yow'}, 'Query URI query params should be populated'; is_deeply [ $uri->query_params ], [ foo => 'bar', foo => 'baz', baz => 'yow' ], 'query URI query params should be populated'; is $uri->as_string, "$prefix://other\@localhost/otherdb?foo=bar&foo=baz&baz=yow", 'Query URI string should be correct'; is "$uri", "$prefix://other\@localhost/otherdb?foo=bar&foo=baz&baz=yow", 'Query URI should correctly strigify'; isa_ok $uri = URI->new("$prefix:foo.db#foo.bar"), 'URI::db', "Fragment URI with $class"; isa_ok $uri->uri, $class, "Fragment URI $class URI"; is $uri->scheme, 'db', 'Scheme should be "db"'; is $uri->engine, $engine, qq{Fragment URI engine should be "$label"}; is $uri->canonical_engine, $canon, qq{Frgement URI canonical engine should be "$clabel"}; is $uri->dbname, 'foo.db', 'Fragment URI db name should be "foo.db"'; is $uri->host, undef, 'Fragment URI host should be undef'; is $uri->port, $port, 'Fragment URI port should be undef'; is $uri->user, undef, 'Fragment URI user should be undef'; is $uri->password, undef, 'Fragment URI password should be undef'; is $uri->fragment, 'foo.bar', 'Fragement URI fragment should be "foo.bar"'; is_deeply $uri->query_form_hash, {}, 'Fragment URI query params should be empty by default'; is_deeply [ $uri->query_params ], [], 'Fragment URI query params should be empty'; is $uri->as_string, "$prefix:foo.db#foo.bar", 'Fragment URI string should be correct'; is "$uri", "$prefix:foo.db#foo.bar", 'Simple URI should correctly strigify'; } done_testing;