sequel 3.47.0 → 3.48.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 (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +230 -0
  3. data/README.rdoc +31 -40
  4. data/Rakefile +1 -14
  5. data/doc/active_record.rdoc +29 -29
  6. data/doc/association_basics.rdoc +4 -13
  7. data/doc/cheat_sheet.rdoc +8 -6
  8. data/doc/code_order.rdoc +89 -0
  9. data/doc/core_extensions.rdoc +3 -3
  10. data/doc/dataset_basics.rdoc +7 -8
  11. data/doc/dataset_filtering.rdoc +7 -2
  12. data/doc/mass_assignment.rdoc +2 -3
  13. data/doc/migration.rdoc +8 -8
  14. data/doc/model_hooks.rdoc +11 -7
  15. data/doc/object_model.rdoc +2 -2
  16. data/doc/opening_databases.rdoc +5 -14
  17. data/doc/prepared_statements.rdoc +5 -9
  18. data/doc/querying.rdoc +23 -28
  19. data/doc/reflection.rdoc +11 -0
  20. data/doc/release_notes/3.48.0.txt +477 -0
  21. data/doc/schema_modification.rdoc +12 -5
  22. data/doc/security.rdoc +2 -2
  23. data/doc/sharding.rdoc +1 -2
  24. data/doc/sql.rdoc +10 -13
  25. data/doc/testing.rdoc +8 -4
  26. data/doc/transactions.rdoc +2 -2
  27. data/doc/validations.rdoc +40 -17
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado.rb +25 -20
  30. data/lib/sequel/adapters/ado/access.rb +1 -0
  31. data/lib/sequel/adapters/ado/mssql.rb +1 -0
  32. data/lib/sequel/adapters/db2.rb +9 -7
  33. data/lib/sequel/adapters/dbi.rb +16 -16
  34. data/lib/sequel/adapters/do.rb +17 -18
  35. data/lib/sequel/adapters/do/mysql.rb +1 -0
  36. data/lib/sequel/adapters/do/postgres.rb +2 -0
  37. data/lib/sequel/adapters/do/sqlite.rb +1 -0
  38. data/lib/sequel/adapters/firebird.rb +5 -7
  39. data/lib/sequel/adapters/ibmdb.rb +23 -20
  40. data/lib/sequel/adapters/informix.rb +8 -2
  41. data/lib/sequel/adapters/jdbc.rb +39 -35
  42. data/lib/sequel/adapters/jdbc/as400.rb +1 -0
  43. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
  44. data/lib/sequel/adapters/jdbc/db2.rb +1 -0
  45. data/lib/sequel/adapters/jdbc/derby.rb +1 -0
  46. data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
  47. data/lib/sequel/adapters/jdbc/h2.rb +1 -0
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
  49. data/lib/sequel/adapters/jdbc/informix.rb +1 -0
  50. data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
  51. data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
  52. data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
  53. data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
  54. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
  55. data/lib/sequel/adapters/jdbc/progress.rb +1 -0
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
  58. data/lib/sequel/adapters/mock.rb +30 -31
  59. data/lib/sequel/adapters/mysql.rb +6 -7
  60. data/lib/sequel/adapters/mysql2.rb +5 -6
  61. data/lib/sequel/adapters/odbc.rb +22 -20
  62. data/lib/sequel/adapters/odbc/mssql.rb +1 -0
  63. data/lib/sequel/adapters/openbase.rb +4 -1
  64. data/lib/sequel/adapters/oracle.rb +10 -8
  65. data/lib/sequel/adapters/postgres.rb +12 -10
  66. data/lib/sequel/adapters/shared/access.rb +6 -0
  67. data/lib/sequel/adapters/shared/cubrid.rb +2 -0
  68. data/lib/sequel/adapters/shared/db2.rb +2 -0
  69. data/lib/sequel/adapters/shared/firebird.rb +2 -0
  70. data/lib/sequel/adapters/shared/informix.rb +2 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +14 -8
  72. data/lib/sequel/adapters/shared/mysql.rb +6 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +2 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +14 -4
  75. data/lib/sequel/adapters/shared/progress.rb +1 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +4 -3
  77. data/lib/sequel/adapters/sqlite.rb +6 -7
  78. data/lib/sequel/adapters/swift.rb +20 -21
  79. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  80. data/lib/sequel/adapters/swift/postgres.rb +2 -0
  81. data/lib/sequel/adapters/swift/sqlite.rb +1 -0
  82. data/lib/sequel/adapters/tinytds.rb +5 -6
  83. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
  84. data/lib/sequel/connection_pool.rb +1 -1
  85. data/lib/sequel/core.rb +57 -50
  86. data/lib/sequel/database/connecting.rb +9 -10
  87. data/lib/sequel/database/dataset.rb +11 -6
  88. data/lib/sequel/database/dataset_defaults.rb +61 -69
  89. data/lib/sequel/database/features.rb +21 -0
  90. data/lib/sequel/database/misc.rb +23 -3
  91. data/lib/sequel/database/query.rb +13 -7
  92. data/lib/sequel/database/schema_methods.rb +6 -6
  93. data/lib/sequel/database/transactions.rb +1 -0
  94. data/lib/sequel/dataset/actions.rb +51 -38
  95. data/lib/sequel/dataset/features.rb +1 -0
  96. data/lib/sequel/dataset/graph.rb +9 -33
  97. data/lib/sequel/dataset/misc.rb +30 -5
  98. data/lib/sequel/dataset/mutation.rb +2 -3
  99. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  100. data/lib/sequel/dataset/query.rb +91 -27
  101. data/lib/sequel/dataset/sql.rb +40 -6
  102. data/lib/sequel/deprecated.rb +74 -0
  103. data/lib/sequel/deprecated_core_extensions.rb +135 -0
  104. data/lib/sequel/extensions/columns_introspection.rb +1 -5
  105. data/lib/sequel/extensions/core_extensions.rb +10 -3
  106. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  107. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
  108. data/lib/sequel/extensions/filter_having.rb +58 -0
  109. data/lib/sequel/extensions/graph_each.rb +63 -0
  110. data/lib/sequel/extensions/hash_aliases.rb +44 -0
  111. data/lib/sequel/extensions/looser_typecasting.rb +14 -3
  112. data/lib/sequel/extensions/migration.rb +2 -3
  113. data/lib/sequel/extensions/named_timezones.rb +14 -1
  114. data/lib/sequel/extensions/null_dataset.rb +7 -1
  115. data/lib/sequel/extensions/pagination.rb +15 -5
  116. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
  117. data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
  118. data/lib/sequel/extensions/pg_json.rb +7 -7
  119. data/lib/sequel/extensions/pg_range_ops.rb +8 -2
  120. data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
  121. data/lib/sequel/extensions/pretty_table.rb +13 -4
  122. data/lib/sequel/extensions/query.rb +21 -4
  123. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
  124. data/lib/sequel/extensions/schema_caching.rb +10 -7
  125. data/lib/sequel/extensions/schema_dumper.rb +35 -48
  126. data/lib/sequel/extensions/select_remove.rb +13 -4
  127. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
  128. data/lib/sequel/extensions/set_overrides.rb +43 -0
  129. data/lib/sequel/extensions/to_dot.rb +6 -0
  130. data/lib/sequel/model.rb +12 -6
  131. data/lib/sequel/model/associations.rb +80 -38
  132. data/lib/sequel/model/base.rb +137 -52
  133. data/lib/sequel/model/errors.rb +7 -2
  134. data/lib/sequel/plugins/active_model.rb +13 -0
  135. data/lib/sequel/plugins/after_initialize.rb +43 -0
  136. data/lib/sequel/plugins/association_proxies.rb +63 -7
  137. data/lib/sequel/plugins/auto_validations.rb +56 -16
  138. data/lib/sequel/plugins/blacklist_security.rb +63 -0
  139. data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
  140. data/lib/sequel/plugins/constraint_validations.rb +50 -8
  141. data/lib/sequel/plugins/dataset_associations.rb +2 -0
  142. data/lib/sequel/plugins/hook_class_methods.rb +7 -1
  143. data/lib/sequel/plugins/identity_map.rb +4 -0
  144. data/lib/sequel/plugins/json_serializer.rb +32 -13
  145. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  146. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  147. data/lib/sequel/plugins/scissors.rb +33 -0
  148. data/lib/sequel/plugins/serialization.rb +1 -1
  149. data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
  150. data/lib/sequel/plugins/tree.rb +5 -1
  151. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  152. data/lib/sequel/plugins/validation_helpers.rb +15 -11
  153. data/lib/sequel/plugins/xml_serializer.rb +12 -3
  154. data/lib/sequel/sql.rb +12 -2
  155. data/lib/sequel/timezones.rb +1 -1
  156. data/lib/sequel/version.rb +1 -1
  157. data/lib/sequel_core.rb +1 -0
  158. data/lib/sequel_model.rb +1 -0
  159. data/spec/adapters/mssql_spec.rb +24 -57
  160. data/spec/adapters/postgres_spec.rb +27 -55
  161. data/spec/adapters/spec_helper.rb +1 -1
  162. data/spec/adapters/sqlite_spec.rb +1 -1
  163. data/spec/bin_spec.rb +251 -0
  164. data/spec/core/database_spec.rb +46 -32
  165. data/spec/core/dataset_spec.rb +233 -181
  166. data/spec/core/deprecated_spec.rb +78 -0
  167. data/spec/core/expression_filters_spec.rb +3 -4
  168. data/spec/core/mock_adapter_spec.rb +9 -9
  169. data/spec/core/object_graph_spec.rb +9 -19
  170. data/spec/core/schema_spec.rb +3 -1
  171. data/spec/core/spec_helper.rb +19 -0
  172. data/spec/core_extensions_spec.rb +80 -30
  173. data/spec/extensions/after_initialize_spec.rb +24 -0
  174. data/spec/extensions/association_proxies_spec.rb +37 -1
  175. data/spec/extensions/auto_validations_spec.rb +20 -4
  176. data/spec/extensions/blacklist_security_spec.rb +87 -0
  177. data/spec/extensions/boolean_readers_spec.rb +2 -1
  178. data/spec/extensions/class_table_inheritance_spec.rb +7 -0
  179. data/spec/extensions/columns_introspection_spec.rb +3 -3
  180. data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
  181. data/spec/extensions/core_refinements_spec.rb +7 -7
  182. data/spec/extensions/dataset_associations_spec.rb +2 -2
  183. data/spec/extensions/date_arithmetic_spec.rb +1 -1
  184. data/spec/extensions/defaults_setter_spec.rb +2 -1
  185. data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
  186. data/spec/extensions/filter_having_spec.rb +40 -0
  187. data/spec/extensions/graph_each_spec.rb +109 -0
  188. data/spec/extensions/hash_aliases_spec.rb +16 -0
  189. data/spec/extensions/hook_class_methods_spec.rb +2 -2
  190. data/spec/extensions/identity_map_spec.rb +3 -3
  191. data/spec/extensions/json_serializer_spec.rb +19 -19
  192. data/spec/extensions/lazy_attributes_spec.rb +1 -0
  193. data/spec/extensions/list_spec.rb +13 -13
  194. data/spec/extensions/looser_typecasting_spec.rb +10 -3
  195. data/spec/extensions/many_through_many_spec.rb +1 -1
  196. data/spec/extensions/migration_spec.rb +7 -7
  197. data/spec/extensions/named_timezones_spec.rb +6 -0
  198. data/spec/extensions/nested_attributes_spec.rb +2 -2
  199. data/spec/extensions/null_dataset_spec.rb +1 -1
  200. data/spec/extensions/pagination_spec.rb +2 -2
  201. data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
  202. data/spec/extensions/pg_range_ops_spec.rb +4 -2
  203. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  204. data/spec/extensions/pretty_table_spec.rb +1 -1
  205. data/spec/extensions/query_literals_spec.rb +1 -1
  206. data/spec/extensions/query_spec.rb +3 -3
  207. data/spec/extensions/schema_caching_spec.rb +3 -3
  208. data/spec/extensions/schema_dumper_spec.rb +27 -2
  209. data/spec/extensions/schema_spec.rb +2 -2
  210. data/spec/extensions/scissors_spec.rb +26 -0
  211. data/spec/extensions/select_remove_spec.rb +1 -1
  212. data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
  213. data/spec/extensions/set_overrides_spec.rb +45 -0
  214. data/spec/extensions/single_table_inheritance_spec.rb +10 -0
  215. data/spec/extensions/spec_helper.rb +24 -1
  216. data/spec/extensions/static_cache_spec.rb +1 -1
  217. data/spec/extensions/string_stripper_spec.rb +2 -1
  218. data/spec/extensions/to_dot_spec.rb +1 -1
  219. data/spec/extensions/typecast_on_load_spec.rb +3 -2
  220. data/spec/extensions/update_primary_key_spec.rb +2 -2
  221. data/spec/extensions/validation_class_methods_spec.rb +19 -19
  222. data/spec/extensions/validation_helpers_spec.rb +30 -21
  223. data/spec/extensions/xml_serializer_spec.rb +5 -5
  224. data/spec/integration/associations_test.rb +10 -30
  225. data/spec/integration/dataset_test.rb +20 -24
  226. data/spec/integration/eager_loader_test.rb +5 -5
  227. data/spec/integration/model_test.rb +3 -3
  228. data/spec/integration/plugin_test.rb +7 -39
  229. data/spec/integration/schema_test.rb +4 -38
  230. data/spec/integration/spec_helper.rb +2 -1
  231. data/spec/model/association_reflection_spec.rb +70 -5
  232. data/spec/model/associations_spec.rb +11 -11
  233. data/spec/model/base_spec.rb +25 -8
  234. data/spec/model/class_dataset_methods_spec.rb +143 -0
  235. data/spec/model/dataset_methods_spec.rb +1 -1
  236. data/spec/model/eager_loading_spec.rb +25 -25
  237. data/spec/model/hooks_spec.rb +1 -1
  238. data/spec/model/model_spec.rb +22 -7
  239. data/spec/model/plugins_spec.rb +1 -6
  240. data/spec/model/record_spec.rb +37 -29
  241. data/spec/model/spec_helper.rb +23 -1
  242. data/spec/model/validations_spec.rb +15 -17
  243. metadata +32 -3
@@ -79,8 +79,14 @@ module Sequel
79
79
  OPERATORS.keys.each do |f|
80
80
  class_eval("def #{f}(v); operator(:#{f}, v) end", __FILE__, __LINE__)
81
81
  end
82
- alias starts_before ends_before
83
- alias ends_after starts_after
82
+ def starts_before(v)
83
+ Sequel::Deprecation.deprecate('Postgres::PGRangeOp#starts_before', "Please switch to Postgres::PGRangeOp#ends_before")
84
+ ends_before(v)
85
+ end
86
+ def ends_after(v)
87
+ Sequel::Deprecation.deprecate('Postgres::PGRangeOp#ends_after', "Please switch to Postgres::PGRangeOp#starts_after")
88
+ starts_after(v)
89
+ end
84
90
 
85
91
  # These operators are already supported by the wrapper, but for ranges they
86
92
  # return ranges, so wrap the results in another RangeOp.
@@ -228,6 +228,7 @@ module Sequel
228
228
  # Set the statement_cache for the connection, using the database's
229
229
  # :statement_cache_opts option.
230
230
  def self.extended(c)
231
+ Sequel::Deprecation.deprecate('The pg_statement_cache extension', 'Please stop loading it') unless defined?(SEQUEL_EXTENSIONS_NO_DEPRECATION_WARNING)
231
232
  c.instance_variable_set(:@statement_cache, StatementCache.new(c.sequel_db.opts[:statement_cache_opts] || {}){|name| c.deallocate(name)})
232
233
  end
233
234
 
@@ -9,22 +9,31 @@
9
9
  # |2 |test |
10
10
  # +--+-------+
11
11
  #
12
- # To load the extension:
12
+ # You can load this extension into specific datasets:
13
13
  #
14
- # Sequel.extension :pretty_table
14
+ # ds = DB[:table]
15
+ # ds.extension(:pretty_table)
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(:pretty_table)
15
21
 
16
22
  module Sequel
17
23
  extension :_pretty_table
18
24
 
25
+ module DatasetPrinter
26
+ end
27
+
19
28
  class Dataset
20
29
  # Pretty prints the records in the dataset as plain-text table.
21
30
  def print(*cols)
31
+ Sequel::Deprecation.deprecate('Loading the pretty_table extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(DatasetPrinter)
22
32
  ds = naked
23
33
  rows = ds.all
24
34
  Sequel::PrettyTable.print(rows, cols.empty? ? ds.columns : cols)
25
35
  end
26
36
  end
27
37
 
28
- Database.register_extension(:pretty_table){}
29
- Dataset.register_extension(:pretty_table){}
38
+ Dataset.register_extension(:pretty_table, DatasetPrinter)
30
39
  end
@@ -2,18 +2,34 @@
2
2
  # a different way to construct queries instead of the usual
3
3
  # method chaining. See Sequel::Dataset#query for details.
4
4
  #
5
- # To load the extension, do:
5
+ # You can load this extension into specific datasets:
6
6
  #
7
- # Sequel.extension :query
7
+ # ds = DB[:table]
8
+ # ds.extension(:query)
9
+ #
10
+ # Or you can load it into all of a database's datasets, which
11
+ # is probably the desired behavior if you are using this extension:
12
+ #
13
+ # DB.extension(:query)
8
14
 
9
15
  module Sequel
16
+ module DatabaseQuery
17
+ def self.extended(db)
18
+ db.extend_datasets(DatasetQuery)
19
+ end
20
+ end
21
+
10
22
  class Database
11
23
  # Return a dataset modified by the query block
12
24
  def query(&block)
25
+ Sequel::Deprecation.deprecate('Loading the query extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(DatabaseQuery)
13
26
  dataset.query(&block)
14
27
  end
15
28
  end
16
29
 
30
+ module DatasetQuery
31
+ end
32
+
17
33
  class Dataset
18
34
  # Translates a query block into a dataset. Query blocks are an
19
35
  # alternative to Sequel's usual method chaining, by using
@@ -29,6 +45,7 @@ module Sequel
29
45
  #
30
46
  # dataset = DB[:items].select(:x, :y, :z).filter{(x > 1) & (y > 2)}.reverse(:z)
31
47
  def query(&block)
48
+ Sequel::Deprecation.deprecate('Loading the query extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(DatasetQuery)
32
49
  query = Query.new(self)
33
50
  query.instance_eval(&block)
34
51
  query.dataset
@@ -52,6 +69,6 @@ module Sequel
52
69
  end
53
70
  end
54
71
 
55
- Dataset.register_extension(:query){}
56
- Database.register_extension(:query){}
72
+ Dataset.register_extension(:query, DatasetQuery)
73
+ Database.register_extension(:query, DatabaseQuery)
57
74
  end
@@ -0,0 +1,22 @@
1
+ # The ruby18_symbol_extensions adds the <, <=, >, >= to Symbol
2
+ # to reflect the mathmatical operators. It also adds the [] method
3
+ # to Symbol for creating SQL functions.
4
+ #
5
+ # Usage of this extension is not recommended. This extension will
6
+ # only load on ruby 1.8, so you will not be able to upgrade to
7
+ # newer ruby versions if you use it. If you still want to use it,
8
+ # you can load it via:
9
+ #
10
+ # Sequel.extension :ruby18_symbol_extensions
11
+
12
+ raise(Sequel::Error, "The ruby18_symbol_extensions is only available on ruby 1.8.") unless RUBY_VERSION < '1.9.0'
13
+
14
+ class Symbol
15
+ include Sequel::SQL::InequalityMethods
16
+
17
+ # Create an SQL Function with the receiver as the function name
18
+ # and the given arguments.
19
+ def [](*args)
20
+ Sequel::SQL::Function.new(self, *args)
21
+ end
22
+ end
@@ -6,10 +6,8 @@
6
6
  #
7
7
  # Basic usage in application code:
8
8
  #
9
- # Sequel.extension :schema_caching
10
- #
11
9
  # DB = Sequel.connect('...')
12
- #
10
+ # DB.extension :schema_caching
13
11
  # DB.load_schema_cache('/path/to/schema.dump')
14
12
  #
15
13
  # # load model files
@@ -23,10 +21,8 @@
23
21
  # all tables, and you don't worry about race conditions, you can
24
22
  # choose to use the following in your application code:
25
23
  #
26
- # Sequel.extension :schema_caching
27
- #
28
24
  # DB = Sequel.connect('...')
29
- #
25
+ # DB.extension :schema_caching
30
26
  # DB.load_schema_cache?('/path/to/schema.dump')
31
27
  #
32
28
  # # load model files
@@ -47,9 +43,13 @@
47
43
  # you should not attempt to load the schema from a untrusted file.
48
44
 
49
45
  module Sequel
46
+ module SchemaCaching
47
+ end
48
+
50
49
  class Database
51
50
  # Dump the cached schema to the filename given in Marshal format.
52
51
  def dump_schema_cache(file)
52
+ Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
53
53
  File.open(file, 'wb'){|f| f.write(Marshal.dump(@schemas))}
54
54
  nil
55
55
  end
@@ -57,12 +57,14 @@ module Sequel
57
57
  # Dump the cached schema to the filename given unless the file
58
58
  # already exists.
59
59
  def dump_schema_cache?(file)
60
+ Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
60
61
  dump_schema_cache(file) unless File.exist?(file)
61
62
  end
62
63
 
63
64
  # Replace the schema cache with the data from the given file, which
64
65
  # should be in Marshal format.
65
66
  def load_schema_cache(file)
67
+ Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
66
68
  @schemas = Marshal.load(File.read(file))
67
69
  nil
68
70
  end
@@ -70,9 +72,10 @@ module Sequel
70
72
  # Replace the schema cache with the data from the given file if the
71
73
  # file exists.
72
74
  def load_schema_cache?(file)
75
+ Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
73
76
  load_schema_cache(file) if File.exist?(file)
74
77
  end
75
78
  end
76
79
 
77
- Database.register_extension(:schema_caching){}
80
+ Database.register_extension(:schema_caching, SchemaCaching)
78
81
  end
@@ -6,11 +6,14 @@
6
6
  #
7
7
  # To load the extension:
8
8
  #
9
- # Sequel.extension :schema_dumper
9
+ # DB.extension :schema_dumper
10
10
 
11
11
  Sequel.extension :eval_inspect
12
12
 
13
13
  module Sequel
14
+ module SchemaDumper
15
+ end
16
+
14
17
  class Database
15
18
  # Dump foreign key constraints for all tables as a migration. This complements
16
19
  # the :foreign_keys=>false option to dump_schema_migration. This only dumps
@@ -20,6 +23,7 @@ module Sequel
20
23
  # Note that the migration this produces does not have a down
21
24
  # block, so you cannot reverse it.
22
25
  def dump_foreign_key_migration(options={})
26
+ Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
23
27
  ts = tables(options)
24
28
  <<END_MIG
25
29
  Sequel.migration do
@@ -38,6 +42,7 @@ END_MIG
38
42
  # set to :namespace, prepend the table name to the index name if the
39
43
  # database does not use a global index namespace.
40
44
  def dump_indexes_migration(options={})
45
+ Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
41
46
  ts = tables(options)
42
47
  <<END_MIG
43
48
  Sequel.migration do
@@ -62,6 +67,7 @@ END_MIG
62
67
  # :index_names :: If set to false, don't record names of indexes. If
63
68
  # set to :namespace, prepend the table name to the index name.
64
69
  def dump_schema_migration(options={})
70
+ Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
65
71
  options = options.dup
66
72
  if options[:indexes] == false && !options.has_key?(:foreign_keys)
67
73
  # Unless foreign_keys option is specifically set, disable if indexes
@@ -91,6 +97,7 @@ END_MIG
91
97
  # Return a string with a create table block that will recreate the given
92
98
  # table's schema. Takes the same options as dump_schema_migration.
93
99
  def dump_table_schema(table, options={})
100
+ Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
94
101
  table = table.value.to_s if table.is_a?(SQL::Identifier)
95
102
  gen = dump_table_generator(table, options)
96
103
  commands = [gen.dump_columns, gen.dump_constraints, gen.dump_indexes].reject{|x| x == ''}.join("\n\n")
@@ -209,13 +216,11 @@ END_MIG
209
216
  # For the table given, get the list of foreign keys and return an alter_table
210
217
  # string that would add the foreign keys if run in a migration.
211
218
  def dump_table_foreign_keys(table, options={})
212
- begin
219
+ if supports_foreign_key_parsing?
213
220
  fks = foreign_key_list(table, options).sort_by{|fk| fk[:columns].map{|c| c.to_s}}
214
- rescue Sequel::NotImplemented
215
- return ''
216
221
  end
217
222
 
218
- if fks.empty?
223
+ if fks.nil? || fks.empty?
219
224
  ''
220
225
  else
221
226
  dump_add_fk_constraints(table, fks)
@@ -233,40 +238,32 @@ END_MIG
233
238
  m = method(:recreate_column)
234
239
  im = method(:index_to_generator_opts)
235
240
 
236
- if options[:indexes] != false
237
- begin
238
- indexes = indexes(table).sort_by{|k,v| k.to_s}
239
- rescue Sequel::NotImplemented
240
- nil
241
- end
241
+ if options[:indexes] != false && supports_index_parsing?
242
+ indexes = indexes(table).sort_by{|k,v| k.to_s}
242
243
  end
243
244
 
244
- if options[:foreign_keys] != false
245
- begin
246
- fk_list = foreign_key_list(table)
247
-
248
- if (sfk = options[:skipped_foreign_keys]) && (sfkt = sfk[table])
249
- fk_list.delete_if{|fk| sfkt.has_key?(fk[:columns])}
250
- end
245
+ if options[:foreign_keys] != false && supports_foreign_key_parsing?
246
+ fk_list = foreign_key_list(table)
247
+
248
+ if (sfk = options[:skipped_foreign_keys]) && (sfkt = sfk[table])
249
+ fk_list.delete_if{|fk| sfkt.has_key?(fk[:columns])}
250
+ end
251
251
 
252
- composite_fks, single_fks = fk_list.partition{|h| h[:columns].length > 1}
253
- fk_hash = {}
252
+ composite_fks, single_fks = fk_list.partition{|h| h[:columns].length > 1}
253
+ fk_hash = {}
254
254
 
255
- single_fks.each do |fk|
256
- column = fk.delete(:columns).first
257
- fk.delete(:name)
258
- fk_hash[column] = fk
259
- end
255
+ single_fks.each do |fk|
256
+ column = fk.delete(:columns).first
257
+ fk.delete(:name)
258
+ fk_hash[column] = fk
259
+ end
260
260
 
261
- s = s.map do |name, info|
262
- if fk_info = fk_hash[name]
263
- [name, fk_info.merge(info)]
264
- else
265
- [name, info]
266
- end
261
+ s = s.map do |name, info|
262
+ if fk_info = fk_hash[name]
263
+ [name, fk_info.merge(info)]
264
+ else
265
+ [name, info]
267
266
  end
268
- rescue Sequel::NotImplemented
269
- nil
270
267
  end
271
268
  end
272
269
 
@@ -281,11 +278,12 @@ END_MIG
281
278
  # Return a string that containing add_index/drop_index method calls for
282
279
  # creating the index migration.
283
280
  def dump_table_indexes(table, meth, options={})
284
- begin
281
+ if supports_index_parsing?
285
282
  indexes = indexes(table).sort_by{|k,v| k.to_s}
286
- rescue Sequel::NotImplemented
283
+ else
287
284
  return ''
288
285
  end
286
+
289
287
  im = method(:index_to_generator_opts)
290
288
  gen = create_table_generator do
291
289
  indexes.each{|iname, iopts| send(:index, iopts[:columns], im.call(table, iname, iopts, options))}
@@ -311,18 +309,7 @@ END_MIG
311
309
  # Sort the tables so that referenced tables are created before tables that
312
310
  # reference them, and then by name. If foreign keys are disabled, just sort by name.
313
311
  def sort_dumped_tables(tables, options={})
314
- sort_topologically = if options[:foreign_keys] != false
315
- begin
316
- foreign_key_list(:some_table_that_does_not_exist)
317
- true
318
- rescue Sequel::NotImplemented
319
- false
320
- rescue
321
- true
322
- end
323
- end
324
-
325
- if sort_topologically
312
+ if options[:foreign_keys] != false && supports_foreign_key_parsing?
326
313
  table_fks = {}
327
314
  tables.each{|t| table_fks[t] = foreign_key_list(t)}
328
315
  # Remove self referential foreign keys, not important when sorting.
@@ -484,5 +471,5 @@ END_MIG
484
471
  end
485
472
  end
486
473
 
487
- Database.register_extension(:schema_dumper){}
474
+ Database.register_extension(:schema_dumper, SchemaDumper)
488
475
  end
@@ -2,11 +2,20 @@
2
2
  # columns from a dataset. It's not part of Sequel core as it is rarely needed and has
3
3
  # some corner cases where it can't work correctly.
4
4
  #
5
- # To load the extension:
5
+ # You can load this extension into specific datasets:
6
6
  #
7
- # Sequel.extension :select_remove
7
+ # ds = DB[:table]
8
+ # ds.extension(:select_remove)
9
+ #
10
+ # Or you can load it into all of a database's datasets, which
11
+ # is probably the desired behavior if you are using this extension:
12
+ #
13
+ # DB.extension(:select_remove)
8
14
 
9
15
  module Sequel
16
+ module SelectRemove
17
+ end
18
+
10
19
  class Dataset
11
20
  # Remove columns from the list of selected columns. If any of the currently selected
12
21
  # columns use expressions/aliases, this will remove selected columns with the given
@@ -29,6 +38,7 @@ module Sequel
29
38
  #
30
39
  # There may be other cases where this method does not work correctly, use it with caution.
31
40
  def select_remove(*cols)
41
+ Sequel::Deprecation.deprecate('Loading the select_remove extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(SelectRemove)
32
42
  if (sel = @opts[:select]) && !sel.empty?
33
43
  select(*(columns.zip(sel).reject{|c, s| cols.include?(c)}.map{|c, s| s} - cols))
34
44
  else
@@ -37,6 +47,5 @@ module Sequel
37
47
  end
38
48
  end
39
49
 
40
- Database.register_extension(:select_remove){}
41
- Dataset.register_extension(:select_remove){}
50
+ Dataset.register_extension(:select_remove, SelectRemove)
42
51
  end
@@ -0,0 +1,117 @@
1
+ # This adds the following dataset methods:
2
+ #
3
+ # []= :: filter with the first argument, update with the second
4
+ # insert_multiple :: insert multiple rows at once
5
+ # set :: alias for update
6
+ # to_csv :: return string in csv format for the dataset
7
+ # db= :: change the dataset's database
8
+ # opts= :: change the dataset's opts
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.extension(:sequel_3_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_3_dataset_methods)
21
+
22
+ module Sequel
23
+ module Sequel3DatasetMethods
24
+ COMMA = Dataset::COMMA
25
+ # The database related to this dataset. This is the Database instance that
26
+ # will execute all of this dataset's queries.
27
+ attr_writer :db
28
+
29
+ # The hash of options for this dataset, keys are symbols.
30
+ attr_writer :opts
31
+
32
+ # Update all records matching the conditions with the values specified.
33
+ # Returns the number of rows affected.
34
+ #
35
+ # DB[:table][:id=>1] = {:id=>2} # UPDATE table SET id = 2 WHERE id = 1
36
+ # # => 1 # number of rows affected
37
+ def []=(conditions, values)
38
+ filter(conditions).update(values)
39
+ end
40
+
41
+ # Inserts multiple values. If a block is given it is invoked for each
42
+ # item in the given array before inserting it. See +multi_insert+ as
43
+ # a possibly faster version that may be able to insert multiple
44
+ # records in one SQL statement (if supported by the database).
45
+ # Returns an array of primary keys of inserted rows.
46
+ #
47
+ # DB[:table].insert_multiple([{:x=>1}, {:x=>2}])
48
+ # # => [4, 5]
49
+ # # INSERT INTO table (x) VALUES (1)
50
+ # # INSERT INTO table (x) VALUES (2)
51
+ #
52
+ # DB[:table].insert_multiple([{:x=>1}, {:x=>2}]){|row| row[:y] = row[:x] * 2; row }
53
+ # # => [6, 7]
54
+ # # INSERT INTO table (x, y) VALUES (1, 2)
55
+ # # INSERT INTO table (x, y) VALUES (2, 4)
56
+ def insert_multiple(array, &block)
57
+ if block
58
+ array.map{|i| insert(block.call(i))}
59
+ else
60
+ array.map{|i| insert(i)}
61
+ end
62
+ end
63
+
64
+ # Return a copy of the dataset with unqualified identifiers in the
65
+ # SELECT, WHERE, GROUP, HAVING, and ORDER clauses qualified by the
66
+ # given table. If no columns are currently selected, select all
67
+ # columns of the given table.
68
+ #
69
+ # DB[:items].filter(:id=>1).qualify_to(:i)
70
+ # # SELECT i.* FROM items WHERE (i.id = 1)
71
+ def qualify_to(table)
72
+ qualify(table)
73
+ end
74
+
75
+ # Qualify the dataset to its current first source. This is useful
76
+ # if you have unqualified identifiers in the query that all refer to
77
+ # the first source, and you want to join to another table which
78
+ # has columns with the same name as columns in the current dataset.
79
+ # See +qualify_to+.
80
+ #
81
+ # DB[:items].filter(:id=>1).qualify_to_first_source
82
+ # # SELECT items.* FROM items WHERE (items.id = 1)
83
+ def qualify_to_first_source
84
+ qualify
85
+ end
86
+
87
+ # Alias for update, but not aliased directly so subclasses
88
+ # don't have to override both methods.
89
+ def set(*args)
90
+ update(*args)
91
+ end
92
+
93
+ # Returns a string in CSV format containing the dataset records. By
94
+ # default the CSV representation includes the column titles in the
95
+ # first line. You can turn that off by passing false as the
96
+ # include_column_titles argument.
97
+ #
98
+ # This does not use a CSV library or handle quoting of values in
99
+ # any way. If any values in any of the rows could include commas or line
100
+ # endings, you shouldn't use this.
101
+ #
102
+ # puts DB[:table].to_csv # SELECT * FROM table
103
+ # # id,name
104
+ # # 1,Jim
105
+ # # 2,Bob
106
+ def to_csv(include_column_titles = true)
107
+ n = naked
108
+ cols = n.columns
109
+ csv = ''
110
+ csv << "#{cols.join(COMMA)}\r\n" if include_column_titles
111
+ n.each{|r| csv << "#{cols.collect{|c| r[c]}.join(COMMA)}\r\n"}
112
+ csv
113
+ end
114
+ end
115
+
116
+ Dataset.register_extension(:sequel_3_dataset_methods, Sequel3DatasetMethods)
117
+ end