sequel 4.37.0 → 4.38.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e32a73f763f4abf6ea2b3e2833cd0d0a85356842
4
- data.tar.gz: 9856a7e6a4c175f16c745339609b8b4d3d6b4d61
3
+ metadata.gz: fbbe9aec719ae1c6ace4c686bf0e02f352b1283a
4
+ data.tar.gz: 347e71c258109c785c11b55e354fd4f616060cdc
5
5
  SHA512:
6
- metadata.gz: 5286ffd2c900e56b4d07598dd6ecb4fcdf7bfd5694a56537ba4ca29a55f1801055e42d6ccd2b49c2aa655065f63380d8f068ef55602bb81c768947540788afa4
7
- data.tar.gz: 842a025e1ecdcbe2990dbfd5f40ebcf2d9db9408d73e62e73ef4c36e0a56c27affa76a60d780845abb34d23e3108d6783fb3f206f7a13f304daad868d62b2667
6
+ metadata.gz: 3e8ef32de9f9efb9ae6b03598ca6a2809409b51a60fe2759fcd2c1556d8376c08fe31366db86f7016ea25745b16f6323428838f6ebd72c96ef4a7036514cf8ce
7
+ data.tar.gz: 986105b21db0f6ffa3455e4cb8972a0b4af165026455d888bdec4054d3b31c71b8118e036c8f201934e99070ce11b3b88b32908a4d405225a11d97383fa0fd3b
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ === 4.38.0 (2016-09-01)
2
+
3
+ * Support :driver_options option when using the postgres adapter with pg driver (jeremyevans)
4
+
5
+ * Don't use after commit/rollback database hooks if the model instance methods are not overridden (jeremyevans)
6
+
7
+ * Add SQL::NumericMethods#coerce, allowing code such as Sequel.expr{1 - x} (jeremyevans)
8
+
9
+ * Support ** operator for exponentiation on expressions, similar to +, -, *, and / (jeremyevans)
10
+
11
+ * Add Sequel::SQLTime.date= to set the date used for SQLTime instances (jeremyevans)
12
+
1
13
  === 4.37.0 (2016-08-01)
2
14
 
3
15
  * Add support for regular expression matching on Oracle 10g+ using REGEXP_LIKE (johndcaldwell) (#1221)
@@ -40,6 +40,16 @@ All of Sequel's extensions to the core classes are stored in Sequel's core_exten
40
40
 
41
41
  Sequel has no internal dependency on the core extensions. This includes Sequel's core, Sequel::Model, and all plugins and extensions that ship with Sequel. However, it is possible that external plugins and extensions will depend on the core extensions. Such plugins and extensions should be updated so that they no longer depend on the core extensions.
42
42
 
43
+ == Refinements
44
+
45
+ Most of the these extensions can be added on a per-file basis using refinements (if you are using Ruby 2.0+). To use refinements, first load them:
46
+
47
+ Sequel.extension :core_refinements
48
+
49
+ Then for each file where you want to use the refinements:
50
+
51
+ using Sequel::CoreRefinements
52
+
43
53
  == Core Extension Methods
44
54
 
45
55
  This section will briefly describe all of the methods added to the core classes, and what the alternative method is that doesn't require the core extensions.
@@ -130,6 +140,11 @@ The standard mathematical operators are defined on Symbol, and return a Sequel n
130
140
  :a - :b # SQL: a - b
131
141
  :a * :b # SQL: a * b
132
142
  :a / :b # SQL: a / b
143
+ :a ** :b # SQL: power(a, b)
144
+
145
+ Sequel also supports ruby's coercion protocols on symbols (note that this does not work when using refinements):
146
+
147
+ 1 + :b # SQL: 1 + b
133
148
 
134
149
  Alternatives:
135
150
 
@@ -137,6 +152,7 @@ Alternatives:
137
152
  Sequel.-(:a, :b)
138
153
  Sequel.*(:a, :b)
139
154
  Sequel./(:a, :b)
155
+ Sequel.**(:a, :b)
140
156
 
141
157
  ==== *
142
158
 
@@ -92,6 +92,9 @@ This works for the standard inequality and arithmetic operators:
92
92
  items.where{price / 100 >= 200}.sql
93
93
  #=> "SELECT * FROM items WHERE ((price / 100) >= 200)
94
94
 
95
+ items.where{price ** 2 >= 200}.sql
96
+ #=> "SELECT * FROM items WHERE (power(price, 2) >= 200)
97
+
95
98
  You use the overloaded bitwise and (&) and or (|) operators to combine expressions:
96
99
 
97
100
  items.where{(price + 100 < 200) & (price * 100 <= 200)}.sql
@@ -331,6 +331,7 @@ The following additional options are supported:
331
331
  as a string, or :float to convert to an infinite float.
332
332
  :connect_timeout :: Set the number of seconds to wait for a connection (default 20, only respected
333
333
  if using the pg library).
334
+ :driver_options :: A hash of options to pass to the underlying driver (only respected if using the pg library)
334
335
  :encoding :: Set the client_encoding to the given string
335
336
  :notice_receiver :: A proc that be called with the PGresult objects that have notice or warning messages.
336
337
  The default notice receiver just prints the messages to stderr, but this can be used
@@ -0,0 +1,67 @@
1
+ = New Features
2
+
3
+ * Sequel::SQL::NumericMethods#coerce has been added, which adds
4
+ support for ruby's coercion protocol when performing numeric
5
+ operations. Previously, Sequel supported code like:
6
+
7
+ Sequel.expr{a - 1}
8
+
9
+ This is because a in this case returns a Sequel::SQL::Indentifier,
10
+ which defines #- to return a Sequel::SQL::NumericExpression. By
11
+ supporting #coerce, the following code now also works:
12
+
13
+ Sequel.expr{1 - a}
14
+
15
+ This is because Integer#- calls #coerce on the argument if it is
16
+ defined (ruby's coercion protocol). Previously, you had to handle
17
+ this differently, using something like:
18
+
19
+ Sequel.expr(1) - a
20
+ # or
21
+ Sequel.-(1, a)
22
+
23
+ * Sequel now supports the ** operator for exponentiation on
24
+ expressions, similar to the +, -, *, and / operators. Sequel uses
25
+ the database power function to implement this by default on the
26
+ databases that support it (most of them). On Access, it uses the ^
27
+ operator, on Derby it is emulated using a combination of exp/ln
28
+ (with some loss of precision). SQLite doesn't support a power
29
+ function at all, but Sequel emulates it using multiplication for
30
+ known integer exponents.
31
+
32
+ * Sequel::SQLTime.date= has been added, which allows you to set the
33
+ date used for Sequel::SQLTime instances. Sequel::SQLTime is a
34
+ subclass of Time that is literalized using only the time components,
35
+ and is the ruby class used to store values of database time columns
36
+ on most adapters. Sequel::SQLTime defaults to using the current
37
+ date, but you can now set a specific date, for more consistency with
38
+ some drivers (Mysql2 uses 2000-01-01, tiny_tds uses 1900-01-01).
39
+
40
+ * The postgres adapter now supports a :driver_options option when
41
+ using the pg driver, which is passed directly to pg. This can be
42
+ used to specify a client SSL certificate or to specify the
43
+ certificate authority root certificate when using
44
+ :sslmode=>'verify-full'.
45
+
46
+ = Other Improvements
47
+
48
+ * Sequel no longer uses after_commit/rollback database hooks by
49
+ default if the after_commit/after_rollback model methods are not
50
+ overridden. This provides a performance speedup, but the main
51
+ benefit is that it no longer causes memory issues when saving a
52
+ large number of model instances in a single transaction, and it
53
+ also works with prepared transactions/2 phase commit. You can
54
+ still set use_after_commit_rollback= manually to force the
55
+ after_commit/rollback setting.
56
+
57
+ Note that Sequel 5 will move after_commit/rollback model hooks to
58
+ a plugin, and the default and recommended approach will be to use
59
+ the database after_commit/rollback hooks in the after_save or
60
+ similar model hooks.
61
+
62
+ = Backwards Compatibility
63
+
64
+ * The Sequel::Model use_after_commit_rollback class and instance
65
+ methods now return nil by default instead of true. nil now
66
+ indicates the default behavior of checking whether the appropriate
67
+ model hook has been defined, and only adding a database hook if so.
@@ -368,6 +368,7 @@ The standard mathematical operates are defined on most Sequel-specific expressio
368
368
  Sequel.expr(:table__column) - 1 # "table"."column" - 1
369
369
  Sequel.qualify(:table, :column) * 1 # "table"."column" * 1
370
370
  Sequel.expr(:column) / 1 # "column" / 1
371
+ Sequel.expr(:column) ** 1 # power("column", 1)
371
372
 
372
373
  You can also call the operator methods directly on the Sequel module:
373
374
 
@@ -375,15 +376,12 @@ You can also call the operator methods directly on the Sequel module:
375
376
  Sequel.-(:table__column, 1) # "table"."column" - 1
376
377
  Sequel.*(Sequel.qualify(:table, :column), 1) # "table"."column" * 1
377
378
  Sequel./(:column, 1) # "column" / 1
379
+ Sequel.**(:column, 1) # power("column", 1)
378
380
 
379
- Note that the following does not work:
381
+ Note that since Sequel implements support for ruby's coercion protocol, the following also works:
380
382
 
381
- 1 + Sequel.expr(:column) # raises TypeError
382
-
383
- For commutative operates such as + and *, this isn't a problem as you can just reorder, but non-commutative operators such as - and / cannot be expressed directly. The solution is to use one of the methods on the Sequel module:
384
-
385
- Sequel.expr(1) / :column # (1 / "column")
386
- Sequel./(1, :column) # (1 / "column")
383
+ 1 + Sequel.expr(:column)
384
+ 1 - Sequel.qualify(:table__column)
387
385
 
388
386
  === Boolean Operators (AND OR)
389
387
 
@@ -224,6 +224,12 @@ module Sequel
224
224
  complex_expression_emulate_append(sql, op, args)
225
225
  when :&, :|, :^, :<<, :>>
226
226
  raise Error, "Derby doesn't support the #{op} operator"
227
+ when :**
228
+ sql << 'exp('
229
+ literal_append(sql, args[1])
230
+ sql << ' * ln('
231
+ literal_append(sql, args[0])
232
+ sql << "))"
227
233
  when :extract
228
234
  sql << args.at(0).to_s << PAREN_OPEN
229
235
  literal_append(sql, args.at(1))
@@ -227,8 +227,8 @@ module Sequel
227
227
  # client encoding for the connection, :connect_timeout is a
228
228
  # connection timeout in seconds, :sslmode sets whether postgres's
229
229
  # sslmode, and :notice_receiver handles server notices in a proc.
230
- # :connect_timeout, :ssl_mode, and :notice_receiver are only supported
231
- # if the pg driver is used.
230
+ # :connect_timeout, :driver_options, :sslmode, and :notice_receiver
231
+ # are only supported if the pg driver is used.
232
232
  def connect(server)
233
233
  opts = server_opts(server)
234
234
  if SEQUEL_POSTGRES_USES_PG
@@ -241,6 +241,7 @@ module Sequel
241
241
  :connect_timeout => opts[:connect_timeout] || 20,
242
242
  :sslmode => opts[:sslmode]
243
243
  }.delete_if { |key, value| blank_object?(value) }
244
+ connection_params.merge!(opts[:driver_options]) if opts[:driver_options]
244
245
  conn = Adapter.connect(connection_params)
245
246
 
246
247
  conn.instance_variable_set(:@prepared_statements, {})
@@ -157,6 +157,12 @@ module Sequel
157
157
  c ||= true
158
158
  end
159
159
  sql << PAREN_CLOSE
160
+ when :**
161
+ sql << PAREN_OPEN
162
+ literal_append(sql, args[0])
163
+ sql << ' ^ '
164
+ literal_append(sql, args[1])
165
+ sql << PAREN_CLOSE
160
166
  when :extract
161
167
  part = args.at(0)
162
168
  raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part]
@@ -555,6 +555,31 @@ module Sequel
555
555
  complex_expression_sql_append(sql, (op == :"NOT ILIKE" ? :ILIKE : :LIKE), args)
556
556
  when :^
557
557
  complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.lit(["((~(", " & ", ")) & (", " | ", "))"], a, b, a, b)}
558
+ when :**
559
+ unless (exp = args[1]).is_a?(Integer)
560
+ raise(Sequel::Error, "can only emulate exponentiation on SQLite if exponent is an integer, given #{exp.inspect}")
561
+ end
562
+ case exp
563
+ when 0
564
+ sql << '1'
565
+ else
566
+ sql << '('
567
+ arg = args.at(0)
568
+ if exp < 0
569
+ invert = true
570
+ exp = exp.abs
571
+ sql << '(1.0 / ('
572
+ end
573
+ (exp - 1).times do
574
+ literal_append(sql, arg)
575
+ sql << " * "
576
+ end
577
+ literal_append(sql, arg)
578
+ sql << PAREN_CLOSE
579
+ if invert
580
+ sql << "))"
581
+ end
582
+ end
558
583
  when :extract
559
584
  part = args.at(0)
560
585
  raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part]
@@ -476,6 +476,8 @@ module Sequel
476
476
  sql << PAREN_CLOSE
477
477
  when :ILIKE, :'NOT ILIKE'
478
478
  complex_expression_sql_append(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|v| Sequel.function(:UPPER, v)})
479
+ when :**
480
+ function_sql_append(sql, Sequel.function(:power, *args))
479
481
  when *TWO_ARITY_OPERATORS
480
482
  if REGEXP_OPERATORS.include?(op) && !supports_regexp?
481
483
  raise InvalidOperation, "Pattern matching via regular expressions is not supported on #{db.database_type}"
@@ -10,6 +10,11 @@
10
10
  #
11
11
  # DB.extension(:connection_expiration)
12
12
  #
13
+ # The default connection timeout is 14400 seconds (4 hours).
14
+ # To override it:
15
+ #
16
+ # DB.pool.connection_expiration_timeout = 3600 # 1 hour
17
+ #
13
18
  # Note that this extension only affects the default threaded
14
19
  # and the sharded threaded connection pool. The single
15
20
  # threaded and sharded single threaded connection pools are
@@ -117,7 +117,7 @@ module Sequel
117
117
  @strict_param_setting = true
118
118
  @typecast_empty_string_to_nil = true
119
119
  @typecast_on_assignment = true
120
- @use_after_commit_rollback = true
120
+ @use_after_commit_rollback = nil
121
121
  @use_transactions = true
122
122
 
123
123
  Sequel.require %w"default_inflections inflections plugins dataset_module base exceptions errors", "model"
@@ -1946,7 +1946,8 @@ module Sequel
1946
1946
  # allow running inside a transaction
1947
1947
  def _destroy(opts)
1948
1948
  sh = {:server=>this_server}
1949
- db.after_rollback(sh){after_destroy_rollback} if uacr = use_after_commit_rollback
1949
+ uacr = use_after_commit_rollback
1950
+ db.after_rollback(sh){after_destroy_rollback} if uacr.nil? ? (method(:after_destroy_rollback).owner != InstanceMethods) : uacr
1950
1951
  called = false
1951
1952
  around_destroy do
1952
1953
  called = true
@@ -1956,7 +1957,7 @@ module Sequel
1956
1957
  true
1957
1958
  end
1958
1959
  raise_hook_failure(:around_destroy) unless called
1959
- db.after_commit(sh){after_destroy_commit} if uacr
1960
+ db.after_commit(sh){after_destroy_commit} if uacr.nil? ? (method(:after_destroy_commit).owner != InstanceMethods) : uacr
1960
1961
  self
1961
1962
  end
1962
1963
 
@@ -2025,7 +2026,8 @@ module Sequel
2025
2026
  # it's own transaction.
2026
2027
  def _save(opts)
2027
2028
  sh = {:server=>this_server}
2028
- db.after_rollback(sh){after_rollback} if uacr = use_after_commit_rollback
2029
+ uacr = use_after_commit_rollback
2030
+ db.after_rollback(sh){after_rollback} if uacr.nil? ? (method(:after_rollback).owner != InstanceMethods) : uacr
2029
2031
  pk = nil
2030
2032
  called_save = false
2031
2033
  called_cu = false
@@ -2071,7 +2073,7 @@ module Sequel
2071
2073
  end
2072
2074
  raise_hook_failure(:around_save) unless called_save
2073
2075
  _after_save(pk)
2074
- db.after_commit(sh){after_commit} if uacr
2076
+ db.after_commit(sh){after_commit} if uacr.nil? ? (method(:after_commit).owner != InstanceMethods) : uacr
2075
2077
  self
2076
2078
  end
2077
2079
 
@@ -45,10 +45,21 @@ module Sequel
45
45
  # Time subclass that gets literalized with only the time value, so it operates
46
46
  # like a standard SQL time type.
47
47
  class SQLTime < ::Time
48
- # Create a new SQLTime instance given an hour, minute, and second.
49
- def self.create(hour, minute, second, usec = 0)
50
- t = now
51
- local(t.year, t.month, t.day, hour, minute, second, usec)
48
+ @date = nil
49
+
50
+ class << self
51
+ # Set the date used for SQLTime instances.
52
+ attr_writer :date
53
+
54
+ def date
55
+ @date || now
56
+ end
57
+
58
+ # Create a new SQLTime instance given an hour, minute, and second.
59
+ def create(hour, minute, second, usec = 0)
60
+ t = date
61
+ local(t.year, t.month, t.day, hour, minute, second, usec)
62
+ end
52
63
  end
53
64
 
54
65
  # Return a string in HH:MM:SS format representing the time.
@@ -163,9 +174,9 @@ module Sequel
163
174
  :'NOT ILIKE'=>:ILIKE}
164
175
 
165
176
  # Standard mathematical operators used in +NumericMethods+
166
- MATHEMATICAL_OPERATORS = [:+, :-, :/, :*]
177
+ MATHEMATICAL_OPERATORS = [:+, :-, :/, :*, :**]
167
178
 
168
- # Bitwise mathematical operators used in +NumericMethods+
179
+ # Bitwise mathematical operators used in +BitwiseMethods+
169
180
  BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>, :%]
170
181
 
171
182
  # Operators that check for equality
@@ -190,10 +201,10 @@ module Sequel
190
201
  LIKE_OPERATORS = [:LIKE, :'NOT LIKE', :ILIKE, :'NOT ILIKE']
191
202
 
192
203
  # Operator symbols that take exactly two arguments
193
- TWO_ARITY_OPERATORS = EQUALITY_OPERATORS + INEQUALITY_OPERATORS + IS_OPERATORS + IN_OPERATORS + REGEXP_OPERATORS + LIKE_OPERATORS
204
+ TWO_ARITY_OPERATORS = EQUALITY_OPERATORS + INEQUALITY_OPERATORS + IS_OPERATORS + IN_OPERATORS + REGEXP_OPERATORS + LIKE_OPERATORS + [:**]
194
205
 
195
206
  # Operator symbols that take one or more arguments
196
- N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS + BITWISE_OPERATORS
207
+ N_ARITY_OPERATORS = [:AND, :OR, :'||'] + MATHEMATICAL_OPERATORS + BITWISE_OPERATORS - [:**]
197
208
 
198
209
  # Operator symbols that take only a single argument
199
210
  ONE_ARITY_OPERATORS = [:NOT, :NOOP, :'B~']
@@ -775,8 +786,21 @@ module Sequel
775
786
  #
776
787
  # :a + 'b' # "a" || 'b'
777
788
  module NumericMethods
778
- ComplexExpression::MATHEMATICAL_OPERATORS.each do |o|
779
- module_eval("def #{o}(o) NumericExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__) unless o == :+
789
+ (ComplexExpression::MATHEMATICAL_OPERATORS - [:+]).each do |o|
790
+ module_eval("def #{o}(o) NumericExpression.new(#{o.inspect}, self, o) end", __FILE__, __LINE__)
791
+ end
792
+
793
+ # If the argument given is Numeric, treat it as a NumericExpression,
794
+ # allowing code such as:
795
+ #
796
+ # 1 + Sequel.expr(:x) # SQL: (1 + x)
797
+ # Sequel.expr{1 - x(y)} # SQL: (1 - x(y))
798
+ def coerce(other)
799
+ if other.is_a?(Numeric)
800
+ [SQL::NumericExpression.new(:NOOP, other), self]
801
+ else
802
+ super
803
+ end
780
804
  end
781
805
 
782
806
  # Use || as the operator when called with StringExpression and String instances,
@@ -852,6 +876,13 @@ module Sequel
852
876
  END
853
877
  end
854
878
  end
879
+
880
+ # Return NumericExpression for the exponentiation:
881
+ #
882
+ # Sequel.**(2, 3) # SQL: power(2, 3)
883
+ def **(a, b)
884
+ SQL::NumericExpression.new(:**, a, b)
885
+ end
855
886
 
856
887
  # Invert the given expression. Returns a <tt>Sequel::SQL::BooleanExpression</tt>
857
888
  # created from this argument, not matching all of the conditions.
@@ -5,7 +5,7 @@ module Sequel
5
5
  MAJOR = 4
6
6
  # The minor version of Sequel. Bumped for every non-patch level
7
7
  # release, generally around once a month.
8
- MINOR = 37
8
+ MINOR = 38
9
9
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
10
10
  # releases that fix regressions from previous versions.
11
11
  TINY = 0
@@ -134,6 +134,7 @@ describe "Blockless Ruby Filters" do
134
134
  @d.lit(Sequel.expr(:x) - true).must_equal "(x - 't')"
135
135
  @d.lit(Sequel.expr(:x) / false).must_equal "(x / 'f')"
136
136
  @d.lit(Sequel.expr(:x) * nil).must_equal '(x * NULL)'
137
+ @d.lit(Sequel.expr(:x) ** 1).must_equal 'power(x, 1)'
137
138
  @d.lit(Sequel.join([:x, nil])).must_equal '(x || NULL)'
138
139
  end
139
140
 
@@ -145,6 +146,17 @@ describe "Blockless Ruby Filters" do
145
146
  @d.lit(Sequel.expr(:x) + Sequel.expr(:y).like('a')).must_equal "(x + (y LIKE 'a' ESCAPE '\\'))"
146
147
  @d.lit(Sequel.expr(:x) - ~Sequel.expr(:y).like('a')).must_equal "(x - (y NOT LIKE 'a' ESCAPE '\\'))"
147
148
  @d.lit(Sequel.join([:x, ~Sequel.expr(:y).like('a')])).must_equal "(x || (y NOT LIKE 'a' ESCAPE '\\'))"
149
+ @d.lit(Sequel.expr(:x) ** (Sequel.expr(:y) + 1)).must_equal 'power(x, (y + 1))'
150
+ end
151
+
152
+ it "should allow mathematical or string operations on numerics when argument is a generic or numeric expressions" do
153
+ @d.lit(1 + Sequel.expr(:x)).must_equal '(1 + x)'
154
+ @d.lit(2**65 - Sequel.+(:x, 1)).must_equal "(#{2**65} - (x + 1))"
155
+ @d.lit(1.0 / Sequel.function(:x)).must_equal '(1.0 / x())'
156
+ @d.lit(BigDecimal.new('1.0') * Sequel.expr(:a__y)).must_equal '(1.0 * a.y)'
157
+ @d.lit(2 ** Sequel.cast(:x, Integer)).must_equal 'power(2, CAST(x AS integer))'
158
+ @d.lit(1 + Sequel.lit('x')).must_equal '(1 + x)'
159
+ @d.lit(1 + Sequel.lit('?', :x)).must_equal '(1 + x)'
148
160
  end
149
161
 
150
162
  it "should support AND conditions via &" do
@@ -192,6 +204,7 @@ describe "Blockless Ruby Filters" do
192
204
  @d.l(Sequel.lit('x').like('a')).must_equal '(x LIKE \'a\' ESCAPE \'\\\')'
193
205
  @d.l(Sequel.lit('x') + 1 > 100).must_equal '((x + 1) > 100)'
194
206
  @d.l((Sequel.lit('x') * :y) < 100.01).must_equal '((x * y) < 100.01)'
207
+ @d.l((Sequel.lit('x') ** :y) < 100.01).must_equal '(power(x, y) < 100.01)'
195
208
  @d.l((Sequel.lit('x') - Sequel.expr(:y)/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
196
209
  @d.l((Sequel.lit('z') * ((Sequel.lit('x') / :y)/(Sequel.expr(:x) + :y))) <= 100).must_equal '((z * (x / y / (x + y))) <= 100)'
197
210
  @d.l(~((((Sequel.lit('x') - :y)/(Sequel.expr(:x) + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
@@ -397,6 +410,7 @@ describe "Blockless Ruby Filters" do
397
410
  @d.lit(d - 1).must_equal '((SELECT a FROM items) - 1)'
398
411
  @d.lit(d * 1).must_equal '((SELECT a FROM items) * 1)'
399
412
  @d.lit(d / 1).must_equal '((SELECT a FROM items) / 1)'
413
+ @d.lit(d ** 1).must_equal 'power((SELECT a FROM items), 1)'
400
414
 
401
415
  @d.lit(d => 1).must_equal '((SELECT a FROM items) = 1)'
402
416
  @d.lit(Sequel.~(d => 1)).must_equal '((SELECT a FROM items) != 1)'
@@ -665,6 +679,7 @@ describe Sequel::SQL::VirtualRow do
665
679
  @d.l{|o| o.+(1, :b) > 2}.must_equal '((1 + "b") > 2)'
666
680
  @d.l{|o| o.-(1, :b) < 2}.must_equal '((1 - "b") < 2)'
667
681
  @d.l{|o| o.*(1, :b) >= 2}.must_equal '((1 * "b") >= 2)'
682
+ @d.l{|o| o.**(1, :b) >= 2}.must_equal '(power(1, "b") >= 2)'
668
683
  @d.l{|o| o./(1, :b) <= 2}.must_equal '((1 / "b") <= 2)'
669
684
  @d.l{|o| o.~(:a=>1)}.must_equal '("a" != 1)'
670
685
  @d.l{|o| o.~([[:a, 1], [:b, 2]])}.must_equal '(("a" != 1) OR ("b" != 2))'
@@ -934,6 +949,16 @@ describe "Sequel core extension replacements" do
934
949
  end
935
950
  end
936
951
 
952
+ it "Sequel.** should use power function if given 2 arguments" do
953
+ l(Sequel.**(1, 2), 'power(1, 2)')
954
+ end
955
+
956
+ it "Sequel.** should raise if not given 2 arguments" do
957
+ proc{Sequel.**}.must_raise(ArgumentError)
958
+ proc{Sequel.**(1)}.must_raise(ArgumentError)
959
+ proc{Sequel.**(1, 2, 3)}.must_raise(ArgumentError)
960
+ end
961
+
937
962
  it "Sequel.like should use a LIKE expression" do
938
963
  l(Sequel.like('a', 'b'), "('a' LIKE 'b' ESCAPE '\\')")
939
964
  l(Sequel.like(:a, :b), "(a LIKE b ESCAPE '\\')")
@@ -1048,12 +1073,24 @@ describe "Sequel::SQLTime" do
1048
1073
  before do
1049
1074
  @db = Sequel.mock
1050
1075
  end
1076
+ after do
1077
+ Sequel::SQLTime.date = nil
1078
+ end
1051
1079
 
1052
1080
  it ".create should create from hour, minutes, seconds and optional microseconds" do
1053
1081
  @db.literal(Sequel::SQLTime.create(1, 2, 3)).must_equal "'01:02:03.000000'"
1054
1082
  @db.literal(Sequel::SQLTime.create(1, 2, 3, 500000)).must_equal "'01:02:03.500000'"
1055
1083
  end
1056
1084
 
1085
+ it ".create should use today's date by default" do
1086
+ Sequel::SQLTime.create(1, 2, 3).strftime('%Y-%m-%d').must_equal Date.today.strftime('%Y-%m-%d')
1087
+ end
1088
+
1089
+ it ".create should use specific date if set" do
1090
+ Sequel::SQLTime.date = Date.new(2000)
1091
+ Sequel::SQLTime.create(1, 2, 3).strftime('%Y-%m-%d').must_equal Date.new(2000).strftime('%Y-%m-%d')
1092
+ end
1093
+
1057
1094
  it "#to_s should include hour, minute, and second by default" do
1058
1095
  Sequel::SQLTime.create(1, 2, 3).to_s.must_equal "01:02:03"
1059
1096
  Sequel::SQLTime.create(1, 2, 3, 500000).to_s.must_equal "01:02:03"
@@ -1082,6 +1119,7 @@ describe "Sequel::SQL::Wrapper" do
1082
1119
  s = Sequel::SQL::Wrapper.new(o)
1083
1120
  @ds.literal(s).must_equal "foo"
1084
1121
  @ds.literal(s+1).must_equal "(foo + 1)"
1122
+ @ds.literal(s**1).must_equal "power(foo, 1)"
1085
1123
  @ds.literal(s & true).must_equal "(foo AND 't')"
1086
1124
  @ds.literal(s < 1).must_equal "(foo < 1)"
1087
1125
  @ds.literal(s.sql_subscript(1)).must_equal "foo[1]"
@@ -87,12 +87,17 @@ describe "Core extensions" do
87
87
  @d.l(~:x__y).must_equal 'NOT x.y'
88
88
  end
89
89
 
90
- it "should support + - * / via Symbol#+,-,*,/" do
90
+ it "should support + - * / power via Symbol#+,-,*,/,**" do
91
91
  @d.l(:x + 1 > 100).must_equal '((x + 1) > 100)'
92
92
  @d.l((:x * :y) < 100.01).must_equal '((x * y) < 100.01)'
93
93
  @d.l((:x - :y/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
94
94
  @d.l((((:x - :y)/(:x + :y))*:z) <= 100).must_equal '((((x - y) / (x + y)) * z) <= 100)'
95
95
  @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
96
+ @d.l(~((((:x ** :y)/(:x + :y))*:z) <= 100)).must_equal '(((power(x, y) / (x + y)) * z) > 100)'
97
+ end
98
+
99
+ it "should support coercion for symbols" do
100
+ @d.l(1 + :x > 2).must_equal '((1 + x) > 2)'
96
101
  end
97
102
 
98
103
  it "should support LIKE via Symbol#like" do
@@ -22,12 +22,13 @@ describe "Core refinements" do
22
22
  @d.l(~:x__y).must_equal 'NOT x.y'
23
23
  end
24
24
 
25
- it "should support + - * / via Symbol#+,-,*,/" do
25
+ it "should support + - * / power via Symbol#+,-,*,/,**" do
26
26
  @d.l(:x + 1 > 100).must_equal '((x + 1) > 100)'
27
27
  @d.l((:x * :y) < 100.01).must_equal '((x * y) < 100.01)'
28
28
  @d.l((:x - :y/2) >= 100000000000000000000000000000000000).must_equal '((x - (y / 2)) >= 100000000000000000000000000000000000)'
29
29
  @d.l((((:x - :y)/(:x + :y))*:z) <= 100).must_equal '((((x - y) / (x + y)) * z) <= 100)'
30
30
  @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).must_equal '((((x - y) / (x + y)) * z) > 100)'
31
+ @d.l(~((((:x ** :y)/(:x + :y))*:z) <= 100)).must_equal '(((power(x, y) / (x + y)) * z) > 100)'
31
32
  end
32
33
 
33
34
  it "should support LIKE via Symbol#like" do
@@ -1297,6 +1297,14 @@ describe "Sequel::Dataset DSL support" do
1297
1297
  @ds.get{a * b}.to_i.must_equal 200
1298
1298
  @ds.get{a / b}.to_i.must_equal 2
1299
1299
  end
1300
+
1301
+ it "should work with exponentiation operator" do
1302
+ @ds.insert(:a=>2)
1303
+ (-4..4).each do |i|
1304
+ # Allow minor differences due to emulation issues on some adapters
1305
+ @ds.get{(a / 1.0) ** i}.to_f.must_be_close_to((2**i).to_f)
1306
+ end
1307
+ end
1300
1308
 
1301
1309
  cspecify "should work with bitwise shift operators", :derby do
1302
1310
  @ds.insert(3, 2)
@@ -601,4 +601,44 @@ describe "Model#after_commit and #after_rollback" do
601
601
  o.save
602
602
  @db.sqls.must_equal ['BEGIN', 'as', 'COMMIT']
603
603
  end
604
+
605
+ it "should handle use_after_commit_rollback when subclassing after loading" do
606
+ @m = Class.new(Sequel::Model(@db[:items]))
607
+ @m.use_transactions = true
608
+ o = @m.load({})
609
+ @db.sqls
610
+ o.save
611
+ @db.sqls.must_equal ['BEGIN', 'COMMIT']
612
+
613
+ c = Class.new(@m)
614
+ o = c.load({})
615
+ def o.after_commit; db.execute 'ac' end
616
+ @db.sqls
617
+ o.save
618
+ @db.sqls.must_equal ['BEGIN', 'COMMIT', 'ac']
619
+
620
+ o = c.load({})
621
+ @db.sqls
622
+ o.save
623
+ @db.sqls.must_equal ['BEGIN', 'COMMIT']
624
+
625
+ c.send(:define_method, :after_commit){db.execute 'ac'}
626
+ o = c.load({})
627
+ @db.sqls
628
+ o.save
629
+ @db.sqls.must_equal ['BEGIN', 'COMMIT', 'ac']
630
+
631
+ c = Class.new(@m)
632
+ c.send(:include, Module.new{def after_commit; db.execute 'ac'; end})
633
+ o = c.load({})
634
+ @db.sqls
635
+ o.save
636
+ @db.sqls.must_equal ['BEGIN', 'COMMIT', 'ac']
637
+
638
+ c.use_after_commit_rollback = false
639
+ o = c.load({})
640
+ @db.sqls
641
+ o.save
642
+ @db.sqls.must_equal ['BEGIN', 'COMMIT']
643
+ end
604
644
  end
@@ -1304,8 +1304,9 @@ describe Sequel::Model, "#(set|update)_(all|only)" do
1304
1304
  end
1305
1305
 
1306
1306
  it "#set_all should set not set restricted fields" do
1307
- @o1.set_all(:x => 1, :use_after_commit_rollback => false)
1308
- @o1.use_after_commit_rollback.must_equal true
1307
+ @o1.use_after_commit_rollback.must_equal nil
1308
+ @o1.set_all(:x => 1, :use_after_commit_rollback => true)
1309
+ @o1.use_after_commit_rollback.must_equal nil
1309
1310
  @o1.values.must_equal(:x => 1)
1310
1311
  end
1311
1312
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.37.0
4
+ version: 4.38.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-01 00:00:00.000000000 Z
11
+ date: 2016-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -238,6 +238,7 @@ extra_rdoc_files:
238
238
  - doc/release_notes/4.35.0.txt
239
239
  - doc/release_notes/4.36.0.txt
240
240
  - doc/release_notes/4.37.0.txt
241
+ - doc/release_notes/4.38.0.txt
241
242
  files:
242
243
  - CHANGELOG
243
244
  - MIT-LICENSE
@@ -364,6 +365,7 @@ files:
364
365
  - doc/release_notes/4.35.0.txt
365
366
  - doc/release_notes/4.36.0.txt
366
367
  - doc/release_notes/4.37.0.txt
368
+ - doc/release_notes/4.38.0.txt
367
369
  - doc/release_notes/4.4.0.txt
368
370
  - doc/release_notes/4.5.0.txt
369
371
  - doc/release_notes/4.6.0.txt