Path: | doc/release_notes/3.32.0.txt |
Last Update: | Thu Nov 12 08:45:04 +0000 2015 |
many_to_one :primary_key_method one_to_many :key_method one_to_many :primary_key_column many_to_many :left_primary_key_column many_to_many :right_primary_key_method
Using these new options, you can now define associations that work correctly when the underlying primary/foreign key columns clash with existing ruby method names. See the RDoc for details.
Previously, Sequel was inconsistent in that it tried to handle NULL values correctly in the IN case, but not in the NOT IN case. Now, it defaults to handling NULL values correctly in both cases:
# 3.31.0 DB[:a].where(:b=>[]) # SELECT * FROM a WHERE (b != b) DB[:a].exclude(:b=>[]) # SELECT * FROM a WHERE (1 = 1) # 3.32.0 DB[:a].where(:b=>[]) # SELECT * FROM a WHERE (b != b) DB[:a].exclude(:b=>[]) # SELECT * FROM a WHERE (b = b)
The important change in behavior is that in the NOT IN case, if the left hand argument is NULL, the filter returns NULL instead of true. This has the potential to change query results.
"Correct" here is really an opinion and not a fact, as there are valid arguments for the alternative behavior:
DB[:a].where(:b=>[]) # SELECT * FROM a WHERE (1 = 0) DB[:a].exclude(:b=>[]) # SELECT * FROM a WHERE (1 = 1)
The difference is that the "correct" NULL behavior is more consistent with the non-empty array cases. For example, if b is NULL:
# "Correct" NULL handling # Empty array: where(:b=>[]) WHERE (b != b) # NULL WHERE (b = b) # NULL # Non-empty array: where(:b=>[1, 2]) WHERE (b IN (1, 2)) # NULL WHERE (b NOT IN (1, 2)) # NULL # Static boolean handling # Empty array: where(:b=>[]) WHERE (1 = 0) # false WHERE (1 = 1) # true # Non-empty array: where(:b=>[1, 2]) WHERE (b IN (1, 2)) # NULL WHERE (b NOT IN (1, 2)) # NULL
Sequel chooses to default to behavior consistent with the non-empty array cases (similar to SQLAlchemy). However, there are two downsides to this handling. The first is that some databases with poor optimizers (e.g. MySQL) might do a full table scan with the default syntax. The second is that the static boolean handling may be generally perferable, if you believe that IN/NOT IN with an empty array should always be true or false and never NULL even if the left hand argument is NULL.
As there really isn‘t a truly correct answer in this case, Sequel defaults to the "correct" NULL handling, and allows you to switch to the static boolean handling via:
Sequel.empty_array_handle_nulls = false
This is currently a global setting, it may be made Database or Dataset specific later if requested. Also, it is possible the default will switch in the future, so if you care about a specific handling, you should set your own default.