viking-sequel 3.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (237) hide show
  1. data/CHANGELOG +3134 -0
  2. data/COPYING +19 -0
  3. data/README.rdoc +723 -0
  4. data/Rakefile +193 -0
  5. data/bin/sequel +196 -0
  6. data/doc/advanced_associations.rdoc +644 -0
  7. data/doc/cheat_sheet.rdoc +218 -0
  8. data/doc/dataset_basics.rdoc +106 -0
  9. data/doc/dataset_filtering.rdoc +158 -0
  10. data/doc/opening_databases.rdoc +296 -0
  11. data/doc/prepared_statements.rdoc +104 -0
  12. data/doc/reflection.rdoc +84 -0
  13. data/doc/release_notes/1.0.txt +38 -0
  14. data/doc/release_notes/1.1.txt +143 -0
  15. data/doc/release_notes/1.3.txt +101 -0
  16. data/doc/release_notes/1.4.0.txt +53 -0
  17. data/doc/release_notes/1.5.0.txt +155 -0
  18. data/doc/release_notes/2.0.0.txt +298 -0
  19. data/doc/release_notes/2.1.0.txt +271 -0
  20. data/doc/release_notes/2.10.0.txt +328 -0
  21. data/doc/release_notes/2.11.0.txt +215 -0
  22. data/doc/release_notes/2.12.0.txt +534 -0
  23. data/doc/release_notes/2.2.0.txt +253 -0
  24. data/doc/release_notes/2.3.0.txt +88 -0
  25. data/doc/release_notes/2.4.0.txt +106 -0
  26. data/doc/release_notes/2.5.0.txt +137 -0
  27. data/doc/release_notes/2.6.0.txt +157 -0
  28. data/doc/release_notes/2.7.0.txt +166 -0
  29. data/doc/release_notes/2.8.0.txt +171 -0
  30. data/doc/release_notes/2.9.0.txt +97 -0
  31. data/doc/release_notes/3.0.0.txt +221 -0
  32. data/doc/release_notes/3.1.0.txt +406 -0
  33. data/doc/release_notes/3.10.0.txt +286 -0
  34. data/doc/release_notes/3.2.0.txt +268 -0
  35. data/doc/release_notes/3.3.0.txt +192 -0
  36. data/doc/release_notes/3.4.0.txt +325 -0
  37. data/doc/release_notes/3.5.0.txt +510 -0
  38. data/doc/release_notes/3.6.0.txt +366 -0
  39. data/doc/release_notes/3.7.0.txt +179 -0
  40. data/doc/release_notes/3.8.0.txt +151 -0
  41. data/doc/release_notes/3.9.0.txt +233 -0
  42. data/doc/schema.rdoc +36 -0
  43. data/doc/sharding.rdoc +113 -0
  44. data/doc/virtual_rows.rdoc +205 -0
  45. data/lib/sequel.rb +1 -0
  46. data/lib/sequel/adapters/ado.rb +90 -0
  47. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  48. data/lib/sequel/adapters/amalgalite.rb +176 -0
  49. data/lib/sequel/adapters/db2.rb +139 -0
  50. data/lib/sequel/adapters/dbi.rb +113 -0
  51. data/lib/sequel/adapters/do.rb +188 -0
  52. data/lib/sequel/adapters/do/mysql.rb +49 -0
  53. data/lib/sequel/adapters/do/postgres.rb +91 -0
  54. data/lib/sequel/adapters/do/sqlite.rb +40 -0
  55. data/lib/sequel/adapters/firebird.rb +283 -0
  56. data/lib/sequel/adapters/informix.rb +77 -0
  57. data/lib/sequel/adapters/jdbc.rb +587 -0
  58. data/lib/sequel/adapters/jdbc/as400.rb +58 -0
  59. data/lib/sequel/adapters/jdbc/h2.rb +133 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
  61. data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
  62. data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
  64. data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
  65. data/lib/sequel/adapters/mysql.rb +421 -0
  66. data/lib/sequel/adapters/odbc.rb +143 -0
  67. data/lib/sequel/adapters/odbc/mssql.rb +42 -0
  68. data/lib/sequel/adapters/openbase.rb +64 -0
  69. data/lib/sequel/adapters/oracle.rb +131 -0
  70. data/lib/sequel/adapters/postgres.rb +504 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +490 -0
  72. data/lib/sequel/adapters/shared/mysql.rb +498 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +195 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +830 -0
  75. data/lib/sequel/adapters/shared/progress.rb +44 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +389 -0
  77. data/lib/sequel/adapters/sqlite.rb +224 -0
  78. data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
  79. data/lib/sequel/connection_pool.rb +99 -0
  80. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  81. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  82. data/lib/sequel/connection_pool/single.rb +29 -0
  83. data/lib/sequel/connection_pool/threaded.rb +150 -0
  84. data/lib/sequel/core.rb +293 -0
  85. data/lib/sequel/core_sql.rb +241 -0
  86. data/lib/sequel/database.rb +1079 -0
  87. data/lib/sequel/database/schema_generator.rb +327 -0
  88. data/lib/sequel/database/schema_methods.rb +203 -0
  89. data/lib/sequel/database/schema_sql.rb +320 -0
  90. data/lib/sequel/dataset.rb +32 -0
  91. data/lib/sequel/dataset/actions.rb +441 -0
  92. data/lib/sequel/dataset/features.rb +86 -0
  93. data/lib/sequel/dataset/graph.rb +254 -0
  94. data/lib/sequel/dataset/misc.rb +119 -0
  95. data/lib/sequel/dataset/mutation.rb +64 -0
  96. data/lib/sequel/dataset/prepared_statements.rb +227 -0
  97. data/lib/sequel/dataset/query.rb +709 -0
  98. data/lib/sequel/dataset/sql.rb +996 -0
  99. data/lib/sequel/exceptions.rb +51 -0
  100. data/lib/sequel/extensions/blank.rb +43 -0
  101. data/lib/sequel/extensions/inflector.rb +242 -0
  102. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  103. data/lib/sequel/extensions/migration.rb +239 -0
  104. data/lib/sequel/extensions/named_timezones.rb +61 -0
  105. data/lib/sequel/extensions/pagination.rb +100 -0
  106. data/lib/sequel/extensions/pretty_table.rb +82 -0
  107. data/lib/sequel/extensions/query.rb +52 -0
  108. data/lib/sequel/extensions/schema_dumper.rb +271 -0
  109. data/lib/sequel/extensions/sql_expr.rb +122 -0
  110. data/lib/sequel/extensions/string_date_time.rb +46 -0
  111. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  112. data/lib/sequel/metaprogramming.rb +9 -0
  113. data/lib/sequel/model.rb +120 -0
  114. data/lib/sequel/model/associations.rb +1514 -0
  115. data/lib/sequel/model/base.rb +1069 -0
  116. data/lib/sequel/model/default_inflections.rb +45 -0
  117. data/lib/sequel/model/errors.rb +39 -0
  118. data/lib/sequel/model/exceptions.rb +21 -0
  119. data/lib/sequel/model/inflections.rb +162 -0
  120. data/lib/sequel/model/plugins.rb +70 -0
  121. data/lib/sequel/plugins/active_model.rb +59 -0
  122. data/lib/sequel/plugins/association_dependencies.rb +103 -0
  123. data/lib/sequel/plugins/association_proxies.rb +41 -0
  124. data/lib/sequel/plugins/boolean_readers.rb +53 -0
  125. data/lib/sequel/plugins/caching.rb +141 -0
  126. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  127. data/lib/sequel/plugins/composition.rb +138 -0
  128. data/lib/sequel/plugins/force_encoding.rb +72 -0
  129. data/lib/sequel/plugins/hook_class_methods.rb +126 -0
  130. data/lib/sequel/plugins/identity_map.rb +116 -0
  131. data/lib/sequel/plugins/instance_filters.rb +98 -0
  132. data/lib/sequel/plugins/instance_hooks.rb +57 -0
  133. data/lib/sequel/plugins/lazy_attributes.rb +77 -0
  134. data/lib/sequel/plugins/many_through_many.rb +208 -0
  135. data/lib/sequel/plugins/nested_attributes.rb +206 -0
  136. data/lib/sequel/plugins/optimistic_locking.rb +81 -0
  137. data/lib/sequel/plugins/rcte_tree.rb +281 -0
  138. data/lib/sequel/plugins/schema.rb +66 -0
  139. data/lib/sequel/plugins/serialization.rb +166 -0
  140. data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
  141. data/lib/sequel/plugins/subclasses.rb +45 -0
  142. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  143. data/lib/sequel/plugins/timestamps.rb +87 -0
  144. data/lib/sequel/plugins/touch.rb +118 -0
  145. data/lib/sequel/plugins/typecast_on_load.rb +72 -0
  146. data/lib/sequel/plugins/validation_class_methods.rb +405 -0
  147. data/lib/sequel/plugins/validation_helpers.rb +223 -0
  148. data/lib/sequel/sql.rb +1020 -0
  149. data/lib/sequel/timezones.rb +161 -0
  150. data/lib/sequel/version.rb +12 -0
  151. data/lib/sequel_core.rb +1 -0
  152. data/lib/sequel_model.rb +1 -0
  153. data/spec/adapters/firebird_spec.rb +407 -0
  154. data/spec/adapters/informix_spec.rb +97 -0
  155. data/spec/adapters/mssql_spec.rb +403 -0
  156. data/spec/adapters/mysql_spec.rb +1019 -0
  157. data/spec/adapters/oracle_spec.rb +286 -0
  158. data/spec/adapters/postgres_spec.rb +969 -0
  159. data/spec/adapters/spec_helper.rb +51 -0
  160. data/spec/adapters/sqlite_spec.rb +432 -0
  161. data/spec/core/connection_pool_spec.rb +808 -0
  162. data/spec/core/core_sql_spec.rb +417 -0
  163. data/spec/core/database_spec.rb +1662 -0
  164. data/spec/core/dataset_spec.rb +3827 -0
  165. data/spec/core/expression_filters_spec.rb +595 -0
  166. data/spec/core/object_graph_spec.rb +296 -0
  167. data/spec/core/schema_generator_spec.rb +159 -0
  168. data/spec/core/schema_spec.rb +830 -0
  169. data/spec/core/spec_helper.rb +56 -0
  170. data/spec/core/version_spec.rb +7 -0
  171. data/spec/extensions/active_model_spec.rb +76 -0
  172. data/spec/extensions/association_dependencies_spec.rb +127 -0
  173. data/spec/extensions/association_proxies_spec.rb +50 -0
  174. data/spec/extensions/blank_spec.rb +67 -0
  175. data/spec/extensions/boolean_readers_spec.rb +92 -0
  176. data/spec/extensions/caching_spec.rb +250 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  178. data/spec/extensions/composition_spec.rb +194 -0
  179. data/spec/extensions/force_encoding_spec.rb +117 -0
  180. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  181. data/spec/extensions/identity_map_spec.rb +202 -0
  182. data/spec/extensions/inflector_spec.rb +181 -0
  183. data/spec/extensions/instance_filters_spec.rb +55 -0
  184. data/spec/extensions/instance_hooks_spec.rb +133 -0
  185. data/spec/extensions/lazy_attributes_spec.rb +153 -0
  186. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  187. data/spec/extensions/many_through_many_spec.rb +884 -0
  188. data/spec/extensions/migration_spec.rb +332 -0
  189. data/spec/extensions/named_timezones_spec.rb +72 -0
  190. data/spec/extensions/nested_attributes_spec.rb +396 -0
  191. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  192. data/spec/extensions/pagination_spec.rb +99 -0
  193. data/spec/extensions/pretty_table_spec.rb +91 -0
  194. data/spec/extensions/query_spec.rb +85 -0
  195. data/spec/extensions/rcte_tree_spec.rb +205 -0
  196. data/spec/extensions/schema_dumper_spec.rb +357 -0
  197. data/spec/extensions/schema_spec.rb +127 -0
  198. data/spec/extensions/serialization_spec.rb +209 -0
  199. data/spec/extensions/single_table_inheritance_spec.rb +96 -0
  200. data/spec/extensions/spec_helper.rb +91 -0
  201. data/spec/extensions/sql_expr_spec.rb +89 -0
  202. data/spec/extensions/string_date_time_spec.rb +93 -0
  203. data/spec/extensions/subclasses_spec.rb +52 -0
  204. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  205. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  206. data/spec/extensions/timestamps_spec.rb +150 -0
  207. data/spec/extensions/touch_spec.rb +155 -0
  208. data/spec/extensions/typecast_on_load_spec.rb +69 -0
  209. data/spec/extensions/validation_class_methods_spec.rb +984 -0
  210. data/spec/extensions/validation_helpers_spec.rb +438 -0
  211. data/spec/integration/associations_test.rb +281 -0
  212. data/spec/integration/database_test.rb +26 -0
  213. data/spec/integration/dataset_test.rb +963 -0
  214. data/spec/integration/eager_loader_test.rb +734 -0
  215. data/spec/integration/model_test.rb +130 -0
  216. data/spec/integration/plugin_test.rb +814 -0
  217. data/spec/integration/prepared_statement_test.rb +213 -0
  218. data/spec/integration/schema_test.rb +361 -0
  219. data/spec/integration/spec_helper.rb +73 -0
  220. data/spec/integration/timezone_test.rb +55 -0
  221. data/spec/integration/transaction_test.rb +122 -0
  222. data/spec/integration/type_test.rb +96 -0
  223. data/spec/model/association_reflection_spec.rb +175 -0
  224. data/spec/model/associations_spec.rb +2633 -0
  225. data/spec/model/base_spec.rb +418 -0
  226. data/spec/model/dataset_methods_spec.rb +78 -0
  227. data/spec/model/eager_loading_spec.rb +1391 -0
  228. data/spec/model/hooks_spec.rb +240 -0
  229. data/spec/model/inflector_spec.rb +26 -0
  230. data/spec/model/model_spec.rb +593 -0
  231. data/spec/model/plugins_spec.rb +236 -0
  232. data/spec/model/record_spec.rb +1500 -0
  233. data/spec/model/spec_helper.rb +97 -0
  234. data/spec/model/validations_spec.rb +153 -0
  235. data/spec/rcov.opts +6 -0
  236. data/spec/spec_config.rb.example +10 -0
  237. metadata +346 -0
@@ -0,0 +1,151 @@
1
+ New Features
2
+ ------------
3
+
4
+ * Dataset#each_server was added, allowing you to run the same query
5
+ (most likely insert/update/delete) on all shards. This is useful
6
+ if you have a sharded database but have lookup tables that should
7
+ be identical on all shards. It works by yielding copies of the
8
+ current dataset that are tied to each server/shard:
9
+
10
+ DB[:table].filter(:id=>1).each_server do |ds|
11
+ ds.update(:name=>'foo')
12
+ end
13
+
14
+ * Database#each_server was added, allowing you to run schema
15
+ modification methods on all shards. It works by yielding a
16
+ new Sequel::Database object for each shard, that will connect to
17
+ only that shard:
18
+
19
+ DB.each_server do |db|
20
+ db.create_table(:t){Integer :num}
21
+ end
22
+
23
+ * You can now add and remove servers/shards from the connection
24
+ pool while Sequel is running:
25
+
26
+ DB.add_servers(:shard1=>{:host=>'s1'}, :shard2=>{:host=>'s2'})
27
+ DB.remove_servers(:shard1, :shard2)
28
+
29
+ * When you attempt to disconnect from a server that has connections
30
+ currently in use, Sequel will now schedule those connections to
31
+ be disconnected when they are returned to the pool. Previously,
32
+ Sequel disconnected available connections, but ignored connections
33
+ currently in use, so it wasn't possible to guarantee complete
34
+ disconnection from the server. Even with this new feature, you can
35
+ only guarantee eventual disconnection, since disconnection of
36
+ connections in use happens asynchronously.
37
+
38
+ * Database#disconnect now accepts a :servers option specifying the
39
+ server(s) from which to disconnect. This should be a symbol or
40
+ array of symbols representing servers/shards. Only those specified
41
+ will be disconnected:
42
+
43
+ DB.disconnect(:servers=>[:shard1, :shard2])
44
+
45
+ * A validates_type validation was added to the validation_helpers
46
+ plugin. It allows you to check that a given column contains
47
+ the correct type. I can be helpful if you are also using the
48
+ serialization plugin to store serialized ruby objects, by making
49
+ sure that the objects are of the correct type (e.g. Hash):
50
+
51
+ def validate
52
+ validates_type(Hash, :options)
53
+ end
54
+
55
+ * Sequel::SQL::Expression#== is now supported for all expressions:
56
+
57
+ :column.qualify(:table).cast(:type) == \
58
+ :column.qualify(:table).cast(:type)
59
+ # => true
60
+ :column.qualify(:table).cast(:type) == \
61
+ :other_column.qualify(:table).cast(:type)
62
+ # => false
63
+
64
+ * When using the generic File type to create blob columns on
65
+ MySQL, you can specify the specific database type by using the
66
+ :size option (with :tiny, :medium, and :long values recognized):
67
+
68
+ DB.create_table(:docs){File :body, :size=>:long} # longblob
69
+
70
+ * The mysql adapter will now default to using mysqlplus, falling
71
+ back to use mysql. mysqlplus is significantly better for threaded
72
+ code because queries do not block the entire interpreter.
73
+
74
+ * The JDBC adapter is now able to detect certain types of disconnect
75
+ errors.
76
+
77
+ * ConnectionPool.servers and Database.servers were added, which
78
+ return an array of symbols specifying the servers/shards in use.
79
+
80
+ Other Improvements
81
+ ------------------
82
+
83
+ * The single-threaded connection pool now raises
84
+ DatabaseConnectionErrors if unable to connect, so it now operates
85
+ more similarly to the default connection pool.
86
+
87
+ * The single-threaded connection pool now operates more similar
88
+ to the default connection pool when given a nonexistent server.
89
+
90
+ * PGErrors are now correctly converted to DatabaseErrors in the
91
+ postgres adapter when preparing statements or executing prepared
92
+ statements.
93
+
94
+ * DatabaseDisconnectErrors are now raised correctly in the postgres
95
+ adapter if the connection status is not OK after a query raises an
96
+ error.
97
+
98
+ * In the mysql adapter, multiple statements in a single query should
99
+ now be handled correctly in the all cases, not just when using
100
+ Dataset#each. So you can now submit multiple queries in a single
101
+ string to Database#run.
102
+
103
+ * Model object creation on Microsoft SQL Server 2000 once again
104
+ works correctly. Previously, an optimization was used that was
105
+ only supported on 2005+.
106
+
107
+ * Backslashes are no longer doubled inside string literals when
108
+ connecting to Microsoft SQL Server.
109
+
110
+ * The ORDER clause now correctly comes after the HAVING clause on
111
+ Microsoft SQL Server.
112
+
113
+ * Sequel now checks that there is an active transaction before
114
+ rolling back transactions on Microsoft SQL Server, since
115
+ there are cases where Microsoft SQL Server will roll back
116
+ transactions implicitly.
117
+
118
+ * Blobs are now handled correctly when connecting to H2.
119
+
120
+ * 64-bit integers are now handled correctly in JDBC prepared
121
+ statements.
122
+
123
+ * In the boolean_readers plugin, correctly handle columns not in
124
+ the db_schema, and don't raise an error if the model's columns
125
+ can't be determined.
126
+
127
+ * In the identity_map plugin, remove instances from the cache if they
128
+ are deleted or destroyed.
129
+
130
+ Backwards Compatibility
131
+ -----------------------
132
+
133
+ * Dataset::FROM_SELF_KEEP_OPTS was merged into
134
+ Dataset::NON_SQL_OPTIONS. While used in different places, they
135
+ were used for the same purpose, and entries missing from one should
136
+ have been included in the other.
137
+
138
+ * The connection pool internals changed substantially. Now,
139
+ ConnectionPool #allocated and #available_connections will return
140
+ nil instead of an array or hash if they are called with a
141
+ nonexistent server. These are generally only used internally,
142
+ though they are part of the public API. #created_count and #size
143
+ still return the size of the :default server when called with a
144
+ nonexistent server, though.
145
+
146
+ * The meta_eval and metaclass private methods were removed from
147
+ Sequel::MetaProgramming (only the meta_def public method remains).
148
+ If you want these methods, use the metaid gem.
149
+
150
+ * The irregular ox->oxen pluralization rule was removed from the
151
+ default inflections, as it screws up the more common box->boxes.
@@ -0,0 +1,233 @@
1
+ New Features
2
+ ------------
3
+
4
+ * The ConnectionPool classes were refactored from 2 separate
5
+ classes to a 5 class hierarchy, with one main class and 4
6
+ subclasses, one for each combination of sharding and threading.
7
+
8
+ The primary reason for this refactoring is to make it so that
9
+ the user doesn't have to pay a performance penalty for sharding
10
+ if they aren't using it. A connection pool that supports sharding
11
+ is automatically used if the :servers option is used when setting
12
+ up the database connection.
13
+
14
+ In addition, the default connection pool no longer contains
15
+ the code to schedule future disconnections of currently allocated
16
+ connections. The sharded connection pool must be used if that
17
+ feature is desired.
18
+
19
+ The unsharded connection pools are about 25-30% faster than the
20
+ sharded versions.
21
+
22
+ * An optimistic_locking plugin was added to Sequel::Model. This
23
+ plugin implements a simple database-independent locking mechanism
24
+ to ensure that concurrent updates do not override changes:
25
+
26
+ class Person < Sequel::Model
27
+ plugin :optimistic_locking
28
+ end
29
+ p1 = Person[1]
30
+ p2 = Person[1]
31
+ # works
32
+ p1.update(:name=>'Jim')
33
+ # raises Sequel::Plugins::OptimisticLocking::Error
34
+ p2.update(:name=>'Bob')
35
+
36
+ In order for this plugin to work, you need to make sure that the
37
+ database table has a lock_version column (or other column you name
38
+ via the lock_column class level accessor) that defaults to 0.
39
+
40
+ The optimistic_locking plugin does not work with the
41
+ class_table_inheritance plugin.
42
+
43
+ * Dataset#unused_table_alias was added, which takes a symbol and
44
+ returns either that symbol or a new symbol which can be used as
45
+ a table alias when joining a table to the dataset. The symbol
46
+ returned is guaranteed to not already be used by the dataset:
47
+
48
+ DB[:test].unused_table_alias(:blah) # => :blah
49
+ DB[:test].unused_table_alias(:test) # => :test_0
50
+
51
+ The use case is when you need to join a table to a dataset, where
52
+ the table may already be used inside the dataset, and you want
53
+ to generate a unique alias:
54
+
55
+ ds.join(:table.as(ds.unused_table_alias(:table)), ...)
56
+
57
+ * The Sequel::ValidationFailed exception now has an errors accessor
58
+ which returns the Sequel::Model::Errors instance with the
59
+ validation errors. This can be helpful in situations where a
60
+ generalized rescue is done where the model object reference is
61
+ not available.
62
+
63
+ * bin/sequel now works without an argument, which is useful for
64
+ testing SQL generation (and not much else).
65
+
66
+ * Support SELECT ... INTO in the MSSQL adapter, using Dataset#into,
67
+ which takes a table argument.
68
+
69
+ * You can now provide your own connection pool class via the
70
+ :pool_class option when instantiating the database.
71
+
72
+ Other Improvements
73
+ ------------------
74
+
75
+ * IN/NOT IN constructs with an empty array are now handled properly.
76
+
77
+ DB[:table].filter(:id=>[]) # IN
78
+ DB[:table].exclude(:id=>[]) # NOT IN
79
+
80
+ Before, the IN construct would mostly work, other than some minor
81
+ differences in NULL semantics. However, the NOT IN construct
82
+ would not work. Sequel now handles the NOT IN case using an
83
+ expression that evaluates to true.
84
+
85
+ * If using an IN/NOT IN construct with multiple columns and a dataset
86
+ argument, where multiple column IN/NOT IN support is emulated, a
87
+ separate query is done to get the records, which is then handled
88
+ like an array of values. This means that the following type of
89
+ query now works on all tested databases:
90
+
91
+ DB[:table1].filter([:id1, :id2]=>DB[:table2].select(:id1, :id2))
92
+
93
+ * Schemas and aliases are now handled correctly when eager graphing.
94
+
95
+ * Implicitly qualified symbols are now handled correctly in update
96
+ statements, useful if you are updating a joined dataset and need
97
+ to reference a column that appears in multiple tables.
98
+
99
+ * The active_model plugin has been brought up to date with
100
+ activemodel 3.0 beta (though it doesn't work on edge).
101
+ Additionally, the active_model plugin now requires active_model
102
+ in order to use ActiveModel::Naming.
103
+
104
+ * In the schema_dumper extension, always include the varchar limit,
105
+ even if it is 255 columns (the default). This makes it so that
106
+ PostgreSQL will use a varchar(255) column instead of a text column
107
+ when restoring a schema dump of a varchar(255) column from another
108
+ database.
109
+
110
+ * You can now load adapters from outside the Sequel lib directory,
111
+ now they just need to be in a sequel/adapters directory somewhere
112
+ in the LOAD_PATH.
113
+
114
+ * You can now load extensions from outside the Sequel lib directory
115
+ using Sequel.extension. External extensions need to be in a
116
+ sequel/extensions directory somewhere in the LOAD_PATH.
117
+
118
+ * Using bound variables for limit and offset in prepared statements
119
+ now works correctly.
120
+
121
+ * Performance of prepared statements was improved in the native
122
+ SQLite adapter.
123
+
124
+ * The schema_dumper extension now passes the options hash from
125
+ dump_*_migration to Database#tables.
126
+
127
+ * In the single_table_inheritance plugin, qualify the sti_key column
128
+ with the table name, so that subclass datasets can safely be joined
129
+ to other tables having the same column name.
130
+
131
+ * In the single_table_inheritance plugin, handle case where the
132
+ sti_key value is nil or '' specially, so that those cases
133
+ always return an instance of the main model class. This fixes
134
+ issues if constantize(nil) returns Object instead of raising
135
+ an exception.
136
+
137
+ * No longer use Date#to_s for literalization, always use ISO8601
138
+ format for dates.
139
+
140
+ * A couple lambdas which were instance_evaled were changed to procs
141
+ for ruby 1.9.2 compatibility.
142
+
143
+ * MSSQL emulated offset support was simplified to only use one
144
+ subquery, and made to work correctly on ruby 1.9.
145
+
146
+ * Emulate multiple column IN/NOT IN on H2, since it doesn't handle
147
+ all cases correctly.
148
+
149
+ * ODBC timestamps are now handled correctly if the database_timezone
150
+ is nil.
151
+
152
+ * ArgumentErrors raised when running queries in the ODBC adapter are
153
+ now raised as DatabaseErrors.
154
+
155
+ * Attempting to use DISTINCT ON on SQLite now raises an error before
156
+ sending the query to the database.
157
+
158
+ * The options hash passed to the database connection method is no
159
+ longer modified. However, there may be additional options
160
+ present in Database#opts that weren't specified by the options
161
+ hash passed to the database connection method.
162
+
163
+ * Make Dataset#add_graph_aliases handle the case where the dataset
164
+ has not yet been graphed.
165
+
166
+ * You can now provide an SQL::Identifier as a 4th argument to
167
+ Dataset#join_table, and unsupported arguments are caught and an
168
+ exception is raised.
169
+
170
+ * The gem specification has been moved out of the Rakefile, so
171
+ that the gem can now be built without rake, and works well with
172
+ gem build and bundler.
173
+
174
+ * The Rakefile no longer assumes the current directory is in the
175
+ $LOAD_PATH, so it should work correctly on ruby 1.9.2.
176
+
177
+ * All internal uses of require are now thread safe.
178
+
179
+ * Empty query parameter keys in connection strings are now ignored
180
+ instead of raising an exception.
181
+
182
+ * The specs were changed so that you can run them in parallel.
183
+ Previously there was a race condition in the migration extension
184
+ specs.
185
+
186
+ Backwards Compatibility
187
+ -----------------------
188
+
189
+ * If you plan on using sharding at any point, you now must pass
190
+ a :servers option when connecting to the database, even if it is
191
+ an empty hash. You can no longer just call Database#add_servers
192
+ later.
193
+
194
+ * The connection_proc and disconnection_proc accessors were removed
195
+ from the connection pools, so you can no longer modify the procs
196
+ after the connection pool has been instantiated. You must now
197
+ provide the connection_proc as the block argument when
198
+ instantiating the pool, and the disconnection_proc via the
199
+ :disconnection_proc option.
200
+
201
+ * In the hash passed to Dataset#update, symbol keys with a double
202
+ embedded underscore are now considerated as implicit qualifiers,
203
+ instead of being used verbatim. If you have a column that includes
204
+ a double underscore, you now need to wrap it in an SQL::Identifier
205
+ or use a String instead.
206
+
207
+ * The connection pools no longer convert non-StandardError based
208
+ exceptions to RuntimeErrors. Previously, all of the common adapters
209
+ turned this feature off, so there is no change for most users.
210
+
211
+ * Sequel::ConnectionPool is now considered an abstract class and
212
+ should not be instantiated directly. Use ConnectionPool.get_pool
213
+ to return an instance of the appropriate subclass.
214
+
215
+ * The Sequel::SingleThreadedPool constant is no longer defined.
216
+
217
+ * The private Dataset#eager_unique_table_alias method was removed,
218
+ use the new public Dataset#unused_table_alias method instead, which
219
+ has a slightly different API.
220
+
221
+ * The private Dataset#eager_graph_qualify_order method was removed,
222
+ used Dataset#qualified_expression instead.
223
+
224
+ * The private Sequel::Model class methods plugin_gem_location and
225
+ plugin_gem_location_old have been removed.
226
+
227
+ * Gems built with the rake tasks now show up in the root directory
228
+ instead of the pkg subdirectory, and no tarball package is created.
229
+
230
+ Other News
231
+ ----------
232
+
233
+ * Sequel now has an official blog at http://sequel.heroku.com.
@@ -0,0 +1,36 @@
1
+ = Schema Modifications with Sequel
2
+
3
+ In addition to its support for getting data from databases, Sequel has good support for modifying the schema of databases. Unfortunately, the documentation from this is spread out in various places in the Sequel RDoc.
4
+
5
+ The recommended way to set up schema modifications in Sequel is through migrations. Migrations are modifications to the schema that handle modifying the schema in two directions, up and down, with down reversing the changes made by up. Migrations are stored in sequentially numbered files inside a directory (see the Sequel::Migrator documentation for file naming format details). The migrations can be run on the database using the sequel command line tool (the -m and -M switches).
6
+
7
+ The format of the individual migration files themselves is explained in the Sequel::Migration documentation. Each migration file contains a single migration class. The migration class acts a proxy for the related database (given on the command line if the sequel command line tool is used, or by the db argument to Sequel::Migration#apply if the API is used). The methods that can be used inside Sequel::Migration#up or Sequel::Migration#down are just Sequel::Database instance methods, such as create_table, drop_table, and alter_table. Most database methods that alter the schema take regular arguments, but create_table and alter_table take a block. The methods you can use inside the create_table block are documented in Sequel::Schema::Generator, and the methods you can use inside the alter_table block are documented in Sequel::Schema::AlterTableGenerator.
8
+
9
+ Migrations are not required, you can just call the schema modification methods directly on the database object. This is often done in test code and examples. However, it is recommended that you use the migration framework unless the database schema will not be changing in the future, as it provides a way to easily handle modifications to existing database schema.
10
+
11
+ Sequel has the ability to have database independent migrations using ruby classes as types. When you use a ruby class as a type, Sequel translates it to the most comparable type in the database you are using. Here's an example using all supported types:
12
+
13
+ DB.create_table(:cats) do
14
+ primary_key :id, :type=>Integer # integer
15
+ String :a # varchar(255)
16
+ String :a2, :size=>50 # varchar(50)
17
+ String :a3, :fixed=>true # char(255)
18
+ String :a4, :fixed=>true, :size=>50 # char(50)
19
+ String :a5, :text=>true # text
20
+ column :b, File # blob
21
+ Fixnum :c # integer
22
+ foreign_key :d, :other_table, :type=>Bignum # bigint
23
+ Float :e # double precision
24
+ BigDecimal :f # numeric
25
+ BigDecimal :f2, :size=>10 # numeric(10)
26
+ BigDecimal :f3, :size=>[10, 2] # numeric(10, 2)
27
+ Date :g # date
28
+ DateTime :h # timestamp
29
+ Time :i # timestamp
30
+ Time :i2, :only_time=>true # time
31
+ Numeric :j # numeric
32
+ TrueClass :k # boolean
33
+ FalseClass :l # boolean
34
+ end
35
+
36
+ Basically, if you use one of the ruby classes above, it will translate into a database specific type. If you use a lowercase method, symbol, or string to specify the type, Sequel won't attempt to translate it.
@@ -0,0 +1,113 @@
1
+ = Read-Only Slaves/Writable Master and Database Sharding
2
+
3
+ Sequel has support for read only slave databases
4
+ with a writable master database, as well as database sharding (where you can
5
+ pick a server to use for a given dataset). Support for both
6
+ features is database independent, and should work for all database adapters
7
+ included with Sequel.
8
+
9
+ == The :servers Database option
10
+
11
+ Both features use the :servers Database option. The :servers option should
12
+ be a hash with symbol keys and values that are either hashes or procs that
13
+ return hashes. Note that all servers should have the same schema for all
14
+ tables you are accessing, unless you really know what you are doing.
15
+
16
+ == Master and Slave Database Configurations
17
+
18
+ === Single Read-Only Slave, Single Master
19
+
20
+ To use a single, read-only slave that handles SELECT queries, the following
21
+ is the simplest configuration:
22
+
23
+ DB=Sequel.connect('postgres://master_server/database', \
24
+ :servers=>{:read_only=>{:host=>'slave_server'}})
25
+
26
+ This will use the slave_server for SELECT queries and master_server for
27
+ other queries.
28
+
29
+ === Multiple Read-Only Slaves, Single Master
30
+
31
+ Let's say you have 4 slave database servers with names slave_server0,
32
+ slave_server1, slave_server2, and slave_server3.
33
+
34
+ DB=Sequel.connect('postgres://master_server/database', \
35
+ :servers=>{:read_only=>proc{|db| {:host=>db.get_slave_host}}})
36
+ def DB.get_slave_host
37
+ @current_host ||= -1
38
+ "slave_server#{(@current_host+=1)%4}"
39
+ end
40
+
41
+ This will use one of the slave servers for SELECT queries and use the
42
+ master_server for other queries. It's also possible to pick a random host
43
+ instead of using the round robin approach presented above, but that can result
44
+ in less optimal resource usage.
45
+
46
+ === Multiple Read-Only Slaves, Multiple Masters
47
+
48
+ This involves the same basic idea as the multiple slaves, single master, but
49
+ it shows that the master database is named :default. So for 4 masters and
50
+ 4 slaves:
51
+
52
+ DB=Sequel.connect('postgres://master_server/database', \
53
+ :servers=>{:read_only=>proc{|db| {:host=>db.get_slave_host}}, \
54
+ :default=>proc{|db| {:host=>db.get_master_host}}})
55
+ def DB.get_slave_host
56
+ @current_slave_host ||= -1
57
+ "slave_server#{(@current_slave_host+=1)%4}"
58
+ end
59
+ def DB.get_master_host
60
+ @current_master_host ||= -1
61
+ "master_server#{(@current_master_host+=1)%4}"
62
+ end
63
+
64
+ == Sharding
65
+
66
+ There is specific support in Sequel for handling master/slave database
67
+ combinations, with the only necessary setup being the database configuration.
68
+ However, since sharding is always going to be implementation dependent, Sequel
69
+ supplies the basic infrastructure, but you have to tell it which server to use
70
+ for each dataset. Let's assume a simple scenario, a distributed rainbow
71
+ table for SHA-1 hashes, sharding based on the first hex character (for a total
72
+ of 16 shards). First, you need to configure the database:
73
+
74
+ servers = {}
75
+ (('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
76
+ servers[hex.to_sym] = {:host=>"hash_host_#{hex}"}
77
+ end
78
+ DB=Sequel.connect('postgres://hash_host/hashes', :servers=>servers)
79
+
80
+ This configures 17 servers, the 16 shard servers (/hash_host_[0-9a-f]/), and 1
81
+ default server which will be used if no shard is specified ("hash_host"). If
82
+ you want the default server to be one of the shard servers (e.g. hash_host_a),
83
+ it's easiest to do:
84
+
85
+ DB=Sequel.connect('postgres://hash_host_a/hashes', :servers=>servers)
86
+
87
+ That will still set up a second pool of connections for the default server,
88
+ since it considers the default server and shard servers independent. Note that
89
+ if you always set the shard on a dataset before using it in queries, it will
90
+ not attempt to connect to the default server. Sequel may use the default
91
+ server in queries it generates itself, such as to get column names or table
92
+ schemas, so you should always have a default server that works.
93
+
94
+ To set the shard for a given query, you use the Dataset#server method:
95
+
96
+ DB[:hashes].server(:a).filter(:hash=>/31337/)
97
+
98
+ That will return all matching rows on the hash_host_a shard that have a hash
99
+ column that contains 31337.
100
+
101
+ Rainbow tables are generally used to find specific hashes, so to save some
102
+ work, you might want to add a method to the dataset that automatically sets
103
+ the shard to use. This is fairly easy using a Sequel::Model:
104
+
105
+ class Rainbow < Sequel::Model(:hashes)
106
+ def_dataset_method(:plaintext_for_hash) do |hash|
107
+ raise(ArgumentError, 'Invalid SHA-1 Hash') unless /\A[0-9a-f]{40}\z/.match(hash)
108
+ row = self.server(hash[0...1].to_sym).first(:hash=>hash)
109
+ row[:plaintext] if row
110
+ end
111
+ end
112
+
113
+ Rainbow.plaintext_for_hash("e580726d31f6e1ad216ffd87279e536d1f74e606")