sequel 5.60.1 → 5.81.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.
- checksums.yaml +4 -4
- data/CHANGELOG +280 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +27 -24
- data/doc/advanced_associations.rdoc +16 -14
- data/doc/association_basics.rdoc +53 -17
- data/doc/cheat_sheet.rdoc +3 -3
- data/doc/code_order.rdoc +5 -3
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +15 -0
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +18 -7
- data/doc/postgresql.rdoc +8 -8
- data/doc/querying.rdoc +7 -2
- data/doc/release_notes/5.61.0.txt +43 -0
- data/doc/release_notes/5.62.0.txt +132 -0
- data/doc/release_notes/5.63.0.txt +33 -0
- data/doc/release_notes/5.64.0.txt +50 -0
- data/doc/release_notes/5.65.0.txt +21 -0
- data/doc/release_notes/5.66.0.txt +24 -0
- data/doc/release_notes/5.67.0.txt +32 -0
- data/doc/release_notes/5.68.0.txt +61 -0
- data/doc/release_notes/5.69.0.txt +26 -0
- data/doc/release_notes/5.70.0.txt +35 -0
- data/doc/release_notes/5.71.0.txt +21 -0
- data/doc/release_notes/5.72.0.txt +33 -0
- data/doc/release_notes/5.73.0.txt +66 -0
- data/doc/release_notes/5.74.0.txt +45 -0
- data/doc/release_notes/5.75.0.txt +35 -0
- data/doc/release_notes/5.76.0.txt +86 -0
- data/doc/release_notes/5.77.0.txt +63 -0
- data/doc/release_notes/5.78.0.txt +67 -0
- data/doc/release_notes/5.79.0.txt +28 -0
- data/doc/release_notes/5.80.0.txt +40 -0
- data/doc/release_notes/5.81.0.txt +31 -0
- data/doc/schema_modification.rdoc +3 -3
- data/doc/security.rdoc +9 -9
- data/doc/sharding.rdoc +3 -1
- data/doc/sql.rdoc +14 -14
- data/doc/testing.rdoc +16 -12
- data/doc/transactions.rdoc +6 -6
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ibmdb.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +3 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -0
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +15 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +4 -0
- data/lib/sequel/adapters/jdbc.rb +10 -6
- data/lib/sequel/adapters/mysql.rb +19 -7
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +1 -0
- data/lib/sequel/adapters/postgres.rb +10 -5
- data/lib/sequel/adapters/shared/access.rb +9 -1
- data/lib/sequel/adapters/shared/db2.rb +12 -0
- data/lib/sequel/adapters/shared/mssql.rb +71 -9
- data/lib/sequel/adapters/shared/mysql.rb +82 -3
- data/lib/sequel/adapters/shared/oracle.rb +17 -7
- data/lib/sequel/adapters/shared/postgres.rb +469 -160
- data/lib/sequel/adapters/shared/sqlanywhere.rb +18 -5
- data/lib/sequel/adapters/shared/sqlite.rb +39 -3
- data/lib/sequel/adapters/sqlite.rb +42 -3
- data/lib/sequel/adapters/trilogy.rb +117 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +16 -11
- data/lib/sequel/connection_pool/sharded_timed_queue.rb +374 -0
- data/lib/sequel/connection_pool/threaded.rb +14 -8
- data/lib/sequel/connection_pool/timed_queue.rb +270 -0
- data/lib/sequel/connection_pool.rb +57 -31
- data/lib/sequel/database/connecting.rb +25 -1
- data/lib/sequel/database/dataset.rb +16 -6
- data/lib/sequel/database/misc.rb +65 -14
- data/lib/sequel/database/query.rb +72 -1
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +12 -5
- data/lib/sequel/database/transactions.rb +6 -0
- data/lib/sequel/dataset/actions.rb +60 -13
- data/lib/sequel/dataset/dataset_module.rb +1 -1
- data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +42 -0
- data/lib/sequel/dataset/features.rb +15 -1
- data/lib/sequel/dataset/graph.rb +1 -0
- data/lib/sequel/dataset/misc.rb +12 -2
- data/lib/sequel/dataset/placeholder_literalizer.rb +20 -9
- data/lib/sequel/dataset/query.rb +119 -45
- data/lib/sequel/dataset/sql.rb +58 -36
- data/lib/sequel/dataset.rb +4 -0
- data/lib/sequel/exceptions.rb +5 -0
- data/lib/sequel/extensions/_model_pg_row.rb +0 -12
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/any_not_empty.rb +2 -2
- data/lib/sequel/extensions/async_thread_pool.rb +21 -13
- data/lib/sequel/extensions/auto_cast_date_and_time.rb +94 -0
- data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/caller_logging.rb +4 -1
- data/lib/sequel/extensions/connection_expiration.rb +15 -9
- data/lib/sequel/extensions/connection_validator.rb +16 -11
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +10 -9
- data/lib/sequel/extensions/index_caching.rb +5 -1
- data/lib/sequel/extensions/looser_typecasting.rb +3 -0
- data/lib/sequel/extensions/migration.rb +65 -15
- data/lib/sequel/extensions/named_timezones.rb +22 -6
- data/lib/sequel/extensions/pg_array.rb +33 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +509 -0
- data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +110 -0
- data/lib/sequel/extensions/pg_enum.rb +1 -2
- data/lib/sequel/extensions/pg_extended_date_support.rb +38 -27
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +5 -0
- data/lib/sequel/extensions/pg_inet.rb +10 -11
- data/lib/sequel/extensions/pg_interval.rb +10 -11
- data/lib/sequel/extensions/pg_json.rb +10 -10
- data/lib/sequel/extensions/pg_json_ops.rb +3 -3
- data/lib/sequel/extensions/pg_multirange.rb +6 -11
- data/lib/sequel/extensions/pg_range.rb +9 -14
- data/lib/sequel/extensions/pg_row.rb +20 -19
- data/lib/sequel/extensions/pg_timestamptz.rb +27 -3
- data/lib/sequel/extensions/provenance.rb +110 -0
- data/lib/sequel/extensions/round_timestamps.rb +1 -1
- data/lib/sequel/extensions/schema_caching.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +32 -9
- data/lib/sequel/extensions/server_block.rb +2 -1
- data/lib/sequel/extensions/set_literalizer.rb +58 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +76 -18
- data/lib/sequel/extensions/temporarily_release_connection.rb +178 -0
- data/lib/sequel/extensions/transaction_connection_validator.rb +78 -0
- data/lib/sequel/model/associations.rb +38 -11
- data/lib/sequel/model/base.rb +32 -18
- data/lib/sequel/model/dataset_module.rb +3 -0
- data/lib/sequel/model/exceptions.rb +15 -3
- data/lib/sequel/plugins/auto_validations.rb +53 -15
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/column_encryption.rb +28 -7
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +4 -4
- data/lib/sequel/plugins/constraint_validations.rb +8 -5
- data/lib/sequel/plugins/defaults_setter.rb +16 -0
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/finder.rb +4 -2
- data/lib/sequel/plugins/input_transformer.rb +1 -1
- data/lib/sequel/plugins/list.rb +5 -2
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -38
- data/lib/sequel/plugins/nested_attributes.rb +4 -4
- data/lib/sequel/plugins/optimistic_locking.rb +9 -42
- data/lib/sequel/plugins/optimistic_locking_base.rb +55 -0
- data/lib/sequel/plugins/paged_operations.rb +181 -0
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +9 -3
- data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +109 -0
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -1
- data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
- data/lib/sequel/plugins/rcte_tree.rb +7 -4
- data/lib/sequel/plugins/single_table_inheritance.rb +8 -0
- data/lib/sequel/plugins/sql_comments.rb +1 -1
- data/lib/sequel/plugins/static_cache.rb +38 -0
- data/lib/sequel/plugins/static_cache_cache.rb +5 -1
- data/lib/sequel/plugins/tactical_eager_loading.rb +14 -14
- data/lib/sequel/plugins/validate_associated.rb +22 -12
- data/lib/sequel/plugins/validation_helpers.rb +29 -2
- data/lib/sequel/plugins/validation_helpers_generic_type_messages.rb +73 -0
- data/lib/sequel/version.rb +2 -2
- metadata +79 -6
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -12,6 +12,10 @@ module Sequel
|
|
|
12
12
|
# in the extension).
|
|
13
13
|
EXTENSIONS = {}
|
|
14
14
|
|
|
15
|
+
# Hash of extension name symbols to modules to load to implement the extension.
|
|
16
|
+
EXTENSION_MODULES = {}
|
|
17
|
+
private_constant :EXTENSION_MODULES
|
|
18
|
+
|
|
15
19
|
EMPTY_ARRAY = [].freeze
|
|
16
20
|
|
|
17
21
|
# The dataset options that require the removal of cached columns if changed.
|
|
@@ -39,18 +43,14 @@ module Sequel
|
|
|
39
43
|
add_graph_aliases distinct except exclude exclude_having
|
|
40
44
|
filter for_update from from_self graph grep group group_and_count group_append group_by having intersect invert
|
|
41
45
|
limit lock_style naked offset or order order_append order_by order_more order_prepend qualify
|
|
42
|
-
reverse reverse_order select select_all select_append select_group select_more server
|
|
46
|
+
reverse reverse_order select select_all select_append select_group select_more select_prepend server
|
|
43
47
|
set_graph_aliases unfiltered ungraphed ungrouped union
|
|
44
48
|
unlimited unordered where with with_recursive with_sql
|
|
45
49
|
METHS
|
|
46
50
|
|
|
47
51
|
# Register an extension callback for Dataset objects. ext should be the
|
|
48
|
-
# extension name symbol, and mod should
|
|
49
|
-
# dataset
|
|
50
|
-
# object. If mod is not provided, a block can be provided and is treated
|
|
51
|
-
# as the mod object.
|
|
52
|
-
#
|
|
53
|
-
# If mod is a module, this also registers a Database extension that will
|
|
52
|
+
# extension name symbol, and mod should be a Module that will be
|
|
53
|
+
# included in the dataset's class. This also registers a Database extension that will
|
|
54
54
|
# extend all of the database's datasets.
|
|
55
55
|
def self.register_extension(ext, mod=nil, &block)
|
|
56
56
|
if mod
|
|
@@ -58,14 +58,20 @@ module Sequel
|
|
|
58
58
|
if mod.is_a?(Module)
|
|
59
59
|
block = proc{|ds| ds.extend(mod)}
|
|
60
60
|
Sequel::Database.register_extension(ext){|db| db.extend_datasets(mod)}
|
|
61
|
+
Sequel.synchronize{EXTENSION_MODULES[ext] = mod}
|
|
61
62
|
else
|
|
62
63
|
block = mod
|
|
63
64
|
end
|
|
64
65
|
end
|
|
66
|
+
|
|
67
|
+
unless mod.is_a?(Module)
|
|
68
|
+
Sequel::Deprecation.deprecate("Providing a block or non-module to Sequel::Dataset.register_extension is deprecated and support for it will be removed in Sequel 6.")
|
|
69
|
+
end
|
|
70
|
+
|
|
65
71
|
Sequel.synchronize{EXTENSIONS[ext] = block}
|
|
66
72
|
end
|
|
67
73
|
|
|
68
|
-
# On Ruby 2.4+, use clone(:
|
|
74
|
+
# On Ruby 2.4+, use clone(freeze: false) to create clones, because
|
|
69
75
|
# we use true freezing in that case, and we need to modify the opts
|
|
70
76
|
# in the frozen copy.
|
|
71
77
|
#
|
|
@@ -116,13 +122,14 @@ module Sequel
|
|
|
116
122
|
# DB[:items].order(:id).distinct(:id) # SQL: SELECT DISTINCT ON (id) * FROM items ORDER BY id
|
|
117
123
|
# DB[:items].order(:id).distinct{func(:id)} # SQL: SELECT DISTINCT ON (func(id)) * FROM items ORDER BY id
|
|
118
124
|
#
|
|
119
|
-
# There is support for
|
|
125
|
+
# There is support for emulating the DISTINCT ON support in MySQL, but it
|
|
120
126
|
# does not support the ORDER of the dataset, and also doesn't work in many
|
|
121
127
|
# cases if the ONLY_FULL_GROUP_BY sql_mode is used, which is the default on
|
|
122
128
|
# MySQL 5.7.5+.
|
|
123
129
|
def distinct(*args, &block)
|
|
124
130
|
virtual_row_columns(args, block)
|
|
125
131
|
if args.empty?
|
|
132
|
+
return self if opts[:distinct] == EMPTY_ARRAY
|
|
126
133
|
cached_dataset(:_distinct_ds){clone(:distinct => EMPTY_ARRAY)}
|
|
127
134
|
else
|
|
128
135
|
raise(InvalidOperation, "DISTINCT ON not supported") unless supports_distinct_on?
|
|
@@ -195,11 +202,15 @@ module Sequel
|
|
|
195
202
|
if TRUE_FREEZE
|
|
196
203
|
# Return a clone of the dataset loaded with the given dataset extensions.
|
|
197
204
|
# If no related extension file exists or the extension does not have
|
|
198
|
-
# specific support for Dataset objects, an
|
|
199
|
-
def extension(*
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
205
|
+
# specific support for Dataset objects, an error will be raised.
|
|
206
|
+
def extension(*exts)
|
|
207
|
+
Sequel.extension(*exts)
|
|
208
|
+
mods = exts.map{|ext| Sequel.synchronize{EXTENSION_MODULES[ext]}}
|
|
209
|
+
if mods.all?
|
|
210
|
+
with_extend(*mods)
|
|
211
|
+
else
|
|
212
|
+
with_extend(DeprecatedSingletonClassMethods).extension(*exts)
|
|
213
|
+
end
|
|
203
214
|
end
|
|
204
215
|
else
|
|
205
216
|
# :nocov:
|
|
@@ -220,6 +231,7 @@ module Sequel
|
|
|
220
231
|
#
|
|
221
232
|
# DB[:table].for_update # SELECT * FROM table FOR UPDATE
|
|
222
233
|
def for_update
|
|
234
|
+
return self if opts[:lock] == :update
|
|
223
235
|
cached_dataset(:_for_update_ds){lock_style(:update)}
|
|
224
236
|
end
|
|
225
237
|
|
|
@@ -631,6 +643,7 @@ module Sequel
|
|
|
631
643
|
# DB.from(:a, DB[:b].where(Sequel[:a][:c]=>Sequel[:b][:d]).lateral)
|
|
632
644
|
# # SELECT * FROM a, LATERAL (SELECT * FROM b WHERE (a.c = b.d))
|
|
633
645
|
def lateral
|
|
646
|
+
return self if opts[:lateral]
|
|
634
647
|
cached_dataset(:_lateral_ds){clone(:lateral=>true)}
|
|
635
648
|
end
|
|
636
649
|
|
|
@@ -734,6 +747,7 @@ module Sequel
|
|
|
734
747
|
# ds.all # => [{2=>:id}]
|
|
735
748
|
# ds.naked.all # => [{:id=>2}]
|
|
736
749
|
def naked
|
|
750
|
+
return self unless opts[:row_proc]
|
|
737
751
|
cached_dataset(:_naked_ds){with_row_proc(nil)}
|
|
738
752
|
end
|
|
739
753
|
|
|
@@ -743,6 +757,7 @@ module Sequel
|
|
|
743
757
|
# DB[:items].for_update.nowait
|
|
744
758
|
# # SELECT * FROM items FOR UPDATE NOWAIT
|
|
745
759
|
def nowait
|
|
760
|
+
return self if opts[:nowait]
|
|
746
761
|
cached_dataset(:_nowait_ds) do
|
|
747
762
|
raise(Error, 'This dataset does not support raises errors instead of waiting for locked rows') unless supports_nowait?
|
|
748
763
|
clone(:nowait=>true)
|
|
@@ -787,7 +802,7 @@ module Sequel
|
|
|
787
802
|
# DB[:items].order(Sequel.lit('a + b')) # SELECT * FROM items ORDER BY a + b
|
|
788
803
|
# DB[:items].order(Sequel[:a] + :b) # SELECT * FROM items ORDER BY (a + b)
|
|
789
804
|
# DB[:items].order(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name DESC
|
|
790
|
-
# DB[:items].order(Sequel.asc(:name, :
|
|
805
|
+
# DB[:items].order(Sequel.asc(:name, nulls: :last)) # SELECT * FROM items ORDER BY name ASC NULLS LAST
|
|
791
806
|
# DB[:items].order{sum(name).desc} # SELECT * FROM items ORDER BY sum(name) DESC
|
|
792
807
|
# DB[:items].order(nil) # SELECT * FROM items
|
|
793
808
|
def order(*columns, &block)
|
|
@@ -857,17 +872,18 @@ module Sequel
|
|
|
857
872
|
# DB[:items].returning(nil) # RETURNING NULL
|
|
858
873
|
# DB[:items].returning(:id, :name) # RETURNING id, name
|
|
859
874
|
#
|
|
860
|
-
# DB[:items].returning.insert(:
|
|
875
|
+
# DB[:items].returning.insert(a: 1) do |hash|
|
|
861
876
|
# # hash for each row inserted, with values for all columns
|
|
862
877
|
# end
|
|
863
|
-
# DB[:items].returning.update(:
|
|
878
|
+
# DB[:items].returning.update(a: 1) do |hash|
|
|
864
879
|
# # hash for each row updated, with values for all columns
|
|
865
880
|
# end
|
|
866
|
-
# DB[:items].returning.delete(:
|
|
881
|
+
# DB[:items].returning.delete(a: 1) do |hash|
|
|
867
882
|
# # hash for each row deleted, with values for all columns
|
|
868
883
|
# end
|
|
869
884
|
def returning(*values)
|
|
870
885
|
if values.empty?
|
|
886
|
+
return self if opts[:returning] == EMPTY_ARRAY
|
|
871
887
|
cached_dataset(:_returning_ds) do
|
|
872
888
|
raise Error, "RETURNING is not supported on #{db.database_type}" unless supports_returning?(:insert)
|
|
873
889
|
clone(:returning=>EMPTY_ARRAY)
|
|
@@ -920,6 +936,7 @@ module Sequel
|
|
|
920
936
|
# DB[:items].select_all(:items, :foo) # SELECT items.*, foo.* FROM items
|
|
921
937
|
def select_all(*tables)
|
|
922
938
|
if tables.empty?
|
|
939
|
+
return self unless opts[:select]
|
|
923
940
|
cached_dataset(:_select_all_ds){clone(:select => nil)}
|
|
924
941
|
else
|
|
925
942
|
select(*tables.map{|t| i, a = split_alias(t); a || i}.map!{|t| SQL::ColumnAll.new(t)}.freeze)
|
|
@@ -934,14 +951,8 @@ module Sequel
|
|
|
934
951
|
# DB[:items].select(:a).select_append(:b) # SELECT a, b FROM items
|
|
935
952
|
# DB[:items].select_append(:b) # SELECT *, b FROM items
|
|
936
953
|
def select_append(*columns, &block)
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
unless supports_select_all_and_column?
|
|
940
|
-
return select_all(*(Array(@opts[:from]) + Array(@opts[:join]))).select_append(*columns, &block)
|
|
941
|
-
end
|
|
942
|
-
cur_sel = [WILDCARD]
|
|
943
|
-
end
|
|
944
|
-
select(*(cur_sel + columns), &block)
|
|
954
|
+
virtual_row_columns(columns, block)
|
|
955
|
+
select(*(_current_select(true) + columns))
|
|
945
956
|
end
|
|
946
957
|
|
|
947
958
|
# Set both the select and group clauses with the given +columns+.
|
|
@@ -963,6 +974,18 @@ module Sequel
|
|
|
963
974
|
select_append(*columns, &block)
|
|
964
975
|
end
|
|
965
976
|
|
|
977
|
+
# Returns a copy of the dataset with the given columns added
|
|
978
|
+
# to the existing selected columns. If no columns are currently selected,
|
|
979
|
+
# it will select the columns given in addition to *.
|
|
980
|
+
#
|
|
981
|
+
# DB[:items].select(:a).select(:b) # SELECT b FROM items
|
|
982
|
+
# DB[:items].select(:a).select_prepend(:b) # SELECT b, a FROM items
|
|
983
|
+
# DB[:items].select_prepend(:b) # SELECT b, * FROM items
|
|
984
|
+
def select_prepend(*columns, &block)
|
|
985
|
+
virtual_row_columns(columns, block)
|
|
986
|
+
select(*(columns + _current_select(false)))
|
|
987
|
+
end
|
|
988
|
+
|
|
966
989
|
# Set the server for this dataset to use. Used to pick a specific database
|
|
967
990
|
# shard to run a query against, or to override the default (where SELECT uses
|
|
968
991
|
# :read_only database and all other queries use the :default database). This
|
|
@@ -989,6 +1012,7 @@ module Sequel
|
|
|
989
1012
|
|
|
990
1013
|
# Specify that the check for limits/offsets when updating/deleting be skipped for the dataset.
|
|
991
1014
|
def skip_limit_check
|
|
1015
|
+
return self if opts[:skip_limit_check]
|
|
992
1016
|
cached_dataset(:_skip_limit_check_ds) do
|
|
993
1017
|
clone(:skip_limit_check=>true)
|
|
994
1018
|
end
|
|
@@ -996,6 +1020,7 @@ module Sequel
|
|
|
996
1020
|
|
|
997
1021
|
# Skip locked rows when returning results from this dataset.
|
|
998
1022
|
def skip_locked
|
|
1023
|
+
return self if opts[:skip_locked]
|
|
999
1024
|
cached_dataset(:_skip_locked_ds) do
|
|
1000
1025
|
raise(Error, 'This dataset does not support skipping locked rows') unless supports_skip_locked?
|
|
1001
1026
|
clone(:skip_locked=>true)
|
|
@@ -1007,6 +1032,7 @@ module Sequel
|
|
|
1007
1032
|
# DB[:items].group(:a).having(a: 1).where(:b).unfiltered
|
|
1008
1033
|
# # SELECT * FROM items GROUP BY a
|
|
1009
1034
|
def unfiltered
|
|
1035
|
+
return self unless opts[:where] || opts[:having]
|
|
1010
1036
|
cached_dataset(:_unfiltered_ds){clone(:where => nil, :having => nil)}
|
|
1011
1037
|
end
|
|
1012
1038
|
|
|
@@ -1015,6 +1041,7 @@ module Sequel
|
|
|
1015
1041
|
# DB[:items].group(:a).having(a: 1).where(:b).ungrouped
|
|
1016
1042
|
# # SELECT * FROM items WHERE b
|
|
1017
1043
|
def ungrouped
|
|
1044
|
+
return self unless opts[:group] || opts[:having]
|
|
1018
1045
|
cached_dataset(:_ungrouped_ds){clone(:group => nil, :having => nil)}
|
|
1019
1046
|
end
|
|
1020
1047
|
|
|
@@ -1042,6 +1069,7 @@ module Sequel
|
|
|
1042
1069
|
#
|
|
1043
1070
|
# DB[:items].limit(10, 20).unlimited # SELECT * FROM items
|
|
1044
1071
|
def unlimited
|
|
1072
|
+
return self unless opts[:limit] || opts[:offset]
|
|
1045
1073
|
cached_dataset(:_unlimited_ds){clone(:limit=>nil, :offset=>nil)}
|
|
1046
1074
|
end
|
|
1047
1075
|
|
|
@@ -1049,6 +1077,7 @@ module Sequel
|
|
|
1049
1077
|
#
|
|
1050
1078
|
# DB[:items].order(:a).unordered # SELECT * FROM items
|
|
1051
1079
|
def unordered
|
|
1080
|
+
return self unless opts[:order]
|
|
1052
1081
|
cached_dataset(:_unordered_ds){clone(:order=>nil)}
|
|
1053
1082
|
end
|
|
1054
1083
|
|
|
@@ -1102,7 +1131,7 @@ module Sequel
|
|
|
1102
1131
|
# referenced in window functions. See Sequel::SQL::Window for a list of
|
|
1103
1132
|
# options that can be passed in. Example:
|
|
1104
1133
|
#
|
|
1105
|
-
# DB[:items].window(:w, :
|
|
1134
|
+
# DB[:items].window(:w, partition: :c1, order: :c2)
|
|
1106
1135
|
# # SELECT * FROM items WINDOW w AS (PARTITION BY c1 ORDER BY c2)
|
|
1107
1136
|
def window(name, opts)
|
|
1108
1137
|
clone(:window=>((@opts[:window]||EMPTY_ARRAY) + [[name, SQL::Window.new(opts)].freeze]).freeze)
|
|
@@ -1163,7 +1192,7 @@ module Sequel
|
|
|
1163
1192
|
# DB[:t].with_recursive(:t,
|
|
1164
1193
|
# DB[:i1].select(:id, :parent_id).where(parent_id: nil),
|
|
1165
1194
|
# DB[:i1].join(:t, id: :parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]),
|
|
1166
|
-
# :
|
|
1195
|
+
# args: [:id, :parent_id])
|
|
1167
1196
|
#
|
|
1168
1197
|
# # WITH RECURSIVE t(id, parent_id) AS (
|
|
1169
1198
|
# # SELECT id, parent_id FROM i1 WHERE (parent_id IS NULL)
|
|
@@ -1199,16 +1228,27 @@ module Sequel
|
|
|
1199
1228
|
end
|
|
1200
1229
|
|
|
1201
1230
|
if TRUE_FREEZE
|
|
1202
|
-
#
|
|
1231
|
+
# Create a subclass of the receiver's class, and include the given modules
|
|
1232
|
+
# into it. If a block is provided, a DatasetModule is created using the block and
|
|
1233
|
+
# is included into the subclass. Create an instance of the subclass using the
|
|
1234
|
+
# same db and opts, so that the returned dataset operates similarly to a clone
|
|
1235
|
+
# extended with the given modules. This approach is used to avoid singleton
|
|
1236
|
+
# classes, which significantly improves performance.
|
|
1237
|
+
#
|
|
1203
1238
|
# Note that like Object#extend, when multiple modules are provided
|
|
1204
|
-
# as arguments the
|
|
1205
|
-
# order. If a block is provided, a DatasetModule is created using the block and
|
|
1206
|
-
# the clone is extended with that module after any modules given as arguments.
|
|
1239
|
+
# as arguments the subclass includes the modules in reverse order.
|
|
1207
1240
|
def with_extend(*mods, &block)
|
|
1208
|
-
c =
|
|
1209
|
-
c.
|
|
1210
|
-
c.
|
|
1211
|
-
c.freeze
|
|
1241
|
+
c = Class.new(self.class)
|
|
1242
|
+
c.include(*mods) unless mods.empty?
|
|
1243
|
+
c.include(DatasetModule.new(&block)) if block
|
|
1244
|
+
o = c.freeze.allocate
|
|
1245
|
+
o.instance_variable_set(:@db, @db)
|
|
1246
|
+
o.instance_variable_set(:@opts, @opts)
|
|
1247
|
+
o.instance_variable_set(:@cache, {})
|
|
1248
|
+
if cols = cache_get(:_columns)
|
|
1249
|
+
o.send(:columns=, cols)
|
|
1250
|
+
end
|
|
1251
|
+
o.freeze
|
|
1212
1252
|
end
|
|
1213
1253
|
else
|
|
1214
1254
|
# :nocov:
|
|
@@ -1241,7 +1281,7 @@ module Sequel
|
|
|
1241
1281
|
#
|
|
1242
1282
|
# You can also provide a method name and arguments to call to get the SQL:
|
|
1243
1283
|
#
|
|
1244
|
-
# DB[:items].with_sql(:insert_sql, :
|
|
1284
|
+
# DB[:items].with_sql(:insert_sql, b: 1) # INSERT INTO items (b) VALUES (1)
|
|
1245
1285
|
#
|
|
1246
1286
|
# Note that datasets that specify custom SQL using this method will generally
|
|
1247
1287
|
# ignore future dataset methods that modify the SQL used, as specifying custom SQL
|
|
@@ -1315,17 +1355,51 @@ module Sequel
|
|
|
1315
1355
|
|
|
1316
1356
|
private
|
|
1317
1357
|
|
|
1318
|
-
#
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
exts
|
|
1322
|
-
|
|
1323
|
-
|
|
1358
|
+
# :nocov:
|
|
1359
|
+
unless TRUE_FREEZE
|
|
1360
|
+
# Load the extensions into the receiver, without checking if the receiver is frozen.
|
|
1361
|
+
def _extension!(exts)
|
|
1362
|
+
Sequel.extension(*exts)
|
|
1363
|
+
exts.each do |ext|
|
|
1364
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
|
1365
|
+
pr.call(self)
|
|
1366
|
+
else
|
|
1367
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets (try: Sequel.extension #{ext.inspect})")
|
|
1368
|
+
end
|
|
1369
|
+
end
|
|
1370
|
+
self
|
|
1371
|
+
end
|
|
1372
|
+
end
|
|
1373
|
+
# :nocov:
|
|
1374
|
+
|
|
1375
|
+
# A frozen array for the currently selected columns.
|
|
1376
|
+
def _current_select(allow_plain_wildcard)
|
|
1377
|
+
cur_sel = @opts[:select]
|
|
1378
|
+
|
|
1379
|
+
if !cur_sel || cur_sel.empty?
|
|
1380
|
+
cur_sel = if allow_plain_wildcard && supports_select_all_and_column?
|
|
1381
|
+
[WILDCARD].freeze
|
|
1324
1382
|
else
|
|
1325
|
-
|
|
1383
|
+
_current_select_column_all
|
|
1326
1384
|
end
|
|
1385
|
+
elsif !allow_plain_wildcard && cur_sel.include?(WILDCARD)
|
|
1386
|
+
cur_sel = cur_sel.dup
|
|
1387
|
+
index = cur_sel.index(WILDCARD)
|
|
1388
|
+
cur_sel.delete(WILDCARD)
|
|
1389
|
+
_current_select_column_all.each_with_index do |ca, i|
|
|
1390
|
+
cur_sel.insert(index+i, ca)
|
|
1391
|
+
end
|
|
1392
|
+
cur_sel.freeze
|
|
1327
1393
|
end
|
|
1328
|
-
|
|
1394
|
+
|
|
1395
|
+
cur_sel
|
|
1396
|
+
end
|
|
1397
|
+
|
|
1398
|
+
# An array of SQL::ColumnAll objects for all FROM and JOIN tables. Used for select_append
|
|
1399
|
+
# and select_prepend.
|
|
1400
|
+
def _current_select_column_all
|
|
1401
|
+
tables = Array(@opts[:from]) + Array(@opts[:join])
|
|
1402
|
+
tables.map{|t| i, a = split_alias(t); a || i}.map!{|t| SQL::ColumnAll.new(t)}.freeze
|
|
1329
1403
|
end
|
|
1330
1404
|
|
|
1331
1405
|
# If invert is true, invert the condition.
|
data/lib/sequel/dataset/sql.rb
CHANGED
|
@@ -82,7 +82,7 @@ module Sequel
|
|
|
82
82
|
when DateTime
|
|
83
83
|
literal_datetime_append(sql, v)
|
|
84
84
|
when Date
|
|
85
|
-
sql
|
|
85
|
+
literal_date_append(sql, v)
|
|
86
86
|
when Dataset
|
|
87
87
|
literal_dataset_append(sql, v)
|
|
88
88
|
else
|
|
@@ -115,6 +115,33 @@ module Sequel
|
|
|
115
115
|
sql
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
+
# Literalize a date or time value, as a SQL string value with no
|
|
119
|
+
# typecasting. If +raw+ is true, remove the surrounding single
|
|
120
|
+
# quotes. This is designed for usage by bound argument code that
|
|
121
|
+
# can work even if the auto_cast_date_and_time extension is
|
|
122
|
+
# used (either manually or implicitly in the related adapter).
|
|
123
|
+
def literal_date_or_time(dt, raw=false)
|
|
124
|
+
value = case dt
|
|
125
|
+
when SQLTime
|
|
126
|
+
literal_sqltime(dt)
|
|
127
|
+
when Time
|
|
128
|
+
literal_time(dt)
|
|
129
|
+
when DateTime
|
|
130
|
+
literal_datetime(dt)
|
|
131
|
+
when Date
|
|
132
|
+
literal_date(dt)
|
|
133
|
+
else
|
|
134
|
+
raise TypeError, "unsupported type: #{dt.inspect}"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
if raw
|
|
138
|
+
value.sub!(/\A'/, '')
|
|
139
|
+
value.sub!(/'\z/, '')
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
value
|
|
143
|
+
end
|
|
144
|
+
|
|
118
145
|
# Returns an array of insert statements for inserting multiple records.
|
|
119
146
|
# This method is used by +multi_insert+ to format insert statements and
|
|
120
147
|
# expects a keys array and and an array of value arrays.
|
|
@@ -977,7 +1004,12 @@ module Sequel
|
|
|
977
1004
|
# order if not. Also removes the row_proc, which isn't needed
|
|
978
1005
|
# for aggregate calculations.
|
|
979
1006
|
def aggregate_dataset
|
|
980
|
-
(
|
|
1007
|
+
(aggreate_dataset_use_from_self? ? from_self : unordered).naked
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
# Whether to use from_self for an aggregate dataset.
|
|
1011
|
+
def aggreate_dataset_use_from_self?
|
|
1012
|
+
options_overlap(COUNT_FROM_SELF_OPTS)
|
|
981
1013
|
end
|
|
982
1014
|
|
|
983
1015
|
# Append aliasing expression to SQL string.
|
|
@@ -1099,9 +1131,14 @@ module Sequel
|
|
|
1099
1131
|
:"t#{number}"
|
|
1100
1132
|
end
|
|
1101
1133
|
|
|
1102
|
-
# The strftime format to use when literalizing
|
|
1134
|
+
# The strftime format to use when literalizing time (Sequel::SQLTime) values.
|
|
1135
|
+
def default_time_format
|
|
1136
|
+
"'%H:%M:%S.%6N'"
|
|
1137
|
+
end
|
|
1138
|
+
|
|
1139
|
+
# The strftime format to use when literalizing timestamp (Time/DateTime) values.
|
|
1103
1140
|
def default_timestamp_format
|
|
1104
|
-
|
|
1141
|
+
"'%Y-%m-%d %H:%M:%S.%6N'"
|
|
1105
1142
|
end
|
|
1106
1143
|
|
|
1107
1144
|
def delete_delete_sql(sql)
|
|
@@ -1164,43 +1201,23 @@ module Sequel
|
|
|
1164
1201
|
{1 => ((op == :IN) ? 0 : 1)}
|
|
1165
1202
|
end
|
|
1166
1203
|
|
|
1167
|
-
# Format the timestamp based on the default_timestamp_format
|
|
1168
|
-
# of modifiers. First, allow %N to be used for fractions seconds (if the
|
|
1169
|
-
# database supports them), and override %z to always use a numeric offset
|
|
1170
|
-
# of hours and minutes.
|
|
1204
|
+
# Format the timestamp based on the default_timestamp_format.
|
|
1171
1205
|
def format_timestamp(v)
|
|
1172
|
-
|
|
1173
|
-
fmt = default_timestamp_format.gsub(/%[Nz]/) do |m|
|
|
1174
|
-
if m == '%N'
|
|
1175
|
-
# Ruby 1.9 supports %N in timestamp formats, but Sequel has supported %N
|
|
1176
|
-
# for longer in a different way, where the . is already appended and only 6
|
|
1177
|
-
# decimal places are used by default.
|
|
1178
|
-
format_timestamp_usec(v.is_a?(DateTime) ? v.sec_fraction*(1000000) : v.usec) if supports_timestamp_usecs?
|
|
1179
|
-
else
|
|
1180
|
-
if supports_timestamp_timezones?
|
|
1181
|
-
# Would like to just use %z format, but it doesn't appear to work on Windows
|
|
1182
|
-
# Instead, the offset fragment is constructed manually
|
|
1183
|
-
minutes = (v2.is_a?(DateTime) ? v2.offset * 1440 : v2.utc_offset/60).to_i
|
|
1184
|
-
format_timestamp_offset(*minutes.divmod(60))
|
|
1185
|
-
end
|
|
1186
|
-
end
|
|
1187
|
-
end
|
|
1188
|
-
v2.strftime(fmt)
|
|
1206
|
+
db.from_application_timestamp(v).strftime(default_timestamp_format)
|
|
1189
1207
|
end
|
|
1190
1208
|
|
|
1191
|
-
#
|
|
1192
|
-
def format_timestamp_offset(hour, minute)
|
|
1193
|
-
sprintf("%+03i%02i", hour, minute)
|
|
1194
|
-
end
|
|
1209
|
+
# :nocov:
|
|
1195
1210
|
|
|
1196
1211
|
# Return the SQL timestamp fragment to use for the fractional time part.
|
|
1197
1212
|
# Should start with the decimal point. Uses 6 decimal places by default.
|
|
1198
1213
|
def format_timestamp_usec(usec, ts=timestamp_precision)
|
|
1214
|
+
# SEQUEL6: Remove
|
|
1199
1215
|
unless ts == 6
|
|
1200
1216
|
usec = usec/(10 ** (6 - ts))
|
|
1201
1217
|
end
|
|
1202
1218
|
sprintf(".%0#{ts}d", usec)
|
|
1203
1219
|
end
|
|
1220
|
+
# :nocov:
|
|
1204
1221
|
|
|
1205
1222
|
# Append literalization of identifier to SQL string, considering regular strings
|
|
1206
1223
|
# as SQL identifiers instead of SQL strings.
|
|
@@ -1342,11 +1359,12 @@ module Sequel
|
|
|
1342
1359
|
|
|
1343
1360
|
# SQL fragment for Date, using the ISO8601 format.
|
|
1344
1361
|
def literal_date(v)
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1362
|
+
v.strftime("'%Y-%m-%d'")
|
|
1363
|
+
end
|
|
1364
|
+
|
|
1365
|
+
# Append literalization of date to SQL string.
|
|
1366
|
+
def literal_date_append(sql, v)
|
|
1367
|
+
sql << literal_date(v)
|
|
1350
1368
|
end
|
|
1351
1369
|
|
|
1352
1370
|
# SQL fragment for DateTime
|
|
@@ -1409,7 +1427,7 @@ module Sequel
|
|
|
1409
1427
|
|
|
1410
1428
|
# SQL fragment for Sequel::SQLTime, containing just the time part
|
|
1411
1429
|
def literal_sqltime(v)
|
|
1412
|
-
v.strftime(
|
|
1430
|
+
v.strftime(default_time_format)
|
|
1413
1431
|
end
|
|
1414
1432
|
|
|
1415
1433
|
# Append literalization of Sequel::SQLTime to SQL string.
|
|
@@ -1725,7 +1743,7 @@ module Sequel
|
|
|
1725
1743
|
# Append literalization of the subselect to SQL string.
|
|
1726
1744
|
def subselect_sql_append(sql, ds)
|
|
1727
1745
|
sds = subselect_sql_dataset(sql, ds)
|
|
1728
|
-
sds
|
|
1746
|
+
subselect_sql_append_sql(sql, sds)
|
|
1729
1747
|
unless sds.send(:cache_sql?)
|
|
1730
1748
|
# If subquery dataset does not allow caching SQL,
|
|
1731
1749
|
# then this dataset should not allow caching SQL.
|
|
@@ -1737,6 +1755,10 @@ module Sequel
|
|
|
1737
1755
|
ds.clone(:append_sql=>sql)
|
|
1738
1756
|
end
|
|
1739
1757
|
|
|
1758
|
+
def subselect_sql_append_sql(sql, ds)
|
|
1759
|
+
ds.sql
|
|
1760
|
+
end
|
|
1761
|
+
|
|
1740
1762
|
# The number of decimal digits of precision to use in timestamps.
|
|
1741
1763
|
def timestamp_precision
|
|
1742
1764
|
supports_timestamp_usecs? ? 6 : 0
|
data/lib/sequel/dataset.rb
CHANGED
|
@@ -53,4 +53,8 @@ module Sequel
|
|
|
53
53
|
require_relative "dataset/sql"
|
|
54
54
|
require_relative "dataset/placeholder_literalizer"
|
|
55
55
|
require_relative "dataset/dataset_module"
|
|
56
|
+
|
|
57
|
+
# :nocov:
|
|
58
|
+
require_relative "dataset/deprecated_singleton_class_methods" if Dataset::TRUE_FREEZE
|
|
59
|
+
# :nocov:
|
|
56
60
|
end
|
data/lib/sequel/exceptions.rb
CHANGED
|
@@ -18,6 +18,11 @@ module Sequel
|
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
(
|
|
23
|
+
# Error raised when there is a failed attempt to acquire an advisory lock.
|
|
24
|
+
AdvisoryLockError = Class.new(Error)
|
|
25
|
+
).name
|
|
21
26
|
|
|
22
27
|
(
|
|
23
28
|
# Error raised when the adapter requested doesn't exist or can't be loaded.
|
|
@@ -23,18 +23,6 @@ module Sequel
|
|
|
23
23
|
super
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
# Handle Sequel::Model instances in bound variable arrays.
|
|
30
|
-
def bound_variable_array(arg)
|
|
31
|
-
case arg
|
|
32
|
-
when Sequel::Model
|
|
33
|
-
"\"(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(',').gsub(/("|\\)/, '\\\\\1')})\""
|
|
34
|
-
else
|
|
35
|
-
super
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
26
|
end
|
|
39
27
|
end
|
|
40
28
|
end
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
# code
|
|
6
6
|
#
|
|
7
7
|
# DB.extension :async_thread_pool
|
|
8
|
-
# foos = DB[:foos].async.where
|
|
8
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
9
9
|
# bar_names = DB[:bar].async.select_order_map(:name)
|
|
10
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
10
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
11
11
|
#
|
|
12
12
|
# All 3 queries will be run in separate threads. +foos+, +bar_names+
|
|
13
13
|
# and +baz_1+ will be proxy objects. Calling a method on the proxy
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
# of calling that method on the result of the query method. For example,
|
|
16
16
|
# if you run:
|
|
17
17
|
#
|
|
18
|
-
# foos = DB[:foos].async.where
|
|
18
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
19
19
|
# bar_names = DB[:bars].async.select_order_map(:name)
|
|
20
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
20
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
21
21
|
# sleep(1)
|
|
22
22
|
# foos.size
|
|
23
23
|
# bar_names.first
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
# These three queries will generally be run concurrently in separate
|
|
27
27
|
# threads. If you instead run:
|
|
28
28
|
#
|
|
29
|
-
# DB[:foos].async.where
|
|
29
|
+
# DB[:foos].async.where(name: 'A'..'M').all.size
|
|
30
30
|
# DB[:bars].async.select_order_map(:name).first
|
|
31
|
-
# DB[:bazes].async.first(:
|
|
31
|
+
# DB[:bazes].async.first(id: 1).name
|
|
32
32
|
#
|
|
33
33
|
# Then will run each query sequentially, since you need the result of
|
|
34
34
|
# one query before running the next query. The queries will still be
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
# What is run in the separate thread is the entire method call that
|
|
38
38
|
# returns results. So with the original example:
|
|
39
39
|
#
|
|
40
|
-
# foos = DB[:foos].async.where
|
|
40
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
41
41
|
# bar_names = DB[:bars].async.select_order_map(:name)
|
|
42
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
42
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
43
43
|
#
|
|
44
|
-
# The +all+, <tt>select_order_map(:name)</tt>, and <tt>first(:
|
|
44
|
+
# The +all+, <tt>select_order_map(:name)</tt>, and <tt>first(id: 1)</tt>
|
|
45
45
|
# calls are run in separate threads. If a block is passed to a method
|
|
46
46
|
# such as +all+ or +each+, the block is also run in that thread. If you
|
|
47
47
|
# have code such as:
|
|
@@ -156,10 +156,10 @@
|
|
|
156
156
|
# so that the query will run in the current thread instead of waiting
|
|
157
157
|
# for an async thread to become available. With the following code:
|
|
158
158
|
#
|
|
159
|
-
# foos = DB[:foos].async.where
|
|
159
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
160
160
|
# bar_names = DB[:bar].async.select_order_map(:name)
|
|
161
161
|
# if foos.length > 4
|
|
162
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
162
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
163
163
|
# end
|
|
164
164
|
#
|
|
165
165
|
# Whether you need the +baz_1+ variable depends on the value of foos.
|
|
@@ -176,6 +176,13 @@
|
|
|
176
176
|
# +:preempt_async_thread+ Database option before loading the
|
|
177
177
|
# async_thread_pool extension.
|
|
178
178
|
#
|
|
179
|
+
# Note that the async_thread_pool extension creates the thread pool
|
|
180
|
+
# when it is loaded into the Database. If you fork after loading
|
|
181
|
+
# the extension, the extension will not work, as fork does not
|
|
182
|
+
# copy the thread pools. If you are using a forking webserver
|
|
183
|
+
# (or any other system that forks worker processes), load this
|
|
184
|
+
# extension in each child process, do not load it before forking.
|
|
185
|
+
#
|
|
179
186
|
# Related module: Sequel::Database::AsyncThreadPool::DatasetMethods
|
|
180
187
|
|
|
181
188
|
|
|
@@ -338,8 +345,9 @@ module Sequel
|
|
|
338
345
|
module DatabaseMethods
|
|
339
346
|
def self.extended(db)
|
|
340
347
|
db.instance_exec do
|
|
341
|
-
|
|
342
|
-
|
|
348
|
+
case pool.pool_type
|
|
349
|
+
when :single, :sharded_single
|
|
350
|
+
raise Error, "cannot load async_thread_pool extension if using single or sharded_single connection pool"
|
|
343
351
|
end
|
|
344
352
|
|
|
345
353
|
num_async_threads = opts[:num_async_threads] ? typecast_value_integer(opts[:num_async_threads]) : (Integer(opts[:max_connections] || 4))
|