sequel 3.10.0 → 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|