sequel 3.38.0 → 3.39.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 (79) hide show
  1. data/CHANGELOG +62 -0
  2. data/README.rdoc +2 -2
  3. data/bin/sequel +12 -2
  4. data/doc/advanced_associations.rdoc +1 -1
  5. data/doc/association_basics.rdoc +13 -0
  6. data/doc/release_notes/3.39.0.txt +237 -0
  7. data/doc/schema_modification.rdoc +4 -4
  8. data/lib/sequel/adapters/jdbc/derby.rb +1 -0
  9. data/lib/sequel/adapters/mock.rb +5 -0
  10. data/lib/sequel/adapters/mysql.rb +8 -1
  11. data/lib/sequel/adapters/mysql2.rb +10 -3
  12. data/lib/sequel/adapters/postgres.rb +72 -8
  13. data/lib/sequel/adapters/shared/db2.rb +1 -0
  14. data/lib/sequel/adapters/shared/mssql.rb +57 -0
  15. data/lib/sequel/adapters/shared/mysql.rb +95 -19
  16. data/lib/sequel/adapters/shared/oracle.rb +14 -0
  17. data/lib/sequel/adapters/shared/postgres.rb +63 -24
  18. data/lib/sequel/adapters/shared/sqlite.rb +6 -9
  19. data/lib/sequel/connection_pool/sharded_threaded.rb +8 -3
  20. data/lib/sequel/connection_pool/threaded.rb +9 -4
  21. data/lib/sequel/database/query.rb +60 -48
  22. data/lib/sequel/database/schema_generator.rb +13 -6
  23. data/lib/sequel/database/schema_methods.rb +65 -12
  24. data/lib/sequel/dataset/actions.rb +22 -4
  25. data/lib/sequel/dataset/features.rb +5 -0
  26. data/lib/sequel/dataset/graph.rb +2 -3
  27. data/lib/sequel/dataset/misc.rb +2 -2
  28. data/lib/sequel/dataset/query.rb +0 -2
  29. data/lib/sequel/dataset/sql.rb +33 -12
  30. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  31. data/lib/sequel/extensions/eval_inspect.rb +17 -2
  32. data/lib/sequel/extensions/pg_array_ops.rb +15 -5
  33. data/lib/sequel/extensions/pg_interval.rb +2 -2
  34. data/lib/sequel/extensions/pg_row_ops.rb +18 -0
  35. data/lib/sequel/extensions/schema_dumper.rb +3 -11
  36. data/lib/sequel/model/associations.rb +3 -2
  37. data/lib/sequel/model/base.rb +57 -13
  38. data/lib/sequel/model/exceptions.rb +20 -2
  39. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  40. data/lib/sequel/plugins/defaults_setter.rb +15 -1
  41. data/lib/sequel/plugins/dirty.rb +2 -2
  42. data/lib/sequel/plugins/identity_map.rb +12 -8
  43. data/lib/sequel/plugins/subclasses.rb +19 -1
  44. data/lib/sequel/plugins/tree.rb +3 -3
  45. data/lib/sequel/plugins/validation_helpers.rb +24 -4
  46. data/lib/sequel/sql.rb +64 -24
  47. data/lib/sequel/timezones.rb +10 -2
  48. data/lib/sequel/version.rb +1 -1
  49. data/spec/adapters/mssql_spec.rb +26 -25
  50. data/spec/adapters/mysql_spec.rb +57 -23
  51. data/spec/adapters/oracle_spec.rb +34 -49
  52. data/spec/adapters/postgres_spec.rb +226 -128
  53. data/spec/adapters/sqlite_spec.rb +50 -49
  54. data/spec/core/connection_pool_spec.rb +22 -0
  55. data/spec/core/database_spec.rb +53 -47
  56. data/spec/core/dataset_spec.rb +36 -32
  57. data/spec/core/expression_filters_spec.rb +14 -2
  58. data/spec/core/mock_adapter_spec.rb +4 -0
  59. data/spec/core/object_graph_spec.rb +0 -13
  60. data/spec/core/schema_spec.rb +64 -5
  61. data/spec/core_extensions_spec.rb +1 -0
  62. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  63. data/spec/extensions/constraint_validations_spec.rb +316 -0
  64. data/spec/extensions/defaults_setter_spec.rb +24 -0
  65. data/spec/extensions/eval_inspect_spec.rb +9 -0
  66. data/spec/extensions/identity_map_spec.rb +11 -2
  67. data/spec/extensions/pg_array_ops_spec.rb +9 -0
  68. data/spec/extensions/pg_row_ops_spec.rb +11 -1
  69. data/spec/extensions/pg_row_plugin_spec.rb +4 -0
  70. data/spec/extensions/schema_dumper_spec.rb +8 -5
  71. data/spec/extensions/subclasses_spec.rb +14 -0
  72. data/spec/extensions/validation_helpers_spec.rb +15 -2
  73. data/spec/integration/dataset_test.rb +75 -1
  74. data/spec/integration/plugin_test.rb +146 -0
  75. data/spec/integration/schema_test.rb +34 -0
  76. data/spec/model/dataset_methods_spec.rb +38 -0
  77. data/spec/model/hooks_spec.rb +6 -0
  78. data/spec/model/validations_spec.rb +27 -2
  79. metadata +8 -2
data/CHANGELOG CHANGED
@@ -1,3 +1,65 @@
1
+ === 3.39.0 (2012-09-01)
2
+
3
+ * Fix defaults_setter to set false default values (jeremyevans)
4
+
5
+ * Fix serial sequence query in Database#primary_key_sequence on PostgreSQL (jeremyevans) (#538)
6
+
7
+ * Add Database#copy_into when using postgres adapter with pg driver, for very fast inserts into tables (jeremyevans)
8
+
9
+ * Combine multiple alter_table operations into a single query where possible on MySQL and PostgreSQL (jeremyevans)
10
+
11
+ * Handle sets of alter_table operations on MySQL and MSSQL where later operations depend on earlier ones (jeremyevans)
12
+
13
+ * Add constraint_validations plugin for automatic validations of constaints defined by extension (jeremyevans)
14
+
15
+ * Add constraint_validations extension for defining database constraints similar to validations (jeremyevans)
16
+
17
+ * Add Database#supports_regexp? for checking for regular expression support (jeremyevans)
18
+
19
+ * Add Sequel.trim for cross platform trim function (jeremyevans)
20
+
21
+ * Add Sequel.char_length for cross platform char_length function (jeremyevans)
22
+
23
+ * Fixing caching of MySQL server version (hannesg) (#536)
24
+
25
+ * Allow overriding the convert_tinyint_to_bool setting on a per-Dataset basis in the mysql and mysql2 adapters (jeremyevans)
26
+
27
+ * Make ValidationFailed and HookFailed exceptions have model method that returns the related model (jeremyevans)
28
+
29
+ * Automatically wrap array arguments to most PGArrayOp methods in PGArrays (jeremyevans)
30
+
31
+ * Add set_column_not_null to alter table generator for marking a column as not null (jeremyevans)
32
+
33
+ * Default second argument of set_column_allow_null to true in alter table generator (jeremyevans)
34
+
35
+ * Allow Dataset#count to take an argument or virtual row block (jeremyevans)
36
+
37
+ * Attempt to recognize CURRENT_{DATE,TIMESTAMP} defaults and return them as Sequel::CURRENT_{DATE,TIMESTAMP} (jeremyevans)
38
+
39
+ * Make dataset.insert(model) assume a single column if model uses the pg_row plugin (jeremyevans)
40
+
41
+ * No longer handle model instances in plain (non-model) datasets when inserting (jeremyevans)
42
+
43
+ * Use subselects for model classes as tables in join methods in model datasets if the model's dataset isn't a simple select (jeremyevans)
44
+
45
+ * No longer handle model classes as tables in join/graph methods in plain (non-model) datasets (jeremyevans)
46
+
47
+ * Make Time->DateTime and DateTime->Time typecasts retain fractional seconds on ruby 1.8 (jeremyevans) (#531)
48
+
49
+ * Add bin/sequel -c support, for running code string instead of using an IRB prompt (jeremyevans)
50
+
51
+ * Allow subclasses plugin to take a block, which is called with each subclasses created (jeremyevans)
52
+
53
+ * Add :where option to validates_unique, for custom uniqueness filters (jeremyevans)
54
+
55
+ * Add :connection_handling=>:disconnect option for threaded connection pools (jeremyevans)
56
+
57
+ * Add Postgres::PGRowOp#* for referencing the members of the composite type as separate columns (jeremyevans)
58
+
59
+ * Make identity_map plugin work with models lacking a primary key (jeremyevans)
60
+
61
+ * Recognize MySQL set type and default value (jeremyevans) (#529)
62
+
1
63
  === 3.38.0 (2012-08-01)
2
64
 
3
65
  * Sequel now recognizes the double(x, y) and double(x, y) unsigned MySQL types (Slike9, jeremyevans) (#528)
data/README.rdoc CHANGED
@@ -93,11 +93,11 @@ Since datasets retrieve records only when needed, they can be stored and later r
93
93
 
94
94
  Sequel also offers convenience methods for extracting data from Datasets, such as an extended +map+ method:
95
95
 
96
- middle_east.map(:name) #=> ['Egypt', 'Greece', 'Israel', ...]
96
+ middle_east.map(:name) #=> ['Egypt', 'Turkey', 'Israel', ...]
97
97
 
98
98
  Or getting results as a hash via +to_hash+, with one column as key and another as value:
99
99
 
100
- middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Greece' => 120000, ...}
100
+ middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Turkey' => 120000, ...}
101
101
 
102
102
  == Getting Started
103
103
 
data/bin/sequel CHANGED
@@ -4,6 +4,7 @@ require 'rubygems'
4
4
  require 'optparse'
5
5
  require 'sequel'
6
6
 
7
+ code = nil
7
8
  copy_databases = nil
8
9
  dump_migration = nil
9
10
  dump_schema = nil
@@ -18,7 +19,7 @@ loggers = []
18
19
 
19
20
  opts = OptionParser.new do |opts|
20
21
  opts.banner = "Sequel: The Database Toolkit for Ruby"
21
- opts.define_head "Usage: sequel <uri|path> [options]"
22
+ opts.define_head "Usage: sequel [options] <uri|path> [file]"
22
23
  opts.separator ""
23
24
  opts.separator "Examples:"
24
25
  opts.separator " sequel sqlite://blog.db"
@@ -34,6 +35,11 @@ opts = OptionParser.new do |opts|
34
35
  exit
35
36
  end
36
37
 
38
+ opts.on("-c", "--code CODE", "run the given code and exit") do |v|
39
+ code = v
40
+ exclusive_options << :c
41
+ end
42
+
37
43
  opts.on("-C", "--copy-databases", "copy one database to another") do
38
44
  copy_databases = true
39
45
  end
@@ -83,7 +89,7 @@ opts = OptionParser.new do |opts|
83
89
  test = false
84
90
  end
85
91
 
86
- opts.on("-r", "--require lib", "require the library, before executing your script") do |v|
92
+ opts.on("-r", "--require LIB", "require the library, before executing your script") do |v|
87
93
  load_dirs << [v]
88
94
  end
89
95
 
@@ -207,6 +213,10 @@ begin
207
213
  puts "Database copy finished in #{Time.now - start_time} seconds"
208
214
  exit
209
215
  end
216
+ if code
217
+ eval(code)
218
+ exit
219
+ end
210
220
  rescue => e
211
221
  raise e if backtrace
212
222
  error_proc["Error: #{e.class}: #{e.message}#{e.backtrace.first}"]
@@ -104,7 +104,7 @@ have the following associations
104
104
  Album.many_to_one :artist
105
105
  Album.one_to_many :tracks
106
106
 
107
- and the following two albums in the database:
107
+ and the following three albums in the database:
108
108
 
109
109
  album1 = Album.create(:artist_id=>3) # id: 1
110
110
  album2 = Album.create(:artist_id=>3) # id: 2
@@ -607,6 +607,19 @@ To fix this, you need to specify the full model class name using the
607
607
  end
608
608
  end
609
609
 
610
+ If both classes are in the same module, but the default class name
611
+ used is not correct, you need to specify the full class name with the
612
+ :class option:
613
+
614
+ module App1
615
+ class AlbumArtist < Sequel::Model
616
+ one_to_many :albums
617
+ end
618
+ class Album < Sequel::Model
619
+ many_to_one :artist, :class=>"App1::AlbumArtist"
620
+ end
621
+ end
622
+
610
623
  == Method Details
611
624
 
612
625
  In all of these methods, _association_ is replaced by the symbol you
@@ -0,0 +1,237 @@
1
+ = New Features
2
+
3
+ * A constraint_validations extension and plugin have been added,
4
+ which allow you to define validations when creating tables,
5
+ which are enforced by database constraints, and have those
6
+ validations be automatically discovered and used by your
7
+ Sequel::Model classes.
8
+
9
+ The extension is designed to be used in your migrations/schema
10
+ modification code:
11
+
12
+ DB.extension(:constraint_validations)
13
+ DB.create_constraint_validations_table
14
+ DB.create_table(:foos) do
15
+ primary_key :id
16
+ String :name
17
+
18
+ validate do
19
+ min_length 5, :name
20
+ end
21
+ end
22
+
23
+ This creates a database CHECK constraint that ensures that the
24
+ minimum length for the column is 5 characters. It also adds
25
+ metadata about the validation to the
26
+ sequel_constraint_validations table.
27
+
28
+ To have the model class automatically create validations, just
29
+ include the plugin in the model:
30
+
31
+ class Foo < Sequel::Model
32
+ plugin :constraint_validations
33
+ end
34
+
35
+ Note that MySQL does not enforce CHECK constraints (it parses
36
+ but ignores them), so using the extension on MySQL does not
37
+ actually enforce constraints at the database level, though it
38
+ still does support the automatic model validations if the plugin
39
+ is used.
40
+
41
+ * Dataset#count now takes an argument or a virtual row block,
42
+ allowing you to do:
43
+
44
+ DB[:table].count(:column_name)
45
+ DB[:table].count{function_name(column1, column2)}
46
+
47
+ When count is given an argument, instead of returning the total
48
+ number of rows, it returns the number of rows where the
49
+ argument has a non-NULL value.
50
+
51
+ * Database#copy_into has been added to the postgres adapter when
52
+ the pg driver is being used, and can be used for very fast
53
+ inserts into tables if you already have the input preformatted
54
+ in PostgreSQL text or CSV format.
55
+
56
+ * set_table_not_null has been added to the alter table generator,
57
+ for a nicer API:
58
+
59
+ alter_table(:t){set_column_not_null :col}
60
+ # instead of
61
+ alter_table(:t){set_column_allow_null :col, false}
62
+
63
+ Additionally, set_column_allow_null now defaults the second
64
+ argument to true for a nicer API:
65
+
66
+ alter_table(:t){set_column_allow_null :col}
67
+ # instead of
68
+ alter_table(:t){set_column_allow_null :col, true}
69
+
70
+ * Database#supports_regexp? has been added for checking if the
71
+ database supports Regexp in filters. Currently, only MySQL and
72
+ PostgreSQL support Regexps.
73
+
74
+ Attempting to use a Regexp on a database that doesn't support it
75
+ now raises an error when attempting to generate the SQL, instead
76
+ of sending invalid SQL to the database.
77
+
78
+ * Sequel.char_length has been added for a cross platform
79
+ char_length function (emulated when char_length is not supported
80
+ natively by the database).
81
+
82
+ * Sequel.trim has been added for a cross platform trim function
83
+ (emulated when trim is not supported natively by the database).
84
+
85
+ * ValidationFailed and HookFailed exceptions now have a model method
86
+ that returns the model instance related to the exception. This
87
+ makes it possible to use Model.create inside a begin/rescue block
88
+ and get access to the underlying instance if there is a validation
89
+ or before/around hook error.
90
+
91
+ * The subclasses plugin now accepts a block, which is called with
92
+ each model class created. This is useful if you want to apply
93
+ changes to classes created in the future instead of just existing
94
+ classes.
95
+
96
+ * The validates_unique validation in the validation_helpers plugin
97
+ now accepts a :where option for a custom uniqueness filter. Among
98
+ other things this makes it easy to implement a case insensitive
99
+ uniqueness validation on a case sensitive column.
100
+
101
+ * The threaded connection pools now support a
102
+ :connection_handling=>:disconnect option, which makes them disconnect
103
+ connections after use instead of returning them to the pool. This
104
+ makes it possible to completely control connection lifetime using
105
+ Database#synchronize.
106
+
107
+ * The pg_row_op extension now has support for PGRowOp#*, for referencing
108
+ the members of the composite type as separate columns.
109
+
110
+ * MySQL's set type and default value are now recognized.
111
+
112
+ * bin/sequel now accepts a -c argument for running an arbitrary
113
+ code string instead of using an IRB prompt.
114
+
115
+ = Other Improvements
116
+
117
+ * Sequel now parses current date/timestamp column defaults when
118
+ parsing the schema for a table. The values will be returned
119
+ as Sequel::CURRENT_DATE for date columns and
120
+ Sequel::CURRENT_TIMESTAMP for timestamp columns.
121
+
122
+ The schema_dumper extension will work with these defaults, so
123
+ if you dump the schema for a table with a column that uses
124
+ a current timestamp default, the dumped schema will include
125
+ the default.
126
+
127
+ The defaults setter plugin also works with these changes, so
128
+ that when new model objects are instantiated, they get the
129
+ current Date/Time/DateTime values set.
130
+
131
+ * On MySQL and PostgreSQL, Sequel will now by default attempt
132
+ to combine multiple alter_table operations into a single
133
+ query where it believes it can do so correctly. This can
134
+ potentially improve performance ~N times, where N is the number
135
+ of alter table operations.
136
+
137
+ This can change the SQL used for old migrations (though it
138
+ shouldn't change the result), and is a potentially risky
139
+ change. This may be disabled by default in future versions
140
+ if it causes problems.
141
+
142
+ * The defaults_setter plugin now correctly sets false default
143
+ values.
144
+
145
+ * The schema_dumper plugin now preserves fractional seconds
146
+ in timestamp column defaults when dumping.
147
+
148
+ * Time->DateTime and DateTime->Time typecasts now retain
149
+ fractional seconds on ruby 1.8.
150
+
151
+ * Array arguments passed to most PGArrayOp methods are now
152
+ automatically wrapped in a PGArray. If you want to use this
153
+ support, you need to make sure to load both the pg_array
154
+ and pg_array_op extensions.
155
+
156
+ * Sequel now does a better job of finding the sequence for a
157
+ given table on PostgreSQL, handling more corner cases. A small
158
+ side effect of this is sometimes sequence names will be quoted.
159
+
160
+ * Some potential thread-safety issues when using Sequel with
161
+ PostgreSQL on a non-GVL ruby implementation have been fixed.
162
+
163
+ * Sequel now correctly caches the server version query on MySQL.
164
+
165
+ * Sets of alter_table operations on MySQL and Microsoft SQL Server
166
+ that require parsing the current database schema, where later
167
+ alter_table operations depend on earlier ones, should now work
168
+ correctly.
169
+
170
+ * You can now drop check constraints on tables on SQLite, though
171
+ doing so drops all check constraints on the table, not only the
172
+ specific check constraint given.
173
+
174
+ * The identity_map plugin no longer breaks if used with a model
175
+ without a primary key.
176
+
177
+ * Sequel::SQL::NegativeBooleanConstant now inherits from Constant
178
+ instead of BooleanConstant. This means that
179
+
180
+ Sequel::NULL == Sequel::NOTNULL
181
+
182
+ is now false instead of true.
183
+
184
+ * You can now override the convert_tinyint_to_bool settings on a
185
+ per-Dataset basis in the mysql and mysql2 adapters, though
186
+ the overriding is different depending on the adapter. Check the
187
+ commit log for details.
188
+
189
+ * timestamp(N) types are now recognized as datetime, which should
190
+ fix certain cases on Oracle.
191
+
192
+ * Dataset#insert now handles a single model instance argument
193
+ as a single value if the model uses the pg_row plugin.
194
+
195
+ * When joining a model dataset using a model class as the table
196
+ argument, a subselect is used unless the model is a simple select
197
+ from the underlying table.
198
+
199
+ * The specs now cleanup after themselves, dropping the tables that
200
+ they create for testing.
201
+
202
+ = Backwards Compatibility
203
+
204
+ * The defaults_setter plugin's behavior changed due to the
205
+ current date/timestamp support. Previously, it would not set
206
+ a value for the column, since the default wasn't recognized.
207
+ Therefore, the database would use the default value on insert,
208
+ which would be the database's current timestamp.
209
+
210
+ Now, the value is set to the current Date/Time/DateTime on
211
+ model object instantiation, so the database wouldn't use the
212
+ column default. Instead of the database's current timestamp
213
+ on insert, the column value will be the application's
214
+ current timestamp on model instantiation.
215
+
216
+ Users who don't want this behavior can remove the default values
217
+ in the model:
218
+
219
+ Model.default_values.delete(:column_name)
220
+
221
+ * Plain (non-model) datasets no longer allow insert to accept
222
+ a single model instance argument. Also, they no longer call
223
+ values on a single argument if the object responds to it.
224
+
225
+ * Plain (non-model) datasets no longer accept model classes as
226
+ tables in the join/graph methods. Also, they no longer call
227
+ table_name on the argument if the object responds to it.
228
+
229
+ * The schema_dumper extension now requires the eval_inspect
230
+ extension, which changes inspect output for
231
+ Sequel::SQL::Expression objects.
232
+
233
+ * Custom adapters that override Database#alter_table_sql_list now
234
+ need to make sure it returns an already flattened array.
235
+
236
+ * The identity_map_key method in the identity_map plugin now returns
237
+ nil instead of a random string if the given pk is nil.
@@ -532,14 +532,14 @@ the first argument is the current name, and the second is the new name:
532
532
  <tt>create_table!</tt> drops the table if it exists
533
533
  before attempting to create it, so:
534
534
 
535
- create_table!(:artists)
535
+ create_table!(:artists) do
536
536
  primary_key :id
537
537
  end
538
538
 
539
539
  is the same as:
540
540
 
541
541
  drop_table?(:artists)
542
- create_table(:artists)
542
+ create_table(:artists) do
543
543
  primary_key :id
544
544
  end
545
545
 
@@ -551,14 +551,14 @@ mess up the migration.
551
551
  <tt>create_table?</tt> only creates the table if it does
552
552
  not already exist, so:
553
553
 
554
- create_table?(:artists)
554
+ create_table?(:artists) do
555
555
  primary_key :id
556
556
  end
557
557
 
558
558
  is the same as:
559
559
 
560
560
  unless table_exists?(:artists)
561
- create_table(:artists)
561
+ create_table(:artists) do
562
562
  primary_key :id
563
563
  end
564
564
  end
@@ -171,6 +171,7 @@ module Sequel
171
171
  BOOL_TRUE = 'TRUE'.freeze
172
172
  BOOL_FALSE = 'FALSE'.freeze
173
173
  SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
174
+ EMULATED_FUNCTION_MAP = {:char_length=>'length'.freeze}
174
175
 
175
176
  # Derby doesn't support an expression between CASE and WHEN,
176
177
  # so emulate it by using an equality statement for all of the
@@ -61,6 +61,11 @@ module Sequel
61
61
  :id
62
62
  end
63
63
  end)
64
+ end,
65
+ 'oracle' => lambda do |db|
66
+ db.instance_eval do
67
+ @primary_key_sequences = {}
68
+ end
64
69
  end
65
70
  }
66
71