sequel 4.22.0 → 4.23.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.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +22 -0
  3. data/README.rdoc +6 -0
  4. data/Rakefile +59 -81
  5. data/doc/migration.rdoc +2 -0
  6. data/doc/release_notes/4.23.0.txt +65 -0
  7. data/doc/sharding.rdoc +16 -14
  8. data/doc/testing.rdoc +61 -77
  9. data/lib/sequel/adapters/jdbc.rb +1 -0
  10. data/lib/sequel/adapters/mock.rb +0 -1
  11. data/lib/sequel/adapters/postgres.rb +1 -0
  12. data/lib/sequel/adapters/postgresql.rb +1 -0
  13. data/lib/sequel/adapters/shared/postgres.rb +3 -3
  14. data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
  15. data/lib/sequel/connection_pool/threaded.rb +9 -1
  16. data/lib/sequel/database/connecting.rb +1 -1
  17. data/lib/sequel/database/transactions.rb +2 -1
  18. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  19. data/lib/sequel/extensions/constraint_validations.rb +12 -12
  20. data/lib/sequel/extensions/date_arithmetic.rb +0 -4
  21. data/lib/sequel/extensions/pagination.rb +14 -2
  22. data/lib/sequel/extensions/pg_enum.rb +2 -2
  23. data/lib/sequel/extensions/pg_hstore.rb +1 -1
  24. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  25. data/lib/sequel/plugins/csv_serializer.rb +2 -0
  26. data/lib/sequel/plugins/delay_add_association.rb +50 -0
  27. data/lib/sequel/plugins/list.rb +2 -2
  28. data/lib/sequel/plugins/nested_attributes.rb +8 -28
  29. data/lib/sequel/plugins/update_refresh.rb +50 -0
  30. data/lib/sequel/plugins/validate_associated.rb +55 -0
  31. data/lib/sequel/version.rb +1 -1
  32. data/spec/adapters/db2_spec.rb +29 -29
  33. data/spec/adapters/firebird_spec.rb +97 -103
  34. data/spec/adapters/informix_spec.rb +25 -25
  35. data/spec/adapters/mssql_spec.rb +156 -172
  36. data/spec/adapters/mysql_spec.rb +334 -359
  37. data/spec/adapters/oracle_spec.rb +67 -69
  38. data/spec/adapters/postgres_spec.rb +1298 -1249
  39. data/spec/adapters/spec_helper.rb +2 -35
  40. data/spec/adapters/sqlanywhere_spec.rb +39 -39
  41. data/spec/adapters/sqlite_spec.rb +203 -200
  42. data/spec/bin_spec.rb +57 -59
  43. data/spec/core/connection_pool_spec.rb +402 -401
  44. data/spec/core/database_spec.rb +953 -944
  45. data/spec/core/dataset_spec.rb +2178 -2168
  46. data/spec/core/deprecated_spec.rb +19 -19
  47. data/spec/core/expression_filters_spec.rb +415 -415
  48. data/spec/core/mock_adapter_spec.rb +212 -212
  49. data/spec/core/object_graph_spec.rb +73 -73
  50. data/spec/core/placeholder_literalizer_spec.rb +71 -71
  51. data/spec/core/schema_generator_spec.rb +44 -44
  52. data/spec/core/schema_spec.rb +470 -472
  53. data/spec/core/spec_helper.rb +5 -20
  54. data/spec/core/version_spec.rb +2 -2
  55. data/spec/core_extensions_spec.rb +320 -320
  56. data/spec/extensions/accessed_columns_spec.rb +12 -12
  57. data/spec/extensions/active_model_spec.rb +3 -3
  58. data/spec/extensions/after_initialize_spec.rb +2 -2
  59. data/spec/extensions/arbitrary_servers_spec.rb +23 -23
  60. data/spec/extensions/association_dependencies_spec.rb +34 -34
  61. data/spec/extensions/association_pks_spec.rb +98 -98
  62. data/spec/extensions/association_proxies_spec.rb +33 -33
  63. data/spec/extensions/auto_validations_spec.rb +46 -46
  64. data/spec/extensions/blacklist_security_spec.rb +19 -18
  65. data/spec/extensions/blank_spec.rb +36 -36
  66. data/spec/extensions/boolean_readers_spec.rb +36 -36
  67. data/spec/extensions/caching_spec.rb +82 -82
  68. data/spec/extensions/class_table_inheritance_spec.rb +72 -72
  69. data/spec/extensions/column_conflicts_spec.rb +19 -14
  70. data/spec/extensions/column_select_spec.rb +19 -19
  71. data/spec/extensions/columns_introspection_spec.rb +43 -43
  72. data/spec/extensions/composition_spec.rb +64 -64
  73. data/spec/extensions/connection_validator_spec.rb +92 -90
  74. data/spec/extensions/constraint_validations_plugin_spec.rb +92 -92
  75. data/spec/extensions/constraint_validations_spec.rb +80 -80
  76. data/spec/extensions/core_refinements_spec.rb +220 -220
  77. data/spec/extensions/csv_serializer_spec.rb +44 -44
  78. data/spec/extensions/current_datetime_timestamp_spec.rb +8 -8
  79. data/spec/extensions/dataset_associations_spec.rb +65 -65
  80. data/spec/extensions/dataset_source_alias_spec.rb +16 -16
  81. data/spec/extensions/date_arithmetic_spec.rb +51 -58
  82. data/spec/extensions/defaults_setter_spec.rb +19 -19
  83. data/spec/extensions/delay_add_association_spec.rb +52 -0
  84. data/spec/extensions/dirty_spec.rb +51 -51
  85. data/spec/extensions/eager_each_spec.rb +8 -8
  86. data/spec/extensions/empty_array_ignore_nulls_spec.rb +10 -10
  87. data/spec/extensions/error_splitter_spec.rb +2 -2
  88. data/spec/extensions/error_sql_spec.rb +4 -4
  89. data/spec/extensions/eval_inspect_spec.rb +3 -3
  90. data/spec/extensions/filter_having_spec.rb +8 -8
  91. data/spec/extensions/force_encoding_spec.rb +30 -30
  92. data/spec/extensions/from_block_spec.rb +7 -7
  93. data/spec/extensions/graph_each_spec.rb +19 -19
  94. data/spec/extensions/hash_aliases_spec.rb +5 -5
  95. data/spec/extensions/hook_class_methods_spec.rb +100 -100
  96. data/spec/extensions/inflector_spec.rb +54 -54
  97. data/spec/extensions/input_transformer_spec.rb +10 -10
  98. data/spec/extensions/insert_returning_select_spec.rb +8 -8
  99. data/spec/extensions/instance_filters_spec.rb +26 -26
  100. data/spec/extensions/instance_hooks_spec.rb +85 -85
  101. data/spec/extensions/json_serializer_spec.rb +68 -68
  102. data/spec/extensions/lazy_attributes_spec.rb +49 -49
  103. data/spec/extensions/list_spec.rb +77 -75
  104. data/spec/extensions/looser_typecasting_spec.rb +16 -16
  105. data/spec/extensions/many_through_many_spec.rb +627 -627
  106. data/spec/extensions/meta_def_spec.rb +7 -7
  107. data/spec/extensions/migration_spec.rb +217 -217
  108. data/spec/extensions/modification_detection_spec.rb +20 -20
  109. data/spec/extensions/mssql_optimistic_locking_spec.rb +21 -21
  110. data/spec/extensions/named_timezones_spec.rb +18 -18
  111. data/spec/extensions/nested_attributes_spec.rb +107 -107
  112. data/spec/extensions/null_dataset_spec.rb +24 -24
  113. data/spec/extensions/optimistic_locking_spec.rb +21 -21
  114. data/spec/extensions/pagination_spec.rb +52 -52
  115. data/spec/extensions/pg_array_associations_spec.rb +273 -273
  116. data/spec/extensions/pg_array_ops_spec.rb +52 -52
  117. data/spec/extensions/pg_array_spec.rb +152 -152
  118. data/spec/extensions/pg_enum_spec.rb +13 -13
  119. data/spec/extensions/pg_hstore_ops_spec.rb +63 -63
  120. data/spec/extensions/pg_hstore_spec.rb +84 -84
  121. data/spec/extensions/pg_inet_spec.rb +15 -15
  122. data/spec/extensions/pg_interval_spec.rb +29 -29
  123. data/spec/extensions/pg_json_ops_spec.rb +86 -84
  124. data/spec/extensions/pg_json_spec.rb +104 -104
  125. data/spec/extensions/pg_loose_count_spec.rb +6 -6
  126. data/spec/extensions/pg_range_ops_spec.rb +24 -24
  127. data/spec/extensions/pg_range_spec.rb +143 -143
  128. data/spec/extensions/pg_row_ops_spec.rb +14 -14
  129. data/spec/extensions/pg_row_plugin_spec.rb +12 -12
  130. data/spec/extensions/pg_row_spec.rb +118 -118
  131. data/spec/extensions/pg_static_cache_updater_spec.rb +28 -28
  132. data/spec/extensions/pg_typecast_on_load_spec.rb +21 -21
  133. data/spec/extensions/prepared_statements_associations_spec.rb +42 -42
  134. data/spec/extensions/prepared_statements_safe_spec.rb +18 -18
  135. data/spec/extensions/prepared_statements_spec.rb +28 -28
  136. data/spec/extensions/prepared_statements_with_pk_spec.rb +11 -11
  137. data/spec/extensions/pretty_table_spec.rb +16 -16
  138. data/spec/extensions/query_literals_spec.rb +37 -37
  139. data/spec/extensions/query_spec.rb +32 -32
  140. data/spec/extensions/rcte_tree_spec.rb +141 -141
  141. data/spec/extensions/round_timestamps_spec.rb +21 -21
  142. data/spec/extensions/schema_caching_spec.rb +8 -8
  143. data/spec/extensions/schema_dumper_spec.rb +78 -78
  144. data/spec/extensions/schema_spec.rb +31 -27
  145. data/spec/extensions/scissors_spec.rb +3 -3
  146. data/spec/extensions/select_remove_spec.rb +14 -14
  147. data/spec/extensions/sequel_3_dataset_methods_spec.rb +28 -28
  148. data/spec/extensions/serialization_modification_detection_spec.rb +33 -33
  149. data/spec/extensions/serialization_spec.rb +79 -78
  150. data/spec/extensions/server_block_spec.rb +17 -17
  151. data/spec/extensions/set_overrides_spec.rb +30 -30
  152. data/spec/extensions/sharding_spec.rb +65 -65
  153. data/spec/extensions/shared_caching_spec.rb +29 -29
  154. data/spec/extensions/single_table_inheritance_spec.rb +79 -79
  155. data/spec/extensions/skip_create_refresh_spec.rb +3 -3
  156. data/spec/extensions/spec_helper.rb +4 -29
  157. data/spec/extensions/split_array_nil_spec.rb +9 -9
  158. data/spec/extensions/split_values_spec.rb +7 -7
  159. data/spec/extensions/sql_expr_spec.rb +32 -32
  160. data/spec/extensions/static_cache_spec.rb +123 -123
  161. data/spec/extensions/string_date_time_spec.rb +34 -34
  162. data/spec/extensions/string_stripper_spec.rb +15 -15
  163. data/spec/extensions/subclasses_spec.rb +31 -31
  164. data/spec/extensions/table_select_spec.rb +15 -15
  165. data/spec/extensions/tactical_eager_loading_spec.rb +23 -23
  166. data/spec/extensions/thread_local_timezones_spec.rb +13 -13
  167. data/spec/extensions/timestamps_spec.rb +40 -40
  168. data/spec/extensions/to_dot_spec.rb +34 -34
  169. data/spec/extensions/touch_spec.rb +52 -52
  170. data/spec/extensions/tree_spec.rb +72 -72
  171. data/spec/extensions/typecast_on_load_spec.rb +25 -25
  172. data/spec/extensions/unlimited_update_spec.rb +2 -2
  173. data/spec/extensions/update_or_create_spec.rb +36 -36
  174. data/spec/extensions/update_primary_key_spec.rb +35 -35
  175. data/spec/extensions/update_refresh_spec.rb +41 -0
  176. data/spec/extensions/validate_associated_spec.rb +52 -0
  177. data/spec/extensions/validation_class_methods_spec.rb +314 -317
  178. data/spec/extensions/validation_helpers_spec.rb +195 -195
  179. data/spec/extensions/xml_serializer_spec.rb +48 -48
  180. data/spec/guards_helper.rb +55 -0
  181. data/spec/integration/associations_test.rb +1089 -1088
  182. data/spec/integration/database_test.rb +29 -29
  183. data/spec/integration/dataset_test.rb +661 -661
  184. data/spec/integration/eager_loader_test.rb +147 -147
  185. data/spec/integration/migrator_test.rb +122 -122
  186. data/spec/integration/model_test.rb +70 -70
  187. data/spec/integration/plugin_test.rb +682 -640
  188. data/spec/integration/prepared_statement_test.rb +172 -172
  189. data/spec/integration/schema_test.rb +245 -245
  190. data/spec/integration/spec_helper.rb +1 -64
  191. data/spec/integration/timezone_test.rb +17 -17
  192. data/spec/integration/transaction_test.rb +87 -87
  193. data/spec/integration/type_test.rb +33 -33
  194. data/spec/model/association_reflection_spec.rb +130 -121
  195. data/spec/model/associations_spec.rb +1112 -1113
  196. data/spec/model/base_spec.rb +197 -196
  197. data/spec/model/class_dataset_methods_spec.rb +118 -118
  198. data/spec/model/dataset_methods_spec.rb +49 -49
  199. data/spec/model/eager_loading_spec.rb +705 -702
  200. data/spec/model/hooks_spec.rb +169 -168
  201. data/spec/model/inflector_spec.rb +5 -5
  202. data/spec/model/model_spec.rb +287 -297
  203. data/spec/model/plugins_spec.rb +47 -47
  204. data/spec/model/record_spec.rb +534 -535
  205. data/spec/model/spec_helper.rb +3 -21
  206. data/spec/model/validations_spec.rb +72 -70
  207. data/spec/spec_config.rb +8 -0
  208. metadata +41 -9
  209. data/lib/sequel/adapters/fdbsql.rb +0 -286
  210. data/lib/sequel/adapters/jdbc/fdbsql.rb +0 -66
  211. data/lib/sequel/adapters/openbase.rb +0 -54
  212. data/lib/sequel/adapters/shared/fdbsql.rb +0 -550
  213. data/spec/adapters/fdbsql_spec.rb +0 -429
  214. data/spec/rspec_helper.rb +0 -22
@@ -698,6 +698,7 @@ module Sequel
698
698
  sql = @sproc_name
699
699
  opts = Hash[opts]
700
700
  opts[:args] = @sproc_args
701
+ opts[:sproc] = true
701
702
  opts[:type] = :insert
702
703
  super
703
704
  end
@@ -37,7 +37,6 @@ module Sequel
37
37
  'cubrid'=>'Cubrid',
38
38
  'db2'=>'DB2',
39
39
  'firebird'=>'Firebird',
40
- 'fdbsql'=>'Fdbsql',
41
40
  'informix'=>'Informix',
42
41
  'mssql'=>'MSSQL',
43
42
  'mysql'=>'MySQL',
@@ -189,6 +189,7 @@ module Sequel
189
189
  INFINITE_TIMESTAMP_STRINGS = ['infinity'.freeze, '-infinity'.freeze].freeze
190
190
  INFINITE_DATETIME_VALUES = ([PLUS_INFINITY, MINUS_INFINITY] + INFINITE_TIMESTAMP_STRINGS).freeze
191
191
 
192
+ set_adapter_scheme :postgresql
192
193
  set_adapter_scheme :postgres
193
194
 
194
195
  # Whether infinite timestamps/dates should be converted on retrieval. By default, no
@@ -0,0 +1 @@
1
+ Sequel.require 'adapters/postgres'
@@ -706,7 +706,7 @@ module Sequel
706
706
  # Convert the hash of named conversion procs into a hash a oid conversion procs.
707
707
  def convert_named_procs_to_procs(named_procs)
708
708
  h = {}
709
- from(:pg_type).where(:typtype=>'b', :typname=>named_procs.keys.map(&:to_s)).select_map([:oid, :typname]).each do |oid, name|
709
+ from(:pg_type).where(:typtype=>['b', 'e'], :typname=>named_procs.keys.map(&:to_s)).select_map([:oid, :typname]).each do |oid, name|
710
710
  h[oid.to_i] = named_procs[name.untaint.to_sym]
711
711
  end
712
712
  h
@@ -1294,9 +1294,9 @@ module Sequel
1294
1294
  # returned rows also include the exact phrase used.
1295
1295
  # :rank :: Set to true to order by the rank, so that closer matches are returned first.
1296
1296
  # :tsquery :: Specifies the terms argument is already a valid SQL expression returning a
1297
- # tsquery, and can be used directly in the query.
1297
+ # tsquery, and can be used directly in the query.
1298
1298
  # :tsvector :: Specifies the cols argument is already a valid SQL expression returning a
1299
- # tsvector, and can be used directly in the query.
1299
+ # tsvector, and can be used directly in the query.
1300
1300
  def full_text_search(cols, terms, opts = OPTS)
1301
1301
  lang = Sequel.cast(opts[:language] || 'simple', :regconfig)
1302
1302
 
@@ -192,8 +192,13 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
192
192
  deadline ||= time + @timeout
193
193
  current_time = Time.now
194
194
  raise(::Sequel::PoolTimeout, "timeout: #{@timeout}, elapsed: #{current_time - time}") if current_time > deadline
195
+ # :nocov:
196
+ # It's difficult to get to this point, it can only happen if there is a race condition
197
+ # where a connection cannot be acquired even after the thread is signalled by the condition
198
+ # variable that a connection is ready.
195
199
  @waiters[server].wait(@mutex, deadline - current_time)
196
200
  Thread.pass
201
+ # :nocov:
197
202
  end
198
203
 
199
204
  conn
@@ -4,7 +4,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
4
4
  # Whether or not a ConditionVariable should be used to wait for connections.
5
5
  # True except on ruby 1.8, where ConditionVariable#wait does not support a
6
6
  # timeout.
7
- USE_WAITER = RUBY_VERSION >= '1.9'
7
+ unless defined?(USE_WAITER)
8
+ USE_WAITER = RUBY_VERSION >= '1.9'
9
+ end
8
10
 
9
11
  # The maximum number of connections this pool will create (per shard/server
10
12
  # if sharding).
@@ -40,7 +42,9 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
40
42
  if USE_WAITER
41
43
  @waiter = ConditionVariable.new
42
44
  else
45
+ # :nocov:
43
46
  @sleep_time = Float(opts[:pool_sleep_time] || 0.001)
47
+ # :nocov:
44
48
  end
45
49
  end
46
50
 
@@ -155,8 +159,12 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
155
159
  deadline ||= time + @timeout
156
160
  current_time = Time.now
157
161
  raise(::Sequel::PoolTimeout, "timeout: #{@timeout}, elapsed: #{current_time - time}") if current_time > deadline
162
+ # :nocov:
163
+ # It's difficult to get to this point, it can only happen if there is a race condition
164
+ # where a connection cannot be acquired even after the thread is signalled by the condition
158
165
  @waiter.wait(@mutex, deadline - current_time)
159
166
  Thread.pass
167
+ # :nocov:
160
168
  end
161
169
 
162
170
  conn
@@ -6,7 +6,7 @@ module Sequel
6
6
  # ---------------------
7
7
 
8
8
  # Array of supported database adapters
9
- ADAPTERS = %w'ado amalgalite cubrid db2 dbi do fdbsql firebird ibmdb informix jdbc mock mysql mysql2 odbc openbase oracle postgres sqlanywhere sqlite swift tinytds'.collect(&:to_sym)
9
+ ADAPTERS = %w'ado amalgalite cubrid db2 dbi do firebird ibmdb informix jdbc mock mysql mysql2 odbc oracle postgres sqlanywhere sqlite swift tinytds'.collect(&:to_sym)
10
10
 
11
11
  @single_threaded = false
12
12
 
@@ -124,7 +124,7 @@ module Sequel
124
124
  begin_transaction(conn, opts)
125
125
  if rollback == :always
126
126
  begin
127
- yield(conn)
127
+ ret = yield(conn)
128
128
  rescue Exception => e1
129
129
  raise e1
130
130
  ensure
@@ -139,6 +139,7 @@ module Sequel
139
139
  rescue Exception
140
140
  end
141
141
  transaction_error(e, :conn=>conn, :rollback=>rollback)
142
+ ret
142
143
  ensure
143
144
  begin
144
145
  committed = commit_or_rollback_transaction(e, conn, opts)
@@ -30,7 +30,7 @@ module Sequel
30
30
  meths.each do |meth|
31
31
  module_eval("def #{meth}(sql, opts=Sequel::OPTS) #{code}; super end", __FILE__, __LINE__)
32
32
  end
33
- private *meths
33
+ private(*meths)
34
34
  end
35
35
  end
36
36
  private_class_method :prepared_statements_module
@@ -224,6 +224,16 @@ module Sequel
224
224
  end
225
225
  end
226
226
 
227
+ # Modify the default create_table generator to include
228
+ # the constraint validation methods.
229
+ def create_table_generator(&block)
230
+ super do
231
+ extend CreateTableGeneratorMethods
232
+ @validations = []
233
+ instance_eval(&block) if block
234
+ end
235
+ end
236
+
227
237
  # Drop the constraint validations table.
228
238
  def drop_constraint_validations_table
229
239
  drop_table(constraint_validations_table)
@@ -262,8 +272,6 @@ module Sequel
262
272
  ds.delete
263
273
  end
264
274
 
265
- private
266
-
267
275
  # Modify the default alter_table generator to include
268
276
  # the constraint validation methods.
269
277
  def alter_table_generator(&block)
@@ -274,6 +282,8 @@ module Sequel
274
282
  end
275
283
  end
276
284
 
285
+ private
286
+
277
287
  # After running all of the table alteration statements,
278
288
  # if there were any constraint validations, run table alteration
279
289
  # statements to create related constraints. This is purposely
@@ -317,16 +327,6 @@ module Sequel
317
327
  super
318
328
  end
319
329
 
320
- # Modify the default create_table generator to include
321
- # the constraint validation methods.
322
- def create_table_generator(&block)
323
- super do
324
- extend CreateTableGeneratorMethods
325
- @validations = []
326
- instance_eval(&block) if block
327
- end
328
- end
329
-
330
330
  # For the given table, generator, and validations, add constraints
331
331
  # to the generator for each of the validations, as well as adding
332
332
  # validation metadata to the constraint validations table.
@@ -123,10 +123,6 @@ module Sequel
123
123
  expr = Sequel.+(expr, Sequel.lit(["", " "], value, sql_unit))
124
124
  end
125
125
  false
126
- when :fdbsql
127
- each_valid_interval_unit(h, FDBSQL_DURATION_UNITS) do |value, sql_unit|
128
- expr = Sequel.+(expr, Sequel.lit(["INTERVAL ", " "], value, sql_unit))
129
- end
130
126
  else
131
127
  raise Error, "date arithmetic is not implemented on #{db.database_type}"
132
128
  end
@@ -1,6 +1,18 @@
1
1
  # The pagination extension adds the Sequel::Dataset#paginate and #each_page methods,
2
- # which return paginated (limited and offset) datasets with some helpful methods
3
- # that make creating a paginated display easier.
2
+ # which return paginated (limited and offset) datasets with the following methods
3
+ # added that make creating a paginated display easier:
4
+ #
5
+ # * +page_size+
6
+ # * +page_count+
7
+ # * +page_range+
8
+ # * +current_page+
9
+ # * +next_page+
10
+ # * +prev_page+
11
+ # * +first_page?+
12
+ # * +last_page?+
13
+ # * +pagination_record_count+
14
+ # * +current_page_record_count+
15
+ # * +current_page_record_range+
4
16
  #
5
17
  # This extension uses Object#extend at runtime, which can hurt performance.
6
18
  #
@@ -18,7 +18,7 @@
18
18
  # Just like any user-created type, after creating the type, you
19
19
  # can create tables that have a column of that type:
20
20
  #
21
- # DB.create_table(:table_name)
21
+ # DB.create_table(:table_name) do
22
22
  # enum_type_name :column_name
23
23
  # end
24
24
  #
@@ -31,7 +31,7 @@
31
31
  # If the pg_array extension is used, arrays of enums are returned as a
32
32
  # PGArray:
33
33
  #
34
- # DB.create_table(:table_name)
34
+ # DB.create_table(:table_name) do
35
35
  # column :column_name, 'enum_type_name[]'
36
36
  # end
37
37
  # DB[:table_name].get(:column_name)
@@ -8,7 +8,7 @@
8
8
  # as instances of Sequel::Postgres::HStore. HStore is
9
9
  # a DelegateClass of Hash, so it mostly acts like a hash, but not
10
10
  # completely (is_a?(Hash) is false). If you want the actual hash,
11
- # you can call Hstore#to_hash. This is done so that Sequel does not
11
+ # you can call HStore#to_hash. This is done so that Sequel does not
12
12
  # treat a HStore like a Hash by default, which would cause issues.
13
13
  #
14
14
  # In addition to the parsers, this extension comes with literalizers
@@ -210,9 +210,9 @@ module Sequel
210
210
  private
211
211
 
212
212
  # Return a placeholder literal with the given str and args, wrapped
213
- # in an JSONOp, used by operators that return json.
213
+ # in an JSONOp or JSONBOp, used by operators that return json or jsonb.
214
214
  def json_op(str, args)
215
- JSONOp.new(Sequel::SQL::PlaceholderLiteralString.new(str, [self, args]))
215
+ self.class.new(Sequel::SQL::PlaceholderLiteralString.new(str, [self, args]))
216
216
  end
217
217
 
218
218
  # Return a function with the given name, and the receiver as the first
@@ -1,5 +1,7 @@
1
1
  if RUBY_VERSION < "1.9"
2
+ # :nocov:
2
3
  require 'fastercsv'
4
+ # :nocov:
3
5
  else
4
6
  require 'csv'
5
7
  end
@@ -0,0 +1,50 @@
1
+ module Sequel
2
+ module Plugins
3
+ # The delay_add_association plugin delays the adding of
4
+ # associated objects to a new (unsaved) object until after the new
5
+ # object is saved. By default, if you attempt to add
6
+ # associated objects to a new object, Sequel will raise
7
+ # an error, because you need to have a primary key before
8
+ # saving the objects.
9
+ #
10
+ # When delaying the add of an associated object, the object
11
+ # will be immediately added to the cached association array.
12
+ # When saving the current object, it will also attempt to
13
+ # validate any associated objects, and if the associated objects
14
+ # are not valid, the current object will also be considered
15
+ # not valid.
16
+ #
17
+ # Usage:
18
+ #
19
+ # # Make all model subclass delay add_association for new objects
20
+ # Sequel::Model.plugin :delay_add_association
21
+ #
22
+ # # Make the Album class delay add_association for new objects
23
+ # Album.plugin :delay_add_association
24
+ module DelayAddAssociation
25
+ # Depend on the validate_associated plugin.
26
+ def self.apply(mod)
27
+ mod.plugin :validate_associated
28
+ end
29
+
30
+ module InstanceMethods
31
+ private
32
+
33
+ # Delay the addition of the associated object till after
34
+ # saving the current object, if the current object is new
35
+ # and the associated dataset requires a primary key on the
36
+ # current object.
37
+ def add_associated_object(opts, o, *args)
38
+ if opts.dataset_need_primary_key? && new?
39
+ delay_validate_associated_object(opts, o)
40
+ send(opts[:name]) << o
41
+ after_create_hook{super(opts, o, *args)}
42
+ o
43
+ else
44
+ super
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -129,11 +129,11 @@ module Sequel
129
129
  checked_transaction do
130
130
  ds = list_dataset
131
131
  op, ds = if target < current
132
- raise(Sequel::Error, "Moving too far up (target = #{target})") if target < 1
132
+ target = 1 if target < 1
133
133
  [:+, ds.filter(position_field=>target...current)]
134
134
  else
135
135
  lp ||= last_position
136
- raise(Sequel::Error, "Moving too far down (target = #{target}, last_position = #{lp})") if target > lp
136
+ target = lp if target > lp
137
137
  [:-, ds.filter(position_field=>(current + 1)..target)]
138
138
  end
139
139
  ds.update(position_field => Sequel::SQL::NumericExpression.new(op, position_field, 1))
@@ -37,14 +37,16 @@ module Sequel
37
37
  # of creating a new album.
38
38
  #
39
39
  # If you would like to delete the associated object instead of updating it, you add a _delete
40
- # entry to the hash:
40
+ # entry to the hash, and also pass the :destroy option when calling +nested_attributes+:
41
41
  #
42
+ # Artist.nested_attributes :albums, :destroy=>true
42
43
  # a.update(:albums_attributes => [{:id=>1, :_delete=>true}])
43
44
  #
44
45
  # This will delete the related associated object from the database. If you want to leave the
45
46
  # associated object in the database, but just remove it from the association, add a _remove
46
- # entry in the hash:
47
+ # entry in the hash, and also pass the :remove option when calling +nested_attributes+:
47
48
  #
49
+ # Artist.nested_attributes :albums, :remove=>true
48
50
  # a.update(:albums_attributes => [{:id=>1, :_remove=>true}])
49
51
  #
50
52
  # The above example was for a one_to_many association, but the plugin also works similarly
@@ -71,9 +73,9 @@ module Sequel
71
73
  # To save changes to the artist, create the first album and associate it to the artist,
72
74
  # and update the other existing associated album.
73
75
  module NestedAttributes
74
- # Depend on the instance_hooks plugin.
76
+ # Depend on the validate_associated plugin.
75
77
  def self.apply(model)
76
- model.plugin(:instance_hooks)
78
+ model.plugin(:validate_associated)
77
79
  end
78
80
 
79
81
  module ClassMethods
@@ -166,7 +168,7 @@ module Sequel
166
168
  reflection = meta[:reflection]
167
169
  obj = reflection.associated_class.new
168
170
  nested_attributes_set_attributes(meta, obj, attributes)
169
- after_validation_hook{validate_associated_object(meta, obj)}
171
+ delay_validate_associated_object(reflection, obj)
170
172
  if reflection.returns_array?
171
173
  send(reflection[:name]) << obj
172
174
  after_save_hook{send(reflection.add_method, obj)}
@@ -282,7 +284,7 @@ module Sequel
282
284
  # Returns the object updated.
283
285
  def nested_attributes_update(meta, obj, attributes)
284
286
  nested_attributes_update_attributes(meta, obj, attributes)
285
- after_validation_hook{validate_associated_object(meta, obj)}
287
+ delay_validate_associated_object(meta[:reflection], obj)
286
288
  # Don't need to validate the object twice if :validate association option is not false
287
289
  # and don't want to validate it at all if it is false.
288
290
  after_save_hook{obj.save_changes(:validate=>false)}
@@ -295,28 +297,6 @@ module Sequel
295
297
  nested_attributes_set_attributes(meta, obj, attributes)
296
298
  end
297
299
  end
298
-
299
- # Validate the given associated object, adding any validation error messages from the
300
- # given object to the parent object.
301
- def validate_associated_object(meta, obj)
302
- reflection = meta[:reflection]
303
- return if reflection[:validate] == false
304
- association = reflection[:name]
305
- if (reflection[:type] == :one_to_many || reflection[:type] == :one_to_one) && (key = reflection[:key]).is_a?(Symbol) && !(pk_val = obj.values[key])
306
- # There could be a presence validation on the foreign key in the associated model,
307
- # which will fail if we validate before saving the current object. If there is
308
- # no value for the foreign key, set it to the current primary key value, or a dummy
309
- # value of 0 if we haven't saved the current object.
310
- p_key = pk unless pk.is_a?(Array)
311
- obj.values[key] = p_key || 0
312
- key = nil if p_key
313
- end
314
- obj.errors.full_messages.each{|m| errors.add(association, m)} unless obj.valid?
315
- if key && !pk_val
316
- # If we used a dummy value of 0, remove it so it doesn't accidently remain.
317
- obj.values.delete(key)
318
- end
319
- end
320
300
  end
321
301
  end
322
302
  end
@@ -0,0 +1,50 @@
1
+ module Sequel
2
+ module Plugins
3
+ # The update_refresh plugin makes the model class refresh
4
+ # the object after updating. By default, Sequel only
5
+ # refreshes automatically after inserting new rows, not
6
+ # after updating. However, if you are using triggers
7
+ # to modify the contents of updated rows, it can be
8
+ # helpful to immediately get the current data after
9
+ # updating.
10
+ #
11
+ # If the dataset supports UPDATE RETURNING, this
12
+ # plugin will use it so that it can retrieve the current
13
+ # data in the same query it uses for the update.
14
+ #
15
+ # Usage:
16
+ #
17
+ # # Make all model subclasses refresh after update
18
+ # Sequel::Model.plugin :update_refresh
19
+ #
20
+ # # Make the Album class refresh after update
21
+ # Album.plugin :update_refresh
22
+ module UpdateRefresh
23
+ module InstanceMethods
24
+ def after_update
25
+ super
26
+ unless this.supports_returning?(:update)
27
+ refresh
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def _update_without_checking(columns)
34
+ ds = _update_dataset
35
+ if ds.supports_returning?(:update)
36
+ ds = ds.opts[:returning] ? ds : ds.returning
37
+ rows = ds.update(columns)
38
+ n = rows.length
39
+ if n == 1
40
+ @values.merge!(rows.first)
41
+ end
42
+ n
43
+ else
44
+ super
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end