sequel 2.11.0 → 2.12.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 +168 -0
- data/README.rdoc +77 -95
- data/Rakefile +100 -80
- data/bin/sequel +2 -1
- data/doc/advanced_associations.rdoc +23 -32
- data/doc/cheat_sheet.rdoc +23 -40
- data/doc/dataset_filtering.rdoc +6 -6
- data/doc/prepared_statements.rdoc +22 -22
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/schema.rdoc +3 -1
- data/doc/sharding.rdoc +8 -8
- data/doc/virtual_rows.rdoc +65 -0
- data/lib/sequel.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
- data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
- data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
- data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
- data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
- data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
- data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
- data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
- data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
- data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
- data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
- data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
- data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
- data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
- data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
- data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
- data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
- data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
- data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
- data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
- data/lib/sequel/core.rb +221 -0
- data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
- data/lib/{sequel_core → sequel}/database.rb +264 -149
- data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
- data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
- data/lib/sequel/database/schema_sql.rb +224 -0
- data/lib/{sequel_core → sequel}/dataset.rb +78 -236
- data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
- data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
- data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
- data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
- data/lib/sequel/deprecated.rb +593 -0
- data/lib/sequel/deprecated_migration.rb +91 -0
- data/lib/sequel/exceptions.rb +48 -0
- data/lib/sequel/extensions/blank.rb +42 -0
- data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
- data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
- data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
- data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
- data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
- data/lib/sequel/extensions/string_date_time.rb +47 -0
- data/lib/sequel/metaprogramming.rb +43 -0
- data/lib/sequel/model.rb +110 -0
- data/lib/sequel/model/associations.rb +1300 -0
- data/lib/sequel/model/base.rb +937 -0
- data/lib/sequel/model/deprecated.rb +204 -0
- data/lib/sequel/model/deprecated_hooks.rb +103 -0
- data/lib/sequel/model/deprecated_inflector.rb +335 -0
- data/lib/sequel/model/deprecated_validations.rb +388 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
- data/lib/sequel/model/inflections.rb +208 -0
- data/lib/sequel/model/plugins.rb +76 -0
- data/lib/sequel/plugins/caching.rb +122 -0
- data/lib/sequel/plugins/hook_class_methods.rb +122 -0
- data/lib/sequel/plugins/schema.rb +53 -0
- data/lib/sequel/plugins/serialization.rb +117 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
- data/lib/sequel/plugins/validation_class_methods.rb +384 -0
- data/lib/sequel/plugins/validation_helpers.rb +150 -0
- data/lib/{sequel_core → sequel}/sql.rb +125 -190
- data/lib/{sequel_core → sequel}/version.rb +2 -1
- data/lib/sequel_core.rb +1 -172
- data/lib/sequel_model.rb +1 -91
- data/spec/adapters/firebird_spec.rb +5 -5
- data/spec/adapters/informix_spec.rb +1 -1
- data/spec/adapters/mysql_spec.rb +128 -42
- data/spec/adapters/oracle_spec.rb +47 -19
- data/spec/adapters/postgres_spec.rb +64 -52
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +12 -17
- data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
- data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
- data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
- data/spec/{sequel_core → core}/database_spec.rb +135 -99
- data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
- data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
- data/spec/core/migration_spec.rb +263 -0
- data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
- data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
- data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
- data/spec/{sequel_core → core}/schema_spec.rb +8 -10
- data/spec/{sequel_core → core}/spec_helper.rb +29 -2
- data/spec/{sequel_core → core}/version_spec.rb +0 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/caching_spec.rb +201 -0
- data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
- data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
- data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
- data/spec/extensions/serialization_spec.rb +109 -0
- data/spec/extensions/single_table_inheritance_spec.rb +53 -0
- data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
- data/spec/extensions/validation_helpers_spec.rb +291 -0
- data/spec/integration/dataset_test.rb +31 -0
- data/spec/integration/eager_loader_test.rb +17 -30
- data/spec/integration/schema_test.rb +8 -5
- data/spec/integration/spec_helper.rb +17 -0
- data/spec/integration/transaction_test.rb +68 -0
- data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
- data/spec/{sequel_model → model}/associations_spec.rb +23 -10
- data/spec/{sequel_model → model}/base_spec.rb +29 -20
- data/spec/{sequel_model → model}/caching_spec.rb +16 -14
- data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
- data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
- data/spec/model/hooks_spec.rb +472 -0
- data/spec/model/inflector_spec.rb +126 -0
- data/spec/{sequel_model → model}/model_spec.rb +25 -20
- data/spec/model/plugins_spec.rb +142 -0
- data/spec/{sequel_model → model}/record_spec.rb +121 -62
- data/spec/model/schema_spec.rb +92 -0
- data/spec/model/spec_helper.rb +124 -0
- data/spec/model/validations_spec.rb +1080 -0
- metadata +136 -107
- data/lib/sequel_core/core_ext.rb +0 -217
- data/lib/sequel_core/dataset/callback.rb +0 -13
- data/lib/sequel_core/dataset/schema.rb +0 -15
- data/lib/sequel_core/deprecated.rb +0 -26
- data/lib/sequel_core/exceptions.rb +0 -44
- data/lib/sequel_core/schema.rb +0 -2
- data/lib/sequel_core/schema/sql.rb +0 -325
- data/lib/sequel_model/association_reflection.rb +0 -267
- data/lib/sequel_model/associations.rb +0 -499
- data/lib/sequel_model/base.rb +0 -539
- data/lib/sequel_model/caching.rb +0 -82
- data/lib/sequel_model/dataset_methods.rb +0 -26
- data/lib/sequel_model/eager_loading.rb +0 -370
- data/lib/sequel_model/hooks.rb +0 -101
- data/lib/sequel_model/plugins.rb +0 -62
- data/lib/sequel_model/record.rb +0 -568
- data/lib/sequel_model/schema.rb +0 -49
- data/lib/sequel_model/validations.rb +0 -429
- data/spec/sequel_model/plugins_spec.rb +0 -80
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
require '
|
|
1
|
+
Sequel.require 'adapters/utils/unsupported'
|
|
2
2
|
|
|
3
3
|
module Sequel
|
|
4
4
|
module SQLite
|
|
5
5
|
module DatabaseMethods
|
|
6
|
-
AUTO_VACUUM =
|
|
7
|
-
SYNCHRONOUS =
|
|
6
|
+
AUTO_VACUUM = [:none, :full, :incremental].freeze
|
|
7
|
+
SYNCHRONOUS = [:off, :normal, :full].freeze
|
|
8
8
|
TABLES_FILTER = "type = 'table' AND NOT name = 'sqlite_sequence'"
|
|
9
|
-
TEMP_STORE =
|
|
10
|
-
TYPES = Sequel::
|
|
9
|
+
TEMP_STORE = [:default, :file, :memory].freeze
|
|
10
|
+
TYPES = Sequel::Database::TYPES.merge(Bignum=>'integer')
|
|
11
11
|
|
|
12
12
|
# Run all alter_table commands in a transaction. This is technically only
|
|
13
13
|
# needed for drop column.
|
|
@@ -15,6 +15,64 @@ module Sequel
|
|
|
15
15
|
transaction{super}
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
# A symbol signifying the value of the auto_vacuum PRAGMA.
|
|
19
|
+
def auto_vacuum
|
|
20
|
+
AUTO_VACUUM[pragma_get(:auto_vacuum).to_i]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Set the auto_vacuum PRAGMA using the given symbol (:none, :full, or
|
|
24
|
+
# :incremental).
|
|
25
|
+
def auto_vacuum=(value)
|
|
26
|
+
value = AUTO_VACUUM.index(value) || (raise Error, "Invalid value for auto_vacuum option. Please specify one of :none, :full, :incremental.")
|
|
27
|
+
pragma_set(:auto_vacuum, value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Get the value of the given PRAGMA.
|
|
31
|
+
def pragma_get(name)
|
|
32
|
+
self["PRAGMA #{name}"].single_value
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Set the value of the given PRAGMA to value.
|
|
36
|
+
def pragma_set(name, value)
|
|
37
|
+
execute_ddl("PRAGMA #{name} = #{value}")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# A symbol signifying the value of the synchronous PRAGMA.
|
|
41
|
+
def synchronous
|
|
42
|
+
SYNCHRONOUS[pragma_get(:synchronous).to_i]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Set the synchronous PRAGMA using the given symbol (:off, :normal, or :full).
|
|
46
|
+
def synchronous=(value)
|
|
47
|
+
value = SYNCHRONOUS.index(value) || (raise Error, "Invalid value for synchronous option. Please specify one of :off, :normal, :full.")
|
|
48
|
+
pragma_set(:synchronous, value)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Array of symbols specifying the table names in the current database.
|
|
52
|
+
#
|
|
53
|
+
# Options:
|
|
54
|
+
# * :server - Set the server to use.
|
|
55
|
+
def tables(opts={})
|
|
56
|
+
ds = self[:sqlite_master].server(opts[:server]).filter(TABLES_FILTER)
|
|
57
|
+
ds.identifier_output_method = nil
|
|
58
|
+
ds.identifier_input_method = nil
|
|
59
|
+
ds2 = dataset
|
|
60
|
+
ds.map{|r| ds2.send(:output_identifier, r[:name])}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# A symbol signifying the value of the temp_store PRAGMA.
|
|
64
|
+
def temp_store
|
|
65
|
+
TEMP_STORE[pragma_get(:temp_store).to_i]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Set the temp_store PRAGMA using the given symbol (:default, :file, or :memory).
|
|
69
|
+
def temp_store=(value)
|
|
70
|
+
value = TEMP_STORE.index(value) || (raise Error, "Invalid value for temp_store option. Please specify one of :default, :file, :memory.")
|
|
71
|
+
pragma_set(:temp_store, value)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
18
76
|
# SQLite supports limited table modification. You can add a column
|
|
19
77
|
# or an index. Dropping columns is supported by copying the table into
|
|
20
78
|
# a temporary table, dropping the table, and creating a new table without
|
|
@@ -68,64 +126,6 @@ module Sequel
|
|
|
68
126
|
end
|
|
69
127
|
end
|
|
70
128
|
|
|
71
|
-
# A symbol signifying the value of the auto_vacuum PRAGMA.
|
|
72
|
-
def auto_vacuum
|
|
73
|
-
AUTO_VACUUM[pragma_get(:auto_vacuum).to_s]
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Set the auto_vacuum PRAGMA using the given symbol (:none, :full, or
|
|
77
|
-
# :incremental).
|
|
78
|
-
def auto_vacuum=(value)
|
|
79
|
-
value = AUTO_VACUUM.key(value) || (raise Error, "Invalid value for auto_vacuum option. Please specify one of :none, :full, :incremental.")
|
|
80
|
-
pragma_set(:auto_vacuum, value)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Get the value of the given PRAGMA.
|
|
84
|
-
def pragma_get(name)
|
|
85
|
-
self["PRAGMA #{name}"].single_value
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# Set the value of the given PRAGMA to value.
|
|
89
|
-
def pragma_set(name, value)
|
|
90
|
-
execute_ddl("PRAGMA #{name} = #{value}")
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# A symbol signifying the value of the synchronous PRAGMA.
|
|
94
|
-
def synchronous
|
|
95
|
-
SYNCHRONOUS[pragma_get(:synchronous).to_s]
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Set the synchronous PRAGMA using the given symbol (:off, :normal, or :full).
|
|
99
|
-
def synchronous=(value)
|
|
100
|
-
value = SYNCHRONOUS.key(value) || (raise Error, "Invalid value for synchronous option. Please specify one of :off, :normal, :full.")
|
|
101
|
-
pragma_set(:synchronous, value)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Array of symbols specifying the table names in the current database.
|
|
105
|
-
#
|
|
106
|
-
# Options:
|
|
107
|
-
# * :server - Set the server to use.
|
|
108
|
-
def tables(opts={})
|
|
109
|
-
ds = self[:sqlite_master].server(opts[:server]).filter(TABLES_FILTER)
|
|
110
|
-
ds.identifier_output_method = nil
|
|
111
|
-
ds.identifier_input_method = nil
|
|
112
|
-
ds2 = dataset
|
|
113
|
-
ds.map{|r| ds2.send(:output_identifier, r[:name])}
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# A symbol signifying the value of the temp_store PRAGMA.
|
|
117
|
-
def temp_store
|
|
118
|
-
TEMP_STORE[pragma_get(:temp_store).to_s]
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# Set the temp_store PRAGMA using the given symbol (:default, :file, or :memory).
|
|
122
|
-
def temp_store=(value)
|
|
123
|
-
value = TEMP_STORE.key(value) || (raise Error, "Invalid value for temp_store option. Please specify one of :default, :file, :memory.")
|
|
124
|
-
pragma_set(:temp_store, value)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
private
|
|
128
|
-
|
|
129
129
|
# The array of column symbols in the table, except for ones given in opts[:except]
|
|
130
130
|
def backup_table_name(table, opts={})
|
|
131
131
|
(opts[:times]||1000).times do |i|
|
|
@@ -172,7 +172,7 @@ module Sequel
|
|
|
172
172
|
row[:allow_null] = row.delete(:notnull).to_i == 0
|
|
173
173
|
row[:default] = row.delete(:dflt_value)
|
|
174
174
|
row[:primary_key] = row.delete(:pk).to_i == 1
|
|
175
|
-
row[:default] = nil if row[:default]
|
|
175
|
+
row[:default] = nil if blank_object?(row[:default])
|
|
176
176
|
row[:db_type] = row.delete(:type)
|
|
177
177
|
row[:type] = schema_column_type(row[:db_type])
|
|
178
178
|
row
|
|
@@ -197,6 +197,7 @@ module Sequel
|
|
|
197
197
|
# Instance methods for datasets that connect to an SQLite database
|
|
198
198
|
module DatasetMethods
|
|
199
199
|
include Dataset::UnsupportedIntersectExceptAll
|
|
200
|
+
include Dataset::UnsupportedIsTrue
|
|
200
201
|
|
|
201
202
|
# SQLite does not support pattern matching via regular expressions.
|
|
202
203
|
# SQLite is case insensitive (depending on pragma), so use LIKE for
|
|
@@ -216,10 +217,14 @@ module Sequel
|
|
|
216
217
|
# SQLite performs a TRUNCATE style DELETE if no filter is specified.
|
|
217
218
|
# Since we want to always return the count of records, add a condition
|
|
218
219
|
# that is always true and then delete.
|
|
219
|
-
def delete(opts = {})
|
|
220
|
+
def delete(opts = (defarg=true;{}))
|
|
220
221
|
# check if no filter is specified
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
if defarg
|
|
223
|
+
@opts[:where] ? super() : filter(1=>1).delete
|
|
224
|
+
else
|
|
225
|
+
opts = @opts.merge(opts)
|
|
226
|
+
super(opts[:where] ? opts : opts.merge(:where=>{1=>1}))
|
|
227
|
+
end
|
|
223
228
|
end
|
|
224
229
|
|
|
225
230
|
# Insert the values into the database.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'sqlite3'
|
|
2
|
-
require '
|
|
2
|
+
Sequel.require 'adapters/shared/sqlite'
|
|
3
3
|
|
|
4
4
|
module Sequel
|
|
5
5
|
# Top level module for holding all SQLite-related modules and classes
|
|
@@ -27,7 +27,7 @@ module Sequel
|
|
|
27
27
|
# be available if it is locked, given in milliseconds (default is 5000).
|
|
28
28
|
def connect(server)
|
|
29
29
|
opts = server_opts(server)
|
|
30
|
-
opts[:database] = ':memory:' if opts[:database]
|
|
30
|
+
opts[:database] = ':memory:' if blank_object?(opts[:database])
|
|
31
31
|
db = ::SQLite3::Database.new(opts[:database])
|
|
32
32
|
db.busy_timeout(opts.fetch(:timeout, 5000))
|
|
33
33
|
db.type_translation = true
|
|
@@ -35,7 +35,7 @@ module Sequel
|
|
|
35
35
|
# Handle datetime's with Sequel.datetime_class
|
|
36
36
|
prok = proc do |t,v|
|
|
37
37
|
v = Time.at(v.to_i).iso8601 if UNIX_EPOCH_TIME_FORMAT.match(v)
|
|
38
|
-
v
|
|
38
|
+
Sequel.string_to_datetime(v)
|
|
39
39
|
end
|
|
40
40
|
db.translator.add_translator("timestamp", &prok)
|
|
41
41
|
db.translator.add_translator("datetime", &prok)
|
|
@@ -86,8 +86,12 @@ module Sequel
|
|
|
86
86
|
# Use the native driver transaction method if there isn't already a transaction
|
|
87
87
|
# in progress on the connection, always yielding a connection inside a transaction
|
|
88
88
|
# transaction.
|
|
89
|
-
def transaction(
|
|
90
|
-
|
|
89
|
+
def transaction(opts={})
|
|
90
|
+
unless opts.is_a?(Hash)
|
|
91
|
+
Deprecation.deprecate('Passing an argument other than a Hash to Database#transaction', "Use DB.transaction(:server=>#{opts.inspect})")
|
|
92
|
+
opts = {:server=>opts}
|
|
93
|
+
end
|
|
94
|
+
synchronize(opts[:server]) do |conn|
|
|
91
95
|
return yield(conn) if conn.transaction_active?
|
|
92
96
|
begin
|
|
93
97
|
result = nil
|
|
@@ -106,7 +110,7 @@ module Sequel
|
|
|
106
110
|
private
|
|
107
111
|
|
|
108
112
|
# Log the SQL and the arguments, and yield an available connection. Rescue
|
|
109
|
-
# any SQLite3::Exceptions and turn the into
|
|
113
|
+
# any SQLite3::Exceptions and turn the into DatabaseErrors.
|
|
110
114
|
def _execute(sql, opts)
|
|
111
115
|
begin
|
|
112
116
|
log_info(sql, opts[:arguments])
|
|
@@ -123,7 +127,7 @@ module Sequel
|
|
|
123
127
|
o = super.merge(:pool_convert_exceptions=>false)
|
|
124
128
|
# Default to only a single connection if a memory database is used,
|
|
125
129
|
# because otherwise each connection will get a separate database
|
|
126
|
-
o[:max_connections] = 1 if @opts[:database] == ':memory:' || @opts[:database]
|
|
130
|
+
o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database])
|
|
127
131
|
o
|
|
128
132
|
end
|
|
129
133
|
|
|
File without changes
|
|
File without changes
|
|
@@ -40,4 +40,23 @@ class Sequel::Dataset
|
|
|
40
40
|
super(ds)
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
# This module should be included in the dataset class for all databases that
|
|
45
|
+
# don't support IS [NOT] (TRUE|FALSE)
|
|
46
|
+
module UnsupportedIsTrue
|
|
47
|
+
# Use an = construct instead of IS and an != OR IS NULL construct instead of IS NOT.
|
|
48
|
+
def complex_expression_sql(op, args)
|
|
49
|
+
case op
|
|
50
|
+
when :IS, :'IS NOT'
|
|
51
|
+
isnot = op != :IS
|
|
52
|
+
return super if (v1 = args.at(1)).nil?
|
|
53
|
+
v0 = literal(args.at(0))
|
|
54
|
+
s = "(#{v0} #{'!' if isnot}= #{literal(v1)})"
|
|
55
|
+
s = "(#{s} OR (#{v0} IS NULL))" if isnot
|
|
56
|
+
s
|
|
57
|
+
else
|
|
58
|
+
super(op, args)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
43
62
|
end
|
|
@@ -28,6 +28,7 @@ class Sequel::ConnectionPool
|
|
|
28
28
|
#
|
|
29
29
|
# The connection pool takes the following options:
|
|
30
30
|
#
|
|
31
|
+
# * :disconnection_proc - The proc called when removing connections from the pool.
|
|
31
32
|
# * :max_connections - The maximum number of connections the connection pool
|
|
32
33
|
# will open (default 4)
|
|
33
34
|
# * :pool_convert_exceptions - Whether to convert non-StandardError based exceptions
|
|
@@ -90,7 +91,7 @@ class Sequel::ConnectionPool
|
|
|
90
91
|
# If no connection is immediately available and the pool is already using the maximum
|
|
91
92
|
# number of connections, Pool#hold will block until a connection
|
|
92
93
|
# is available or the timeout expires. If the timeout expires before a
|
|
93
|
-
# connection can be acquired, a Sequel::
|
|
94
|
+
# connection can be acquired, a Sequel::PoolTimeout is
|
|
94
95
|
# raised.
|
|
95
96
|
def hold(server=:default)
|
|
96
97
|
begin
|
|
@@ -102,7 +103,7 @@ class Sequel::ConnectionPool
|
|
|
102
103
|
return yield(conn)
|
|
103
104
|
end
|
|
104
105
|
until conn = acquire(t, server)
|
|
105
|
-
raise(::Sequel::
|
|
106
|
+
raise(::Sequel::PoolTimeout) if Time.new > timeout
|
|
106
107
|
sleep sleep_time
|
|
107
108
|
end
|
|
108
109
|
begin
|
|
@@ -203,9 +204,6 @@ end
|
|
|
203
204
|
# A SingleThreadedPool acts as a replacement for a ConnectionPool for use
|
|
204
205
|
# in single-threaded applications. ConnectionPool imposes a substantial
|
|
205
206
|
# performance penalty, so SingleThreadedPool is used to gain some speed.
|
|
206
|
-
#
|
|
207
|
-
# Note that using a single threaded pool with some adapters can cause
|
|
208
|
-
# errors in certain cases, see Sequel.single_threaded=.
|
|
209
207
|
class Sequel::SingleThreadedPool
|
|
210
208
|
# The proc used to create a new database connection
|
|
211
209
|
attr_writer :connection_proc
|
|
@@ -217,8 +215,12 @@ class Sequel::SingleThreadedPool
|
|
|
217
215
|
#
|
|
218
216
|
# The single threaded pool takes the following options:
|
|
219
217
|
#
|
|
218
|
+
# * :disconnection_proc - The proc called when removing connections from the pool.
|
|
220
219
|
# * :pool_convert_exceptions - Whether to convert non-StandardError based exceptions
|
|
221
220
|
# to RuntimeError exceptions (default true)
|
|
221
|
+
# * :servers - A hash of servers to use. Keys should be symbols. If not
|
|
222
|
+
# present, will use a single :default server. The server name symbol will
|
|
223
|
+
# be passed to the connection_proc.
|
|
222
224
|
def initialize(opts={}, &block)
|
|
223
225
|
@connection_proc = block
|
|
224
226
|
@disconnection_proc = opts[:disconnection_proc]
|
data/lib/sequel/core.rb
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
%w'bigdecimal date thread time uri'.each{|f| require f}
|
|
2
|
+
|
|
3
|
+
# Top level module for Sequel
|
|
4
|
+
#
|
|
5
|
+
# There are some class methods that are added via metaprogramming, one for
|
|
6
|
+
# each supported adapter. For example:
|
|
7
|
+
#
|
|
8
|
+
# DB = Sequel.sqlite # Memory database
|
|
9
|
+
# DB = Sequel.sqlite('blog.db')
|
|
10
|
+
# DB = Sequel.postgres('database_name', :user=>'user',
|
|
11
|
+
# :password=>'password', :host=>'host', :port=>5432,
|
|
12
|
+
# :max_connections=>10)
|
|
13
|
+
#
|
|
14
|
+
# If a block is given to these methods, it is passed the opened Database
|
|
15
|
+
# object, which is closed (disconnected) when the block exits, just
|
|
16
|
+
# like a block passed to connect. For example:
|
|
17
|
+
#
|
|
18
|
+
# Sequel.sqlite('blog.db'){|db| puts db[:users].count}
|
|
19
|
+
#
|
|
20
|
+
# Sequel converts the column type tinyint to a boolean by default,
|
|
21
|
+
# you can override the conversion to use tinyint as an integer:
|
|
22
|
+
#
|
|
23
|
+
# Sequel.convert_tinyint_to_bool = false
|
|
24
|
+
#
|
|
25
|
+
# Sequel converts two digit years in Dates and DateTimes by default,
|
|
26
|
+
# so 01/02/03 is interpreted at January 2nd, 2003, and 12/13/99 is interpreted
|
|
27
|
+
# as December 13, 1999. You can override this to treat those dates as
|
|
28
|
+
# January 2nd, 0003 and December 13, 0099, respectively, by setting:
|
|
29
|
+
#
|
|
30
|
+
# Sequel.convert_two_digit_years = false
|
|
31
|
+
#
|
|
32
|
+
# Sequel can use either Time or DateTime for times returned from the
|
|
33
|
+
# database. It defaults to Time. To change it to DateTime, use:
|
|
34
|
+
#
|
|
35
|
+
# Sequel.datetime_class = DateTime
|
|
36
|
+
#
|
|
37
|
+
# Sequel currently does not use instance_eval for virtual row blocks by default
|
|
38
|
+
# (e.g. the block passed to Dataset#filter, #select, #order and other similar
|
|
39
|
+
# methods). If you want to use instance_eval for these blocks, don't have any
|
|
40
|
+
# block arguments, and set:
|
|
41
|
+
#
|
|
42
|
+
# Sequel.virtual_row_instance_eval = true
|
|
43
|
+
#
|
|
44
|
+
# When this is set, you can do:
|
|
45
|
+
#
|
|
46
|
+
# dataset.filter{|o| o.column > 0} # no instance_eval
|
|
47
|
+
# dataset.filter{column > 0} # instance eval
|
|
48
|
+
#
|
|
49
|
+
# When the virtual_row_instance_eval is false, using a virtual row block without a block
|
|
50
|
+
# argument will generate a deprecation message.
|
|
51
|
+
#
|
|
52
|
+
# The option to not use instance_eval for a block with no arguments will be removed in Sequel 3.0.
|
|
53
|
+
# If you have any virtual row blocks that you don't want to use instance_eval for,
|
|
54
|
+
# make sure the blocks have block arguments.
|
|
55
|
+
#
|
|
56
|
+
# You can set the SEQUEL_NO_CORE_EXTENSIONS constant or environment variable to have
|
|
57
|
+
# Sequel not extend the core classes.
|
|
58
|
+
module Sequel
|
|
59
|
+
@convert_tinyint_to_bool = true
|
|
60
|
+
@convert_two_digit_years = true
|
|
61
|
+
@datetime_class = Time
|
|
62
|
+
@virtual_row_instance_eval = false
|
|
63
|
+
|
|
64
|
+
class << self
|
|
65
|
+
attr_accessor :convert_tinyint_to_bool, :convert_two_digit_years, :datetime_class, :virtual_row_instance_eval
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns true if the passed object could be a specifier of conditions, false otherwise.
|
|
69
|
+
# Currently, Sequel considers hashes and arrays of all two pairs as
|
|
70
|
+
# condition specifiers.
|
|
71
|
+
def self.condition_specifier?(obj)
|
|
72
|
+
case obj
|
|
73
|
+
when Hash
|
|
74
|
+
true
|
|
75
|
+
when Array
|
|
76
|
+
!obj.empty? && obj.all?{|i| (Array === i) && (i.length == 2)}
|
|
77
|
+
else
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Creates a new database object based on the supplied connection string
|
|
83
|
+
# and optional arguments. The specified scheme determines the database
|
|
84
|
+
# class used, and the rest of the string specifies the connection options.
|
|
85
|
+
# For example:
|
|
86
|
+
#
|
|
87
|
+
# DB = Sequel.connect('sqlite:/') # Memory database
|
|
88
|
+
# DB = Sequel.connect('sqlite://blog.db') # ./blog.db
|
|
89
|
+
# DB = Sequel.connect('sqlite:///blog.db') # /blog.db
|
|
90
|
+
# DB = Sequel.connect('postgres://user:password@host:port/database_name')
|
|
91
|
+
# DB = Sequel.connect('sqlite:///blog.db', :max_connections=>10)
|
|
92
|
+
#
|
|
93
|
+
# If a block is given, it is passed the opened Database object, which is
|
|
94
|
+
# closed when the block exits. For example:
|
|
95
|
+
#
|
|
96
|
+
# Sequel.connect('sqlite://blog.db'){|db| puts db[:users].count}
|
|
97
|
+
def self.connect(*args, &block)
|
|
98
|
+
Database.connect(*args, &block)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Set the method to call on identifiers going into the database. This affects
|
|
102
|
+
# the literalization of identifiers by calling this method on them before they are input.
|
|
103
|
+
# Sequel upcases identifiers in all SQL strings for most databases, so to turn that off:
|
|
104
|
+
#
|
|
105
|
+
# Sequel.identifier_input_method = nil
|
|
106
|
+
#
|
|
107
|
+
# to downcase instead:
|
|
108
|
+
#
|
|
109
|
+
# Sequel.identifier_input_method = :downcase
|
|
110
|
+
#
|
|
111
|
+
# Other String instance methods work as well.
|
|
112
|
+
def self.identifier_input_method=(value)
|
|
113
|
+
Database.identifier_input_method = value
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Set the method to call on identifiers coming out of the database. This affects
|
|
117
|
+
# the literalization of identifiers by calling this method on them when they are
|
|
118
|
+
# retrieved from the database. Sequel downcases identifiers retrieved for most
|
|
119
|
+
# databases, so to turn that off:
|
|
120
|
+
#
|
|
121
|
+
# Sequel.identifier_output_method = nil
|
|
122
|
+
#
|
|
123
|
+
# to upcase instead:
|
|
124
|
+
#
|
|
125
|
+
# Sequel.identifier_output_method = :upcase
|
|
126
|
+
#
|
|
127
|
+
# Other String instance methods work as well.
|
|
128
|
+
def self.identifier_output_method=(value)
|
|
129
|
+
Database.identifier_output_method = value
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Set whether to quote identifiers for all databases by default. By default,
|
|
133
|
+
# Sequel quotes identifiers in all SQL strings, so to turn that off:
|
|
134
|
+
#
|
|
135
|
+
# Sequel.quote_identifiers = false
|
|
136
|
+
def self.quote_identifiers=(value)
|
|
137
|
+
Database.quote_identifiers = value
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Require all given files which should be in the same or a subdirectory of
|
|
141
|
+
# this file. If a subdir is given, assume all files are in that subdir.
|
|
142
|
+
def self.require(files, subdir=nil)
|
|
143
|
+
Array(files).each{|f| super("#{File.dirname(__FILE__)}/#{"#{subdir}/" if subdir}#{f}")}
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Set whether to set the single threaded mode for all databases by default. By default,
|
|
147
|
+
# Sequel uses a threadsafe connection pool, which isn't as fast as the
|
|
148
|
+
# single threaded connection pool. If your program will only have one thread,
|
|
149
|
+
# and speed is a priority, you may want to set this to true:
|
|
150
|
+
#
|
|
151
|
+
# Sequel.single_threaded = true
|
|
152
|
+
def self.single_threaded=(value)
|
|
153
|
+
Database.single_threaded = value
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Converts the given string into a Date object.
|
|
157
|
+
def self.string_to_date(s)
|
|
158
|
+
begin
|
|
159
|
+
Date.parse(s, Sequel.convert_two_digit_years)
|
|
160
|
+
rescue => e
|
|
161
|
+
raise InvalidValue, "Invalid Date value '#{self}' (#{e.message})"
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Converts the given string into a Time or DateTime object, depending on the
|
|
166
|
+
# value of Sequel.datetime_class.
|
|
167
|
+
def self.string_to_datetime(s)
|
|
168
|
+
begin
|
|
169
|
+
if datetime_class == DateTime
|
|
170
|
+
DateTime.parse(s, convert_two_digit_years)
|
|
171
|
+
else
|
|
172
|
+
datetime_class.parse(s)
|
|
173
|
+
end
|
|
174
|
+
rescue => e
|
|
175
|
+
raise InvalidValue, "Invalid #{datetime_class} value '#{self}' (#{e.message})"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Converts the given string into a Time object.
|
|
180
|
+
def self.string_to_time(s)
|
|
181
|
+
begin
|
|
182
|
+
Time.parse(s)
|
|
183
|
+
rescue => e
|
|
184
|
+
raise InvalidValue, "Invalid Time value '#{self}' (#{e.message})"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
### Private Class Methods ###
|
|
189
|
+
|
|
190
|
+
# Helper method that the database adapter class methods that are added to Sequel via
|
|
191
|
+
# metaprogramming use to parse arguments.
|
|
192
|
+
def self.adapter_method(adapter, *args, &block) # :nodoc:
|
|
193
|
+
raise(::Sequel::Error, "Wrong number of arguments, 0-2 arguments valid") if args.length > 2
|
|
194
|
+
opts = {:adapter=>adapter.to_sym}
|
|
195
|
+
opts[:database] = args.shift if args.length >= 1 && !(args[0].is_a?(Hash))
|
|
196
|
+
if Hash === (arg = args[0])
|
|
197
|
+
opts.merge!(arg)
|
|
198
|
+
elsif !arg.nil?
|
|
199
|
+
raise ::Sequel::Error, "Wrong format of arguments, either use (), (String), (Hash), or (String, Hash)"
|
|
200
|
+
end
|
|
201
|
+
connect(opts, &block)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Method that adds a database adapter class method to Sequel that calls
|
|
205
|
+
# Sequel.adapter_method.
|
|
206
|
+
def self.def_adapter_method(*adapters) # :nodoc:
|
|
207
|
+
adapters.each do |adapter|
|
|
208
|
+
instance_eval("def #{adapter}(*args, &block); adapter_method('#{adapter}', *args, &block) end")
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
private_class_method :adapter_method, :def_adapter_method
|
|
213
|
+
|
|
214
|
+
require(%w"metaprogramming sql connection_pool exceptions dataset database version deprecated")
|
|
215
|
+
require(%w"schema_generator schema_methods schema_sql", 'database')
|
|
216
|
+
require(%w"convenience graph prepared_statements sql", 'dataset')
|
|
217
|
+
require('core_sql') if !defined?(::SEQUEL_NO_CORE_EXTENSIONS) && !ENV.has_key?('SEQUEL_NO_CORE_EXTENSIONS')
|
|
218
|
+
|
|
219
|
+
# Add the database adapter class methods to Sequel via metaprogramming
|
|
220
|
+
def_adapter_method(*Database::ADAPTERS)
|
|
221
|
+
end
|