From 562d5076bf4ec2b1f7ab7c8c16e9b96b19ceabf0 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Wed, 3 Feb 2016 18:29:09 -0300 Subject: [PATCH] use URI as connection string --- spec/std/db/db_spec.cr | 10 ++++++---- spec/std/db/dummy_driver.cr | 8 ++++---- src/db/database.cr | 6 +++--- src/db/db.cr | 31 +++++++++++++++++++++---------- src/db/driver.cr | 6 +++--- 5 files changed, 37 insertions(+), 24 deletions(-) diff --git a/spec/std/db/db_spec.cr b/spec/std/db/db_spec.cr index ca7f65b..17a9da1 100644 --- a/spec/std/db/db_spec.cr +++ b/spec/std/db/db_spec.cr @@ -11,15 +11,17 @@ describe DB do DB.driver_class("dummy").should eq(DummyDriver) end - it "should instantiate driver with connection_string" do - db = DB.open "dummy", "localhost:1027" + it "should instantiate driver with connection uri" do + db = DB.open "dummy://localhost:1027" db.driver_class.should eq(DummyDriver) - db.connection_string.should eq("localhost:1027") + db.uri.scheme.should eq("dummy") + db.uri.host.should eq("localhost") + db.uri.port.should eq(1027) end it "should create a connection and close it" do cnn = nil - DB.open "dummy", "localhost" do |db| + DB.open "dummy://localhost" do |db| cnn = db.connection end diff --git a/spec/std/db/dummy_driver.cr b/spec/std/db/dummy_driver.cr index 12db753..35f0059 100644 --- a/spec/std/db/dummy_driver.cr +++ b/spec/std/db/dummy_driver.cr @@ -2,13 +2,13 @@ require "spec" class DummyDriver < DB::Driver def build_connection - DummyConnection.new(connection_string) + DummyConnection.new(uri) end class DummyConnection < DB::Connection - getter connection_string + getter uri - def initialize(@connection_string) + def initialize(@uri) @@connections ||= [] of DummyConnection @@connections.not_nil! << self end @@ -173,7 +173,7 @@ end def with_dummy DummyDriver::DummyConnection.clear_connections - DB.open "dummy", "" do |db| + DB.open "dummy://host" do |db| yield db end end diff --git a/src/db/database.cr b/src/db/database.cr index d32ef5a..38be06b 100644 --- a/src/db/database.cr +++ b/src/db/database.cr @@ -11,11 +11,11 @@ module DB getter driver_class # Connection configuration to the database. - getter connection_string + getter uri # :nodoc: - def initialize(@driver_class, @connection_string) - @driver = @driver_class.new(@connection_string) + def initialize(@driver_class, @uri) + @driver = @driver_class.new(@uri) @connection = @driver.build_connection end diff --git a/src/db/db.cr b/src/db/db.cr index a61c3c9..a8decf2 100644 --- a/src/db/db.cr +++ b/src/db/db.cr @@ -1,3 +1,5 @@ +require "uri" + # The DB module is a unified interface to database access. # Database dialects is supported by custom database driver shards. # Check [manastech/crystal-sqlite3](https://github.com/manastech/crystal-sqlite3) for example. @@ -12,14 +14,14 @@ # Assuming `crystal-sqlite3` is included a sqlite3 database can be opened with `#open`. # # ``` -# db = DB.open "sqlite3", ":memory:" # or the sqlite3 file path +# db = DB.open "sqlite3://%3Amemory%3A" # or sqlite3:///path/to/db/file.db # db.close # ``` # # If a block is given to `#open` the database is closed automatically # # ``` -# DB.open "sqlite3", ":memory:" do |db| +# DB.open "sqlite3://%3Amemory%3A" do |db| # # work with db # end # db is closed # ``` @@ -37,7 +39,7 @@ # require "db" # require "sqlite3" # -# DB.open "sqlite3", ":memory:" do |db| +# DB.open "sqlite3://%3Amemory%3A" do |db| # db.exec "create table contacts (name string, age integer)" # db.exec "insert into contacts values (?, ?)", "John Doe", 30 # db.exec "insert into contacts values (:name, :age)", {name: "Sarah", age: 33} @@ -75,27 +77,36 @@ module DB @@drivers.not_nil![driver_name] end - # Registers a driver class for a given `driver_name`. + # Registers a driver class for a given *driver_name*. # Should be called by drivers implementors only. def self.register_driver(driver_name, driver_class : Driver.class) @@drivers ||= {} of String => Driver.class @@drivers.not_nil![driver_name] = driver_class end - # Opens a database using the `driver_name` registered driver. - # Uses `connection_string` for connection configuration. + # Opens a database using the specified *uri*. + # The scheme of the *uri* determines the driver to use. # Returned database must be closed by `Database#close`. - def self.open(driver_name, connection_string) - Database.new(driver_class(driver_name), connection_string) + # If a block is used the database is yielded and closed automatically. + def self.open(uri : URI | String) + build_database(uri) end # Same as `#open` but the database is yielded and closed automatically. - def self.open(driver_name, connection_string, &block) - open(driver_name, connection_string).tap do |db| + def self.open(uri : URI | String, &block) + build_database(uri).tap do |db| yield db db.close end end + + private def self.build_database(connection_string : String) + build_database(URI.parse(connection_string)) + end + + private def self.build_database(uri : URI) + Database.new(driver_class(uri.scheme), uri) + end end require "./query_methods" diff --git a/src/db/driver.cr b/src/db/driver.cr index b5f495b..4115f42 100644 --- a/src/db/driver.cr +++ b/src/db/driver.cr @@ -8,7 +8,7 @@ module DB # # class FakeDriver < Driver # def build_connection - # FakeConnection.new connection_string + # FakeConnection.new uri # end # end # @@ -26,9 +26,9 @@ module DB # Refer to `Connection`, `Statement` and `ResultSet` for further # driver implementation instructions. abstract class Driver - getter connection_string + getter uri - def initialize(@connection_string : String) + def initialize(@uri : URI) end abstract def build_connection : Connection