sequel 4.41.0 → 4.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +98 -0
  3. data/README.rdoc +23 -10
  4. data/doc/active_record.rdoc +4 -4
  5. data/doc/advanced_associations.rdoc +2 -2
  6. data/doc/association_basics.rdoc +5 -2
  7. data/doc/cheat_sheet.rdoc +3 -3
  8. data/doc/core_extensions.rdoc +2 -2
  9. data/doc/dataset_basics.rdoc +4 -4
  10. data/doc/dataset_filtering.rdoc +1 -1
  11. data/doc/migration.rdoc +19 -1
  12. data/doc/prepared_statements.rdoc +2 -2
  13. data/doc/release_notes/4.42.0.txt +221 -0
  14. data/doc/testing.rdoc +3 -1
  15. data/lib/sequel/adapters/ado/access.rb +0 -1
  16. data/lib/sequel/adapters/ado/mssql.rb +0 -1
  17. data/lib/sequel/adapters/do/mysql.rb +0 -1
  18. data/lib/sequel/adapters/do/postgres.rb +0 -1
  19. data/lib/sequel/adapters/do/sqlite3.rb +0 -1
  20. data/lib/sequel/adapters/ibmdb.rb +21 -25
  21. data/lib/sequel/adapters/jdbc.rb +8 -16
  22. data/lib/sequel/adapters/jdbc/as400.rb +0 -1
  23. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -1
  24. data/lib/sequel/adapters/jdbc/db2.rb +0 -1
  25. data/lib/sequel/adapters/jdbc/derby.rb +0 -1
  26. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -1
  27. data/lib/sequel/adapters/jdbc/h2.rb +0 -1
  28. data/lib/sequel/adapters/jdbc/hsqldb.rb +0 -1
  29. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -1
  30. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -1
  31. data/lib/sequel/adapters/jdbc/jtds.rb +0 -1
  32. data/lib/sequel/adapters/jdbc/mssql.rb +0 -1
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -1
  34. data/lib/sequel/adapters/jdbc/oracle.rb +0 -1
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -13
  36. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +0 -1
  37. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -1
  38. data/lib/sequel/adapters/jdbc/sqlserver.rb +3 -4
  39. data/lib/sequel/adapters/mock.rb +54 -12
  40. data/lib/sequel/adapters/mysql.rb +1 -1
  41. data/lib/sequel/adapters/mysql2.rb +11 -17
  42. data/lib/sequel/adapters/odbc/mssql.rb +0 -1
  43. data/lib/sequel/adapters/oracle.rb +8 -20
  44. data/lib/sequel/adapters/postgres.rb +11 -29
  45. data/lib/sequel/adapters/shared/access.rb +5 -12
  46. data/lib/sequel/adapters/shared/cubrid.rb +4 -13
  47. data/lib/sequel/adapters/shared/db2.rb +4 -2
  48. data/lib/sequel/adapters/shared/firebird.rb +2 -4
  49. data/lib/sequel/adapters/shared/informix.rb +4 -2
  50. data/lib/sequel/adapters/shared/mssql.rb +3 -5
  51. data/lib/sequel/adapters/shared/mysql.rb +4 -14
  52. data/lib/sequel/adapters/shared/oracle.rb +1 -3
  53. data/lib/sequel/adapters/shared/postgres.rb +16 -38
  54. data/lib/sequel/adapters/shared/progress.rb +0 -2
  55. data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -2
  56. data/lib/sequel/adapters/shared/sqlite.rb +20 -16
  57. data/lib/sequel/adapters/sqlite.rb +8 -20
  58. data/lib/sequel/adapters/swift/mysql.rb +0 -1
  59. data/lib/sequel/adapters/swift/postgres.rb +0 -1
  60. data/lib/sequel/adapters/swift/sqlite.rb +0 -1
  61. data/lib/sequel/adapters/tinytds.rb +4 -12
  62. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  63. data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -2
  64. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +11 -34
  65. data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
  66. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +26 -0
  67. data/lib/sequel/ast_transformer.rb +2 -2
  68. data/lib/sequel/database/dataset.rb +1 -1
  69. data/lib/sequel/database/dataset_defaults.rb +0 -66
  70. data/lib/sequel/database/features.rb +6 -0
  71. data/lib/sequel/database/misc.rb +31 -17
  72. data/lib/sequel/database/query.rb +7 -4
  73. data/lib/sequel/database/schema_methods.rb +1 -1
  74. data/lib/sequel/dataset.rb +8 -8
  75. data/lib/sequel/dataset/actions.rb +140 -46
  76. data/lib/sequel/dataset/features.rb +1 -5
  77. data/lib/sequel/dataset/graph.rb +7 -8
  78. data/lib/sequel/dataset/misc.rb +127 -56
  79. data/lib/sequel/dataset/mutation.rb +9 -20
  80. data/lib/sequel/dataset/placeholder_literalizer.rb +10 -1
  81. data/lib/sequel/dataset/prepared_statements.rb +102 -46
  82. data/lib/sequel/dataset/query.rb +155 -72
  83. data/lib/sequel/dataset/sql.rb +26 -9
  84. data/lib/sequel/extensions/columns_introspection.rb +3 -1
  85. data/lib/sequel/extensions/core_extensions.rb +5 -5
  86. data/lib/sequel/extensions/core_refinements.rb +5 -5
  87. data/lib/sequel/extensions/duplicate_columns_handler.rb +4 -2
  88. data/lib/sequel/extensions/freeze_datasets.rb +69 -0
  89. data/lib/sequel/extensions/identifier_mangling.rb +196 -0
  90. data/lib/sequel/extensions/looser_typecasting.rb +11 -7
  91. data/lib/sequel/extensions/migration.rb +1 -1
  92. data/lib/sequel/extensions/null_dataset.rb +5 -2
  93. data/lib/sequel/extensions/pagination.rb +42 -23
  94. data/lib/sequel/extensions/pg_enum.rb +3 -3
  95. data/lib/sequel/extensions/query.rb +3 -3
  96. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +15 -8
  97. data/lib/sequel/model/associations.rb +25 -8
  98. data/lib/sequel/model/base.rb +88 -29
  99. data/lib/sequel/model/dataset_module.rb +37 -0
  100. data/lib/sequel/plugins/association_pks.rb +4 -4
  101. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  102. data/lib/sequel/plugins/constraint_validations.rb +1 -2
  103. data/lib/sequel/plugins/csv_serializer.rb +2 -2
  104. data/lib/sequel/plugins/dataset_associations.rb +8 -8
  105. data/lib/sequel/plugins/eager_each.rb +2 -2
  106. data/lib/sequel/plugins/instance_filters.rb +1 -1
  107. data/lib/sequel/plugins/json_serializer.rb +2 -2
  108. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  109. data/lib/sequel/plugins/list.rb +4 -4
  110. data/lib/sequel/plugins/prepared_statements.rb +2 -4
  111. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -3
  112. data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
  113. data/lib/sequel/plugins/rcte_tree.rb +13 -13
  114. data/lib/sequel/plugins/sharding.rb +1 -1
  115. data/lib/sequel/plugins/single_table_inheritance.rb +9 -4
  116. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  117. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  118. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  119. data/lib/sequel/plugins/xml_serializer.rb +2 -2
  120. data/lib/sequel/sql.rb +69 -36
  121. data/lib/sequel/version.rb +1 -1
  122. data/spec/adapters/db2_spec.rb +10 -0
  123. data/spec/adapters/firebird_spec.rb +1 -1
  124. data/spec/adapters/mssql_spec.rb +4 -5
  125. data/spec/adapters/mysql_spec.rb +9 -9
  126. data/spec/adapters/postgres_spec.rb +67 -68
  127. data/spec/adapters/spec_helper.rb +6 -1
  128. data/spec/adapters/sqlite_spec.rb +29 -15
  129. data/spec/core/connection_pool_spec.rb +14 -14
  130. data/spec/core/database_spec.rb +38 -180
  131. data/spec/core/dataset_mutation_spec.rb +253 -0
  132. data/spec/core/dataset_spec.rb +394 -537
  133. data/spec/core/expression_filters_spec.rb +34 -32
  134. data/spec/core/mock_adapter_spec.rb +27 -35
  135. data/spec/core/placeholder_literalizer_spec.rb +2 -4
  136. data/spec/core/schema_generator_spec.rb +4 -4
  137. data/spec/core/schema_spec.rb +1 -2
  138. data/spec/core_extensions_spec.rb +22 -29
  139. data/spec/extensions/active_model_spec.rb +6 -6
  140. data/spec/extensions/association_dependencies_spec.rb +2 -2
  141. data/spec/extensions/blacklist_security_spec.rb +3 -3
  142. data/spec/extensions/boolean_readers_spec.rb +12 -12
  143. data/spec/extensions/caching_spec.rb +13 -10
  144. data/spec/extensions/class_table_inheritance_spec.rb +38 -43
  145. data/spec/extensions/column_conflicts_spec.rb +1 -3
  146. data/spec/extensions/columns_introspection_spec.rb +2 -3
  147. data/spec/extensions/composition_spec.rb +5 -3
  148. data/spec/extensions/constraint_validations_plugin_spec.rb +5 -5
  149. data/spec/extensions/constraint_validations_spec.rb +14 -8
  150. data/spec/extensions/core_refinements_spec.rb +22 -29
  151. data/spec/extensions/csv_serializer_spec.rb +7 -6
  152. data/spec/extensions/date_arithmetic_spec.rb +15 -15
  153. data/spec/extensions/defaults_setter_spec.rb +2 -2
  154. data/spec/extensions/delay_add_association_spec.rb +1 -1
  155. data/spec/extensions/dirty_spec.rb +19 -10
  156. data/spec/extensions/duplicate_columns_handler_spec.rb +12 -18
  157. data/spec/extensions/eager_each_spec.rb +12 -16
  158. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  159. data/spec/extensions/eval_inspect_spec.rb +4 -3
  160. data/spec/extensions/force_encoding_spec.rb +12 -12
  161. data/spec/extensions/freeze_datasets_spec.rb +31 -0
  162. data/spec/extensions/graph_each_spec.rb +6 -18
  163. data/spec/extensions/hook_class_methods_spec.rb +7 -7
  164. data/spec/extensions/identifier_mangling_spec.rb +307 -0
  165. data/spec/extensions/instance_filters_spec.rb +5 -6
  166. data/spec/extensions/instance_hooks_spec.rb +12 -12
  167. data/spec/extensions/json_serializer_spec.rb +12 -15
  168. data/spec/extensions/lazy_attributes_spec.rb +4 -4
  169. data/spec/extensions/list_spec.rb +19 -21
  170. data/spec/extensions/many_through_many_spec.rb +108 -163
  171. data/spec/extensions/meta_def_spec.rb +7 -2
  172. data/spec/extensions/migration_spec.rb +10 -12
  173. data/spec/extensions/mssql_optimistic_locking_spec.rb +4 -3
  174. data/spec/extensions/named_timezones_spec.rb +4 -3
  175. data/spec/extensions/nested_attributes_spec.rb +2 -2
  176. data/spec/extensions/null_dataset_spec.rb +17 -12
  177. data/spec/extensions/optimistic_locking_spec.rb +4 -5
  178. data/spec/extensions/pagination_spec.rb +8 -10
  179. data/spec/extensions/pg_array_associations_spec.rb +28 -27
  180. data/spec/extensions/pg_array_ops_spec.rb +2 -1
  181. data/spec/extensions/pg_array_spec.rb +6 -2
  182. data/spec/extensions/pg_enum_spec.rb +5 -3
  183. data/spec/extensions/pg_hstore_ops_spec.rb +3 -1
  184. data/spec/extensions/pg_hstore_spec.rb +7 -6
  185. data/spec/extensions/pg_inet_ops_spec.rb +2 -1
  186. data/spec/extensions/pg_inet_spec.rb +2 -1
  187. data/spec/extensions/pg_interval_spec.rb +2 -1
  188. data/spec/extensions/pg_json_ops_spec.rb +2 -1
  189. data/spec/extensions/pg_json_spec.rb +6 -3
  190. data/spec/extensions/pg_loose_count_spec.rb +1 -0
  191. data/spec/extensions/pg_range_ops_spec.rb +3 -1
  192. data/spec/extensions/pg_range_spec.rb +9 -5
  193. data/spec/extensions/pg_row_ops_spec.rb +2 -1
  194. data/spec/extensions/pg_row_plugin_spec.rb +4 -6
  195. data/spec/extensions/pg_row_spec.rb +5 -3
  196. data/spec/extensions/pg_static_cache_updater_spec.rb +2 -1
  197. data/spec/extensions/pg_typecast_on_load_spec.rb +1 -1
  198. data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
  199. data/spec/extensions/prepared_statements_spec.rb +12 -11
  200. data/spec/extensions/pretty_table_spec.rb +1 -1
  201. data/spec/extensions/query_spec.rb +8 -5
  202. data/spec/extensions/rcte_tree_spec.rb +39 -39
  203. data/spec/extensions/round_timestamps_spec.rb +2 -2
  204. data/spec/extensions/schema_dumper_spec.rb +3 -2
  205. data/spec/extensions/schema_spec.rb +2 -2
  206. data/spec/extensions/scissors_spec.rb +1 -2
  207. data/spec/extensions/sequel_3_dataset_methods_spec.rb +30 -17
  208. data/spec/extensions/serialization_modification_detection_spec.rb +2 -2
  209. data/spec/extensions/serialization_spec.rb +15 -13
  210. data/spec/extensions/set_overrides_spec.rb +14 -8
  211. data/spec/extensions/sharding_spec.rb +9 -18
  212. data/spec/extensions/shared_caching_spec.rb +3 -4
  213. data/spec/extensions/single_table_inheritance_spec.rb +11 -11
  214. data/spec/extensions/skip_create_refresh_spec.rb +2 -1
  215. data/spec/extensions/spec_helper.rb +1 -1
  216. data/spec/extensions/split_values_spec.rb +2 -2
  217. data/spec/extensions/sql_comments_spec.rb +6 -0
  218. data/spec/extensions/static_cache_spec.rb +7 -9
  219. data/spec/extensions/string_agg_spec.rb +30 -29
  220. data/spec/extensions/tactical_eager_loading_spec.rb +4 -5
  221. data/spec/extensions/thread_local_timezones_spec.rb +2 -2
  222. data/spec/extensions/timestamps_spec.rb +28 -3
  223. data/spec/extensions/to_dot_spec.rb +1 -2
  224. data/spec/extensions/tree_spec.rb +33 -29
  225. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  226. data/spec/extensions/unlimited_update_spec.rb +1 -0
  227. data/spec/extensions/update_primary_key_spec.rb +11 -7
  228. data/spec/extensions/update_refresh_spec.rb +1 -1
  229. data/spec/extensions/uuid_spec.rb +0 -1
  230. data/spec/extensions/validate_associated_spec.rb +1 -1
  231. data/spec/extensions/validation_class_methods_spec.rb +10 -10
  232. data/spec/extensions/validation_helpers_spec.rb +10 -10
  233. data/spec/extensions/xml_serializer_spec.rb +7 -3
  234. data/spec/integration/associations_test.rb +31 -31
  235. data/spec/integration/dataset_test.rb +17 -19
  236. data/spec/integration/eager_loader_test.rb +24 -24
  237. data/spec/integration/model_test.rb +6 -6
  238. data/spec/integration/plugin_test.rb +43 -43
  239. data/spec/integration/prepared_statement_test.rb +6 -6
  240. data/spec/integration/schema_test.rb +63 -52
  241. data/spec/integration/spec_helper.rb +6 -1
  242. data/spec/integration/transaction_test.rb +13 -13
  243. data/spec/model/association_reflection_spec.rb +17 -17
  244. data/spec/model/associations_spec.rb +101 -96
  245. data/spec/model/base_spec.rb +175 -49
  246. data/spec/model/class_dataset_methods_spec.rb +5 -9
  247. data/spec/model/dataset_methods_spec.rb +5 -5
  248. data/spec/model/eager_loading_spec.rb +209 -235
  249. data/spec/model/hooks_spec.rb +15 -15
  250. data/spec/model/model_spec.rb +28 -21
  251. data/spec/model/plugins_spec.rb +4 -5
  252. data/spec/model/record_spec.rb +59 -57
  253. data/spec/model/spec_helper.rb +1 -1
  254. data/spec/model/validations_spec.rb +6 -6
  255. data/spec/spec_config.rb +1 -1
  256. metadata +10 -2
@@ -28,7 +28,9 @@ module Sequel
28
28
  # Symbols, SQL::Identifiers, SQL::QualifiedIdentifiers, and
29
29
  # SQL::AliasedExpressions.
30
30
  def columns
31
- return @columns if @columns
31
+ if cols = _columns
32
+ return cols
33
+ end
32
34
  if (pcs = probable_columns) && pcs.all?
33
35
  self.columns = pcs
34
36
  else
@@ -42,9 +42,9 @@ class Array
42
42
  # this array as a value in a filter, but may be necessary if you are using it as a
43
43
  # value with placeholder SQL:
44
44
  #
45
- # DB[:a].filter([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
46
- # DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
47
- # DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
45
+ # DB[:a].where([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
46
+ # DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
47
+ # DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
48
48
  def sql_value_list
49
49
  ::Sequel::SQL::ValueList.new(self)
50
50
  end
@@ -174,10 +174,10 @@ class String
174
174
  # Converts a string into a <tt>Sequel::LiteralString</tt>, in order to override string
175
175
  # literalization, e.g.:
176
176
  #
177
- # DB[:items].filter(:abc => 'def').sql #=>
177
+ # DB[:items].where(:abc => 'def').sql #=>
178
178
  # "SELECT * FROM items WHERE (abc = 'def')"
179
179
  #
180
- # DB[:items].filter(:abc => 'def'.lit).sql #=>
180
+ # DB[:items].where(:abc => 'def'.lit).sql #=>
181
181
  # "SELECT * FROM items WHERE (abc = def)"
182
182
  #
183
183
  # You can also provide arguments, to create a <tt>Sequel::SQL::PlaceholderLiteralString</tt>:
@@ -38,9 +38,9 @@ module Sequel::CoreRefinements
38
38
  # this array as a value in a filter, but may be necessary if you are using it as a
39
39
  # value with placeholder SQL:
40
40
  #
41
- # DB[:a].filter([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
42
- # DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
43
- # DB[:a].filter('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
41
+ # DB[:a].where([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
42
+ # DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
43
+ # DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
44
44
  def sql_value_list
45
45
  ::Sequel::SQL::ValueList.new(self)
46
46
  end
@@ -167,10 +167,10 @@ module Sequel::CoreRefinements
167
167
  # Converts a string into a <tt>Sequel::LiteralString</tt>, in order to override string
168
168
  # literalization, e.g.:
169
169
  #
170
- # DB[:items].filter(:abc => 'def').sql #=>
170
+ # DB[:items].where(:abc => 'def').sql #=>
171
171
  # "SELECT * FROM items WHERE (abc = 'def')"
172
172
  #
173
- # DB[:items].filter(:abc => 'def'.lit).sql #=>
173
+ # DB[:items].where(:abc => 'def'.lit).sql #=>
174
174
  # "SELECT * FROM items WHERE (abc = def)"
175
175
  #
176
176
  # You can also provide arguments, to create a <tt>Sequel::SQL::PlaceholderLiteralString</tt>:
@@ -35,6 +35,8 @@
35
35
 
36
36
  module Sequel
37
37
  module DuplicateColumnsHandler
38
+ CALLER_ARGS = RUBY_VERSION >= '2.0' ? [0,1] : [0]
39
+
38
40
  # Customize handling of duplicate columns for this dataset.
39
41
  def on_duplicate_columns(handler = (raise Error, "Must provide either an argument or a block to on_duplicate_columns" unless block_given?; nil), &block)
40
42
  raise Error, "Cannot provide both an argument and a block to on_duplicate_columns" if handler && block
@@ -47,14 +49,14 @@ module Sequel
47
49
  if cols && cols.uniq.size != cols.size
48
50
  handle_duplicate_columns(cols)
49
51
  end
50
- @columns = cols
52
+ super
51
53
  end
52
54
 
53
55
  private
54
56
 
55
57
  # Invoke the appropriate behavior when duplicate columns are present.
56
58
  def handle_duplicate_columns(cols)
57
- message = "One or more duplicate columns present in #{cols.inspect}"
59
+ message = "#{caller(*CALLER_ARGS).first}: One or more duplicate columns present in #{cols.inspect}"
58
60
 
59
61
  case duplicate_columns_handler_type(cols)
60
62
  when :raise
@@ -0,0 +1,69 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The freeze_datasets extension freezes a databases's datasets by
4
+ # default, and makes it so the databases's datasets are always
5
+ # frozen. This makes sure you can never accidentally modify a
6
+ # dataset that may be used elsewhere (such as a model class's
7
+ # dataset or the same dataset being used in another thread).
8
+ # Frozen datasets can also perform caching for many
9
+ # different methods that can significantly improve performance.
10
+ #
11
+ # In addition to the caching provided by frozen datasets, this
12
+ # also adds caching of Database#from calls if the method is
13
+ # called with a single Symbol argument and not a block. In
14
+ # addition to speeding up Dataset#from itself, because it
15
+ # returns a cached dataset, all caching done by that dataset
16
+ # can also improve performance.
17
+ #
18
+ # Usage:
19
+ #
20
+ # DB.extension(:freeze_datasets)
21
+ #
22
+ # Related module: Sequel::FreezeDatasets
23
+
24
+ #
25
+ module Sequel
26
+ class Database
27
+ module FreezeDatasets
28
+ module DatasetMethods
29
+ # Make dup be an alias to clone, so that it
30
+ # returns a frozen dataset.
31
+ def dup
32
+ clone
33
+ end
34
+ end
35
+
36
+ # Reset the default dataset for this database after
37
+ # loading the extension.
38
+ def self.extended(db)
39
+ db.extend_datasets(DatasetMethods)
40
+ end
41
+
42
+ # Cache returned dataset if given a single argument and no block.
43
+ def from(*args, &block)
44
+ if !block && args.length == 1 && (table = args[0]).is_a?(Symbol)
45
+ @default_dataset.send(:cached_dataset, :"_from_#{table}_ds"){super}
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ # Freeze datasets created from this dataset.
52
+ def dataset
53
+ super.freeze
54
+ end
55
+
56
+ private
57
+
58
+ # Clear the cache of the default dataset when removing a cached
59
+ # schema, in order to clear the from table cache.
60
+ def remove_cached_schema(table)
61
+ cache = @default_dataset.send(:cache)
62
+ Sequel.synchronize{cache.clear}
63
+ super
64
+ end
65
+ end
66
+
67
+ register_extension(:freeze_datasets, FreezeDatasets)
68
+ end
69
+ end
@@ -0,0 +1,196 @@
1
+ # frozen-string-literal: true
2
+ #
3
+ # The identifier_mangling extension adds support for to change
4
+ # the default identifier mangling for datasets, as well as all
5
+ # datasets for a given database.
6
+ #
7
+ # # Use uppercase identifiers in database, and lowercase in ruby.
8
+ # # Default behavior of Sequel, as the SQL standard behavior
9
+ # # folds unquoted identifiers to uppercase.
10
+ # DB.identifier_input_method = :upcase
11
+ # DB.identifier_output_method = :downcase
12
+ #
13
+ # # Don't modify identifiers.
14
+ # # Default behavior of Sequel on PostgreSQL, MySQL, SQLite,
15
+ # # as they fold unquoted identifiers to lowercase.
16
+ # DB.identifier_input_method = nil
17
+ # DB.identifier_output_method = nil
18
+ #
19
+ # You can also choose to turn on or off identifier quoting:
20
+ #
21
+ # # Quote identifiers. Sequel's default behavior.
22
+ # DB.quote_identifiers = true
23
+ #
24
+ # # Don't quote identifiers. Sequel's default behavior on DB2.
25
+ # DB.quote_identifiers = false
26
+ #
27
+ # To modify the identifiers on a per-dataset basis:
28
+ #
29
+ # ds = DB[:a].with_input_indentifier(:upcase).
30
+ # with_output_identifier(:downcase).
31
+ # with_quote_identifiers(true)
32
+ #
33
+ # To load the extension into the database:
34
+ #
35
+ # DB.extension :identifier_mangling
36
+ #
37
+ # Historically, Sequel supported these methods by default on
38
+ # Databases and Datasets. Sequel 4 will continue to support
39
+ # the methods for backwards compatibility, by loading this
40
+ # extension automatically for databases unless the
41
+ # <tt>:identifier_mangling=>false</tt> Database option is
42
+ # used.
43
+ #
44
+ # Related modules: Sequel::IdentifierMangling::DatabaseMethods,
45
+ # Sequel::IdentifierMangling::DatasetMethods
46
+
47
+ #
48
+ module Sequel
49
+ module IdentifierMangling
50
+ module DatabaseMethods
51
+ def self.extended(db)
52
+ db.instance_exec do
53
+ @identifier_input_method = nil
54
+ @identifier_output_method = nil
55
+ @quote_identifiers = nil
56
+ reset_identifier_mangling
57
+ extend_datasets(DatasetMethods)
58
+ end
59
+ end
60
+
61
+ # The identifier input method to use by default for this database (default: adapter default)
62
+ attr_reader :identifier_input_method
63
+
64
+ # The identifier output method to use by default for this database (default: adapter default)
65
+ attr_reader :identifier_output_method
66
+
67
+ # Set the method to call on identifiers going into the database:
68
+ #
69
+ # DB[:items] # SELECT * FROM items
70
+ # DB.identifier_input_method = :upcase
71
+ # DB[:items] # SELECT * FROM ITEMS
72
+ def identifier_input_method=(v)
73
+ reset_default_dataset
74
+ @identifier_input_method = v
75
+ end
76
+
77
+ # Set the method to call on identifiers coming from the database:
78
+ #
79
+ # DB[:items].first # {:id=>1, :name=>'foo'}
80
+ # DB.identifier_output_method = :upcase
81
+ # DB[:items].first # {:ID=>1, :NAME=>'foo'}
82
+ def identifier_output_method=(v)
83
+ reset_default_dataset
84
+ @identifier_output_method = v
85
+ end
86
+
87
+ # Set whether to quote identifiers (columns and tables) for this database:
88
+ #
89
+ # DB[:items] # SELECT * FROM items
90
+ # DB.quote_identifiers = true
91
+ # DB[:items] # SELECT * FROM "items"
92
+ def quote_identifiers=(v)
93
+ reset_default_dataset
94
+ @quote_identifiers = v
95
+ end
96
+
97
+ # Returns true if the database quotes identifiers.
98
+ def quote_identifiers?
99
+ @quote_identifiers
100
+ end
101
+
102
+ private
103
+
104
+ # Return a dataset that uses the default identifier input and output methods
105
+ # for this database. Used when parsing metadata so that column symbols are
106
+ # returned as expected.
107
+ def _metadata_dataset
108
+ super.
109
+ with_identifier_input_method(identifier_input_method_default).
110
+ with_identifier_output_method(identifier_output_method_default)
111
+ end
112
+
113
+ # Upcase identifiers on input if database folds unquoted identifiers to
114
+ # uppercase.
115
+ def identifier_input_method_default
116
+ return super if defined?(super)
117
+ :upcase if folds_unquoted_identifiers_to_uppercase?
118
+ end
119
+
120
+ # Downcase identifiers on output if database folds unquoted identifiers to
121
+ # uppercase.
122
+ def identifier_output_method_default
123
+ return super if defined?(super)
124
+ :downcase if folds_unquoted_identifiers_to_uppercase?
125
+ end
126
+
127
+ # Reset the identifier mangling options. Overrides any already set on
128
+ # the instance. Only for internal use by shared adapters.
129
+ def reset_identifier_mangling
130
+ @quote_identifiers = @opts.fetch(:quote_identifiers){(qi = Database.quote_identifiers).nil? ? quote_identifiers_default : qi}
131
+ @identifier_input_method = @opts.fetch(:identifier_input_method){(iim = Database.identifier_input_method).nil? ? identifier_input_method_default : (iim if iim)}
132
+ @identifier_output_method = @opts.fetch(:identifier_output_method){(iom = Database.identifier_output_method).nil? ? identifier_output_method_default : (iom if iom)}
133
+ reset_default_dataset
134
+ end
135
+ end
136
+
137
+ module DatasetMethods
138
+ # The String instance method to call on identifiers before sending them to
139
+ # the database.
140
+ def identifier_input_method
141
+ @opts.fetch(:identifier_input_method, db.identifier_input_method)
142
+ end
143
+
144
+ # Set the method to call on identifiers going into the database for this dataset
145
+ def identifier_input_method=(v)
146
+ raise_if_frozen!
147
+ skip_symbol_cache!
148
+ @opts[:identifier_input_method] = v
149
+ end
150
+
151
+ # The String instance method to call on identifiers before sending them to
152
+ # the database.
153
+ def identifier_output_method
154
+ @opts.fetch(:identifier_output_method, db.identifier_output_method)
155
+ end
156
+
157
+ # Set the method to call on identifiers coming the database for this dataset
158
+ def identifier_output_method=(v)
159
+ raise_if_frozen!
160
+ @opts[:identifier_output_method] = v
161
+ end
162
+
163
+ # Check with the database to see if identifier quoting is enabled
164
+ def quote_identifiers?
165
+ @opts.fetch(:quote_identifiers, db.quote_identifiers?)
166
+ end
167
+
168
+ # Return a modified dataset with identifier_input_method set.
169
+ def with_identifier_input_method(meth)
170
+ clone(:identifier_input_method=>meth, :skip_symbol_cache=>true)
171
+ end
172
+
173
+ # Return a modified dataset with identifier_output_method set.
174
+ def with_identifier_output_method(meth)
175
+ clone(:identifier_output_method=>meth)
176
+ end
177
+
178
+ private
179
+
180
+ # Convert the identifier to the version used in the database via
181
+ # identifier_input_method.
182
+ def input_identifier(v)
183
+ (i = identifier_input_method) ? v.to_s.send(i) : v.to_s
184
+ end
185
+
186
+ # Modify the identifier returned from the database based on the
187
+ # identifier_output_method.
188
+ def output_identifier(v)
189
+ v = 'untitled' if v == ''
190
+ (i = identifier_output_method) ? v.to_s.send(i).to_sym : v.to_sym
191
+ end
192
+ end
193
+ end
194
+
195
+ Database.register_extension(:identifier_mangling, IdentifierMangling::DatabaseMethods)
196
+ end
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # :float :: use to_f instead of Float()
7
7
  # :integer :: use to_i instead of Integer()
8
- # :decimal :: don't check string conversion with Float()
8
+ # :decimal :: use 0.0 for unsupported strings
9
9
  # :string :: silently allow hash and array conversion to string
10
10
  #
11
11
  # To load the extension into the database:
@@ -17,6 +17,8 @@
17
17
  #
18
18
  module Sequel
19
19
  module LooserTypecasting
20
+ private
21
+
20
22
  # Typecast the value to a Float using to_f instead of Kernel.Float
21
23
  def typecast_value_float(value)
22
24
  value.to_f
@@ -32,13 +34,15 @@ module Sequel
32
34
  value.to_s
33
35
  end
34
36
 
35
- # Typecast the value to a BigDecimal, without checking if strings
36
- # have a valid format.
37
- def typecast_value_decimal(value)
38
- if value.is_a?(String)
37
+ if RUBY_VERSION >= '2.4'
38
+ def _typecast_value_string_to_decimal(value)
39
+ BigDecimal.new(value)
40
+ rescue
41
+ BigDecimal.new('0.0')
42
+ end
43
+ else
44
+ def _typecast_value_string_to_decimal(value)
39
45
  BigDecimal.new(value)
40
- else
41
- super
42
46
  end
43
47
  end
44
48
  end
@@ -687,7 +687,7 @@ module Sequel
687
687
  checked_transaction(m) do
688
688
  m.apply(db, direction)
689
689
  fi = f.downcase
690
- direction == :up ? ds.insert(column=>fi) : ds.filter(column=>fi).delete
690
+ direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete
691
691
  end
692
692
  db.log_info("Finished applying migration #{f}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds")
693
693
  end
@@ -41,7 +41,7 @@ module Sequel
41
41
  module Nullifiable
42
42
  # Return a cloned nullified dataset.
43
43
  def nullify
44
- clone.nullify!
44
+ clone.with_extend(NullDataset)
45
45
  end
46
46
 
47
47
  # Nullify the current dataset
@@ -54,7 +54,10 @@ module Sequel
54
54
  # Create a new dataset from the dataset (which won't
55
55
  # be nulled) to get the columns if they aren't already cached.
56
56
  def columns
57
- @columns ||= db.dataset.clone(@opts).columns
57
+ if cols = _columns
58
+ return cols
59
+ end
60
+ self.columns = db.dataset.clone(@opts).columns
58
61
  end
59
62
 
60
63
  # Return 0 without sending a database query.
@@ -39,9 +39,14 @@ module Sequel
39
39
  # number of records for this dataset.
40
40
  def paginate(page_no, page_size, record_count=nil)
41
41
  raise(Error, "You cannot paginate a dataset that already has a limit") if @opts[:limit]
42
- paginated = limit(page_size, (page_no - 1) * page_size)
43
- paginated.extend(Dataset::Pagination)
44
- paginated.set_pagination_info(page_no, page_size, record_count || count)
42
+
43
+ record_count ||= count
44
+ page_count = (record_count / page_size.to_f).ceil
45
+ page_count = 1 if page_count == 0
46
+
47
+ limit(page_size, (page_no - 1) * page_size).
48
+ with_extend(Dataset::Pagination).
49
+ clone(:page_size=>page_size, :current_page=>page_no, :pagination_record_count=>record_count, :page_count=>page_count)
45
50
  end
46
51
 
47
52
  # Yields a paginated dataset for each page and returns the receiver. Does
@@ -61,49 +66,59 @@ module Sequel
61
66
  # Holds methods that only relate to paginated datasets. Paginated dataset
62
67
  # have pages starting at 1 (page 1 is offset 0, page 1 is offset page_size).
63
68
  module Pagination
69
+ Sequel::Dataset.def_deprecated_opts_setter(self, :page_size, :page_count, :current_page, :pagination_record_count)
70
+
64
71
  # The number of records per page (the final page may have fewer than
65
72
  # this number of records).
66
- attr_accessor :page_size
73
+ def page_size
74
+ @opts[:page_size]
75
+ end
67
76
 
68
77
  # The number of pages in the dataset before pagination, of which
69
78
  # this paginated dataset is one. Empty datasets are considered
70
79
  # to have a single page.
71
- attr_accessor :page_count
80
+ def page_count
81
+ @opts[:page_count]
82
+ end
72
83
 
73
84
  # The current page of the dataset, starting at 1 and not 0.
74
- attr_accessor :current_page
85
+ def current_page
86
+ @opts[:current_page]
87
+ end
75
88
 
76
89
  # The total number of records in the dataset before pagination.
77
- attr_accessor :pagination_record_count
90
+ def pagination_record_count
91
+ @opts[:pagination_record_count]
92
+ end
78
93
 
79
94
  # Returns the record range for the current page
80
95
  def current_page_record_range
81
- return (0..0) if @current_page > @page_count
96
+ return (0..0) if current_page > page_count
82
97
 
83
- a = 1 + (@current_page - 1) * @page_size
84
- b = a + @page_size - 1
85
- b = @pagination_record_count if b > @pagination_record_count
98
+ a = 1 + (current_page - 1) * page_size
99
+ b = a + page_size - 1
100
+ b = pagination_record_count if b > pagination_record_count
86
101
  a..b
87
102
  end
88
103
 
89
104
  # Returns the number of records in the current page
90
105
  def current_page_record_count
91
- return 0 if @current_page > @page_count
106
+ return 0 if current_page > page_count
92
107
 
93
- a = 1 + (@current_page - 1) * @page_size
94
- b = a + @page_size - 1
95
- b = @pagination_record_count if b > @pagination_record_count
108
+ a = 1 + (current_page - 1) * page_size
109
+ b = a + page_size - 1
110
+ b = pagination_record_count if b > pagination_record_count
96
111
  b - a + 1
97
112
  end
98
113
 
99
114
  # Returns true if the current page is the first page
100
115
  def first_page?
101
- @current_page == 1
116
+ current_page == 1
102
117
  end
103
118
 
104
119
  # Returns true if the current page is the last page
105
120
  def last_page?
106
- @current_page == @page_count
121
+ current_page == page_count
107
122
  end
108
123
 
109
124
  # Returns the next page number or nil if the current page is the last page
@@ -121,15 +136,19 @@ module Sequel
121
136
  current_page > 1 ? (current_page - 1) : nil
122
137
  end
123
138
 
124
- # Sets the pagination info for this paginated dataset, and returns self.
139
+ # SEQUEL5: Remove
140
+ # :nocov:
125
141
  def set_pagination_info(page_no, page_size, record_count)
126
- @current_page = page_no
127
- @page_size = page_size
128
- @pagination_record_count = record_count
129
- @page_count = (record_count / page_size.to_f).ceil
130
- @page_count = 1 if @page_count == 0
142
+ Sequel::Deprecation.deprecate("Dataset#set_pagination_info", "It should no longer be necessary to call this method.")
143
+ self.current_page = page_no
144
+ self.page_size = page_size
145
+ self.pagination_record_count = record_count
146
+ page_count = (record_count / page_size.to_f).ceil
147
+ page_count = 1 if page_count == 0
148
+ self.page_count = page_count
131
149
  self
132
150
  end
151
+ # :nocov:
133
152
  end
134
153
  end
135
154