sequel 3.47.0 → 3.48.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -5,14 +5,14 @@ Here's a brief description of the most common schema modification methods:
5
5
  == +create_table+
6
6
 
7
7
  +create_table+ is the most common schema modification method, and it's used for adding new tables
8
- to the schema. You provide it with the name of the table as a symbol, as well a block:
8
+ to the database. You provide it with the name of the table as a symbol, as well a block:
9
9
 
10
10
  create_table(:artists) do
11
11
  primary_key :id
12
12
  String :name
13
13
  end
14
14
 
15
- Not that if you want a primary key for the table, you need to specify it, Sequel does not create one
15
+ Note that if you want a primary key for the table, you need to specify it, Sequel does not create one
16
16
  by default.
17
17
 
18
18
  === Column types
@@ -521,11 +521,18 @@ ruby class, in which case it gets converted to an appropriate database type.
521
521
 
522
522
  === +set_column_allow_null+
523
523
 
524
- This changes the NULL or NOT NULL setting of a column:
524
+ This allows you to set the column as allowing NULL values:
525
525
 
526
526
  alter_table(:albums) do
527
- set_column_allow_null :artist_id, true # NULL
528
- set_column_allow_null :copies_sold, false # NOT NULL
527
+ set_column_allow_null :artist_id
528
+ end
529
+
530
+ === +set_column_not_null+
531
+
532
+ This allows you to set the column as not allowing NULL values:
533
+
534
+ alter_table(:albums) do
535
+ set_column_not_null :artist_id
529
536
  end
530
537
 
531
538
  == Other +Database+ schema modification methods
@@ -32,7 +32,7 @@ vulnerable to code execution.
32
32
  == SQL Injection
33
33
 
34
34
  The primary security concern in SQL database libraries is SQL injection.
35
- Because Sequel mostly promotes using ruby objects for SQL concepts instead
35
+ Because Sequel promotes using ruby objects for SQL concepts instead
36
36
  of raw SQL, it is less likely to be vulnerable to SQL injection.
37
37
  However, because Sequel still makes it easy to use raw SQL, misuse of the
38
38
  library can result in SQL injection in your application.
@@ -153,7 +153,7 @@ class methods also call down to the filter methods.
153
153
 
154
154
  ==== SQL Fragment passed to Dataset#update
155
155
 
156
- Similar to the filter methods, Sequel::Dataset#update (and alias Sequel::Dataset#set) also treat a
156
+ Similar to the filter methods, Sequel::Dataset#update also treats a
157
157
  string argument as raw SQL:
158
158
 
159
159
  DB[:table].update("column = 1")
@@ -15,8 +15,7 @@ support is to use the empty hash:
15
15
 
16
16
  DB=Sequel.connect('postgres://master_server/database', :servers=>{})
17
17
 
18
- In most cases, you are probably not going to want to use an empty hash,
19
- so you'll want to have entries in the hash. Keys in the server hash are
18
+ In most cases, you are probably not going to want to use an empty hash. Keys in the server hash are
20
19
  not restricted to type, but the general recommendation is to use a symbol
21
20
  unless you have special requirements. Values in the server hash should be
22
21
  either hashes or procs that return hashes. These hashes are merged into
@@ -86,13 +86,13 @@ So you can use Sequel's DSL everywhere you find it helpful, and fallback to lite
86
86
 
87
87
  == Translating SQL Expressions into Sequel
88
88
 
89
- The rest of this guide assumes you want to use Sequel's DSL to represent your query, that you know how to write the query in SQL, but you aren't sure how to write it in Sequel.
89
+ The rest of this guide assumes you want to use Sequel's DSL to represent your query, that you know how to write the query in SQL, but you aren't sure how to write it in Sequel's DSL.
90
90
 
91
91
  This section will describe how specific SQL expressions are handled in Sequel. The next section will discuss how to create queries by using method chaining on datasets.
92
92
 
93
93
  === <tt>Database#literal</tt>
94
94
 
95
- Before we get started, I think it's important to get familiar with the <tt>Database#literal</tt> method, which will return the SQL that will be used for a given expression:
95
+ It's important to get familiar with the <tt>Database#literal</tt> method, which will return the SQL that will be used for a given expression:
96
96
 
97
97
  DB.literal(1)
98
98
  # => "1"
@@ -101,7 +101,7 @@ Before we get started, I think it's important to get familiar with the <tt>Datab
101
101
  DB.literal('string')
102
102
  # => "'string'"
103
103
 
104
- I encourage you to just play around to see how different objects get literalized into SQL
104
+ Try playing around to see how different objects get literalized into SQL
105
105
 
106
106
  === Database Loggers
107
107
 
@@ -346,18 +346,15 @@ Sequel defines the & and | methods on most Sequel-specific expression objects to
346
346
  Sequel.expr(:column1=>1) | {:column2=>2} # (("column1" = 1) OR ("column2" = 2))
347
347
  (Sequel.function(:func) > 1) & :column3 # ((func() > 1) AND "column3")
348
348
 
349
- Note the use of parentheses in the last statement. If you omit them, you won't get what you expect:
349
+ Note the use of parentheses in the last statement. If you omit them, you won't get what you expect.
350
+ Because & has higher precedence than >
350
351
 
351
- Sequel.function(:func) > 1 & :column3 # (func() > 1)
352
+ Sequel.function(:func) > 1 & :column3
352
353
 
353
- This is because & has higher precedence than >, so it is parsed as:
354
+ is parsed as:
354
355
 
355
356
  Sequel.function(:func) > (1 & :column3)
356
357
 
357
- In this case, <tt>:column3.to_int</tt> returns an odd integer, so:
358
-
359
- 1 & :column3 # => 1
360
-
361
358
  You and also use the <tt>Sequel.&</tt> and <tt>Sequel.|</tt> methods:
362
359
 
363
360
  Sequel.&(:column1, :column2) # ("column1" AND "column2")
@@ -505,7 +502,7 @@ If the hash or array has multiple arguments, multiple WHEN clauses are used:
505
502
  Sequel.case({:c=>1, :d=>2}, 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
506
503
  Sequel.case([[:c, 1], [:d, 2]], 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
507
504
 
508
- If you provide a 2nd argument to CASE, it goes between CASE and WHEN:
505
+ If you provide a 3rd argument to <tt>Sequel.case</tt>, it goes between CASE and WHEN:
509
506
 
510
507
  Sequel.case({2=>1, 3=>5}, 0, :column) # (CASE column WHEN 2 THEN 1 WHEN 3 THEN 5 ELSE 0 END)
511
508
 
@@ -538,9 +535,9 @@ If you want to select from multiple FROM tables, use multiple arguments:
538
535
 
539
536
  DB[:albums, :artists] # SELECT * FROM albums, artists
540
537
 
541
- If you don't want to select from any FROM tables, use no arguments:
538
+ If you don't want to select from any FROM tables, just call dataset:
542
539
 
543
- DB[] # SELECT *
540
+ DB.dataset # SELECT *
544
541
 
545
542
  === Chaining Methods
546
543
 
@@ -6,8 +6,6 @@ Whether or not you use Sequel in your application, you are usually going to want
6
6
 
7
7
  These run each test in its own transaction, the recommended way to test.
8
8
 
9
- Make sure you are using Sequel 3.29.0 or above when using these examples, as older versions don't support the <tt>:rollback=>:always</tt> option.
10
-
11
9
  === RSpec 1
12
10
 
13
11
  class Spec::Example::ExampleGroup
@@ -103,7 +101,7 @@ Use Sequel.transaction with an array of databases:
103
101
 
104
102
  In some cases, it is not possible to use transactions. For example, if you are testing a web application that is running in a separate process, you don't have access to that process's database connections, so you can't run your examples in transactions. In that case, the best way to handle things is to cleanup after each test by deleting or truncating the database tables used in the test.
105
103
 
106
- The order in which you delete/truncate the tables is important if you are using referential integrity in your database (which you probably should be doing). If you are using referential integrity, you need to make sure to delete in tables referencing other tables before the tables that are being referenced. For example, if you have an +albums+ table with an +artist_id+ field referencing the +artists+ table, you want to delete/truncate the +albums+ table before the +artists+ table. Note that if you have cyclic references in your database, you will probably need to write your own custom cleaning code.
104
+ The order in which you delete/truncate the tables is important if you are using referential integrity in your database (which you should be doing). If you are using referential integrity, you need to make sure to delete in tables referencing other tables before the tables that are being referenced. For example, if you have an +albums+ table with an +artist_id+ field referencing the +artists+ table, you want to delete/truncate the +albums+ table before the +artists+ table. Note that if you have cyclic references in your database, you will probably need to write your own custom cleaning code.
107
105
 
108
106
  === RSpec
109
107
 
@@ -138,16 +136,22 @@ The +spec+ rake task (which is also the default rake task) runs Sequel's core an
138
136
 
139
137
  The +spec_plugin+ rake task runs the specs for the plugins and extensions that ship with Sequel. These also use a mocked database connection, and operate very similarly to the general Sequel core and model specs.
140
138
 
139
+ == rake spec_bin
140
+
141
+ The +spec_bin+ rake task runs the specs for bin/sequel. These use an SQLite3 database, and require either the sqlite3 (non-JRuby) or jdbc-sqlite3 (JRuby) gem.
142
+
141
143
  == rake spec_<i>adapter</i> (e.g. rake spec_postgres)
142
144
 
143
145
  The <tt>spec_<i>adapter</i></tt> specs run against a real database connection with nothing mocked, and test for correct results. They are slower than the standard specs, but they will catch errors that are mocked out by the default specs, as well as show issues that only occur on a certain database, adapter, or a combination of the two.
144
146
 
145
- These specs are broken down into two parts. For each database, there are specific specs that only apply to that database, and these are called the adapter specs. There are also shared specs that apply to all (or almost all) databases, these are called the integration specs.
147
+ These specs are broken down into two parts. For each database, there are specific specs that only apply to that database, and these are called the adapter specs. There are also shared specs that apply to all (or almost all) databases, these are called the integration specs. For database types that don't have specific adapter tests, you can use rake spec_integration to just run the shared integration tests.
146
148
 
147
149
  == Environment variables
148
150
 
149
151
  Sequel often uses environment variables when testing to specify either the database to be tested or specify how testing should be done. You can also specify the databases to test by copying spec/spec_config.rb.example to spec/spec_config.rb and modifying it. See that file for details. It may be necessary to use spec_config.rb as opposed to an environment variable if your database connection cannot be specified by a connection string.
150
152
 
153
+ Sequel does not create test databases automatically, except for file-based databases such as SQLite/H2/HSQLDB/Derby. It's up to the user to create the test databases manually and give Sequel a valid connection string in an environment variable (or setup the connection object in spec_config.rb).
154
+
151
155
  === Connection Strings
152
156
 
153
157
  The following environment variables specify Database connection URL strings:
@@ -27,7 +27,6 @@ If the block raises a Sequel::Rollback exception, the transaction is rolled back
27
27
 
28
28
  If any other exception is raised, the transaction is rolled back, and the exception is raised outside the block:
29
29
 
30
- # ArgumentError raised
31
30
  DB.transaction do # BEGIN
32
31
  raise ArgumentError
33
32
  end # ROLLBACK
@@ -45,6 +44,7 @@ If you always want to rollback (useful for testing), use the <tt>:rollback => :a
45
44
  DB.transaction(:rollback => :always) do # BEGIN
46
45
  DB[:foo].insert(1) # INSERT
47
46
  end # ROLLBACK
47
+ # no exception raised
48
48
 
49
49
  If you want to check whether you are currently in a transaction, use the Database#in_transaction? method:
50
50
 
@@ -129,7 +129,7 @@ or roll the prepared transaction back:
129
129
 
130
130
  == Transaction Isolation Levels
131
131
 
132
- The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, and SERIALIZABLE. Not all databases implement the levels as specified in the standard (or implement the levels at all), but on PostgreSQL, MySQL, and Microsoft SQL Server, you can specify which transaction isolation level you want to use via the :isolation option to <tt>Database#transaction</tt>. The isolation level is specified as one of the following symbols: :uncommitted, :committed, :repeatable, and :serializable. Using this option make Sequel use the correct transaction isolation syntax for your database:
132
+ The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, and SERIALIZABLE. Not all databases implement the levels as specified in the standard (or implement the levels at all), but on most databases, you can specify which transaction isolation level you want to use via the :isolation option to <tt>Database#transaction</tt>. The isolation level is specified as one of the following symbols: :uncommitted, :committed, :repeatable, and :serializable. Using this option make Sequel use the correct transaction isolation syntax for your database:
133
133
 
134
134
  DB.transaction(:isolation => :serializable) do # BEGIN
135
135
  # SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
@@ -32,7 +32,7 @@ to ensure that all values have at least two characters.
32
32
  Unfortunately, sometimes there are situations where that is not possible. For
33
33
  example, if you are using MySQL and don't have control over the database configuration,
34
34
  it's possible that if you attempt to insert a string with 300 characters into a
35
- varchar(255) field, that MySQL will just silently truncate it for you, instead of
35
+ varchar(255) field, then MySQL may just silently truncate it for you, instead of
36
36
  raising an error. In that case, it may be necessary to use a model validation
37
37
  to enforce the database integrity.
38
38
 
@@ -172,16 +172,22 @@ This is probably the most commonly used helper method, which checks if the speci
172
172
 
173
173
  class Album < Sequel::Model
174
174
  def validate
175
+ super
175
176
  validates_presence [:name, :website, :debut_album]
176
177
  end
177
178
  end
178
179
 
180
+ === +validates_not_null+
181
+
182
+ This is similar to +validates_presence+, but only checks for NULL/nil values, allowing other blank objects such as empty strings or strings with just whitespace.
183
+
179
184
  === +validates_format+
180
185
 
181
186
  +validates_format+ is used to ensure that the string value of the specified attributes matches the specified regular expression. It's useful for checking that fields such as email addresses, URLs, UPC codes, ISBN codes, and the like, are in a specific format. It can also be used to validate that only certain characters are used in the string.
182
187
 
183
188
  class Album < Sequel::Model
184
189
  def validate
190
+ super
185
191
  validates_format /\A\d\d\d-\d-\d{7}-\d-\d\z/, :isbn
186
192
  validates_format /\a[0-9a-zA-Z:' ]+\z/, :name
187
193
  end
@@ -194,6 +200,7 @@ These methods all deal with ensuring that the length of the specified attribute
194
200
 
195
201
  class Album < Sequel::Model
196
202
  def validate
203
+ super
197
204
  validates_exact_length 17, :isbn
198
205
  validates_min_length 3, :name
199
206
  validates_max_length 100, :name
@@ -207,6 +214,7 @@ These methods check that the specified attributes can be valid integers or valid
207
214
 
208
215
  class Album < Sequel::Model
209
216
  def validate
217
+ super
210
218
  validates_integer :copies_sold
211
219
  validates_numeric :replaygain
212
220
  end
@@ -224,35 +232,33 @@ These methods check that the specified attributes can be valid integers or valid
224
232
 
225
233
  === +validates_type+
226
234
 
227
- +validates_type+ checks that the specified attributes are instances of the class specified in the first argument. The class can be specified as the class itself, or as a string or symbol with the class name:
235
+ +validates_type+ checks that the specified attributes are instances of the class specified in the first argument. The class can be specified as the class itself, or as a string or symbol with the class name, or as a an array of classes.
228
236
 
229
237
  class Album < Sequel::Model
230
238
  def validate
239
+ super
231
240
  validates_type String, [:name, :website]
232
241
  validates_type :Artist, :artist
242
+ validates_type [String, Integer], :foo
233
243
  end
234
244
  end
235
245
 
236
- === +validates_not_string+
237
-
238
- +validates_not_string+ is a special validation designed to be used with the <tt>raise_on_typecast_failure = false</tt> setting. By default, Sequel raises errors when typecasting fails, immediately when you try to set the value on the object:
246
+ === +validates_schema_types+
239
247
 
240
- album = Album.new
241
- album.copies_sold = 'banana' # raises Sequel::InvalidValue
242
-
243
- The <tt>raise_on_typecast_failure = false</tt> setting tells Sequel to attempt to typecast values, but to silently ignore any errors raised:
248
+ +validates_schema_types+ uses the database metadata for the model's table to determine which ruby type(s) should be used for the given database type, and calls +validates_type+ with that ruby type. It's designed to be used with the <tt>raise_on_typecast_failure = false</tt> setting (the default starting in Sequel 4). <tt>raise_on_typecast_failure = false</tt, Sequel attempts to typecast values, but silently ignores any errors raised:
244
249
 
245
250
  Album.raise_on_typecast_failure = false
246
251
  album = Album.new
247
252
  album.copies_sold = 'banana'
248
253
  album.copies_sold # => 'banana'
249
254
 
250
- +validates_not_string+ is designed to be used in web applications where all user input comes in as strings. When the <tt>raise_on_typecast_failure = false</tt> setting is used in such an application, you can call +validates_not_string+ with all non-string columns. If any of those columns has a string value, it's because the column was set and Sequel was not able to typecast it correctly, which means it probably isn't valid. For example, let's say that you want to check that a couple of columns contain valid dates:
255
+ When <tt>raise_on_typecast_failure = false</tt>, you can call +validates_schema_types+ with all columns. If any of those columns has a value that doesn't match the type that Sequel expects, it's probably because the column was set and Sequel was not able to typecast it correctly, which means it probably isn't valid. For example, let's say that you want to check that a couple of columns contain valid dates:
251
256
 
252
257
  class Album < Sequel::Model
253
258
  self.raise_on_typecast_failure = false
254
259
  def validate
255
- validates_not_string [:release_date, :record_date]
260
+ super
261
+ validates_schema_types [:release_date, :record_date]
256
262
  end
257
263
  end
258
264
 
@@ -264,7 +270,7 @@ The <tt>raise_on_typecast_failure = false</tt> setting tells Sequel to attempt t
264
270
  album.valid? # => false
265
271
  album.errors # => {:release_date=>["is not a valid date"]}
266
272
 
267
- For web applications, you usually want the <tt>raise_on_typecast_failure = false</tt> setting, so that you can accept all of the input without raising an error, and then present the user with all error messages. Without the setting, if the user submits any invalid data, Sequel will immediately raise an error. +validates_not_string+ is helpful because it allows you to check for typecasting errors on non-string columns, and provides a good default error message stating that the attribute is not of the expected type.
273
+ For web applications, you usually want the <tt>raise_on_typecast_failure = false</tt> setting, so that you can accept all of the input without raising an error, and then present the user with all error messages. Without the setting, if the user submits any invalid data, Sequel will immediately raise an error. +validates_schema_types+ is helpful because it allows you to check for typecasting errors on columns, and provides a good default error message stating that the attribute is not of the expected type.
268
274
 
269
275
  === +validates_unique+
270
276
 
@@ -301,10 +307,11 @@ All +validation_helpers+ methods except +validates_unique+ accept the following
301
307
 
302
308
  === <tt>:message</tt>
303
309
 
304
- The most commonly used option, used to override the default validation message. Can be either a string or a proc. If a string, it is used directly. If a proc, the proc is called and should return a string. If the validation method takes an argument before the array of attributes, that argument is passed as an argument to the proc. The exception is the +validates_not_string+ method, which doesn't take an argument, but passes the schema type symbol as the argument to the proc.
310
+ The most commonly used option, used to override the default validation message. Can be either a string or a proc. If a string, it is used directly. If a proc, the proc is called and should return a string. If the validation method takes an argument before the array of attributes, that argument is passed as an argument to the proc. The exception is the +validates_not_string+ method, which doesn't take an argument, but passes the schema type symbol as the argument to the proc.
305
311
 
306
312
  class Album < Sequel::Model
307
313
  def validate
314
+ super
308
315
  validates_presence :copies_sold, :message=>'was not given'
309
316
  validates_min_length 3, :name, :message=>proc{|s| "should be more than #{s} characters"}
310
317
  end
@@ -316,6 +323,7 @@ The <tt>:allow_nil</tt> option skips the validation if the attribute value is ni
316
323
 
317
324
  class Album < Sequel::Model
318
325
  def validate
326
+ super
319
327
  validates_presence :copies_sold
320
328
  validates_integer :copies_sold, :allow_nil=>true
321
329
  end
@@ -329,6 +337,7 @@ The <tt>:allow_blank</tt> is similar to the <tt>:allow_nil</tt> option, but inst
329
337
 
330
338
  class Album < Sequel::Model
331
339
  def validate
340
+ super
332
341
  validates_format /\Ahttps?:\/\//, :website, :allow_blank=>true
333
342
  end
334
343
  end
@@ -386,8 +395,9 @@ These are the default error messages for all of the helper methods in +validatio
386
395
  :length_range :: is too short or too long
387
396
  :max_length :: is longer than #{arg} characters
388
397
  :min_length :: is shorter than #{arg} characters
389
- :not_string :: is not a valid #{schema_type}
398
+ :not_null :: is not present
390
399
  :numeric :: is not a number
400
+ :schema_types :: is not a valid #{schema_type}
391
401
  :type :: is not a #{arg}
392
402
  :presence :: is not present
393
403
  :unique :: is already taken
@@ -404,6 +414,8 @@ It's easy to modify the default options used by +validation_helpers+. All of th
404
414
 
405
415
  This updates the default messages that will be used for the presence, includes, max_length, and format validations, and sets the default value of the <tt>:allow_nil</tt> option to true for the includes, max_length, and format validations.
406
416
 
417
+ You can also override <tt>Sequel::Model#default_validation_helpers_options</tt> private method to override these settings on a per-model or even per-instance basis.
418
+
407
419
  == Custom Validations
408
420
 
409
421
  Just as the first validation example showed, you aren't limited to the validation methods defined by +validation_helpers+. Inside the +validate+ method, you can add your own validations by adding to the instance's errors using <tt>errors.add</tt> whenever an attribute is not valid:
@@ -442,7 +454,7 @@ Let's say you want to add some default validations that apply to all of your mod
442
454
 
443
455
  def validate
444
456
  super
445
- validates_format(/\A[^\x00-\x08\x0e-\x1f\x7f\x81\x8d\x8f\x90\x9d]*\z/,
457
+ validates_format(/\A[^\x00-\x08\x0e-\x1f\x7f\x81\x8d\x8f\x90\x9d]*\z/n,
446
458
  model.string_columns,
447
459
  :message=>"contains invalid characters")
448
460
  end
@@ -496,6 +508,17 @@ Here, you don't care about validating the release date if there were validation
496
508
 
497
509
  album.errors.count # => 1
498
510
 
499
- == +validation_class_methods+
511
+ == Other Validation Plugins
512
+
513
+ === +constraint_validations+
514
+
515
+ Sequel ships with a +constraint_validations+ plugin and extension, that allows you to setup constraints when creating your database tables, and have Model validations automatically created that mirror those constraints.
516
+
517
+ === +auto_validations+
518
+
519
+ Autovalidations uses the not null and type information obtained from parsing the database schema, and the unique index information from parsing the database's index information, and automatically setting up not_null, schema_types, and unique validations. If you don't require customizing validation messages on a per-column basis, it can DRY up a lot of validation code.
520
+
521
+ === +validation_class_methods+
522
+
523
+ Sequel ships with the +validation_class_methods+ plugin, which uses class methods instead of instance methods to define validations. It exists mostly for legacy compatibility, but it is still supported.
500
524
 
501
- Sequel actually ships with two validation plugins. The recommended one that this guide focused on is the +validation_helpers+ plugin. However, Sequel also ships with the +validation_class_methods+ plugin, which uses class methods instead of instance methods to define validations. It exists mostly for legacy compatibility, but it is still supported.
@@ -9,7 +9,7 @@ many Sequel::Dataset methods that take virtual row blocks.
9
9
 
10
10
  Virtual Rows were created to work around the issue that some parts of
11
11
  Sequel's standard DSL could not be used on ruby 1.9. For example, the
12
- following Sequel code works on ruby 1.8, but not ruby 1.9:
12
+ following Sequel code historically worked on ruby 1.8, but not ruby 1.9:
13
13
 
14
14
  dataset.where(:a > :b[:c])
15
15
  # WHERE a > b(c)
@@ -243,7 +243,7 @@ doesn't look as nice:
243
243
  == Returning multiple values
244
244
 
245
245
  It's common when using select and order virtual row blocks to want to
246
- return multiple values. If you want to do that, you just need to return a single
246
+ return multiple values. If you want to do that, you just need to return an
247
247
  array:
248
248
 
249
249
  ds.select{|o| [o.column1, o.sum(o.column2).as(o.sum)]}
@@ -8,25 +8,6 @@ module Sequel
8
8
 
9
9
  set_adapter_scheme :ado
10
10
 
11
- def initialize(opts)
12
- super
13
- case @opts[:conn_string]
14
- when /Microsoft\.(Jet|ACE)\.OLEDB/io
15
- Sequel.ts_require 'adapters/ado/access'
16
- extend Sequel::ADO::Access::DatabaseMethods
17
- @dataset_class = ADO::Access::Dataset
18
- else
19
- @opts[:driver] ||= 'SQL Server'
20
- case @opts[:driver]
21
- when 'SQL Server'
22
- Sequel.ts_require 'adapters/ado/mssql'
23
- extend Sequel::ADO::MSSQL::DatabaseMethods
24
- @dataset_class = ADO::MSSQL::Dataset
25
- set_mssql_unicode_strings
26
- end
27
- end
28
- end
29
-
30
11
  # In addition to the usual database options,
31
12
  # the following options have an effect:
32
13
  #
@@ -59,6 +40,8 @@ module Sequel
59
40
 
60
41
  def disconnect_connection(conn)
61
42
  conn.Close
43
+ rescue WIN32OLERuntimeError
44
+ nil
62
45
  end
63
46
 
64
47
  # Just execute so it doesn't attempt to return the number of rows modified.
@@ -98,10 +81,32 @@ module Sequel
98
81
  end
99
82
  nil
100
83
  end
101
- alias do execute
84
+ def do(*a, &block)
85
+ Sequel::Deprecation.deprecate('Database#do', 'Please use Database#execute')
86
+ execute(*a, &block)
87
+ end
102
88
 
103
89
  private
104
90
 
91
+ def adapter_initialize
92
+ case @opts[:conn_string]
93
+ when /Microsoft\.(Jet|ACE)\.OLEDB/io
94
+ Sequel.require 'adapters/ado/access'
95
+ extend Sequel::ADO::Access::DatabaseMethods
96
+ self.dataset_class = ADO::Access::Dataset
97
+ else
98
+ @opts[:driver] ||= 'SQL Server'
99
+ case @opts[:driver]
100
+ when 'SQL Server'
101
+ Sequel.require 'adapters/ado/mssql'
102
+ extend Sequel::ADO::MSSQL::DatabaseMethods
103
+ self.dataset_class = ADO::MSSQL::Dataset
104
+ set_mssql_unicode_strings
105
+ end
106
+ end
107
+ super
108
+ end
109
+
105
110
  # The ADO adapter's default provider doesn't support transactions, since it
106
111
  # creates a new native connection for each query. So Sequel only attempts
107
112
  # to use transactions if an explicit :provider is given.