sequel 3.10.0 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +68 -0
- data/COPYING +1 -1
- data/README.rdoc +87 -27
- data/bin/sequel +2 -4
- data/doc/association_basics.rdoc +1383 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/opening_databases.rdoc +45 -16
- data/doc/querying.rdoc +210 -0
- data/doc/release_notes/3.11.0.txt +254 -0
- data/doc/virtual_rows.rdoc +217 -31
- data/lib/sequel/adapters/ado.rb +28 -12
- data/lib/sequel/adapters/ado/mssql.rb +33 -1
- data/lib/sequel/adapters/amalgalite.rb +13 -8
- data/lib/sequel/adapters/db2.rb +1 -2
- data/lib/sequel/adapters/dbi.rb +7 -4
- data/lib/sequel/adapters/do.rb +14 -15
- data/lib/sequel/adapters/do/postgres.rb +4 -5
- data/lib/sequel/adapters/do/sqlite.rb +9 -0
- data/lib/sequel/adapters/firebird.rb +5 -10
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +111 -49
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +4 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +8 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +12 -0
- data/lib/sequel/adapters/mysql.rb +14 -5
- data/lib/sequel/adapters/odbc.rb +2 -4
- data/lib/sequel/adapters/odbc/mssql.rb +2 -4
- data/lib/sequel/adapters/openbase.rb +1 -2
- data/lib/sequel/adapters/oracle.rb +4 -8
- data/lib/sequel/adapters/postgres.rb +4 -11
- data/lib/sequel/adapters/shared/mssql.rb +22 -9
- data/lib/sequel/adapters/shared/mysql.rb +33 -30
- data/lib/sequel/adapters/shared/oracle.rb +0 -5
- data/lib/sequel/adapters/shared/postgres.rb +13 -11
- data/lib/sequel/adapters/shared/sqlite.rb +56 -10
- data/lib/sequel/adapters/sqlite.rb +16 -9
- data/lib/sequel/connection_pool.rb +6 -1
- data/lib/sequel/connection_pool/single.rb +1 -0
- data/lib/sequel/core.rb +6 -1
- data/lib/sequel/database.rb +52 -23
- data/lib/sequel/database/schema_generator.rb +6 -0
- data/lib/sequel/database/schema_methods.rb +5 -5
- data/lib/sequel/database/schema_sql.rb +1 -1
- data/lib/sequel/dataset.rb +4 -190
- data/lib/sequel/dataset/actions.rb +323 -1
- data/lib/sequel/dataset/features.rb +18 -2
- data/lib/sequel/dataset/graph.rb +7 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +272 -6
- data/lib/sequel/dataset/sql.rb +186 -394
- data/lib/sequel/model.rb +4 -2
- data/lib/sequel/model/associations.rb +31 -14
- data/lib/sequel/model/base.rb +32 -13
- data/lib/sequel/model/exceptions.rb +8 -4
- data/lib/sequel/model/plugins.rb +3 -13
- data/lib/sequel/plugins/active_model.rb +26 -7
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +25 -9
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +26 -0
- data/spec/adapters/mysql_spec.rb +33 -4
- data/spec/adapters/postgres_spec.rb +24 -1
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/adapters/sqlite_spec.rb +28 -0
- data/spec/core/connection_pool_spec.rb +17 -5
- data/spec/core/database_spec.rb +101 -1
- data/spec/core/dataset_spec.rb +42 -4
- data/spec/core/schema_spec.rb +13 -0
- data/spec/extensions/active_model_spec.rb +34 -11
- data/spec/extensions/caching_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/spec_helper.rb +2 -0
- data/spec/integration/dataset_test.rb +12 -1
- data/spec/integration/model_test.rb +12 -0
- data/spec/integration/plugin_test.rb +61 -1
- data/spec/integration/schema_test.rb +14 -3
- data/spec/model/base_spec.rb +27 -0
- data/spec/model/plugins_spec.rb +0 -22
- data/spec/model/record_spec.rb +32 -1
- data/spec/model/spec_helper.rb +2 -0
- metadata +14 -3
- data/lib/sequel/dataset/convenience.rb +0 -326
@@ -130,11 +130,6 @@ module Sequel
|
|
130
130
|
clone(:sequence=>s)
|
131
131
|
end
|
132
132
|
|
133
|
-
# Oracle does not support DISTINCT ON
|
134
|
-
def supports_distinct_on?
|
135
|
-
false
|
136
|
-
end
|
137
|
-
|
138
133
|
# Oracle does not support INTERSECT ALL or EXCEPT ALL
|
139
134
|
def supports_intersect_except_all?
|
140
135
|
false
|
@@ -113,24 +113,19 @@ module Sequel
|
|
113
113
|
# is true.
|
114
114
|
def apply_connection_settings
|
115
115
|
if Postgres.force_standard_strings
|
116
|
-
sql = "SET standard_conforming_strings = ON"
|
117
|
-
@db.log_info(sql)
|
118
116
|
# This setting will only work on PostgreSQL 8.2 or greater
|
119
117
|
# and we don't know the server version at this point, so
|
120
118
|
# try it unconditionally and rescue any errors.
|
121
|
-
execute(
|
119
|
+
execute("SET standard_conforming_strings = ON") rescue nil
|
122
120
|
end
|
123
121
|
if cmm = Postgres.client_min_messages
|
124
|
-
|
125
|
-
@db.log_info(sql)
|
126
|
-
execute(sql)
|
122
|
+
execute("SET client_min_messages = '#{cmm.to_s.upcase}'")
|
127
123
|
end
|
128
124
|
end
|
129
125
|
|
130
126
|
# Get the last inserted value for the given sequence.
|
131
127
|
def last_insert_id(sequence)
|
132
128
|
sql = SELECT_CURRVAL % sequence
|
133
|
-
@db.log_info(sql)
|
134
129
|
execute(sql) do |r|
|
135
130
|
val = single_value(r)
|
136
131
|
return val.to_i if val
|
@@ -140,7 +135,6 @@ module Sequel
|
|
140
135
|
# Get the primary key for the given table.
|
141
136
|
def primary_key(schema, table)
|
142
137
|
sql = SELECT_PK[schema, table]
|
143
|
-
@db.log_info(sql)
|
144
138
|
execute(sql) do |r|
|
145
139
|
return single_value(r)
|
146
140
|
end
|
@@ -149,14 +143,12 @@ module Sequel
|
|
149
143
|
# Get the primary key and sequence for the given table.
|
150
144
|
def sequence(schema, table)
|
151
145
|
sql = SELECT_SERIAL_SEQUENCE[schema, table]
|
152
|
-
@db.log_info(sql)
|
153
146
|
execute(sql) do |r|
|
154
147
|
seq = single_value(r)
|
155
148
|
return seq if seq
|
156
149
|
end
|
157
150
|
|
158
151
|
sql = SELECT_CUSTOM_SEQUENCE[schema, table]
|
159
|
-
@db.log_info(sql)
|
160
152
|
execute(sql) do |r|
|
161
153
|
return single_value(r)
|
162
154
|
end
|
@@ -501,6 +493,11 @@ module Sequel
|
|
501
493
|
nil
|
502
494
|
end
|
503
495
|
end
|
496
|
+
|
497
|
+
# Don't log, since logging is done by the underlying connection.
|
498
|
+
def log_connection_execute(conn, sql)
|
499
|
+
conn.execute(sql)
|
500
|
+
end
|
504
501
|
|
505
502
|
# Use a dollar sign instead of question mark for the argument
|
506
503
|
# placeholder.
|
@@ -702,6 +699,11 @@ module Sequel
|
|
702
699
|
[insert_sql(columns, LiteralString.new('VALUES ' + values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)))]
|
703
700
|
end
|
704
701
|
|
702
|
+
# DISTINCT ON is a PostgreSQL extension
|
703
|
+
def supports_distinct_on?
|
704
|
+
true
|
705
|
+
end
|
706
|
+
|
705
707
|
# PostgreSQL supports modifying joined datasets
|
706
708
|
def supports_modifying_joins?
|
707
709
|
true
|
@@ -758,7 +760,7 @@ module Sequel
|
|
758
760
|
|
759
761
|
# Use a generic blob quoting method, hopefully overridden in one of the subadapter methods
|
760
762
|
def literal_blob(v)
|
761
|
-
"'#{v.gsub(/[\000-\037\047\134\177-\377]/){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"}}'"
|
763
|
+
"'#{v.gsub(/[\000-\037\047\134\177-\377]/n){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"}}'"
|
762
764
|
end
|
763
765
|
|
764
766
|
# PostgreSQL uses FALSE for false values
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Sequel
|
2
2
|
module SQLite
|
3
|
+
# No matter how you connect to SQLite, the following Database options
|
4
|
+
# can be used to set PRAGMAs on connections in a thread-safe manner:
|
5
|
+
# :auto_vacuum, :foreign_keys, :synchronous, and :temp_store.
|
3
6
|
module DatabaseMethods
|
4
7
|
AUTO_VACUUM = [:none, :full, :incremental].freeze
|
5
8
|
PRIMARY_KEY_INDEX_RE = /\Asqlite_autoindex_/.freeze
|
@@ -21,7 +24,8 @@ module Sequel
|
|
21
24
|
end
|
22
25
|
|
23
26
|
# Set the auto_vacuum PRAGMA using the given symbol (:none, :full, or
|
24
|
-
# :incremental).
|
27
|
+
# :incremental). See pragma_set. Consider using the :auto_vacuum
|
28
|
+
# Database option instead.
|
25
29
|
def auto_vacuum=(value)
|
26
30
|
value = AUTO_VACUUM.index(value) || (raise Error, "Invalid value for auto_vacuum option. Please specify one of :none, :full, :incremental.")
|
27
31
|
pragma_set(:auto_vacuum, value)
|
@@ -31,6 +35,19 @@ module Sequel
|
|
31
35
|
def database_type
|
32
36
|
:sqlite
|
33
37
|
end
|
38
|
+
|
39
|
+
# Boolean signifying the value of the foreign_keys PRAGMA, or nil
|
40
|
+
# if not using SQLite 3.6.19+.
|
41
|
+
def foreign_keys
|
42
|
+
pragma_get(:foreign_keys).to_i == 1 if sqlite_version >= 30619
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set the foreign_keys PRAGMA using the given boolean value, if using
|
46
|
+
# SQLite 3.6.19+. If not using 3.6.19+, no error is raised. See pragma_set.
|
47
|
+
# Consider using the :foreign_keys Database option instead.
|
48
|
+
def foreign_keys=(value)
|
49
|
+
pragma_set(:foreign_keys, !!value ? 'on' : 'off') if sqlite_version >= 30619
|
50
|
+
end
|
34
51
|
|
35
52
|
# Return a hash containing index information. Hash keys are index name symbols.
|
36
53
|
# Values are subhashes with two keys, :columns and :unique. The value of :columns
|
@@ -61,13 +78,30 @@ module Sequel
|
|
61
78
|
end
|
62
79
|
|
63
80
|
# Set the value of the given PRAGMA to value.
|
81
|
+
#
|
82
|
+
# This method is not thread safe, and will not work correctly if there
|
83
|
+
# are multiple connections in the Database's connection pool. PRAGMA
|
84
|
+
# modifications should be done when the connection is created, using
|
85
|
+
# an option provided when creating the Database object.
|
64
86
|
def pragma_set(name, value)
|
65
87
|
execute_ddl("PRAGMA #{name} = #{value}")
|
66
88
|
end
|
67
89
|
|
68
|
-
#
|
90
|
+
# The version of the server as an integer, where 3.6.19 = 30619.
|
91
|
+
# If the server version can't be determined, 0 is used.
|
92
|
+
def sqlite_version
|
93
|
+
return @sqlite_version if defined?(@sqlite_version)
|
94
|
+
@sqlite_version = begin
|
95
|
+
v = get{sqlite_version{}}
|
96
|
+
[10000, 100, 1].zip(v.split('.')).inject(0){|a, m| a + m[0] * Integer(m[1])}
|
97
|
+
rescue
|
98
|
+
0
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# SQLite 3.6.8+ supports savepoints.
|
69
103
|
def supports_savepoints?
|
70
|
-
|
104
|
+
sqlite_version >= 30608
|
71
105
|
end
|
72
106
|
|
73
107
|
# A symbol signifying the value of the synchronous PRAGMA.
|
@@ -75,7 +109,8 @@ module Sequel
|
|
75
109
|
SYNCHRONOUS[pragma_get(:synchronous).to_i]
|
76
110
|
end
|
77
111
|
|
78
|
-
# Set the synchronous PRAGMA using the given symbol (:off, :normal, or :full).
|
112
|
+
# Set the synchronous PRAGMA using the given symbol (:off, :normal, or :full). See pragma_set.
|
113
|
+
# Consider using the :synchronous Database option instead.
|
79
114
|
def synchronous=(value)
|
80
115
|
value = SYNCHRONOUS.index(value) || (raise Error, "Invalid value for synchronous option. Please specify one of :off, :normal, :full.")
|
81
116
|
pragma_set(:synchronous, value)
|
@@ -95,7 +130,8 @@ module Sequel
|
|
95
130
|
TEMP_STORE[pragma_get(:temp_store).to_i]
|
96
131
|
end
|
97
132
|
|
98
|
-
# Set the temp_store PRAGMA using the given symbol (:default, :file, or :memory).
|
133
|
+
# Set the temp_store PRAGMA using the given symbol (:default, :file, or :memory). See pragma_set.
|
134
|
+
# Consider using the :temp_store Database option instead.
|
99
135
|
def temp_store=(value)
|
100
136
|
value = TEMP_STORE.index(value) || (raise Error, "Invalid value for temp_store option. Please specify one of :default, :file, :memory.")
|
101
137
|
pragma_set(:temp_store, value)
|
@@ -195,6 +231,21 @@ module Sequel
|
|
195
231
|
def identifier_output_method_default
|
196
232
|
nil
|
197
233
|
end
|
234
|
+
|
235
|
+
# Array of PRAGMA SQL statements based on the Database options that should be applied to
|
236
|
+
# new connections.
|
237
|
+
def connection_pragmas
|
238
|
+
ps = []
|
239
|
+
v = typecast_value_boolean(opts.fetch(:foreign_keys, 1))
|
240
|
+
ps << "PRAGMA foreign_keys = #{v ? 1 : 0}"
|
241
|
+
[[:auto_vacuum, AUTO_VACUUM], [:synchronous, SYNCHRONOUS], [:temp_store, TEMP_STORE]].each do |prag, con|
|
242
|
+
if v = opts[prag]
|
243
|
+
raise(Error, "Value for PRAGMA #{prag} not supported, should be one of #{con.join(', ')}") unless v = con.index(v.to_sym)
|
244
|
+
ps << "PRAGMA #{prag} = #{v}"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
ps
|
248
|
+
end
|
198
249
|
|
199
250
|
# Parse the output of the table_info pragma
|
200
251
|
def parse_pragma(table_name, opts)
|
@@ -265,11 +316,6 @@ module Sequel
|
|
265
316
|
@opts[:where] ? super : filter(1=>1).delete
|
266
317
|
end
|
267
318
|
|
268
|
-
# SQLite does not support DISTINCT ON
|
269
|
-
def supports_distinct_on?
|
270
|
-
false
|
271
|
-
end
|
272
|
-
|
273
319
|
# Return an array of strings specifying a query explanation for a SELECT of the
|
274
320
|
# current dataset.
|
275
321
|
def explain
|
@@ -37,6 +37,8 @@ module Sequel
|
|
37
37
|
db.busy_timeout(opts.fetch(:timeout, 5000))
|
38
38
|
db.type_translation = true
|
39
39
|
|
40
|
+
connection_pragmas.each{|s| log_yield(s){db.execute_batch(s)}}
|
41
|
+
|
40
42
|
# Handle datetimes with Sequel.datetime_class
|
41
43
|
prok = proc do |t,v|
|
42
44
|
v = Time.at(v.to_i).iso8601 if UNIX_EPOCH_TIME_FORMAT.match(v)
|
@@ -70,32 +72,37 @@ module Sequel
|
|
70
72
|
|
71
73
|
# Run the given SQL with the given arguments and return the number of changed rows.
|
72
74
|
def execute_dui(sql, opts={})
|
73
|
-
_execute(
|
75
|
+
_execute(opts){|conn| log_yield(sql, opts[:arguments]){conn.execute_batch(sql, opts[:arguments])}; conn.changes}
|
74
76
|
end
|
75
77
|
|
76
78
|
# Run the given SQL with the given arguments and return the last inserted row id.
|
77
79
|
def execute_insert(sql, opts={})
|
78
|
-
_execute(
|
80
|
+
_execute(opts){|conn| log_yield(sql, opts[:arguments]){conn.execute(sql, opts[:arguments])}; conn.last_insert_row_id}
|
79
81
|
end
|
80
82
|
|
81
83
|
# Run the given SQL with the given arguments and yield each row.
|
82
|
-
def execute(sql, opts={}
|
83
|
-
_execute(
|
84
|
+
def execute(sql, opts={})
|
85
|
+
_execute(opts) do |conn|
|
86
|
+
begin
|
87
|
+
yield(result = log_yield(sql, opts[:arguments]){conn.query(sql, opts[:arguments])})
|
88
|
+
ensure
|
89
|
+
result.close if result
|
90
|
+
end
|
91
|
+
end
|
84
92
|
end
|
85
93
|
|
86
94
|
# Run the given SQL with the given arguments and return the first value of the first row.
|
87
95
|
def single_value(sql, opts={})
|
88
|
-
_execute(
|
96
|
+
_execute(opts){|conn| log_yield(sql, opts[:arguments]){conn.get_first_value(sql, opts[:arguments])}}
|
89
97
|
end
|
90
98
|
|
91
99
|
private
|
92
100
|
|
93
|
-
#
|
101
|
+
# Yield an available connection. Rescue
|
94
102
|
# any SQLite3::Exceptions and turn them into DatabaseErrors.
|
95
|
-
def _execute(
|
103
|
+
def _execute(opts, &block)
|
96
104
|
begin
|
97
|
-
|
98
|
-
synchronize(opts[:server]){|conn| yield conn}
|
105
|
+
synchronize(opts[:server], &block)
|
99
106
|
rescue SQLite3::Exception => e
|
100
107
|
raise_error(e)
|
101
108
|
end
|
@@ -60,12 +60,16 @@ class Sequel::ConnectionPool
|
|
60
60
|
# Instantiates a connection pool with the given options. The block is called
|
61
61
|
# with a single symbol (specifying the server/shard to use) every time a new
|
62
62
|
# connection is needed. The following options are respected for all connection
|
63
|
-
# pools:
|
63
|
+
# pools:
|
64
|
+
# * :after_connect - The proc called after each new connection is made, with the
|
65
|
+
# connection object, useful for customizations that you want to apply to all
|
66
|
+
# connections.
|
64
67
|
# * :disconnection_proc - The proc called when removing connections from the pool,
|
65
68
|
# which is passed the connection to disconnect.
|
66
69
|
def initialize(opts={}, &block)
|
67
70
|
raise(Sequel::Error, "No connection proc specified") unless @connection_proc = block
|
68
71
|
@disconnection_proc = opts[:disconnection_proc]
|
72
|
+
@after_connect = opts[:after_connect]
|
69
73
|
end
|
70
74
|
|
71
75
|
# Alias for size, not aliased directly for ease of subclass implementation
|
@@ -85,6 +89,7 @@ class Sequel::ConnectionPool
|
|
85
89
|
def make_new(server)
|
86
90
|
begin
|
87
91
|
conn = @connection_proc.call(server)
|
92
|
+
@after_connect.call(conn) if @after_connect
|
88
93
|
rescue Exception=>exception
|
89
94
|
raise Sequel.convert_exception_class(exception, Sequel::DatabaseConnectionError)
|
90
95
|
end
|
data/lib/sequel/core.rb
CHANGED
@@ -46,6 +46,9 @@
|
|
46
46
|
#
|
47
47
|
# You can set the SEQUEL_NO_CORE_EXTENSIONS constant or environment variable to have
|
48
48
|
# Sequel not extend the core classes.
|
49
|
+
#
|
50
|
+
# For a more expanded introduction, see the {README}[link:files/README_rdoc.html].
|
51
|
+
# For a quicker introduction, see the {cheat sheet}[link:files/doc/cheat_sheet_rdoc.html].
|
49
52
|
module Sequel
|
50
53
|
@convert_two_digit_years = true
|
51
54
|
@datetime_class = Time
|
@@ -117,6 +120,9 @@ module Sequel
|
|
117
120
|
# closed when the block exits. For example:
|
118
121
|
#
|
119
122
|
# Sequel.connect('sqlite://blog.db'){|db| puts db[:users].count}
|
123
|
+
#
|
124
|
+
# For details, see the {"Connecting to a Database" guide}[link:files/doc/opening_databases_rdoc.html].
|
125
|
+
# To set up a master/slave or sharded database connection, see the {"Master/Slave Databases and Sharding" guide}[link:files/doc/sharding_rdoc.html].
|
120
126
|
def self.connect(*args, &block)
|
121
127
|
Database.connect(*args, &block)
|
122
128
|
end
|
@@ -280,7 +286,6 @@ module Sequel
|
|
280
286
|
|
281
287
|
require(%w"metaprogramming sql connection_pool exceptions dataset database timezones version")
|
282
288
|
require(%w"schema_generator schema_methods schema_sql", 'database')
|
283
|
-
require(%w"actions convenience features graph prepared_statements query sql", 'dataset')
|
284
289
|
require('core_sql') if !defined?(::SEQUEL_NO_CORE_EXTENSIONS) && !ENV.has_key?('SEQUEL_NO_CORE_EXTENSIONS')
|
285
290
|
|
286
291
|
# Add the database adapter class methods to Sequel via metaprogramming
|
data/lib/sequel/database.rb
CHANGED
@@ -50,6 +50,10 @@ module Sequel
|
|
50
50
|
# The default schema to use, generally should be nil.
|
51
51
|
attr_accessor :default_schema
|
52
52
|
|
53
|
+
# Numeric specifying the duration beyond which queries are logged at warn
|
54
|
+
# level instead of info level.
|
55
|
+
attr_accessor :log_warn_duration
|
56
|
+
|
53
57
|
# Array of SQL loggers to use for this database
|
54
58
|
attr_accessor :loggers
|
55
59
|
|
@@ -82,13 +86,14 @@ module Sequel
|
|
82
86
|
@opts ||= opts
|
83
87
|
@opts = connection_pool_default_options.merge(@opts)
|
84
88
|
@loggers = Array(@opts[:logger]) + Array(@opts[:loggers])
|
89
|
+
self.log_warn_duration = @opts[:log_warn_duration]
|
85
90
|
@opts[:disconnection_proc] ||= proc{|conn| disconnect_connection(conn)}
|
86
91
|
block ||= proc{|server| connect(server)}
|
87
92
|
@opts[:servers] = {} if @opts[:servers].is_a?(String)
|
88
93
|
|
89
|
-
@opts[:single_threaded] = @single_threaded = @opts.
|
94
|
+
@opts[:single_threaded] = @single_threaded = typecast_value_boolean(@opts.fetch(:single_threaded, @@single_threaded))
|
90
95
|
@schemas = {}
|
91
|
-
@default_schema = opts.
|
96
|
+
@default_schema = @opts.fetch(:default_schema, default_schema_default)
|
92
97
|
@prepared_statements = {}
|
93
98
|
@transactions = []
|
94
99
|
@identifier_input_method = nil
|
@@ -129,7 +134,7 @@ module Sequel
|
|
129
134
|
end
|
130
135
|
|
131
136
|
# Connects to a database. See Sequel.connect.
|
132
|
-
def self.connect(conn_string, opts = {}
|
137
|
+
def self.connect(conn_string, opts = {})
|
133
138
|
case conn_string
|
134
139
|
when String
|
135
140
|
if match = /\A(jdbc|do):/o.match(conn_string)
|
@@ -157,18 +162,17 @@ module Sequel
|
|
157
162
|
m[k.to_sym] = v
|
158
163
|
m
|
159
164
|
end
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
+
begin
|
166
|
+
db = c.new(opts)
|
167
|
+
db.test_connection if opts[:test] && db.send(:typecast_value_boolean, opts[:test])
|
168
|
+
result = yield(db) if block_given?
|
169
|
+
ensure
|
170
|
+
if block_given?
|
165
171
|
db.disconnect if db
|
166
172
|
::Sequel::DATABASES.delete(db)
|
167
173
|
end
|
168
|
-
result
|
169
|
-
else
|
170
|
-
c.new(opts)
|
171
174
|
end
|
175
|
+
block_given? ? result : db
|
172
176
|
end
|
173
177
|
|
174
178
|
# The method to call on identifiers going into the database
|
@@ -389,7 +393,7 @@ module Sequel
|
|
389
393
|
def identifier_input_method
|
390
394
|
case @identifier_input_method
|
391
395
|
when nil
|
392
|
-
@identifier_input_method = @opts.
|
396
|
+
@identifier_input_method = @opts.fetch(:identifier_input_method, (@@identifier_input_method.nil? ? identifier_input_method_default : @@identifier_input_method))
|
393
397
|
@identifier_input_method == "" ? nil : @identifier_input_method
|
394
398
|
when ""
|
395
399
|
nil
|
@@ -408,7 +412,7 @@ module Sequel
|
|
408
412
|
def identifier_output_method
|
409
413
|
case @identifier_output_method
|
410
414
|
when nil
|
411
|
-
@identifier_output_method = @opts.
|
415
|
+
@identifier_output_method = @opts.fetch(:identifier_output_method, (@@identifier_output_method.nil? ? identifier_output_method_default : @@identifier_output_method))
|
412
416
|
@identifier_output_method == "" ? nil : @identifier_output_method
|
413
417
|
when ""
|
414
418
|
nil
|
@@ -435,11 +439,25 @@ module Sequel
|
|
435
439
|
schema_utility_dataset.literal(v)
|
436
440
|
end
|
437
441
|
|
438
|
-
# Log a message at level info to all loggers.
|
439
|
-
# goes through this method.
|
442
|
+
# Log a message at level info to all loggers.
|
440
443
|
def log_info(message, args=nil)
|
441
|
-
|
442
|
-
|
444
|
+
log_each(:info, args ? "#{message}; #{args.inspect}" : message)
|
445
|
+
end
|
446
|
+
|
447
|
+
# Yield to the block, logging any errors at error level to all loggers,
|
448
|
+
# and all other queries with the duration at warn or info level.
|
449
|
+
def log_yield(sql, args=nil)
|
450
|
+
return yield if @loggers.empty?
|
451
|
+
sql = "#{sql}; #{args.inspect}" if args
|
452
|
+
start = Time.now
|
453
|
+
begin
|
454
|
+
yield
|
455
|
+
rescue => e
|
456
|
+
log_each(:error, "#{e.class}: #{e.message.strip}: #{sql}")
|
457
|
+
raise
|
458
|
+
ensure
|
459
|
+
log_duration(Time.now - start, sql) unless e
|
460
|
+
end
|
443
461
|
end
|
444
462
|
|
445
463
|
# Remove any existing loggers and just use the given logger.
|
@@ -456,7 +474,7 @@ module Sequel
|
|
456
474
|
# Returns true if the database quotes identifiers.
|
457
475
|
def quote_identifiers?
|
458
476
|
return @quote_identifiers unless @quote_identifiers.nil?
|
459
|
-
@quote_identifiers = @opts.
|
477
|
+
@quote_identifiers = @opts.fetch(:quote_identifiers, (@@quote_identifiers.nil? ? quote_identifiers_default : @@quote_identifiers))
|
460
478
|
end
|
461
479
|
|
462
480
|
# Dynamically remove existing servers from the connection pool. Intended for
|
@@ -818,8 +836,19 @@ module Sequel
|
|
818
836
|
# Log the given SQL and then execute it on the connection, used by
|
819
837
|
# the transaction code.
|
820
838
|
def log_connection_execute(conn, sql)
|
821
|
-
|
822
|
-
|
839
|
+
log_yield(sql){conn.send(connection_execute_method, sql)}
|
840
|
+
end
|
841
|
+
|
842
|
+
# Log message with message prefixed by duration at info level, or
|
843
|
+
# warn level if duration is greater than log_warn_duration.
|
844
|
+
def log_duration(duration, message)
|
845
|
+
log_each((lwd = log_warn_duration and duration >= lwd) ? :warn : :info, "(#{sprintf('%0.6fs', duration)}) #{message}")
|
846
|
+
end
|
847
|
+
|
848
|
+
# Log message at level (which should be :error, :warn, or :info)
|
849
|
+
# to all loggers.
|
850
|
+
def log_each(level, message)
|
851
|
+
@loggers.each{|logger| logger.send(level, message)}
|
823
852
|
end
|
824
853
|
|
825
854
|
# Return a dataset that uses the default identifier input and output methods
|
@@ -924,11 +953,11 @@ module Sequel
|
|
924
953
|
:boolean
|
925
954
|
when /\A(real|float|double( precision)?)\z/io
|
926
955
|
:float
|
927
|
-
when /\A(((
|
928
|
-
:decimal
|
956
|
+
when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(\d+)\))?)|(?:small)?money)\z/io
|
957
|
+
$1 && $1 == '0' ? :integer : :decimal
|
929
958
|
when /bytea|blob|image|(var)?binary/io
|
930
959
|
:blob
|
931
|
-
when /\Aenum/
|
960
|
+
when /\Aenum/io
|
932
961
|
:enum
|
933
962
|
end
|
934
963
|
end
|