sequel 3.38.0 → 3.39.0

Sign up to get free protection for your applications and to get access to all the features.
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