arel_extensions 1.2.23 → 1.3.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +358 -71
- data/Gemfile +8 -8
- data/README.md +86 -0
- data/arel_extensions.gemspec +1 -1
- data/gemfiles/rails5_2.gemfile +8 -7
- data/gemfiles/rails6.gemfile +7 -8
- data/gemfiles/rails6_1.gemfile +6 -7
- data/gemfiles/rails7.gemfile +22 -0
- data/gemspecs/arel_extensions-v1.gemspec +1 -1
- data/gemspecs/arel_extensions-v2.gemspec +1 -1
- data/lib/arel_extensions/aliases.rb +14 -0
- data/lib/arel_extensions/attributes.rb +2 -0
- data/lib/arel_extensions/date_duration.rb +2 -2
- data/lib/arel_extensions/helpers.rb +48 -0
- data/lib/arel_extensions/insert_manager.rb +19 -17
- data/lib/arel_extensions/math.rb +22 -32
- data/lib/arel_extensions/nodes/case.rb +5 -6
- data/lib/arel_extensions/nodes/cast.rb +1 -1
- data/lib/arel_extensions/nodes/date_diff.rb +23 -4
- data/lib/arel_extensions/nodes/format.rb +3 -2
- data/lib/arel_extensions/nodes/function.rb +2 -6
- data/lib/arel_extensions/nodes/json.rb +3 -1
- data/lib/arel_extensions/nodes/length.rb +6 -0
- data/lib/arel_extensions/nodes/replace.rb +0 -8
- data/lib/arel_extensions/nodes/union.rb +1 -1
- data/lib/arel_extensions/nodes/union_all.rb +1 -1
- data/lib/arel_extensions/string_functions.rb +10 -2
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +109 -51
- data/lib/arel_extensions/visitors/mysql.rb +15 -2
- data/lib/arel_extensions/visitors/oracle.rb +8 -3
- data/lib/arel_extensions/visitors/postgresql.rb +21 -11
- data/lib/arel_extensions/visitors/sqlite.rb +6 -3
- data/lib/arel_extensions/visitors/to_sql.rb +14 -9
- data/lib/arel_extensions/visitors.rb +9 -1
- data/lib/arel_extensions.rb +66 -12
- data/test/arelx_test_helper.rb +45 -0
- data/test/database.yml +8 -2
- data/test/real_db_test.rb +5 -1
- data/test/support/fake_record.rb +1 -1
- data/test/visitors/test_to_sql.rb +39 -11
- data/test/with_ar/all_agnostic_test.rb +79 -6
- data/test/with_ar/insert_agnostic_test.rb +6 -2
- data/test/with_ar/test_bulk_sqlite.rb +6 -2
- data/test/with_ar/test_math_sqlite.rb +6 -2
- data/test/with_ar/test_string_mysql.rb +6 -2
- data/test/with_ar/test_string_sqlite.rb +6 -2
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +10 -8
- data/appveyor.yml +0 -44
data/lib/arel_extensions.rb
CHANGED
@@ -33,6 +33,12 @@ class Arel::Nodes::Grouping
|
|
33
33
|
include Arel::OrderPredications
|
34
34
|
end
|
35
35
|
|
36
|
+
class Arel::Nodes::Ordering
|
37
|
+
def eql? other
|
38
|
+
self.hash.eql? other.hash
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
36
42
|
class Arel::Nodes::Function
|
37
43
|
include Arel::Math
|
38
44
|
include Arel::Expressions
|
@@ -46,6 +52,7 @@ if Gem::Version.new(Arel::VERSION) >= Gem::Version.new("7.1.0")
|
|
46
52
|
end
|
47
53
|
|
48
54
|
require 'arel_extensions/version'
|
55
|
+
require 'arel_extensions/aliases'
|
49
56
|
require 'arel_extensions/attributes'
|
50
57
|
require 'arel_extensions/visitors'
|
51
58
|
require 'arel_extensions/nodes'
|
@@ -70,7 +77,17 @@ require 'arel_extensions/nodes/soundex'
|
|
70
77
|
require 'arel_extensions/nodes/cast'
|
71
78
|
require 'arel_extensions/nodes/json'
|
72
79
|
|
73
|
-
|
80
|
+
# It seems like the code in lib/arel_extensions/visitors.rb that is supposed
|
81
|
+
# to inject ArelExtension is not enough. Different versions of the sqlserver
|
82
|
+
# adapter behave differently. It doesn't always proc, so we added this for
|
83
|
+
# coverage.
|
84
|
+
if defined?(Arel::Visitors::SQLServer)
|
85
|
+
Arel::Visitors.const_set('MSSQL', Arel::Visitors::SQLServer)
|
86
|
+
require 'arel_extensions/visitors/mssql'
|
87
|
+
class Arel::Visitors::SQLServer
|
88
|
+
include ArelExtensions::Visitors::MSSQL
|
89
|
+
end
|
90
|
+
end
|
74
91
|
|
75
92
|
module Arel
|
76
93
|
def self.rand
|
@@ -82,11 +99,13 @@ module Arel
|
|
82
99
|
end
|
83
100
|
|
84
101
|
def self.json *expr
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
102
|
+
ArelExtensions::Nodes::Json.new(
|
103
|
+
if expr.length == 1
|
104
|
+
expr.first
|
105
|
+
else
|
106
|
+
expr
|
107
|
+
end
|
108
|
+
)
|
90
109
|
end
|
91
110
|
|
92
111
|
def self.when condition
|
@@ -94,20 +113,31 @@ module Arel
|
|
94
113
|
end
|
95
114
|
|
96
115
|
def self.duration s, expr
|
97
|
-
ArelExtensions::Nodes::Duration.new(s
|
116
|
+
ArelExtensions::Nodes::Duration.new("#{s}i", expr)
|
98
117
|
end
|
99
118
|
|
119
|
+
def self.grouping *v
|
120
|
+
Arel::Nodes::Grouping.new(*v)
|
121
|
+
end
|
122
|
+
|
123
|
+
# The TRUE pseudo literal.
|
100
124
|
def self.true
|
101
|
-
Arel::Nodes::Equality.new(1,1)
|
125
|
+
Arel::Nodes::Equality.new(1, 1)
|
102
126
|
end
|
103
127
|
|
128
|
+
# The FALSE pseudo literal.
|
104
129
|
def self.false
|
105
|
-
Arel::Nodes::Equality.new(1,0)
|
130
|
+
Arel::Nodes::Equality.new(1, 0)
|
131
|
+
end
|
132
|
+
|
133
|
+
# The NULL literal.
|
134
|
+
def self.null
|
135
|
+
Arel::Nodes.build_quoted(nil)
|
106
136
|
end
|
107
137
|
|
108
138
|
def self.tuple *v
|
109
|
-
tmp = Arel
|
110
|
-
Arel
|
139
|
+
tmp = Arel.grouping(nil)
|
140
|
+
Arel.grouping v.map{|e| tmp.convert_to_node(e)}
|
111
141
|
end
|
112
142
|
end
|
113
143
|
|
@@ -117,6 +147,7 @@ class Arel::Attributes::Attribute
|
|
117
147
|
end
|
118
148
|
|
119
149
|
class Arel::Nodes::Function
|
150
|
+
include ArelExtensions::Aliases
|
120
151
|
include ArelExtensions::Math
|
121
152
|
include ArelExtensions::Comparators
|
122
153
|
include ArelExtensions::DateDuration
|
@@ -152,6 +183,9 @@ class Arel::Nodes::Unary
|
|
152
183
|
include ArelExtensions::MathFunctions
|
153
184
|
include ArelExtensions::Comparators
|
154
185
|
include ArelExtensions::Predications
|
186
|
+
def eql? other
|
187
|
+
hash == other.hash
|
188
|
+
end
|
155
189
|
end
|
156
190
|
|
157
191
|
class Arel::Nodes::Binary
|
@@ -161,6 +195,9 @@ class Arel::Nodes::Binary
|
|
161
195
|
include ArelExtensions::Comparators
|
162
196
|
include ArelExtensions::BooleanFunctions
|
163
197
|
include ArelExtensions::Predications
|
198
|
+
def eql? other
|
199
|
+
hash == other.hash
|
200
|
+
end
|
164
201
|
end
|
165
202
|
|
166
203
|
class Arel::Nodes::Equality
|
@@ -177,6 +214,19 @@ end
|
|
177
214
|
class Arel::SelectManager
|
178
215
|
include ArelExtensions::SetFunctions
|
179
216
|
include ArelExtensions::Nodes
|
217
|
+
|
218
|
+
def as table_name
|
219
|
+
Arel::Nodes::TableAlias.new(self, table_name)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Install an alias, if present.
|
223
|
+
def xas table_name
|
224
|
+
if table_name.present?
|
225
|
+
as table_name
|
226
|
+
else
|
227
|
+
self
|
228
|
+
end
|
229
|
+
end
|
180
230
|
end
|
181
231
|
|
182
232
|
class Arel::Nodes::As
|
@@ -186,7 +236,11 @@ end
|
|
186
236
|
class Arel::Table
|
187
237
|
alias_method(:old_alias, :alias) rescue nil
|
188
238
|
def alias(name = "#{self.name}_2")
|
189
|
-
name.
|
239
|
+
if name.present?
|
240
|
+
Arel::Nodes::TableAlias.new(self, name)
|
241
|
+
else
|
242
|
+
self
|
243
|
+
end
|
190
244
|
end
|
191
245
|
end
|
192
246
|
|
data/test/arelx_test_helper.rb
CHANGED
@@ -6,6 +6,51 @@ require 'active_record'
|
|
6
6
|
|
7
7
|
require 'support/fake_record'
|
8
8
|
|
9
|
+
def colored(color, msg)
|
10
|
+
ENV["TERM"] =~ /^xterm|-256color$/ ? "\x1b[#{color}m#{msg}\x1b[89m\x1b[0m" : "#{msg}"
|
11
|
+
end
|
12
|
+
|
13
|
+
YELLOW = "33"
|
14
|
+
|
15
|
+
def warn(msg)
|
16
|
+
$stderr.puts(colored(YELLOW, msg))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load gems specific to databases
|
20
|
+
# NOTE:
|
21
|
+
# It's strongly advised to test each database on its own. Loading multiple
|
22
|
+
# backend gems leads to undefined behavior according to tests; the backend
|
23
|
+
# might not recognize the correct DB visitor and will fallback to `ToSQL`
|
24
|
+
# and screw all tests.
|
25
|
+
#
|
26
|
+
# The issue also seems to be related to arel version: at some point, arel
|
27
|
+
# dropped its wide support for DBs and kept Postgres, MySQL and SQLite.
|
28
|
+
# Here, we're just trying to load the correct ones.
|
29
|
+
db_and_gem = if RUBY_ENGINE == 'jruby'
|
30
|
+
{
|
31
|
+
'oracle' => 'activerecord-oracle_enhanced-adapter',
|
32
|
+
'mssql' => 'activerecord-jdbcsqlserver-adapter'
|
33
|
+
}
|
34
|
+
else
|
35
|
+
{
|
36
|
+
'oracle' => 'activerecord-oracle_enhanced-adapter',
|
37
|
+
'mssql' => 'activerecord-sqlserver-adapter'
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_lib(gem)
|
42
|
+
if gem && (RUBY_ENGINE == 'jruby' || Arel::VERSION.to_i > 9)
|
43
|
+
begin
|
44
|
+
Gem::Specification.find_by_name(gem)
|
45
|
+
require gem
|
46
|
+
rescue Gem::MissingSpecError
|
47
|
+
warn "Warning: failed to load gem #{gem}. Are you sure it's installed?"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
load_lib(db_and_gem[ENV['DB']])
|
53
|
+
|
9
54
|
require 'arel_extensions'
|
10
55
|
Arel::Table.engine = FakeRecord::Base.new
|
11
56
|
|
data/test/database.yml
CHANGED
@@ -9,23 +9,29 @@ jdbc-sqlite:
|
|
9
9
|
mysql:
|
10
10
|
adapter: mysql2
|
11
11
|
database: arext_test
|
12
|
-
username:
|
12
|
+
username: root
|
13
13
|
host: 127.0.0.1
|
14
14
|
port: 3306
|
15
15
|
encoding: utf8
|
16
16
|
jdbc-mysql:
|
17
17
|
adapter: jdbcmysql
|
18
18
|
database: arext_test
|
19
|
-
username:
|
19
|
+
username: root
|
20
20
|
encoding: utf8
|
21
21
|
postgresql:
|
22
22
|
adapter: postgresql
|
23
23
|
database: arext_test
|
24
24
|
username: postgres
|
25
|
+
password: secret
|
26
|
+
host: 127.0.0.1
|
27
|
+
port: 5432
|
25
28
|
jdbc-postgresql:
|
26
29
|
adapter: jdbcpostgresql
|
27
30
|
database: arext_test
|
28
31
|
username: postgres
|
32
|
+
password: secret
|
33
|
+
host: 127.0.0.1
|
34
|
+
port: 5432
|
29
35
|
oracle:
|
30
36
|
adapter: oracle_enhanced
|
31
37
|
database: xe
|
data/test/real_db_test.rb
CHANGED
@@ -8,7 +8,11 @@ require 'arel_extensions'
|
|
8
8
|
def setup_db
|
9
9
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
10
10
|
ActiveRecord::Base.establish_connection(ENV['DB'].try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
11
|
-
ActiveRecord::
|
11
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
12
|
+
ActiveRecord.default_timezone = :utc
|
13
|
+
else
|
14
|
+
ActiveRecord::Base.default_timezone = :utc
|
15
|
+
end
|
12
16
|
@cnx = ActiveRecord::Base.connection
|
13
17
|
if ActiveRecord::Base.connection.adapter_name =~ /sqlite/i
|
14
18
|
$sqlite = true
|
data/test/support/fake_record.rb
CHANGED
@@ -105,7 +105,7 @@ module FakeRecord
|
|
105
105
|
attr_reader :spec, :connection
|
106
106
|
|
107
107
|
def initialize
|
108
|
-
@spec = Spec.new(:adapter => 'america')
|
108
|
+
@spec = Spec.new({:adapter => 'america'})
|
109
109
|
@connection = Connection.new
|
110
110
|
@connection.visitor = Arel::Visitors::ToSql.new(connection)
|
111
111
|
end
|
@@ -5,6 +5,27 @@ module ArelExtensions
|
|
5
5
|
module VisitorToSql
|
6
6
|
describe 'the to_sql visitor' do
|
7
7
|
before do
|
8
|
+
if Arel::Table.engine.is_a?(ActiveRecord::Base)
|
9
|
+
puts "This is a hack."
|
10
|
+
# As a matter of fact, if the whole if-block is removed, the to_sql
|
11
|
+
# test become flaky.
|
12
|
+
#
|
13
|
+
# The first time `Arel::Table.engine` is called
|
14
|
+
# from `ArelExtenstions::column_of_via_arel_table(table_name, column_name)`
|
15
|
+
# in `lib/arel_extensions/helpers.rb`
|
16
|
+
# will almost always fail. It's important to note that when the test
|
17
|
+
# fails, it's always on 1 test case, and every subsequent test that
|
18
|
+
# calls to these methods passes.
|
19
|
+
#
|
20
|
+
# After investigation, it turned out that `Arel::Table.engine` will be
|
21
|
+
# of type `ActiveRecord::Base` instead of the expected `FakeRecord::Base`
|
22
|
+
# as set in this `before` block, in the `@conn` instance variable.
|
23
|
+
# Subsequent calls to `column_of_via_arel_table` will have
|
24
|
+
# `Arel::Table.engine` of the expected type.
|
25
|
+
#
|
26
|
+
# It is still unclear why the call in the condition of this if-block
|
27
|
+
# fixes this behavior.
|
28
|
+
end
|
8
29
|
@conn = FakeRecord::Base.new
|
9
30
|
Arel::Table.engine = @conn
|
10
31
|
@visitor = Arel::Visitors::ToSql.new @conn.connection
|
@@ -282,16 +303,23 @@ module ArelExtensions
|
|
282
303
|
.must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END ILIKE 'value'}
|
283
304
|
end
|
284
305
|
|
285
|
-
it "should be possible to use as on anything" do
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
.
|
306
|
+
it "should be possible to use as/xas on anything" do
|
307
|
+
{
|
308
|
+
@table[:name] => %{"users"."name" AS alias},
|
309
|
+
@table[:name].concat(' test') => %{CONCAT("users"."name", ' test') AS alias},
|
310
|
+
(@table[:name] + ' test') => %{CONCAT("users"."name", ' test') AS alias},
|
311
|
+
(@table[:age] + 42) => %{("users"."age" + 42) AS alias},
|
312
|
+
@table[:name].coalesce('') => %{COALESCE("users"."name", '') AS alias},
|
313
|
+
Arel::Nodes.build_quoted('test') => %{'test' AS alias},
|
314
|
+
@table.project(@table[:name]) => %{(SELECT "users"."name" FROM "users") "alias"},
|
315
|
+
@table[:name].when("smith").then("cool").else("uncool") => %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias},
|
316
|
+
}.each do |exp, res|
|
317
|
+
_(compile(exp.as('alias'))).must_be_like res
|
318
|
+
_(compile(exp.xas('alias'))).must_be_like res
|
319
|
+
|
320
|
+
res_no_alias = res.gsub(/\s*(?:AS alias|"alias")\s*\z/, '')
|
321
|
+
_(compile(exp.xas(nil))).must_be_like res_no_alias
|
322
|
+
end
|
295
323
|
end
|
296
324
|
|
297
325
|
it "should accept comparators on functions" do
|
@@ -373,7 +401,7 @@ module ArelExtensions
|
|
373
401
|
end
|
374
402
|
|
375
403
|
it "should respecting Grouping" do
|
376
|
-
g = ->(*v) { Arel
|
404
|
+
g = ->(*v) { Arel.grouping(v) }
|
377
405
|
_(compile(g[@table[:id], @table[:age]].in [g[1, 42]]))
|
378
406
|
.must_be_like %{("users"."id", "users"."age") IN ((1, 42))}
|
379
407
|
_(compile(g[@table[:id], @table[:age]].in [g[1, 42], g[2, 51]]))
|
@@ -2,7 +2,7 @@ require 'arelx_test_helper'
|
|
2
2
|
require 'date'
|
3
3
|
|
4
4
|
module ArelExtensions
|
5
|
-
module
|
5
|
+
module WithAr
|
6
6
|
class ListTest < Minitest::Test
|
7
7
|
require 'minitest/pride'
|
8
8
|
def connect_db
|
@@ -14,7 +14,11 @@ module ArelExtensions
|
|
14
14
|
@env_db = ENV['DB']
|
15
15
|
end
|
16
16
|
ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
17
|
-
ActiveRecord::
|
17
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
18
|
+
ActiveRecord.default_timezone = :utc
|
19
|
+
else
|
20
|
+
ActiveRecord::Base.default_timezone = :utc
|
21
|
+
end
|
18
22
|
@cnx = ActiveRecord::Base.connection
|
19
23
|
$sqlite = @cnx.adapter_name =~ /sqlite/i
|
20
24
|
$load_extension_disabled ||= false
|
@@ -29,7 +33,7 @@ module ArelExtensions
|
|
29
33
|
t.column :name, :string
|
30
34
|
t.column :comments, :text
|
31
35
|
t.column :created_at, :date
|
32
|
-
t.column :updated_at, :datetime
|
36
|
+
t.column :updated_at, :datetime, precision: nil
|
33
37
|
t.column :duration, :time
|
34
38
|
t.column :other, :string
|
35
39
|
t.column :score, :decimal, :precision => 20, :scale => 10
|
@@ -166,6 +170,12 @@ module ArelExtensions
|
|
166
170
|
# Since Arel10 (Rails6.1), some unwanted behaviors on aggregated calculation were present.
|
167
171
|
# This should works no matter which version of rails is used
|
168
172
|
assert User.group(:score).average(:id).values.all?{|e| !e.nil?}
|
173
|
+
|
174
|
+
# Since Rails 7, a patch to calculations.rb has tirggered a double
|
175
|
+
# quoting of the alias name. See https://github.com/rails/rails/commit/7e6e9091e55c3357b0162d44b6ab955ed0c718d5
|
176
|
+
# Before the patch that fixed this the following error would occur:
|
177
|
+
# ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: zero-length delimited identifier at or near """"
|
178
|
+
assert User.group(:score).count(:id).values.all?{|e| !e.nil?}
|
169
179
|
end
|
170
180
|
|
171
181
|
# String Functions
|
@@ -358,9 +368,70 @@ module ArelExtensions
|
|
358
368
|
|
359
369
|
def test_format
|
360
370
|
assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
|
361
|
-
skip "SQL Server does not accept any format" if @env_db == 'mssql'
|
362
371
|
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
|
363
372
|
assert_equal '12:42%', t(@lucas, @updated_at.format('%R%%'))
|
373
|
+
|
374
|
+
# The following tests will ensure proper conversion of timestamps to
|
375
|
+
# requested timezones.
|
376
|
+
#
|
377
|
+
# The names of the timezones is highly dependant on the underlying
|
378
|
+
# operating system, and this is why we need to handle each database
|
379
|
+
# separately: the images we're using to test these databases are
|
380
|
+
# different. So don't rely on the provided examples. Your setup is your
|
381
|
+
# reference.
|
382
|
+
#
|
383
|
+
# One could always have portable code if s/he uses standard
|
384
|
+
# abbreviations, like:
|
385
|
+
#
|
386
|
+
# 1. CET => Central European Time
|
387
|
+
# 2. CEST => Central European Summer Time
|
388
|
+
#
|
389
|
+
# Which implies that the caller should handle daylight saving detection.
|
390
|
+
# In fact, CET will handle daylight saving in MySQL but not Postgres.
|
391
|
+
#
|
392
|
+
# It looks like the posix convention is supported by mysql and
|
393
|
+
# postgresql, e.g.:
|
394
|
+
#
|
395
|
+
# posix/Europe/Paris
|
396
|
+
# posix/America/Nipigon
|
397
|
+
#
|
398
|
+
# so it looks like a more reliably portable way of specifying it.
|
399
|
+
time_zones = {
|
400
|
+
'mssql' => {
|
401
|
+
'utc' => 'UTC',
|
402
|
+
'sao_paulo' => 'Argentina Standard Time',
|
403
|
+
'tahiti' => 'Hawaiian Standard Time',
|
404
|
+
'paris' => 'Central European Standard Time'
|
405
|
+
},
|
406
|
+
'mysql' => {
|
407
|
+
'utc' => 'UTC',
|
408
|
+
'sao_paulo' => 'America/Sao_Paulo',
|
409
|
+
'tahiti' => 'Pacific/Tahiti',
|
410
|
+
'paris' => 'Europe/Paris'
|
411
|
+
},
|
412
|
+
'oracle' => {
|
413
|
+
'utc' => 'UTC',
|
414
|
+
'sao_paulo' => 'America/Sao_Paulo',
|
415
|
+
'tahiti' => 'Pacific/Tahiti',
|
416
|
+
'paris' => 'Europe/Paris'
|
417
|
+
},
|
418
|
+
'postgresql' => {
|
419
|
+
'utc' => 'UTC',
|
420
|
+
'sao_paulo' => 'America/Sao Paulo (-03)',
|
421
|
+
'tahiti' => 'Pacific/Tahiti (-10)',
|
422
|
+
'paris' => 'Europe/Paris'
|
423
|
+
},
|
424
|
+
}
|
425
|
+
|
426
|
+
tz = time_zones[ENV['DB']]
|
427
|
+
skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if tz.nil?
|
428
|
+
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
|
429
|
+
assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['sao_paulo']))
|
430
|
+
assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['tahiti']))
|
431
|
+
|
432
|
+
# Winter/Summer time
|
433
|
+
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel::Nodes.build_quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
|
434
|
+
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel::Nodes.build_quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
|
364
435
|
end
|
365
436
|
|
366
437
|
def test_coalesce
|
@@ -500,7 +571,8 @@ module ArelExtensions
|
|
500
571
|
assert_equal Time, t(@lucas,@updated_at.cast(:string).cast(:datetime)).class
|
501
572
|
assert_equal Time, t(@lucas,@updated_at.cast(:time)).class
|
502
573
|
|
503
|
-
|
574
|
+
# mysql adapter in rails7 adds some infos we just squeeze here
|
575
|
+
assert_equal "2014-03-03 12:42:00", t(@lucas,@updated_at.cast(:string)).split('.').first unless @env_db == 'mssql' # locale dependent
|
504
576
|
assert_equal Date.parse("2014-03-03"), t(@lucas,Arel::Nodes.build_quoted('2014-03-03').cast(:date))
|
505
577
|
assert_equal Date.parse("5014-03-03"), t(@lucas,(@age.cast(:string) + '014-03-03').cast(:date))
|
506
578
|
assert_equal Time.parse("2014-03-03 12:42:00 UTC"), t(@lucas,@updated_at.cast(:string).cast(:datetime))
|
@@ -515,7 +587,7 @@ module ArelExtensions
|
|
515
587
|
# puts @age.is_null.inspect
|
516
588
|
# puts @age.is_null.to_sql
|
517
589
|
# puts @age=='34'
|
518
|
-
assert_equal "Test", User.select(@name).where(@age.is_null
|
590
|
+
assert_equal "Test", User.select(@name).where(@age.is_null).first.name
|
519
591
|
end
|
520
592
|
|
521
593
|
def test_math_plus
|
@@ -663,6 +735,7 @@ module ArelExtensions
|
|
663
735
|
end
|
664
736
|
|
665
737
|
def test_subquery_with_order
|
738
|
+
skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
|
666
739
|
assert_equal 9, User.where(:name => User.select(:name).order(:name)).count
|
667
740
|
assert_equal 9, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
|
668
741
|
if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
|
@@ -2,7 +2,7 @@ require 'arelx_test_helper'
|
|
2
2
|
require 'date'
|
3
3
|
|
4
4
|
module ArelExtensions
|
5
|
-
module
|
5
|
+
module WithAr
|
6
6
|
class InsertManagerTest < Minitest::Test
|
7
7
|
def setup_db
|
8
8
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
@@ -13,7 +13,11 @@ module ArelExtensions
|
|
13
13
|
@env_db = ENV['DB']
|
14
14
|
end
|
15
15
|
ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
16
|
-
ActiveRecord::
|
16
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
17
|
+
ActiveRecord.default_timezone = :utc
|
18
|
+
else
|
19
|
+
ActiveRecord::Base.default_timezone = :utc
|
20
|
+
end
|
17
21
|
@cnx = ActiveRecord::Base.connection
|
18
22
|
Arel::Table.engine = ActiveRecord::Base
|
19
23
|
if File.exist?("init/#{@env_db}.sql")
|
@@ -1,12 +1,16 @@
|
|
1
1
|
require 'arelx_test_helper'
|
2
2
|
|
3
3
|
module ArelExtensions
|
4
|
-
module
|
4
|
+
module WithAr
|
5
5
|
describe 'the sqlite visitor' do
|
6
6
|
before do
|
7
7
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
8
8
|
ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
9
|
-
ActiveRecord::
|
9
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
10
|
+
ActiveRecord.default_timezone = :utc
|
11
|
+
else
|
12
|
+
ActiveRecord::Base.default_timezone = :utc
|
13
|
+
end
|
10
14
|
@cnx = ActiveRecord::Base.connection
|
11
15
|
Arel::Table.engine = ActiveRecord::Base
|
12
16
|
@cnx.drop_table(:users) rescue nil
|
@@ -1,12 +1,16 @@
|
|
1
1
|
require 'arelx_test_helper'
|
2
2
|
|
3
3
|
module ArelExtensions
|
4
|
-
module
|
4
|
+
module WithAr
|
5
5
|
describe 'the sqlite visitor can do maths' do
|
6
6
|
before do
|
7
7
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
8
8
|
ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
9
|
-
ActiveRecord::
|
9
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
10
|
+
ActiveRecord.default_timezone = :utc
|
11
|
+
else
|
12
|
+
ActiveRecord::Base.default_timezone = :utc
|
13
|
+
end
|
10
14
|
Arel::Table.engine = ActiveRecord::Base
|
11
15
|
@cnx = ActiveRecord::Base.connection
|
12
16
|
@cnx.drop_table(:users) rescue nil
|
@@ -2,12 +2,16 @@ require 'arelx_test_helper'
|
|
2
2
|
require 'date'
|
3
3
|
|
4
4
|
module ArelExtensions
|
5
|
-
module
|
5
|
+
module WithAr
|
6
6
|
describe 'the mysql visitor can do string operations' do
|
7
7
|
before do
|
8
8
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
9
9
|
ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-mysql" : :mysql))
|
10
|
-
ActiveRecord::
|
10
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
11
|
+
ActiveRecord.default_timezone = :utc
|
12
|
+
else
|
13
|
+
ActiveRecord::Base.default_timezone = :utc
|
14
|
+
end
|
11
15
|
begin
|
12
16
|
@cnx = ActiveRecord::Base.connection
|
13
17
|
rescue => e
|
@@ -2,12 +2,16 @@ require 'arelx_test_helper'
|
|
2
2
|
require 'date'
|
3
3
|
|
4
4
|
module ArelExtensions
|
5
|
-
module
|
5
|
+
module WithAr
|
6
6
|
describe 'the sqlite visitor can do string operations' do
|
7
7
|
before do
|
8
8
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
9
9
|
ActiveRecord::Base.establish_connection(ENV['DB'] || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
10
|
-
ActiveRecord::
|
10
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
11
|
+
ActiveRecord.default_timezone = :utc
|
12
|
+
else
|
13
|
+
ActiveRecord::Base.default_timezone = :utc
|
14
|
+
end
|
11
15
|
@cnx = ActiveRecord::Base.connection
|
12
16
|
Arel::Table.engine = ActiveRecord::Base
|
13
17
|
@cnx.drop_table(:users) rescue nil
|
data/version_v1.rb
CHANGED
data/version_v2.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yann Azoury
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2022-03-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|
@@ -44,16 +44,16 @@ dependencies:
|
|
44
44
|
name: rdoc
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- - "
|
47
|
+
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
49
|
+
version: 6.3.1
|
50
50
|
type: :development
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
|
-
- - "
|
54
|
+
- - ">="
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: 6.3.1
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: rake
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,7 +97,6 @@ files:
|
|
97
97
|
- Rakefile
|
98
98
|
- SQL_Challenges.md
|
99
99
|
- TODO
|
100
|
-
- appveyor.yml
|
101
100
|
- arel_extensions.gemspec
|
102
101
|
- functions.html
|
103
102
|
- gemfiles/rails3.gemfile
|
@@ -107,6 +106,7 @@ files:
|
|
107
106
|
- gemfiles/rails5_2.gemfile
|
108
107
|
- gemfiles/rails6.gemfile
|
109
108
|
- gemfiles/rails6_1.gemfile
|
109
|
+
- gemfiles/rails7.gemfile
|
110
110
|
- gemspecs/arel_extensions-v1.gemspec
|
111
111
|
- gemspecs/arel_extensions-v2.gemspec
|
112
112
|
- generate_gems.sh
|
@@ -116,11 +116,13 @@ files:
|
|
116
116
|
- init/postgresql.sql
|
117
117
|
- init/sqlite.sql
|
118
118
|
- lib/arel_extensions.rb
|
119
|
+
- lib/arel_extensions/aliases.rb
|
119
120
|
- lib/arel_extensions/attributes.rb
|
120
121
|
- lib/arel_extensions/boolean_functions.rb
|
121
122
|
- lib/arel_extensions/common_sql_functions.rb
|
122
123
|
- lib/arel_extensions/comparators.rb
|
123
124
|
- lib/arel_extensions/date_duration.rb
|
125
|
+
- lib/arel_extensions/helpers.rb
|
124
126
|
- lib/arel_extensions/insert_manager.rb
|
125
127
|
- lib/arel_extensions/math.rb
|
126
128
|
- lib/arel_extensions/math_functions.rb
|
@@ -222,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
224
|
- !ruby/object:Gem::Version
|
223
225
|
version: '0'
|
224
226
|
requirements: []
|
225
|
-
rubygems_version: 3.
|
227
|
+
rubygems_version: 3.2.3
|
226
228
|
signing_key:
|
227
229
|
specification_version: 4
|
228
230
|
summary: Extending Arel
|