arel_extensions 2.3.3 → 2.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +92 -43
- data/.gitignore +2 -1
- data/.rubocop.yml +131 -5
- data/Makefile +48 -0
- data/NEWS.md +22 -0
- data/README.md +32 -5
- data/Rakefile +5 -3
- data/arel_extensions.gemspec +3 -5
- data/dev/arelx.dockerfile +13 -16
- data/dev/compose.yaml +26 -28
- data/gemfiles/rails5.gemfile +15 -8
- data/gemfiles/rails5_1_4.gemfile +11 -9
- data/gemfiles/rails5_2.gemfile +16 -9
- data/gemfiles/rails6.gemfile +13 -7
- data/gemfiles/rails6_1.gemfile +13 -7
- data/gemfiles/rails7.gemfile +15 -9
- data/gemfiles/rails7_1.gemfile +15 -8
- data/gemfiles/rails7_2.gemfile +12 -6
- data/gemfiles/rails8.gemfile +40 -0
- data/gemfiles/rails8_1.gemfile +41 -0
- data/gemspecs/arel_extensions-v1.gemspec +3 -5
- data/gemspecs/arel_extensions-v2.gemspec +3 -5
- data/lib/arel_extensions/aliases.rb +3 -3
- data/lib/arel_extensions/attributes.rb +2 -0
- data/lib/arel_extensions/boolean_functions.rb +9 -7
- data/lib/arel_extensions/common_sql_functions.rb +5 -3
- data/lib/arel_extensions/comparators.rb +6 -4
- data/lib/arel_extensions/constants.rb +13 -0
- data/lib/arel_extensions/date_duration.rb +2 -0
- data/lib/arel_extensions/helpers.rb +18 -19
- data/lib/arel_extensions/insert_manager.rb +5 -1
- data/lib/arel_extensions/math.rb +40 -44
- data/lib/arel_extensions/math_functions.rb +29 -31
- data/lib/arel_extensions/nodes/aggregate_function.rb +4 -4
- data/lib/arel_extensions/nodes/blank.rb +6 -4
- data/lib/arel_extensions/nodes/byte_size.rb +11 -0
- data/lib/arel_extensions/nodes/case.rb +16 -13
- data/lib/arel_extensions/nodes/cast.rb +3 -5
- data/lib/arel_extensions/nodes/char_length.rb +11 -0
- data/lib/arel_extensions/nodes/coalesce.rb +1 -1
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/concat.rb +6 -6
- data/lib/arel_extensions/nodes/date_diff.rb +40 -49
- data/lib/arel_extensions/nodes/duration.rb +2 -2
- data/lib/arel_extensions/nodes/format.rb +2 -2
- data/lib/arel_extensions/nodes/formatted_date.rb +2 -2
- data/lib/arel_extensions/nodes/formatted_number.rb +2 -2
- data/lib/arel_extensions/nodes/function.rb +7 -7
- data/lib/arel_extensions/nodes/is_null.rb +2 -0
- data/lib/arel_extensions/nodes/json.rb +27 -15
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
- data/lib/arel_extensions/nodes/locate.rb +1 -1
- data/lib/arel_extensions/nodes/matches.rb +2 -2
- data/lib/arel_extensions/nodes/power.rb +2 -2
- data/lib/arel_extensions/nodes/rand.rb +2 -2
- data/lib/arel_extensions/nodes/repeat.rb +2 -2
- data/lib/arel_extensions/nodes/replace.rb +3 -3
- data/lib/arel_extensions/nodes/rollup.rb +4 -4
- data/lib/arel_extensions/nodes/round.rb +3 -3
- data/lib/arel_extensions/nodes/select.rb +1 -1
- data/lib/arel_extensions/nodes/std.rb +4 -4
- data/lib/arel_extensions/nodes/substring.rb +52 -2
- data/lib/arel_extensions/nodes/then.rb +1 -1
- data/lib/arel_extensions/nodes/trim.rb +2 -2
- data/lib/arel_extensions/nodes/union.rb +3 -3
- data/lib/arel_extensions/nodes/union_all.rb +3 -3
- data/lib/arel_extensions/nodes/wday.rb +2 -2
- data/lib/arel_extensions/null_functions.rb +5 -7
- data/lib/arel_extensions/predications.rb +23 -19
- data/lib/arel_extensions/string_functions.rb +37 -28
- data/lib/arel_extensions/version.rb +3 -1
- data/lib/arel_extensions/visitors/convert_format.rb +2 -2
- data/lib/arel_extensions/visitors/ibm_db.rb +5 -5
- data/lib/arel_extensions/visitors/mssql.rb +111 -97
- data/lib/arel_extensions/visitors/mysql.rb +101 -67
- data/lib/arel_extensions/visitors/oracle.rb +113 -103
- data/lib/arel_extensions/visitors/oracle12.rb +5 -6
- data/lib/arel_extensions/visitors/postgresql.rb +119 -92
- data/lib/arel_extensions/visitors/sqlite.rb +72 -64
- data/lib/arel_extensions/visitors/to_sql.rb +85 -75
- data/lib/arel_extensions/visitors.rb +7 -7
- data/lib/arel_extensions/warning.rb +5 -5
- data/lib/arel_extensions.rb +47 -31
- data/test/arelx_test_helper.rb +8 -6
- data/test/config_loader.rb +9 -0
- data/test/database.yml +8 -6
- data/test/real_db_test.rb +33 -33
- data/test/support/fake_record.rb +3 -1
- data/test/visitors/test_bulk_insert_oracle.rb +2 -2
- data/test/visitors/test_bulk_insert_sqlite.rb +2 -2
- data/test/visitors/test_to_sql.rb +2 -2
- data/test/with_ar/all_agnostic_test.rb +214 -32
- data/test/with_ar/insert_agnostic_test.rb +2 -2
- data/test/with_ar/test_bulk_sqlite.rb +2 -2
- data/test/with_ar/test_math_sqlite.rb +2 -2
- data/test/with_ar/test_string_mysql.rb +2 -2
- data/test/with_ar/test_string_sqlite.rb +2 -2
- data/version_v1.rb +3 -1
- data/version_v2.rb +3 -1
- metadata +9 -33
- data/bin/compose +0 -6
- data/gemfiles/rails3.gemfile +0 -20
- data/gemfiles/rails4_2.gemfile +0 -38
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'arel_extensions/nodes/then'
|
|
2
4
|
|
|
3
5
|
module ArelExtensions
|
|
@@ -6,7 +8,7 @@ module ArelExtensions
|
|
|
6
8
|
self.and(other)
|
|
7
9
|
end
|
|
8
10
|
|
|
9
|
-
def and
|
|
11
|
+
def and(*others)
|
|
10
12
|
Arel::Nodes::And.new self, others
|
|
11
13
|
end
|
|
12
14
|
|
|
@@ -14,7 +16,7 @@ module ArelExtensions
|
|
|
14
16
|
self.or(other)
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
def or
|
|
19
|
+
def or(*others)
|
|
18
20
|
Arel::Nodes::Or.new self, others
|
|
19
21
|
end
|
|
20
22
|
|
|
@@ -27,7 +29,7 @@ end
|
|
|
27
29
|
class Arel::Nodes::And
|
|
28
30
|
include ArelExtensions::BooleanFunctions
|
|
29
31
|
|
|
30
|
-
def self.new
|
|
32
|
+
def self.new(*children)
|
|
31
33
|
children =
|
|
32
34
|
children.flatten.map { |c|
|
|
33
35
|
c.is_a?(self) ? c.children : c
|
|
@@ -47,15 +49,15 @@ class Arel::Nodes::Or
|
|
|
47
49
|
|
|
48
50
|
attr_reader :children
|
|
49
51
|
|
|
50
|
-
def self.new
|
|
52
|
+
def self.new(*children)
|
|
51
53
|
children =
|
|
52
54
|
children.flatten.map { |c|
|
|
53
55
|
c.is_a?(self) ? c.children : c
|
|
54
56
|
}.flatten
|
|
55
|
-
super
|
|
57
|
+
super
|
|
56
58
|
end
|
|
57
59
|
|
|
58
|
-
def initialize
|
|
60
|
+
def initialize(*children)
|
|
59
61
|
@children = children
|
|
60
62
|
end
|
|
61
63
|
|
|
@@ -80,5 +82,5 @@ class Arel::Nodes::Or
|
|
|
80
82
|
self.class == other.class &&
|
|
81
83
|
children == other.children
|
|
82
84
|
end
|
|
83
|
-
alias
|
|
85
|
+
alias == eql?
|
|
84
86
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ArelExtensions
|
|
2
4
|
class CommonSqlFunctions
|
|
3
5
|
def initialize(cnx)
|
|
@@ -9,7 +11,7 @@ module ArelExtensions
|
|
|
9
11
|
db.load_extension('/usr/lib/sqlite3/pcre.so')
|
|
10
12
|
db.load_extension('/usr/lib/sqlite3/extension-functions.so')
|
|
11
13
|
db.enable_load_extension(0)
|
|
12
|
-
rescue => e
|
|
14
|
+
rescue StandardError => e
|
|
13
15
|
$load_extension_disabled = true
|
|
14
16
|
puts "cannot load extensions #{e.inspect}"
|
|
15
17
|
end
|
|
@@ -42,14 +44,14 @@ module ArelExtensions
|
|
|
42
44
|
if /sqlite/i.match?(env_db)
|
|
43
45
|
begin
|
|
44
46
|
add_sqlite_functions
|
|
45
|
-
rescue => e
|
|
47
|
+
rescue StandardError => e
|
|
46
48
|
puts "cannot add sqlite functions #{e.inspect}"
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
if File.exist?("init/#{env_db}.sql")
|
|
50
52
|
sql = File.read("init/#{env_db}.sql")
|
|
51
53
|
if env_db == 'mssql'
|
|
52
|
-
sql.split(/^GO\s*$/).each {|str|
|
|
54
|
+
sql.split(/^GO\s*$/).each { |str|
|
|
53
55
|
@cnx.execute(str.strip) unless str.blank?
|
|
54
56
|
}
|
|
55
57
|
elsif env_db == 'mysql'
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ArelExtensions
|
|
2
4
|
module Comparators
|
|
3
5
|
def >(other)
|
|
@@ -19,8 +21,8 @@ module ArelExtensions
|
|
|
19
21
|
# REGEXP function
|
|
20
22
|
# Pattern matching using regular expressions
|
|
21
23
|
def =~(other)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
# arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
|
25
|
+
# if arg == :string || arg == :text
|
|
24
26
|
Arel::Nodes::Regexp.new self, convert_regexp(other)
|
|
25
27
|
# end
|
|
26
28
|
end
|
|
@@ -30,8 +32,8 @@ module ArelExtensions
|
|
|
30
32
|
# NOT_REGEXP function
|
|
31
33
|
# Negation of Regexp
|
|
32
34
|
def !~(other)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
# arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
|
36
|
+
# if arg == :string || arg == :text
|
|
35
37
|
Arel::Nodes::NotRegexp.new self, convert_regexp(other)
|
|
36
38
|
# end
|
|
37
39
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module ArelExtensions
|
|
2
|
+
ACTIVE_RECORD_VERSION = Gem::Version.new(ActiveRecord::VERSION::STRING).freeze
|
|
3
|
+
AREL_VERSION = Gem::Version.new(Arel::VERSION).freeze
|
|
4
|
+
V10 = Gem::Version.new('10.0').freeze
|
|
5
|
+
V5 = Gem::Version.new('5.0').freeze
|
|
6
|
+
V6 = Gem::Version.new('6.0').freeze
|
|
7
|
+
V7 = Gem::Version.new('7.0').freeze
|
|
8
|
+
V7_0 = Gem::Version.new('7.0').freeze
|
|
9
|
+
V7_1 = Gem::Version.new('7.1').freeze
|
|
10
|
+
V7_2 = Gem::Version.new('7.2').freeze
|
|
11
|
+
V8_1 = Gem::Version.new('8.1').freeze
|
|
12
|
+
V9_0 = Gem::Version.new('9.0').freeze
|
|
13
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
module ArelExtensions
|
|
3
4
|
#
|
|
4
5
|
# column_of
|
|
5
6
|
#
|
|
@@ -19,7 +20,7 @@ module ArelExtensions
|
|
|
19
20
|
Arel::Table.engine.connection.schema_cache.columns_hash(table_name)[column_name]
|
|
20
21
|
rescue NoMethodError
|
|
21
22
|
nil
|
|
22
|
-
rescue => e
|
|
23
|
+
rescue StandardError => e
|
|
23
24
|
warn("Warning: Unexpected exception caught while fetching column name for #{table_name}.#{column_name} in `column_of_via_arel_table`\n#{e.class}")
|
|
24
25
|
warn(e.backtrace)
|
|
25
26
|
nil
|
|
@@ -27,33 +28,31 @@ module ArelExtensions
|
|
|
27
28
|
|
|
28
29
|
def self.column_of(table_name, column_name)
|
|
29
30
|
pool = ActiveRecord::Base.connection.pool
|
|
30
|
-
use_arel_table = !ActiveRecord::Base.connected?
|
|
31
|
-
(pool.respond_to?(:schema_cache) && pool.schema_cache.nil?)
|
|
31
|
+
use_arel_table = !ActiveRecord::Base.connected? \
|
|
32
|
+
|| (pool.respond_to?(:schema_cache) && pool.schema_cache.nil?)
|
|
32
33
|
|
|
33
34
|
if use_arel_table
|
|
34
35
|
column_of_via_arel_table(table_name, column_name)
|
|
35
|
-
|
|
36
|
-
if pool.respond_to?(:
|
|
37
|
-
if
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
pool.pool_config.schema_reflection.columns_hash(ActiveRecord::Base.connection, table_name)[column_name]
|
|
42
|
-
end
|
|
43
|
-
else # activerecord < 7.1
|
|
44
|
-
pool.pool_config.schema_cache.columns_hash(table_name)[column_name]
|
|
36
|
+
elsif pool.respond_to?(:pool_config)
|
|
37
|
+
if pool.pool_config.respond_to?(:schema_reflection) # activerecord >= 7.1
|
|
38
|
+
if ActiveRecord.version >= Gem::Version.create('7.2')
|
|
39
|
+
pool.pool_config.schema_reflection.columns_hash(pool, table_name)[column_name]
|
|
40
|
+
else
|
|
41
|
+
pool.pool_config.schema_reflection.columns_hash(ActiveRecord::Base.connection, table_name)[column_name]
|
|
45
42
|
end
|
|
46
|
-
|
|
47
|
-
pool.schema_cache.columns_hash(table_name)[column_name]
|
|
48
|
-
else # activerecord < 5.0
|
|
49
|
-
column_of_via_arel_table(table_name, column_name)
|
|
43
|
+
else # activerecord < 7.1
|
|
44
|
+
pool.pool_config.schema_cache.columns_hash(table_name)[column_name]
|
|
50
45
|
end
|
|
46
|
+
elsif pool.respond_to?(:schema_cache) # activerecord < 6.1
|
|
47
|
+
pool.schema_cache.columns_hash(table_name)[column_name]
|
|
48
|
+
else # activerecord < 5.0
|
|
49
|
+
column_of_via_arel_table(table_name, column_name)
|
|
51
50
|
end
|
|
52
51
|
rescue ActiveRecord::ConnectionNotEstablished
|
|
53
52
|
column_of_via_arel_table(table_name, column_name)
|
|
54
53
|
rescue ActiveRecord::StatementInvalid
|
|
55
54
|
nil
|
|
56
|
-
rescue => e
|
|
55
|
+
rescue StandardError => e
|
|
57
56
|
warn("Warning: Unexpected exception caught while fetching column name for #{table_name}.#{column_name} in `column_of`")
|
|
58
57
|
warn(e)
|
|
59
58
|
warn(e.backtrace)
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'arel'
|
|
2
4
|
|
|
3
5
|
module ArelExtensions
|
|
4
6
|
module InsertManager
|
|
5
7
|
def bulk_insert(cols, data)
|
|
6
8
|
raise ArgumentError, 'cols must be present' if cols.blank?
|
|
9
|
+
|
|
7
10
|
columns =
|
|
8
11
|
case cols.first
|
|
9
12
|
when Array
|
|
@@ -11,7 +14,7 @@ module ArelExtensions
|
|
|
11
14
|
when Arel::Attributes::Attribute
|
|
12
15
|
cols
|
|
13
16
|
when String, Symbol
|
|
14
|
-
cols.map {|c| [@ast.relation[c.first]] }
|
|
17
|
+
cols.map { |c| [@ast.relation[c.first]] }
|
|
15
18
|
else
|
|
16
19
|
raise ArgumentError, "cols has an invalid type: #{cols.first.first.class}"
|
|
17
20
|
end
|
|
@@ -28,6 +31,7 @@ module ArelExtensions
|
|
|
28
31
|
attr_accessor :left, :cols
|
|
29
32
|
|
|
30
33
|
def initialize(cols, values)
|
|
34
|
+
super()
|
|
31
35
|
@left = values
|
|
32
36
|
@cols = cols
|
|
33
37
|
end
|
data/lib/arel_extensions/math.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'arel_extensions/nodes'
|
|
2
4
|
require 'arel_extensions/nodes/function'
|
|
3
5
|
require 'arel_extensions/nodes/concat'
|
|
@@ -17,48 +19,46 @@ module ArelExtensions
|
|
|
17
19
|
def +(other)
|
|
18
20
|
case self
|
|
19
21
|
when Arel::Nodes::Quoted
|
|
20
|
-
|
|
22
|
+
concat(other)
|
|
21
23
|
when Arel::Nodes::Grouping
|
|
22
|
-
if
|
|
23
|
-
|
|
24
|
+
if expr.left.is_a?(String) || expr.right.is_a?(String)
|
|
25
|
+
concat(other)
|
|
24
26
|
else
|
|
25
|
-
Arel.grouping(Arel::Nodes::Addition.new
|
|
27
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, other))
|
|
26
28
|
end
|
|
27
29
|
when ArelExtensions::Nodes::Function, ArelExtensions::Nodes::Case
|
|
28
|
-
case
|
|
29
|
-
when :string, :text
|
|
30
|
-
self.concat(other)
|
|
30
|
+
case return_type
|
|
31
31
|
when :integer, :decimal, :float, :number, :int
|
|
32
|
-
Arel.grouping(Arel::Nodes::Addition.new
|
|
32
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, other))
|
|
33
33
|
when :date, :datetime
|
|
34
34
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
|
35
35
|
else
|
|
36
|
-
|
|
36
|
+
concat(other)
|
|
37
37
|
end
|
|
38
38
|
when Arel::Nodes::Function
|
|
39
|
-
Arel.grouping(Arel::Nodes::Addition.new
|
|
39
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, other))
|
|
40
40
|
else
|
|
41
41
|
col =
|
|
42
|
-
if
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Arel.column_of(
|
|
42
|
+
if is_a?(Arel::Attribute) && respond_to?(:type_caster) && able_to_type_cast?
|
|
43
|
+
type_caster
|
|
44
|
+
elsif respond_to?(:relation)
|
|
45
|
+
Arel.column_of(relation.table_name, name.to_s)
|
|
46
46
|
end
|
|
47
|
-
if
|
|
48
|
-
Arel.grouping(Arel::Nodes::Addition.new(self, Arel.quoted(other)))
|
|
49
|
-
else
|
|
47
|
+
if col
|
|
50
48
|
arg = col.type
|
|
51
49
|
if arg == :integer || !arg
|
|
52
50
|
other = other.to_i if other.is_a?(String)
|
|
53
|
-
Arel.grouping(Arel::Nodes::Addition.new
|
|
54
|
-
elsif
|
|
51
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, Arel.quoted(other)))
|
|
52
|
+
elsif %i[decimal float].include?(arg)
|
|
55
53
|
other = Arel.sql(other) if other.is_a?(String) # Arel should accept Float & BigDecimal!
|
|
56
|
-
Arel.grouping(Arel::Nodes::Addition.new
|
|
57
|
-
elsif
|
|
54
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, Arel.quoted(other)))
|
|
55
|
+
elsif %i[datetime date].include?(arg)
|
|
58
56
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
|
59
|
-
elsif
|
|
60
|
-
|
|
57
|
+
elsif %i[string text].include?(arg)
|
|
58
|
+
concat(other)
|
|
61
59
|
end
|
|
60
|
+
else
|
|
61
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, Arel.quoted(other)))
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -68,17 +68,13 @@ module ArelExtensions
|
|
|
68
68
|
def -(other)
|
|
69
69
|
case self
|
|
70
70
|
when Arel::Nodes::Grouping
|
|
71
|
-
if
|
|
72
|
-
Arel.grouping(ArelExtensions::Nodes::DateSub.new
|
|
71
|
+
if expr.left.is_a?(Date) || expr.left.is_a?(DateTime)
|
|
72
|
+
Arel.grouping(ArelExtensions::Nodes::DateSub.new([self, Arel.quoted(other)]))
|
|
73
73
|
else
|
|
74
74
|
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
75
75
|
end
|
|
76
76
|
when ArelExtensions::Nodes::Function, ArelExtensions::Nodes::Case
|
|
77
|
-
case
|
|
78
|
-
when :string, :text # ???
|
|
79
|
-
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other))) # ??
|
|
80
|
-
when :integer, :decimal, :float, :number
|
|
81
|
-
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
77
|
+
case return_type
|
|
82
78
|
when :date, :datetime
|
|
83
79
|
ArelExtensions::Nodes::DateSub.new [self, Arel.quoted(other)]
|
|
84
80
|
else
|
|
@@ -88,33 +84,31 @@ module ArelExtensions
|
|
|
88
84
|
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
89
85
|
else
|
|
90
86
|
col =
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Arel.column_of(
|
|
87
|
+
if is_a?(Arel::Attribute) && respond_to?(:type_caster) && able_to_type_cast?
|
|
88
|
+
type_caster
|
|
89
|
+
elsif respond_to?(:relation)
|
|
90
|
+
Arel.column_of(relation.table_name, name.to_s)
|
|
95
91
|
end
|
|
96
|
-
if
|
|
97
|
-
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
98
|
-
else
|
|
92
|
+
if col
|
|
99
93
|
arg = col.type
|
|
100
|
-
if
|
|
94
|
+
if %i[date datetime].include?(arg)
|
|
101
95
|
case other
|
|
102
96
|
when Arel::Attributes::Attribute
|
|
103
97
|
col2 =
|
|
104
98
|
if other.is_a?(Arel::Attribute) && other.respond_to?(:type_caster) && other.able_to_type_cast?
|
|
105
99
|
other.type_caster
|
|
106
|
-
|
|
107
|
-
Arel.column_of(other.relation.table_name, other.name.to_s)
|
|
100
|
+
elsif other.respond_to?(:relation)
|
|
101
|
+
Arel.column_of(other.relation.table_name, other.name.to_s)
|
|
108
102
|
end
|
|
109
|
-
if
|
|
110
|
-
ArelExtensions::Nodes::DateSub.new [self, other]
|
|
111
|
-
else
|
|
103
|
+
if col2
|
|
112
104
|
arg2 = col2.type
|
|
113
|
-
if
|
|
105
|
+
if %i[date datetime].include?(arg2)
|
|
114
106
|
ArelExtensions::Nodes::DateDiff.new [self, other]
|
|
115
107
|
else
|
|
116
108
|
ArelExtensions::Nodes::DateSub.new [self, other]
|
|
117
109
|
end
|
|
110
|
+
else
|
|
111
|
+
ArelExtensions::Nodes::DateSub.new [self, other]
|
|
118
112
|
end
|
|
119
113
|
when Arel::Nodes::Node, DateTime, Time, String, Date
|
|
120
114
|
ArelExtensions::Nodes::DateDiff.new [self, other]
|
|
@@ -133,6 +127,8 @@ module ArelExtensions
|
|
|
133
127
|
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
134
128
|
end
|
|
135
129
|
end
|
|
130
|
+
else
|
|
131
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
136
132
|
end
|
|
137
133
|
end
|
|
138
134
|
end
|
|
@@ -12,22 +12,22 @@ require 'arel_extensions/nodes/sum'
|
|
|
12
12
|
module ArelExtensions
|
|
13
13
|
module MathFunctions
|
|
14
14
|
# Arel does not handle Decimal literal properly
|
|
15
|
-
def *
|
|
15
|
+
def *(other)
|
|
16
16
|
case other
|
|
17
17
|
when Float, BigDecimal
|
|
18
18
|
super(Arel.quoted(other))
|
|
19
19
|
else
|
|
20
|
-
super
|
|
20
|
+
super
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# Arel does not handle Decimal literal properly
|
|
25
|
-
def /
|
|
25
|
+
def /(other)
|
|
26
26
|
case other
|
|
27
27
|
when Float, BigDecimal
|
|
28
28
|
super(Arel.quoted(other))
|
|
29
29
|
else
|
|
30
|
-
super
|
|
30
|
+
super
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -52,26 +52,26 @@ module ArelExtensions
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# function gives the power of a number
|
|
55
|
-
def pow
|
|
55
|
+
def pow(exposant = 0)
|
|
56
56
|
ArelExtensions::Nodes::Power.new [self, exposant]
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
# function gives the power of a number
|
|
60
|
-
def power
|
|
60
|
+
def power(exposant = 0)
|
|
61
61
|
ArelExtensions::Nodes::Power.new [self, exposant]
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
# Aggregate Functions
|
|
65
|
-
def std
|
|
65
|
+
def std(opts = {unbiased: true})
|
|
66
66
|
ArelExtensions::Nodes::Std.new self, **opts
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
def variance
|
|
69
|
+
def variance(opts = {unbiased: true})
|
|
70
70
|
ArelExtensions::Nodes::Variance.new self, **opts
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def sum
|
|
74
|
-
if
|
|
73
|
+
def sum(opts = {unbiased: true})
|
|
74
|
+
if AREL_VERSION >= V9_0
|
|
75
75
|
Arel::Nodes::Sum.new [self]
|
|
76
76
|
else
|
|
77
77
|
ArelExtensions::Nodes::Sum.new self, **opts
|
|
@@ -82,10 +82,10 @@ module ArelExtensions
|
|
|
82
82
|
# def rand seed = nil
|
|
83
83
|
# ArelExtensions::Nodes::Rand.new [seed]
|
|
84
84
|
# end
|
|
85
|
-
|
|
85
|
+
alias random rand rescue nil
|
|
86
86
|
|
|
87
87
|
# function is used to round a numeric field to the number of decimals specified
|
|
88
|
-
def round
|
|
88
|
+
def round(precision = nil)
|
|
89
89
|
if precision
|
|
90
90
|
ArelExtensions::Nodes::Round.new [self, precision]
|
|
91
91
|
else
|
|
@@ -94,25 +94,23 @@ module ArelExtensions
|
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
# function returning a number at a specific format
|
|
97
|
-
def format_number
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
Arel.quoted('Wrong Format')
|
|
115
|
-
end
|
|
97
|
+
def format_number(format_string, locale = nil)
|
|
98
|
+
format(format_string, 0) # this line is to get the right error message if the format_string is not correct
|
|
99
|
+
m = /^(.*)%([ #+\-0]*)([1-9][0-9]+|[1-9]?)[.]?([0-9]*)([a-zA-Z])(.*)$/.match(format_string)
|
|
100
|
+
opts = {
|
|
101
|
+
prefix: m[1],
|
|
102
|
+
flags: m[2].split('').uniq.join,
|
|
103
|
+
width: m[3].to_i,
|
|
104
|
+
precision: m[4] == '' ? 6 : m[4].to_i,
|
|
105
|
+
type: m[5],
|
|
106
|
+
suffix: m[6],
|
|
107
|
+
locale: locale,
|
|
108
|
+
original_string: format_string
|
|
109
|
+
}
|
|
110
|
+
# opts = {locale: 'fr_FR', type: "e"/"f"/"d", prefix: "$ ", suffix: " %", flags: " +-#0", width: 5, precision: 6}
|
|
111
|
+
ArelExtensions::Nodes::FormattedNumber.new [self, opts]
|
|
112
|
+
rescue Exception
|
|
113
|
+
Arel.quoted('Wrong Format')
|
|
116
114
|
end
|
|
117
115
|
end
|
|
118
116
|
end
|
|
@@ -3,10 +3,10 @@ module ArelExtensions
|
|
|
3
3
|
class AggregateFunction < Function
|
|
4
4
|
attr_accessor :order, :group
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
@order = Array.wrap(opts[:order]).map{|e| convert_to_node(e)}
|
|
8
|
-
@group = Array.wrap(opts[:group]).map{|e| convert_to_node(e)}
|
|
9
|
-
super
|
|
6
|
+
def initialize(node, **opts)
|
|
7
|
+
@order = Array.wrap(opts[:order]).map { |e| convert_to_node(e) }
|
|
8
|
+
@group = Array.wrap(opts[:group]).map { |e| convert_to_node(e) }
|
|
9
|
+
super([node])
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -4,19 +4,21 @@ module ArelExtensions
|
|
|
4
4
|
module Nodes
|
|
5
5
|
class Blank < Arel::Nodes::Unary
|
|
6
6
|
include ArelExtensions::BooleanFunctions
|
|
7
|
+
|
|
7
8
|
RETURN_TYPE = :boolean
|
|
8
9
|
|
|
9
|
-
def initialize
|
|
10
|
-
super
|
|
10
|
+
def initialize(expr)
|
|
11
|
+
super(expr.first)
|
|
11
12
|
end
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
class NotBlank < Arel::Nodes::Unary
|
|
15
16
|
include ArelExtensions::BooleanFunctions
|
|
17
|
+
|
|
16
18
|
RETURN_TYPE = :boolean
|
|
17
19
|
|
|
18
|
-
def initialize
|
|
19
|
-
super
|
|
20
|
+
def initialize(expr)
|
|
21
|
+
super(expr.first)
|
|
20
22
|
end
|
|
21
23
|
end
|
|
22
24
|
end
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
|
-
if
|
|
3
|
+
if AREL_VERSION < V7_1
|
|
4
4
|
class Case < Arel::Nodes::Node
|
|
5
5
|
include Arel::Expressions
|
|
6
6
|
include Arel::Math
|
|
7
7
|
include Arel::Predications
|
|
8
8
|
include Arel::OrderPredications
|
|
9
|
+
|
|
9
10
|
attr_accessor :case, :conditions, :default
|
|
10
11
|
|
|
11
|
-
def initialize
|
|
12
|
+
def initialize(expression = nil, default = nil)
|
|
12
13
|
@case = expression
|
|
13
14
|
@conditions = []
|
|
14
15
|
@default = default
|
|
@@ -24,6 +25,7 @@ module ArelExtensions
|
|
|
24
25
|
class Case < Arel::Nodes::Case
|
|
25
26
|
class When < Arel::Nodes::When # :nodoc:
|
|
26
27
|
end
|
|
28
|
+
|
|
27
29
|
class Else < Arel::Nodes::Else # :nodoc:
|
|
28
30
|
end
|
|
29
31
|
end
|
|
@@ -44,8 +46,9 @@ module ArelExtensions
|
|
|
44
46
|
include ArelExtensions::StringFunctions
|
|
45
47
|
|
|
46
48
|
def return_type
|
|
47
|
-
obj =
|
|
48
|
-
|
|
49
|
+
obj =
|
|
50
|
+
if @conditions.length > 0
|
|
51
|
+
@conditions.last.right
|
|
49
52
|
elsif @default
|
|
50
53
|
@default.expr
|
|
51
54
|
end
|
|
@@ -65,22 +68,22 @@ module ArelExtensions
|
|
|
65
68
|
end
|
|
66
69
|
end
|
|
67
70
|
|
|
68
|
-
def when
|
|
71
|
+
def when(condition, expression = nil)
|
|
69
72
|
@conditions << Case::When.new(condition, expression)
|
|
70
73
|
self
|
|
71
74
|
end
|
|
72
75
|
|
|
73
|
-
def then
|
|
76
|
+
def then(expression)
|
|
74
77
|
@conditions.last.right = expression
|
|
75
78
|
self
|
|
76
79
|
end
|
|
77
80
|
|
|
78
|
-
def else
|
|
81
|
+
def else(expression)
|
|
79
82
|
@default = Case::Else.new expression
|
|
80
83
|
self
|
|
81
84
|
end
|
|
82
85
|
|
|
83
|
-
def initialize_copy
|
|
86
|
+
def initialize_copy(other)
|
|
84
87
|
super
|
|
85
88
|
@case = @case.clone if @case
|
|
86
89
|
@conditions = @conditions.map { |x| x.clone }
|
|
@@ -91,15 +94,15 @@ module ArelExtensions
|
|
|
91
94
|
[@case, @conditions, @default].hash
|
|
92
95
|
end
|
|
93
96
|
|
|
94
|
-
def eql?
|
|
97
|
+
def eql?(other)
|
|
95
98
|
self.class == other.class &&
|
|
96
99
|
self.case == other.case &&
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
conditions == other.conditions &&
|
|
101
|
+
default == other.default
|
|
99
102
|
end
|
|
100
|
-
alias
|
|
103
|
+
alias == eql?
|
|
101
104
|
|
|
102
|
-
def as
|
|
105
|
+
def as(other)
|
|
103
106
|
Arel::Nodes::As.new self, Arel.sql(other)
|
|
104
107
|
end
|
|
105
108
|
end
|
|
@@ -5,7 +5,7 @@ module ArelExtensions
|
|
|
5
5
|
|
|
6
6
|
attr_accessor :as_attr
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
8
|
+
def initialize(expr)
|
|
9
9
|
@as_attr = expr[1]
|
|
10
10
|
case expr[1]
|
|
11
11
|
when :int, 'bigint', 'int', 'smallint', 'tinyint', 'bit'
|
|
@@ -42,13 +42,11 @@ module ArelExtensions
|
|
|
42
42
|
when :ruby_time
|
|
43
43
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
|
44
44
|
else
|
|
45
|
-
Arel.grouping(Arel::Nodes::Addition.new
|
|
45
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, other))
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
@return_type
|
|
51
|
-
end
|
|
49
|
+
attr_reader :return_type
|
|
52
50
|
end
|
|
53
51
|
end
|
|
54
52
|
end
|