Class: Sequel::Database
- Includes:
- Dataset::SQL, Schema::SQL
- Defined in:
- lib/sequel/database.rb
Overview
A Database object represents a virtual connection to a database. The Database class is meant to be subclassed by database adapters in order to provide the functionality needed for executing queries.
Constant Summary collapse
- SQL_BEGIN =
'BEGIN'.freeze
- SQL_COMMIT =
'COMMIT'.freeze
- SQL_ROLLBACK =
'ROLLBACK'.freeze
- @@adapters =
Hash.new
- @@single_threaded =
false
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#opts ⇒ Object
readonly
Returns the value of attribute opts.
-
#pool ⇒ Object
readonly
Returns the value of attribute pool.
Class Method Summary collapse
- .adapter_class(scheme) ⇒ Object
-
.adapter_scheme ⇒ Object
Returns the scheme for the Database class.
-
.connect(conn_string, opts = nil) ⇒ Object
call-seq: Sequel::Database.connect(conn_string) Sequel::Database.connect(opts) Sequel.connect(conn_string) Sequel.connect(opts) Sequel.open(conn_string) Sequel.open(opts).
-
.set_adapter_scheme(scheme) ⇒ Object
Sets the adapter scheme for the Database class.
-
.single_threaded=(value) ⇒ Object
Sets the default single_threaded mode for new databases.
-
.uri_to_options(uri) ⇒ Object
Converts a uri to an options hash.
Instance Method Summary collapse
-
#<<(sql) ⇒ Object
Executes the supplied SQL statement.
-
#[](*args) ⇒ Object
Returns a dataset from the database.
-
#connect ⇒ Object
Connects to the database.
-
#create_table(name, &block) ⇒ Object
Creates a table.
-
#dataset ⇒ Object
Returns a blank dataset.
-
#disconnect ⇒ Object
Disconnects from the database.
-
#drop_table(*names) ⇒ Object
Drops one or more tables corresponding to the given table names.
-
#execute(sql) ⇒ Object
Raises a NotImplementedError.
-
#fetch(sql, *args, &block) ⇒ Object
(also: #>>)
Fetches records for an arbitrary SQL statement.
-
#from(*args, &block) ⇒ Object
Returns a new dataset with the from method invoked.
-
#initialize(opts = {}, &block) ⇒ Database
constructor
Constructs a new instance of a database connection with the specified options hash.
-
#multi_threaded? ⇒ Boolean
Returns true if the database is using a multi-threaded connection pool.
-
#query(&block) ⇒ Object
Converts a query block into a dataset.
-
#select(*args) ⇒ Object
Returns a new dataset with the select method invoked.
-
#serial_primary_key_options ⇒ Object
default serial primary key definition.
-
#single_threaded? ⇒ Boolean
Returns true if the database is using a single-threaded connection pool.
-
#synchronize(&block) ⇒ Object
Acquires a database connection, yielding it to the passed block.
-
#table_exists?(name) ⇒ Boolean
Returns true if the given table exists.
-
#test_connection ⇒ Object
Returns true if there is a database connection.
-
#transaction ⇒ Object
A simple implementation of SQL transactions.
-
#uri ⇒ Object
(also: #url)
Returns the URI identifying the database.
Constructor Details
#initialize(opts = {}, &block) ⇒ Database
Constructs a new instance of a database connection with the specified options hash.
Sequel::Database is an abstract class that is not useful by itself.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/sequel/database.rb', line 15 def initialize(opts = {}, &block) Model.database_opened(self) @opts = opts # Determine if the DB is single threaded or multi threaded @single_threaded = opts[:single_threaded] || @@single_threaded # Construct pool if @single_threaded @pool = SingleThreadedPool.new(&block) else @pool = ConnectionPool.new(opts[:max_connections] || 4, &block) end @pool.connection_proc = block || proc {connect} @logger = opts[:logger] end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
9 10 11 |
# File 'lib/sequel/database.rb', line 9 def logger @logger end |
#opts ⇒ Object (readonly)
Returns the value of attribute opts.
8 9 10 |
# File 'lib/sequel/database.rb', line 8 def opts @opts end |
#pool ⇒ Object (readonly)
Returns the value of attribute pool.
8 9 10 |
# File 'lib/sequel/database.rb', line 8 def pool @pool end |
Class Method Details
.adapter_class(scheme) ⇒ Object
259 260 261 262 263 264 265 266 267 |
# File 'lib/sequel/database.rb', line 259 def self.adapter_class(scheme) scheme = scheme.to_s =~ /\-/ ? scheme.to_s.gsub('-', '_').to_sym : scheme.to_sym unless c = @@adapters[scheme.to_sym] require File.join(File.dirname(__FILE__), "adapters/#{scheme}") c = @@adapters[scheme.to_sym] end raise SequelError, "Invalid database scheme" unless c c end |
.adapter_scheme ⇒ Object
Returns the scheme for the Database class.
243 244 245 |
# File 'lib/sequel/database.rb', line 243 def self.adapter_scheme @scheme end |
.connect(conn_string, opts = nil) ⇒ Object
call-seq:
Sequel::Database.connect(conn_string)
Sequel::Database.connect(opts)
Sequel.connect(conn_string)
Sequel.connect(opts)
Sequel.open(conn_string)
Sequel.open(opts)
Creates a new database object based on the supplied connection string and or options. If a URI is used, the URI scheme determines the database class used, and the rest of the string specifies the connection options. For example:
DB = Sequel.open 'sqlite:///blog.db'
The second form of this method takes an options:
DB = Sequel.open :adapter => :sqlite, :database => 'blog.db'
287 288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/sequel/database.rb', line 287 def self.connect(conn_string, opts = nil) if conn_string.is_a?(String) uri = URI.parse(conn_string) scheme = uri.scheme scheme = :dbi if scheme =~ /^dbi-(.+)/ c = adapter_class(scheme) c.new(c.(uri).merge(opts || {})) else opts = conn_string.merge(opts || {}) c = adapter_class(opts[:adapter]) c.new(opts) end end |
.set_adapter_scheme(scheme) ⇒ Object
Sets the adapter scheme for the Database class. Call this method in descendnants of Database to allow connection using a URL. For example the following:
class DB2::Database < Sequel::Database
set_adapter_scheme :db2
...
end
would allow connection using:
Sequel.open('db2://user:password@dbserver/mydb')
237 238 239 240 |
# File 'lib/sequel/database.rb', line 237 def self.set_adapter_scheme(scheme) @scheme = scheme @@adapters[scheme.to_sym] = self end |
.single_threaded=(value) ⇒ Object
Sets the default single_threaded mode for new databases.
304 305 306 |
# File 'lib/sequel/database.rb', line 304 def self.single_threaded=(value) @@single_threaded = value end |
.uri_to_options(uri) ⇒ Object
Converts a uri to an options hash. These options are then passed to a newly created database object.
249 250 251 252 253 254 255 256 257 |
# File 'lib/sequel/database.rb', line 249 def self.(uri) { :user => uri.user, :password => uri.password, :host => uri.host, :port => uri.port, :database => (uri.path =~ /\/(.*)/) && ($1) } end |
Instance Method Details
#<<(sql) ⇒ Object
Executes the supplied SQL statement. The SQL can be supplied as a string or as an array of strings. If an array is give, comments and excessive white space are removed. See also Array#to_sql.
147 |
# File 'lib/sequel/database.rb', line 147 def <<(sql); execute((Array === sql) ? sql.to_sql : sql); end |
#[](*args) ⇒ Object
Returns a dataset from the database. If the first argument is a string, the method acts as an alias for Database#fetch, returning a dataset for arbitrary SQL:
DB['SELECT * FROM items WHERE name = ?', my_name].print
Otherwise, the dataset returned has its from option set to the given arguments:
DB[:items].sql #=> "SELECT * FROM items"
135 136 137 |
# File 'lib/sequel/database.rb', line 135 def [](*args) (String === args.first) ? fetch(*args) : from(*args) end |
#connect ⇒ Object
Connects to the database. This method should be overriden by descendants.
33 34 35 |
# File 'lib/sequel/database.rb', line 33 def connect raise NotImplementedError, "#connect should be overriden by adapters" end |
#create_table(name, &block) ⇒ Object
Creates a table. The easiest way to use this method is to provide a block:
DB.create_table :posts do
primary_key :id, :serial
column :title, :text
column :content, :text
index :title
end
176 177 178 179 |
# File 'lib/sequel/database.rb', line 176 def create_table(name, &block) g = Schema::Generator.new(self, name, &block) create_table_sql_list(*g.create_info).each {|sta| execute(sta)} end |
#dataset ⇒ Object
Returns a blank dataset
73 74 75 |
# File 'lib/sequel/database.rb', line 73 def dataset ds = Sequel::Dataset.new(self) end |
#disconnect ⇒ Object
Disconnects from the database. This method should be overriden by descendants.
39 40 41 |
# File 'lib/sequel/database.rb', line 39 def disconnect raise NotImplementedError, "#disconnect should be overriden by adapters" end |
#drop_table(*names) ⇒ Object
Drops one or more tables corresponding to the given table names.
182 183 184 |
# File 'lib/sequel/database.rb', line 182 def drop_table(*names) names.each {|n| execute(drop_table_sql(n))} end |
#execute(sql) ⇒ Object
Raises a NotImplementedError. This method is overriden in descendants.
140 141 142 |
# File 'lib/sequel/database.rb', line 140 def execute(sql) raise NotImplementedError end |
#fetch(sql, *args, &block) ⇒ Object Also known as: >>
Fetches records for an arbitrary SQL statement. If a block is given, it is used to iterate over the records:
DB.fetch('SELECT * FROM items') {|r| p r}
If a block is not given, the method returns a dataset instance:
DB.fetch('SELECT * FROM items').print
Fetch can also perform parameterized queries for protection against SQL injection:
DB.fetch('SELECT * FROM items WHERE name = ?', my_name).print
A short-hand form for Database#fetch is Database#[]:
DB['SELECT * FROM items'].each {|r| p r}
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/sequel/database.rb', line 95 def fetch(sql, *args, &block) ds = dataset sql = sql.gsub('?') {|m| ds.literal(args.shift)} if block ds.fetch_rows(sql, &block) else ds.(:select_sql) {|*args| sql} ds.(:sql) {|*args| sql} ds end end |
#from(*args, &block) ⇒ Object
Returns a new dataset with the from method invoked. If a block is given, it is used as a filter on the dataset.
116 117 118 119 |
# File 'lib/sequel/database.rb', line 116 def from(*args, &block) ds = dataset.from(*args) block ? ds.filter(&block) : ds end |
#multi_threaded? ⇒ Boolean
Returns true if the database is using a multi-threaded connection pool.
44 45 46 |
# File 'lib/sequel/database.rb', line 44 def multi_threaded? !@single_threaded end |
#query(&block) ⇒ Object
Converts a query block into a dataset. For more information see Dataset#query.
110 111 112 |
# File 'lib/sequel/database.rb', line 110 def query(&block) dataset.query(&block) end |
#select(*args) ⇒ Object
Returns a new dataset with the select method invoked.
122 |
# File 'lib/sequel/database.rb', line 122 def select(*args); dataset.select(*args); end |
#serial_primary_key_options ⇒ Object
default serial primary key definition. this should be overriden for each adapter.
164 165 166 |
# File 'lib/sequel/database.rb', line 164 def {:primary_key => true, :type => :integer, :auto_increment => true} end |
#single_threaded? ⇒ Boolean
Returns true if the database is using a single-threaded connection pool.
49 50 51 |
# File 'lib/sequel/database.rb', line 49 def single_threaded? @single_threaded end |
#synchronize(&block) ⇒ Object
Acquires a database connection, yielding it to the passed block.
150 151 152 |
# File 'lib/sequel/database.rb', line 150 def synchronize(&block) @pool.hold(&block) end |
#table_exists?(name) ⇒ Boolean
Returns true if the given table exists.
187 188 189 190 191 192 193 194 195 |
# File 'lib/sequel/database.rb', line 187 def table_exists?(name) if respond_to?(:tables) tables.include?(name.to_sym) else from(name).first && true end rescue false end |
#test_connection ⇒ Object
Returns true if there is a database connection
155 156 157 158 |
# File 'lib/sequel/database.rb', line 155 def test_connection @pool.hold {|conn|} true end |
#transaction ⇒ Object
A simple implementation of SQL transactions. Nested transactions are not supported - calling #transaction within a transaction will reuse the current transaction. May be overridden for databases that support nested transactions.
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/sequel/database.rb', line 205 def transaction @pool.hold do |conn| @transactions ||= [] if @transactions.include? Thread.current return yield(conn) end conn.execute(SQL_BEGIN) begin @transactions << Thread.current result = yield(conn) conn.execute(SQL_COMMIT) result rescue => e conn.execute(SQL_ROLLBACK) raise e unless SequelRollbackError === e ensure @transactions.delete(Thread.current) end end end |
#uri ⇒ Object Also known as: url
Returns the URI identifying the database.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/sequel/database.rb', line 54 def uri uri = URI::Generic.new( self.class.adapter_scheme.to_s, nil, @opts[:host], @opts[:port], nil, "/#{@opts[:database]}", nil, nil, nil ) uri.user = @opts[:user] uri.password = @opts[:password] if uri.user uri.to_s end |