sequel 4.47.0 → 4.48.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +134 -0
  3. data/Rakefile +1 -1
  4. data/doc/release_notes/4.48.0.txt +293 -0
  5. data/lib/sequel/adapters/ado/access.rb +2 -1
  6. data/lib/sequel/adapters/do/postgres.rb +5 -2
  7. data/lib/sequel/adapters/ibmdb.rb +24 -7
  8. data/lib/sequel/adapters/jdbc.rb +36 -22
  9. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  10. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  11. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  12. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
  13. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  14. data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
  15. data/lib/sequel/adapters/mock.rb +24 -19
  16. data/lib/sequel/adapters/mysql.rb +17 -16
  17. data/lib/sequel/adapters/mysql2.rb +4 -5
  18. data/lib/sequel/adapters/oracle.rb +5 -9
  19. data/lib/sequel/adapters/postgres.rb +89 -102
  20. data/lib/sequel/adapters/shared/db2.rb +22 -6
  21. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  22. data/lib/sequel/adapters/shared/mysql.rb +75 -24
  23. data/lib/sequel/adapters/shared/postgres.rb +196 -94
  24. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  25. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  26. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  27. data/lib/sequel/adapters/sqlite.rb +5 -3
  28. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  29. data/lib/sequel/adapters/tinytds.rb +0 -5
  30. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  31. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  32. data/lib/sequel/core.rb +2 -2
  33. data/lib/sequel/database/connecting.rb +5 -5
  34. data/lib/sequel/database/dataset.rb +6 -3
  35. data/lib/sequel/database/misc.rb +1 -1
  36. data/lib/sequel/database/query.rb +3 -0
  37. data/lib/sequel/database/schema_methods.rb +1 -1
  38. data/lib/sequel/dataset/actions.rb +18 -10
  39. data/lib/sequel/dataset/graph.rb +1 -1
  40. data/lib/sequel/dataset/misc.rb +1 -0
  41. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  42. data/lib/sequel/dataset/query.rb +19 -8
  43. data/lib/sequel/extensions/core_extensions.rb +4 -1
  44. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  45. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  46. data/lib/sequel/extensions/filter_having.rb +2 -0
  47. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  48. data/lib/sequel/extensions/from_block.rb +1 -1
  49. data/lib/sequel/extensions/graph_each.rb +2 -2
  50. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  51. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  52. data/lib/sequel/extensions/meta_def.rb +2 -0
  53. data/lib/sequel/extensions/migration.rb +6 -6
  54. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  55. data/lib/sequel/extensions/pagination.rb +1 -1
  56. data/lib/sequel/extensions/pg_array.rb +207 -130
  57. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  58. data/lib/sequel/extensions/pg_inet.rb +18 -6
  59. data/lib/sequel/extensions/pg_interval.rb +19 -12
  60. data/lib/sequel/extensions/pg_json.rb +25 -14
  61. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  62. data/lib/sequel/extensions/pg_range.rb +133 -100
  63. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  64. data/lib/sequel/extensions/pg_row.rb +68 -39
  65. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  66. data/lib/sequel/extensions/query_literals.rb +2 -0
  67. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  68. data/lib/sequel/extensions/s.rb +1 -1
  69. data/lib/sequel/extensions/schema_dumper.rb +24 -24
  70. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  71. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  72. data/lib/sequel/extensions/set_overrides.rb +2 -2
  73. data/lib/sequel/extensions/string_agg.rb +0 -1
  74. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  75. data/lib/sequel/model.rb +25 -57
  76. data/lib/sequel/model/associations.rb +14 -5
  77. data/lib/sequel/model/base.rb +96 -32
  78. data/lib/sequel/plugins/association_pks.rb +73 -46
  79. data/lib/sequel/plugins/association_proxies.rb +1 -1
  80. data/lib/sequel/plugins/auto_validations.rb +6 -2
  81. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  82. data/lib/sequel/plugins/caching.rb +19 -13
  83. data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
  84. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  85. data/lib/sequel/plugins/column_select.rb +1 -1
  86. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  87. data/lib/sequel/plugins/defaults_setter.rb +10 -0
  88. data/lib/sequel/plugins/eager_each.rb +1 -1
  89. data/lib/sequel/plugins/force_encoding.rb +2 -2
  90. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  91. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  92. data/lib/sequel/plugins/instance_filters.rb +3 -1
  93. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  94. data/lib/sequel/plugins/json_serializer.rb +17 -10
  95. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  96. data/lib/sequel/plugins/modification_detection.rb +3 -0
  97. data/lib/sequel/plugins/nested_attributes.rb +5 -1
  98. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  99. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  100. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  101. data/lib/sequel/plugins/serialization.rb +3 -10
  102. data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
  103. data/lib/sequel/plugins/split_values.rb +6 -5
  104. data/lib/sequel/plugins/static_cache.rb +31 -25
  105. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  106. data/lib/sequel/plugins/table_select.rb +1 -1
  107. data/lib/sequel/plugins/touch.rb +2 -1
  108. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  109. data/lib/sequel/plugins/validation_helpers.rb +2 -4
  110. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  111. data/lib/sequel/sql.rb +2 -2
  112. data/lib/sequel/version.rb +1 -1
  113. data/spec/adapters/db2_spec.rb +115 -14
  114. data/spec/adapters/mysql_spec.rb +78 -28
  115. data/spec/adapters/oracle_spec.rb +24 -24
  116. data/spec/adapters/postgres_spec.rb +38 -24
  117. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  118. data/spec/adapters/sqlite_spec.rb +29 -24
  119. data/spec/core/connection_pool_spec.rb +17 -0
  120. data/spec/core/database_spec.rb +6 -0
  121. data/spec/core/dataset_spec.rb +46 -36
  122. data/spec/core/schema_spec.rb +16 -0
  123. data/spec/core/spec_helper.rb +1 -0
  124. data/spec/core_extensions_spec.rb +6 -2
  125. data/spec/extensions/active_model_spec.rb +1 -1
  126. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  127. data/spec/extensions/association_pks_spec.rb +34 -2
  128. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  129. data/spec/extensions/auto_validations_spec.rb +2 -0
  130. data/spec/extensions/boolean_readers_spec.rb +1 -1
  131. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  132. data/spec/extensions/class_table_inheritance_spec.rb +48 -2
  133. data/spec/extensions/column_conflicts_spec.rb +11 -0
  134. data/spec/extensions/connection_validator_spec.rb +1 -1
  135. data/spec/extensions/dataset_associations_spec.rb +8 -8
  136. data/spec/extensions/defaults_setter_spec.rb +1 -1
  137. data/spec/extensions/filter_having_spec.rb +5 -3
  138. data/spec/extensions/hash_aliases_spec.rb +3 -1
  139. data/spec/extensions/identifier_columns_spec.rb +3 -1
  140. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  141. data/spec/extensions/json_serializer_spec.rb +18 -0
  142. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  143. data/spec/extensions/meta_def_spec.rb +9 -0
  144. data/spec/extensions/migration_spec.rb +3 -3
  145. data/spec/extensions/nested_attributes_spec.rb +14 -3
  146. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  147. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  148. data/spec/extensions/pg_array_spec.rb +44 -25
  149. data/spec/extensions/pg_hstore_spec.rb +10 -0
  150. data/spec/extensions/pg_inet_spec.rb +26 -0
  151. data/spec/extensions/pg_interval_spec.rb +20 -0
  152. data/spec/extensions/pg_json_spec.rb +24 -0
  153. data/spec/extensions/pg_range_spec.rb +98 -14
  154. data/spec/extensions/pg_row_spec.rb +14 -4
  155. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  156. data/spec/extensions/query_literals_spec.rb +3 -1
  157. data/spec/extensions/schema_dumper_spec.rb +96 -98
  158. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  159. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  160. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  161. data/spec/extensions/spec_helper.rb +7 -1
  162. data/spec/extensions/static_cache_spec.rb +75 -24
  163. data/spec/extensions/string_agg_spec.rb +1 -1
  164. data/spec/extensions/touch_spec.rb +9 -0
  165. data/spec/extensions/validation_helpers_spec.rb +9 -3
  166. data/spec/extensions/whitelist_security_spec.rb +26 -0
  167. data/spec/integration/dataset_test.rb +45 -44
  168. data/spec/integration/plugin_test.rb +20 -0
  169. data/spec/integration/prepared_statement_test.rb +3 -0
  170. data/spec/integration/schema_test.rb +21 -1
  171. data/spec/integration/transaction_test.rb +40 -40
  172. data/spec/model/class_dataset_methods_spec.rb +14 -4
  173. data/spec/model/dataset_methods_spec.rb +12 -3
  174. data/spec/model/model_spec.rb +8 -0
  175. metadata +6 -4
  176. data/spec/adapters/firebird_spec.rb +0 -405
  177. data/spec/adapters/informix_spec.rb +0 -100
@@ -23,6 +23,8 @@
23
23
  #
24
24
  # Related module: Sequel::Sequel3DatasetMethods
25
25
 
26
+ Sequel::Deprecation.deprecate("The sequel_3_dataset_methods extension", "Please consider maintaining it yourself as an external gem if you want to continue using it")
27
+
26
28
  #
27
29
  module Sequel
28
30
  module Sequel3DatasetMethods
@@ -122,7 +124,7 @@ module Sequel
122
124
  cols = n.columns
123
125
  csv = String.new
124
126
  csv << "#{cols.join(', ')}\r\n" if include_column_titles
125
- n.each{|r| csv << "#{cols.collect{|c| r[c]}.join(', ')}\r\n"}
127
+ n.each{|r| csv << "#{cols.map{|c| r[c]}.join(', ')}\r\n"}
126
128
  csv
127
129
  end
128
130
  end
@@ -0,0 +1,83 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # This adds the following dataset methods:
4
+ #
5
+ # and :: alias for where
6
+ # exclude_where :: alias for exclude
7
+ # interval :: Returns max - min, using a single query
8
+ # range :: Returns min..max, using a single query
9
+ #
10
+ # It is only recommended to use this for backwards compatibility.
11
+ #
12
+ # You can load this extension into specific datasets:
13
+ #
14
+ # ds = DB[:table]
15
+ # ds = ds.extension(:sequel_4_dataset_methods)
16
+ #
17
+ # Or you can load it into all of a database's datasets, which
18
+ # is probably the desired behavior if you are using this extension:
19
+ #
20
+ # DB.extension(:sequel_4_dataset_methods)
21
+ #
22
+ # Related module: Sequel::Sequel4DatasetMethods
23
+
24
+ #
25
+ module Sequel
26
+ module Sequel4DatasetMethods
27
+ # Alias for where.
28
+ def and(*cond, &block)
29
+ where(*cond, &block)
30
+ end
31
+
32
+ # Alias for exclude.
33
+ def exclude_where(*cond, &block)
34
+ exclude(*cond, &block)
35
+ end
36
+
37
+ # Returns the interval between minimum and maximum values for the given
38
+ # column/expression. Uses a virtual row block if no argument is given.
39
+ #
40
+ # DB[:table].interval(:id) # SELECT (max(id) - min(id)) FROM table LIMIT 1
41
+ # # => 6
42
+ # DB[:table].interval{function(column)} # SELECT (max(function(column)) - min(function(column))) FROM table LIMIT 1
43
+ # # => 7
44
+ def interval(column=Sequel.virtual_row(&Proc.new))
45
+ if loader = cached_placeholder_literalizer(:_interval_loader) do |pl|
46
+ arg = pl.arg
47
+ aggregate_dataset.limit(1).select((SQL::Function.new(:max, arg) - SQL::Function.new(:min, arg)).as(:interval))
48
+ end
49
+
50
+ loader.get(column)
51
+ else
52
+ aggregate_dataset.get{(max(column) - min(column)).as(:interval)}
53
+ end
54
+ end
55
+
56
+ # Returns a +Range+ instance made from the minimum and maximum values for the
57
+ # given column/expression. Uses a virtual row block if no argument is given.
58
+ #
59
+ # DB[:table].range(:id) # SELECT max(id) AS v1, min(id) AS v2 FROM table LIMIT 1
60
+ # # => 1..10
61
+ # DB[:table].interval{function(column)} # SELECT max(function(column)) AS v1, min(function(column)) AS v2 FROM table LIMIT 1
62
+ # # => 0..7
63
+ def range(column=Sequel.virtual_row(&Proc.new))
64
+ r = if loader = cached_placeholder_literalizer(:_range_loader) do |pl|
65
+ arg = pl.arg
66
+ aggregate_dataset.limit(1).select(SQL::Function.new(:min, arg).as(:v1), SQL::Function.new(:max, arg).as(:v2))
67
+ end
68
+
69
+ loader.first(column)
70
+ else
71
+ aggregate_dataset.select{[min(column).as(v1), max(column).as(v2)]}.first
72
+ end
73
+
74
+ if r
75
+ (r[:v1]..r[:v2])
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ Dataset.register_extension(:sequel_4_dataset_methods, Sequel4DatasetMethods)
82
+ end
83
+
@@ -73,8 +73,8 @@ module Sequel
73
73
  end
74
74
 
75
75
  # Dataset options that do not affect the generated SQL.
76
- def non_sql_options
77
- super + [:defaults, :overrides]
76
+ def non_sql_option?(key)
77
+ super || key == :defaults || key == :overrides
78
78
  end
79
79
  end
80
80
 
@@ -53,7 +53,6 @@
53
53
  # * DB2 9.7+ (except distinct)
54
54
  # * MySQL
55
55
  # * HSQLDB
56
- # * CUBRID
57
56
  # * H2
58
57
  #
59
58
  # Related module: Sequel::SQL::StringAgg
@@ -18,10 +18,6 @@
18
18
  # If you are using Ruby 2+, and you would like to use refinements, there
19
19
  # is a refinement version of this in the symbol_aref_refinement extension.
20
20
  #
21
- # If you are using the ruby18_symbol_extensions, and would like symbol_aref
22
- # to take affect, load the symbol_aref extension after the
23
- # ruby18_symbol_extensions.
24
- #
25
21
  # Related module: Sequel::SymbolAref
26
22
 
27
23
  if RUBY_VERSION >= '2.0'
@@ -31,62 +31,36 @@ module Sequel
31
31
  class Model
32
32
  OPTS = Sequel::OPTS
33
33
 
34
- # Class methods added to model that call the method of the same name on the dataset
35
- DATASET_METHODS = (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server, :where_all, :where_each, :where_single_value]) -
36
- [:and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases] # SEQUEL5: Remove set_graph_aliases
37
-
38
- # Boolean settings that can be modified at the global, class, or instance level.
39
- BOOLEAN_SETTINGS = [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, \
40
- :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions,
41
- :use_after_commit_rollback # SEQUEL5: Remove
42
- ]
43
-
44
- # Hooks that are called before an action. Can return false to not do the action. When
45
- # overriding these, it is recommended to call +super+ as the last line of your method,
46
- # so later hooks are called before earlier hooks.
34
+ DATASET_METHODS = (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server, :where_all, :where_each, :where_single_value]) - [:and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases]
35
+ Sequel::Deprecation.deprecate_constant(self, :DATASET_METHODS)
36
+ BOOLEAN_SETTINGS = [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions, :use_after_commit_rollback]
37
+ Sequel::Deprecation.deprecate_constant(self, :BOOLEAN_SETTINGS)
47
38
  BEFORE_HOOKS = [:before_create, :before_update, :before_save, :before_destroy, :before_validation]
48
-
49
- # Hooks that are called after an action. When overriding these, it is recommended to call
50
- # +super+ on the first line of your method, so later hooks are called after earlier hooks.
51
- AFTER_HOOKS = [:after_create, :after_update, :after_save, :after_destroy, :after_validation,
52
- :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback] # SEQUEL5: Remove commit/rollback hooks
53
-
54
- # Hooks that are called around an action. If overridden, these methods must call super
55
- # exactly once if the behavior they wrap is desired. The can be used to rescue exceptions
56
- # raised by the code they wrap or ensure that some behavior is executed no matter what.
39
+ Sequel::Deprecation.deprecate_constant(self, :BEFORE_HOOKS)
40
+ AFTER_HOOKS = [:after_create, :after_update, :after_save, :after_destroy, :after_validation, :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback]
41
+ Sequel::Deprecation.deprecate_constant(self, :AFTER_HOOKS)
57
42
  AROUND_HOOKS = [:around_create, :around_update, :around_save, :around_destroy, :around_validation]
43
+ Sequel::Deprecation.deprecate_constant(self, :AROUND_HOOKS)
44
+ NORMAL_METHOD_NAME_REGEXP = /\A[A-Za-z_][A-Za-z0-9_]*\z/
45
+ Sequel::Deprecation.deprecate_constant(self, :NORMAL_METHOD_NAME_REGEXP)
46
+ SETTER_METHOD_REGEXP = /=\z/
47
+ Sequel::Deprecation.deprecate_constant(self, :SETTER_METHOD_REGEXP)
48
+ ANONYMOUS_MODEL_CLASSES = @Model_cache = {}
49
+ Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES)
50
+ ANONYMOUS_MODEL_CLASSES_MUTEX = Mutex.new
51
+ Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES_MUTEX)
52
+ INHERITED_INSTANCE_VARIABLES = { :@allowed_columns=>:dup, :@dataset_method_modules=>:dup, :@primary_key=>nil, :@use_transactions=>nil, :@raise_on_save_failure=>nil, :@require_modification=>nil, :@restrict_primary_key=>nil, :@simple_pk=>nil, :@simple_table=>nil, :@strict_param_setting=>nil, :@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil, :@raise_on_typecast_failure=>nil, :@plugins=>:dup, :@setter_methods=>nil, :@use_after_commit_rollback=>nil, :@fast_pk_lookup_sql=>nil, :@fast_instance_delete_sql=>nil, :@finders=>:dup, :@finder_loaders=>:dup, :@db=>nil, :@default_set_fields_options=>:dup, :@require_valid_table=>nil, :@cache_anonymous_models=>nil, :@dataset_module_class=>nil}
53
+ Sequel::Deprecation.deprecate_constant(self, :INHERITED_INSTANCE_VARIABLES)
58
54
 
59
55
  # Empty instance methods to create that the user can override to get hook/callback behavior.
60
56
  # Just like any other method defined by Sequel, if you override one of these, you should
61
57
  # call +super+ to get the default behavior (while empty by default, they can also be defined
62
58
  # by plugins). See the {"Model Hooks" guide}[rdoc-ref:doc/model_hooks.rdoc] for
63
59
  # more detail on hooks.
64
- HOOKS = BEFORE_HOOKS + AFTER_HOOKS
65
-
66
- # Class instance variables that are inherited in subclasses. If the value is <tt>:dup</tt>, dup is called
67
- # on the superclass's instance variable when creating the instance variable in the subclass.
68
- # If the value is +nil+, the superclass's instance variable is used directly in the subclass.
69
- INHERITED_INSTANCE_VARIABLES = {
70
- :@allowed_columns=>:dup, # SEQUEL5: Remove
71
- :@dataset_method_modules=>:dup, :@primary_key=>nil, :@use_transactions=>nil,
72
- :@raise_on_save_failure=>nil, :@require_modification=>nil, :@restrict_primary_key=>nil,
73
- :@simple_pk=>nil, :@simple_table=>nil, :@strict_param_setting=>nil,
74
- :@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil,
75
- :@raise_on_typecast_failure=>nil, :@plugins=>:dup, :@setter_methods=>nil,
76
- :@use_after_commit_rollback=>nil, :@fast_pk_lookup_sql=>nil,
77
- :@fast_instance_delete_sql=>nil,
78
- :@finders=>:dup, :@finder_loaders=>:dup, # SEQUEL5: Remove
79
- :@db=>nil, :@default_set_fields_options=>:dup, :@require_valid_table=>nil,
80
- :@cache_anonymous_models=>nil, :@dataset_module_class=>nil}
81
-
82
- # Regular expression that determines if a method name is normal in the sense that
83
- # it could be used literally in ruby code without using send. Used to
84
- # avoid problems when using eval with a string to define methods.
85
- NORMAL_METHOD_NAME_REGEXP = /\A[A-Za-z_][A-Za-z0-9_]*\z/
86
-
87
- # Regular expression that determines if the method is a valid setter name
88
- # (i.e. it ends with =).
89
- SETTER_METHOD_REGEXP = /=\z/
60
+ HOOKS = [:before_create, :before_update, :before_save, :before_destroy, :before_validation,
61
+ :after_create, :after_update, :after_save, :after_destroy, :after_validation,
62
+ :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback # SEQUEL5: Remove commit/rollback hooks
63
+ ]#.freeze # SEQUEL5
90
64
 
91
65
  @allowed_columns = nil # SEQUEL5: Remove
92
66
  @cache_anonymous_models = true
@@ -123,11 +97,11 @@ module Sequel
123
97
  plugin Model::Associations
124
98
  end
125
99
 
100
+ def_Model(::Sequel)
101
+
126
102
  # The setter methods (methods ending with =) that are never allowed
127
103
  # to be called automatically via +set+/+update+/+new+/etc..
128
- RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).grep(SETTER_METHOD_REGEXP)
129
-
130
- def_Model(::Sequel)
104
+ RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).select{|l| l.end_with?('=')}#.freeze # SEQUEL5
131
105
 
132
106
  # SEQUEL5: Remove
133
107
  class DeprecatedColumnsUpdated # :nodoc:
@@ -140,11 +114,5 @@ module Sequel
140
114
  @columns_updated.send(*args, &block)
141
115
  end
142
116
  end
143
-
144
- ANONYMOUS_MODEL_CLASSES = @Model_cache # :nodoc:
145
- Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES)
146
-
147
- ANONYMOUS_MODEL_CLASSES_MUTEX = Mutex.new # :nodoc:
148
- Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES_MUTEX)
149
117
  end
150
118
  end
@@ -1450,7 +1450,7 @@ module Sequel
1450
1450
 
1451
1451
  # This module contains methods added to all association datasets
1452
1452
  module AssociationDatasetMethods
1453
- Dataset.def_deprecated_opts_setter(self, :model, :association_reflection)
1453
+ Dataset.def_deprecated_opts_setter(self, :model_object, :association_reflection)
1454
1454
 
1455
1455
  # The model object that created the association dataset
1456
1456
  def model_object
@@ -1461,6 +1461,12 @@ module Sequel
1461
1461
  def association_reflection
1462
1462
  @opts[:association_reflection]
1463
1463
  end
1464
+
1465
+ private
1466
+
1467
+ def non_sql_option?(key)
1468
+ super || key == :model_object || key == :association_reflection
1469
+ end
1464
1470
  end
1465
1471
 
1466
1472
  # Each kind of association adds a number of instance methods to the model class which
@@ -1782,7 +1788,6 @@ module Sequel
1782
1788
  opts.merge!(orig_opts)
1783
1789
  opts.merge!(:type => type, :name => name, :cache=>({} if cache_associations), :model => self)
1784
1790
 
1785
- opts
1786
1791
  opts[:block] = block if block
1787
1792
  if !opts.has_key?(:instance_specific) && (block || orig_opts[:block] || orig_opts[:dataset])
1788
1793
  # It's possible the association is instance specific, in that it depends on
@@ -1912,7 +1917,7 @@ module Sequel
1912
1917
  # Adds the association method to the association methods module.
1913
1918
  def def_association_method(opts)
1914
1919
  association_module_def(opts.association_method, opts) do |*dynamic_opts, &block|
1915
- Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored.") if dynamic_opts.length > 1
1920
+ Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored") if dynamic_opts.length > 1
1916
1921
  load_associated_objects(opts, dynamic_opts.length == 0 ? OPTS : dynamic_opts[0], &block)
1917
1922
  end
1918
1923
  end
@@ -2815,7 +2820,7 @@ END
2815
2820
 
2816
2821
  # If the dataset is being eagerly loaded, default to calling all
2817
2822
  # instead of each.
2818
- def to_hash(key_column=nil, value_column=nil, opts=OPTS)
2823
+ def as_hash(key_column=nil, value_column=nil, opts=OPTS)
2819
2824
  if (@opts[:eager_graph] || @opts[:eager]) && !opts.has_key?(:all)
2820
2825
  opts = Hash[opts]
2821
2826
  opts[:all] = true
@@ -3040,7 +3045,7 @@ END
3040
3045
  # specific foreign/primary key
3041
3046
  key_hash = {}
3042
3047
  # Reflections for all associations to eager load
3043
- reflections = eager_assoc.keys.collect{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
3048
+ reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
3044
3049
 
3045
3050
  # Populate the key_hash entry for each association being eagerly loaded
3046
3051
  reflections.each do |r|
@@ -3136,6 +3141,10 @@ END
3136
3141
  end
3137
3142
  alias one_to_one_association_filter_expression one_to_many_association_filter_expression
3138
3143
 
3144
+ def non_sql_option?(key)
3145
+ super || key == :eager || key == :eager_graph
3146
+ end
3147
+
3139
3148
  # Build associations from the graph if #eager_graph was used,
3140
3149
  # and/or load other associations if #eager was used.
3141
3150
  def post_load(all_records)
@@ -7,8 +7,20 @@ module Sequel
7
7
 
8
8
  # Class methods for Sequel::Model that implement basic model functionality.
9
9
  #
10
- # * All of the method names in Model::DATASET_METHODS have class methods created that call
11
- # the Model's dataset with the method of the same name with the given arguments.
10
+ # * All of the following methods have class methods created that send the method
11
+ # to the model's dataset: all, as_hash, avg, count, cross_join, distinct, each,
12
+ # each_server, empty?, except, exclude, exclude_having, fetch_rows,
13
+ # filter, first, first!, for_update, from, from_self, full_join, full_outer_join,
14
+ # get, graph, grep, group, group_and_count, group_append, group_by, having, import,
15
+ # inner_join, insert, intersect, invert, join, join_table, last, left_join,
16
+ # left_outer_join, limit, lock_style, map, max, min, multi_insert, naked, natural_full_join,
17
+ # natural_join, natural_left_join, natural_right_join, offset, order, order_append, order_by,
18
+ # order_more, order_prepend, paged_each, qualify, reverse, reverse_order, right_join,
19
+ # right_outer_join, select, select_all, select_append, select_group, select_hash,
20
+ # select_hash_groups, select_map, select_more, select_order_map, server,
21
+ # single_record, single_record!, single_value, single_value!, sum, to_hash, to_hash_groups,
22
+ # truncate, unfiltered, ungraphed, ungrouped, union, unlimited, unordered, where, where_all,
23
+ # where_each, where_single_value, with, with_recursive, with_sql
12
24
  module ClassMethods
13
25
  # Which columns should be the only columns allowed in a call to a mass assignment method (e.g. set)
14
26
  # (default: not set, so all columns not otherwise restricted are allowed).
@@ -215,16 +227,20 @@ module Sequel
215
227
  end
216
228
 
217
229
  def initialize_copy(_)
218
- Sequel::Deprecation.deprecate("Model.clone", "Create a subclass of the model instead of cloning it.")
230
+ Sequel::Deprecation.deprecate("Model.clone", "Create a subclass of the model instead of cloning it")
219
231
  # raise(Error, "cannot dup/clone a Sequel::Model class") # SEQUEL5
220
232
  super
221
233
  end
222
234
  def dup
223
- Sequel::Deprecation.deprecate("Model.dup", "Create a subclass of the model instead of duping it.")
235
+ Sequel::Deprecation.deprecate("Model.dup", "Create a subclass of the model instead of duping it")
224
236
  # raise(Error, "cannot dup/clone a Sequel::Model class") # SEQUEL5
225
237
  super
226
238
  end
227
239
 
240
+ def <<(arg)
241
+ Sequel::Deprecation.deprecate("Sequel::Model.<<", "Switch to using #insert")
242
+ dataset << (arg)
243
+ end
228
244
 
229
245
  # Returns the first record from the database matching the conditions.
230
246
  # If a hash is given, it is used as the conditions. If another
@@ -661,7 +677,7 @@ module Sequel
661
677
  # end
662
678
  def inherited(subclass)
663
679
  super
664
- ivs = subclass.instance_variables.collect(&:to_s)
680
+ ivs = subclass.instance_variables.map(&:to_s)
665
681
  inherited_instance_variables.each do |iv, dup|
666
682
  next if ivs.include?(iv.to_s)
667
683
  if (sup_class_value = instance_variable_get(iv)) && dup
@@ -707,7 +723,7 @@ module Sequel
707
723
 
708
724
  # Clear the setter_methods cache when a setter method is added
709
725
  def method_added(meth)
710
- clear_setter_methods_cache if meth.to_s =~ SETTER_METHOD_REGEXP
726
+ clear_setter_methods_cache if meth.to_s.end_with?('=')
711
727
  super
712
728
  end
713
729
 
@@ -976,7 +992,8 @@ module Sequel
976
992
  end
977
993
 
978
994
  # Add model methods that call dataset methods
979
- Plugins.def_dataset_methods(self, DATASET_METHODS)
995
+ Plugins.def_dataset_methods(self, (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server, :where_all, :where_each, :where_single_value]) - [:<<, :and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases])
996
+ # SEQUEL5: add :set_graph_aliases to remove list and remove :and
980
997
 
981
998
  private
982
999
 
@@ -1007,6 +1024,7 @@ module Sequel
1007
1024
  ds = db.from(ds)
1008
1025
  when Dataset
1009
1026
  if ds.joined_dataset?
1027
+ # raise Error, "Using a joined dataset as a model dataset is not support, use from_self on the dataset to wrap it in a subquery" # SEQUEL5
1010
1028
  Sequel::Deprecation.deprecate("Using a joined dataset as a Sequel::Model dataset", respond_to?(:cti_base_model) ? "Use the class_table_inheritance plugin :alias option in #{cti_base_model.inspect}" : "Call from_self on the dataset to wrap it in a subquery")
1011
1029
  end
1012
1030
 
@@ -1045,9 +1063,9 @@ module Sequel
1045
1063
  # use a string to define the method for speed. For other columns names, use a block.
1046
1064
  def def_column_accessor(*columns)
1047
1065
  clear_setter_methods_cache
1048
- columns, bad_columns = columns.partition{|x| NORMAL_METHOD_NAME_REGEXP.match(x.to_s)}
1066
+ columns, bad_columns = columns.partition{|x| /\A[A-Za-z_][A-Za-z0-9_]*\z/.match(x.to_s)}
1049
1067
  bad_columns.each{|x| def_bad_column_accessor(x)}
1050
- im = instance_methods.collect(&:to_s)
1068
+ im = instance_methods.map(&:to_s)
1051
1069
  columns.each do |column|
1052
1070
  meth = "#{column}="
1053
1071
  overridable_methods_module.module_eval("def #{column}; self[:#{column}] end", __FILE__, __LINE__) unless im.include?(column.to_s)
@@ -1061,7 +1079,7 @@ module Sequel
1061
1079
  def def_model_dataset_method(meth)
1062
1080
  return if respond_to?(meth, true)
1063
1081
 
1064
- if meth.to_s =~ NORMAL_METHOD_NAME_REGEXP
1082
+ if meth.to_s =~ /\A[A-Za-z_][A-Za-z0-9_]*\z/
1065
1083
  instance_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__)
1066
1084
  else
1067
1085
  (class << self; self; end).send(:define_method, meth){|*args, &block| dataset.send(meth, *args, &block)}
@@ -1111,7 +1129,7 @@ module Sequel
1111
1129
  # Set the primary key(s) based on the schema information,
1112
1130
  # if the schema information includes primary key information
1113
1131
  if schema_array.all?{|k,v| v.has_key?(:primary_key)}
1114
- pks = schema_array.collect{|k,v| k if v[:primary_key]}.compact
1132
+ pks = schema_array.map{|k,v| k if v[:primary_key]}.compact
1115
1133
  pks.length > 0 ? set_primary_key(pks) : no_primary_key
1116
1134
  end
1117
1135
 
@@ -1126,7 +1144,7 @@ module Sequel
1126
1144
  # Dataset is for a single table with all columns,
1127
1145
  # so set the columns based on the order they were
1128
1146
  # returned by the schema.
1129
- cols = schema_array.collect{|k,v| k}
1147
+ cols = schema_array.map{|k,v| k}
1130
1148
  set_columns(cols)
1131
1149
  # Also set the columns for the dataset, so the dataset
1132
1150
  # doesn't have to do a query to get them.
@@ -1148,18 +1166,46 @@ module Sequel
1148
1166
  # SEQUEL5: Remove allowed_columns handling
1149
1167
  allowed_columns.map{|x| "#{x}="}
1150
1168
  else
1151
- meths = instance_methods.collect(&:to_s).grep(SETTER_METHOD_REGEXP) - RESTRICTED_SETTER_METHODS
1169
+ meths = instance_methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
1152
1170
  meths -= Array(primary_key).map{|x| "#{x}="} if primary_key && restrict_primary_key?
1153
1171
  meths
1154
1172
  end
1155
1173
  end
1156
1174
 
1157
1175
  # A hash of instance variables to automatically set up in subclasses.
1158
- # See Sequel::Model::INHERITED_INSTANCE_VARIABLES. It is safe to modify
1159
- # the hash returned by this method, though it may not be safe to modify
1160
- # values of the hash.
1176
+ # Keys are instance variable symbols, values should be:
1177
+ # nil :: Assign directly from superclass to subclass (frozen objects)
1178
+ # :dup :: Dup object when assigning from superclass to subclass (mutable objects)
1179
+ # :hash_dup :: Assign hash with same keys, but dup all the values
1180
+ # Proc :: Call with subclass to do the assignment
1161
1181
  def inherited_instance_variables
1162
- INHERITED_INSTANCE_VARIABLES.dup
1182
+ {
1183
+ :@allowed_columns=>:dup, # SEQUEL5: Remove
1184
+ :@cache_anonymous_models=>nil,
1185
+ :@dataset_method_modules=>:dup,
1186
+ :@dataset_module_class=>nil,
1187
+ :@db=>nil,
1188
+ :@default_set_fields_options=>:dup,
1189
+ :@fast_instance_delete_sql=>nil,
1190
+ :@fast_pk_lookup_sql=>nil,
1191
+ :@finder_loaders=>:dup, # SEQUEL5: Remove
1192
+ :@finders=>:dup, # SEQUEL5: Remove
1193
+ :@plugins=>:dup,
1194
+ :@primary_key=>nil,
1195
+ :@raise_on_save_failure=>nil,
1196
+ :@raise_on_typecast_failure=>nil,
1197
+ :@require_modification=>nil,
1198
+ :@require_valid_table=>nil,
1199
+ :@restrict_primary_key=>nil,
1200
+ :@setter_methods=>nil,
1201
+ :@simple_pk=>nil,
1202
+ :@simple_table=>nil,
1203
+ :@strict_param_setting=>nil,
1204
+ :@typecast_empty_string_to_nil=>nil,
1205
+ :@typecast_on_assignment=>nil,
1206
+ :@use_after_commit_rollback=>nil,
1207
+ :@use_transactions=>nil
1208
+ }
1163
1209
  end
1164
1210
 
1165
1211
  # For the given opts hash and default name or :class option, add a
@@ -1256,6 +1302,7 @@ module Sequel
1256
1302
  ds.fetch_rows(sql){|r| return ds.row_proc.call(r)}
1257
1303
  nil
1258
1304
  elsif dataset.joined_dataset?
1305
+ # SEQUEL5: Remove as joined model datasets are not allowed
1259
1306
  dataset.first(qualified_primary_key_hash(pk))
1260
1307
  else
1261
1308
  dataset.first(primary_key_hash(pk))
@@ -1318,19 +1365,21 @@ module Sequel
1318
1365
 
1319
1366
  # Sequel::Model instance methods that implement basic model functionality.
1320
1367
  #
1321
- # * All of the methods in +HOOKS+ and +AROUND_HOOKS+ create instance methods that are called
1368
+ # * All of the model before/after/around hooks are implemented as instance methods that are called
1322
1369
  # by Sequel when the appropriate action occurs. For example, when destroying
1323
1370
  # a model object, Sequel will call +around_destroy+, which will call +before_destroy+, do
1324
1371
  # the destroy, and then call +after_destroy+.
1325
1372
  # * The following instance_methods all call the class method of the same
1326
1373
  # name: columns, db, primary_key, db_schema.
1327
- # * All of the methods in +BOOLEAN_SETTINGS+ create attr_writers allowing you
1328
- # to set values for the attribute. It also creates instance getters returning
1329
- # the value of the setting. If the value has not yet been set, it
1330
- # gets the default value from the class by calling the class method of the same name.
1374
+ # * The following accessor methods are defined via metaprogramming:
1375
+ # raise_on_save_failure, raise_on_typecast_failure, require_modification,
1376
+ # strict_param_setting, typecast_empty_string_to_nil, typecast_on_assignment,
1377
+ # and use_transactions. The setter methods will change the setting for the
1378
+ # instance, and the getter methods will check for an instance setting, then
1379
+ # try the class setting if no instance setting has been set.
1331
1380
  module InstanceMethods
1332
1381
  HOOKS.each{|h| class_eval("def #{h}; end", __FILE__, __LINE__)}
1333
- AROUND_HOOKS.each{|h| class_eval("def #{h}; yield end", __FILE__, __LINE__)}
1382
+ [:around_create, :around_update, :around_save, :around_destroy, :around_validation].each{|h| class_eval("def #{h}; yield end", __FILE__, __LINE__)}
1334
1383
 
1335
1384
  # Define instance method(s) that calls class method(s) of the
1336
1385
  # same name. Replaces the construct:
@@ -1341,8 +1390,13 @@ module Sequel
1341
1390
  # Define instance method(s) that calls class method(s) of the
1342
1391
  # same name, caching the result in an instance variable. Define
1343
1392
  # standard attr_writer method for modifying that instance variable.
1344
- BOOLEAN_SETTINGS.each{|meth| class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)}
1345
- attr_writer(*BOOLEAN_SETTINGS)
1393
+ [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, \
1394
+ :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions,
1395
+ :use_after_commit_rollback # SEQUEL5: Remove
1396
+ ].each do |meth|
1397
+ class_eval("def #{meth}; !defined?(@#{meth}) ? (frozen? ? self.class.#{meth} : (@#{meth} = self.class.#{meth})) : @#{meth} end", __FILE__, __LINE__)
1398
+ attr_writer(meth)
1399
+ end
1346
1400
 
1347
1401
  # The hash of attribute values. Keys are symbols with the names of the
1348
1402
  # underlying database columns. The returned hash is a reference to the
@@ -1889,7 +1943,7 @@ module Sequel
1889
1943
 
1890
1944
  # Clear the setter_methods cache when a method is added
1891
1945
  def singleton_method_added(meth)
1892
- @singleton_setter_added = true if meth.to_s =~ SETTER_METHOD_REGEXP
1946
+ @singleton_setter_added = true if meth.to_s.end_with?('=')
1893
1947
  super
1894
1948
  end
1895
1949
 
@@ -1902,6 +1956,7 @@ module Sequel
1902
1956
  raise Error, "No dataset for model #{model}" unless ds = model.instance_dataset
1903
1957
 
1904
1958
  cond = if ds.joined_dataset?
1959
+ # SEQUEL5: Remove as joined model datasets are now allowed
1905
1960
  qualified_pk_hash
1906
1961
  else
1907
1962
  pk_hash
@@ -2143,7 +2198,7 @@ module Sequel
2143
2198
  sh = {:server=>this_server}
2144
2199
  uacr = use_after_commit_rollback
2145
2200
  if uacr.nil? ? (method(:after_rollback).owner != InstanceMethods) : uacr
2146
- Sequel::Deprecation.deprecate("Model#after_rollback", "Instead, call db.after_rollback in Model#before_save.")
2201
+ Sequel::Deprecation.deprecate("Model#after_rollback", "Instead, call db.after_rollback in Model#before_save")
2147
2202
  db.after_rollback(sh){after_rollback}
2148
2203
  end
2149
2204
  pk = nil
@@ -2210,7 +2265,7 @@ module Sequel
2210
2265
  raise_hook_failure(:around_save) unless called_save
2211
2266
  _after_save(pk) # SEQUEL5: Remove
2212
2267
  if uacr.nil? ? (method(:after_commit).owner != InstanceMethods) : uacr
2213
- Sequel::Deprecation.deprecate("Model#after_commit", "Instead, call db.after_commit in Model#after_save.")
2268
+ Sequel::Deprecation.deprecate("Model#after_commit", "Instead, call db.after_commit in Model#after_save")
2214
2269
  db.after_commit(sh){after_commit}
2215
2270
  end
2216
2271
  self
@@ -2443,7 +2498,7 @@ module Sequel
2443
2498
  if type.is_a?(Array)
2444
2499
  type.map{|x| "#{x}="}
2445
2500
  else
2446
- meths = methods.collect(&:to_s).grep(SETTER_METHOD_REGEXP) - RESTRICTED_SETTER_METHODS
2501
+ meths = methods.map(&:to_s).select{|l| l.end_with?('=')} - RESTRICTED_SETTER_METHODS
2447
2502
  meths -= Array(primary_key).map{|x| "#{x}="} if type != :all && primary_key && model.restrict_primary_key?
2448
2503
  meths
2449
2504
  end
@@ -2607,15 +2662,15 @@ module Sequel
2607
2662
  end
2608
2663
  end
2609
2664
 
2610
- # This allows you to call +to_hash+ without any arguments, which will
2665
+ # This allows you to call +as_hash+ without any arguments, which will
2611
2666
  # result in a hash with the primary key value being the key and the
2612
2667
  # model object being the value.
2613
2668
  #
2614
- # Artist.dataset.to_hash # SELECT * FROM artists
2669
+ # Artist.dataset.as_hash # SELECT * FROM artists
2615
2670
  # # => {1=>#<Artist {:id=>1, ...}>,
2616
2671
  # # 2=>#<Artist {:id=>2, ...}>,
2617
2672
  # # ...}
2618
- def to_hash(key_column=nil, value_column=nil, opts=OPTS)
2673
+ def as_hash(key_column=nil, value_column=nil, opts=OPTS)
2619
2674
  if key_column
2620
2675
  super
2621
2676
  else
@@ -2624,6 +2679,11 @@ module Sequel
2624
2679
  end
2625
2680
  end
2626
2681
 
2682
+ # Alias of as_hash for backwards compatibility.
2683
+ def to_hash(*a)
2684
+ as_hash(*a)
2685
+ end
2686
+
2627
2687
  # Return an array of all rows matching the given filter condition, also
2628
2688
  # yielding each row to the given block. Basically the same as where(cond).all(&block),
2629
2689
  # except it can be optimized to not create an intermediate dataset.
@@ -2727,6 +2787,10 @@ module Sequel
2727
2787
  where(cond).limit(1)
2728
2788
  end
2729
2789
  end
2790
+
2791
+ def non_sql_option?(key)
2792
+ super || key == :model
2793
+ end
2730
2794
  end
2731
2795
 
2732
2796
  extend ClassMethods