arel_extensions 1.3.5 → 2.0.0.rc3
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/.codeclimate.yml +2 -1
- data/.gitignore +6 -7
- data/.rubocop.yml +3 -67
- data/.travis/oracle/download.js +152 -0
- data/.travis/oracle/download.sh +30 -0
- data/.travis/oracle/download_ojdbc.js +116 -0
- data/.travis/oracle/install.sh +34 -0
- data/.travis/setup_accounts.sh +9 -0
- data/.travis/sqlite3/extension-functions.sh +6 -0
- data/.travis.yml +223 -0
- data/Gemfile +21 -16
- data/README.md +13 -125
- data/Rakefile +30 -41
- data/TODO +1 -0
- data/appveyor.yml +22 -51
- data/arel_extensions.gemspec +14 -14
- data/functions.html +3 -3
- data/gemfiles/rails3.gemfile +10 -10
- data/gemfiles/rails4.gemfile +14 -14
- data/gemfiles/rails5_0.gemfile +14 -14
- data/gemfiles/rails5_1_4.gemfile +14 -14
- data/gemfiles/rails5_2.gemfile +14 -16
- data/init/mssql.sql +4 -4
- data/init/mysql.sql +38 -38
- data/init/oracle.sql +0 -0
- data/init/postgresql.sql +21 -21
- data/init/sqlite.sql +0 -0
- data/lib/arel_extensions/attributes.rb +3 -4
- data/lib/arel_extensions/boolean_functions.rb +14 -53
- data/lib/arel_extensions/common_sql_functions.rb +17 -16
- data/lib/arel_extensions/comparators.rb +28 -27
- data/lib/arel_extensions/date_duration.rb +14 -13
- data/lib/arel_extensions/insert_manager.rb +15 -18
- data/lib/arel_extensions/math.rb +53 -55
- data/lib/arel_extensions/math_functions.rb +39 -46
- data/lib/arel_extensions/nodes/abs.rb +1 -0
- data/lib/arel_extensions/nodes/blank.rb +2 -1
- data/lib/arel_extensions/nodes/case.rb +16 -16
- data/lib/arel_extensions/nodes/cast.rb +8 -10
- data/lib/arel_extensions/nodes/ceil.rb +1 -1
- data/lib/arel_extensions/nodes/coalesce.rb +4 -3
- data/lib/arel_extensions/nodes/collate.rb +10 -9
- data/lib/arel_extensions/nodes/concat.rb +18 -9
- data/lib/arel_extensions/nodes/date_diff.rb +26 -42
- data/lib/arel_extensions/nodes/duration.rb +3 -0
- data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
- data/lib/arel_extensions/nodes/floor.rb +1 -1
- data/lib/arel_extensions/nodes/format.rb +8 -35
- data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
- data/lib/arel_extensions/nodes/function.rb +37 -42
- data/lib/arel_extensions/nodes/is_null.rb +0 -0
- data/lib/arel_extensions/nodes/json.rb +39 -48
- data/lib/arel_extensions/nodes/length.rb +0 -5
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +1 -1
- data/lib/arel_extensions/nodes/locate.rb +2 -1
- data/lib/arel_extensions/nodes/log10.rb +2 -1
- data/lib/arel_extensions/nodes/matches.rb +7 -5
- data/lib/arel_extensions/nodes/md5.rb +1 -0
- data/lib/arel_extensions/nodes/power.rb +5 -5
- data/lib/arel_extensions/nodes/rand.rb +1 -0
- data/lib/arel_extensions/nodes/repeat.rb +5 -3
- data/lib/arel_extensions/nodes/replace.rb +8 -16
- data/lib/arel_extensions/nodes/round.rb +6 -5
- data/lib/arel_extensions/nodes/soundex.rb +15 -15
- data/lib/arel_extensions/nodes/std.rb +21 -18
- data/lib/arel_extensions/nodes/substring.rb +16 -8
- data/lib/arel_extensions/nodes/then.rb +1 -1
- data/lib/arel_extensions/nodes/trim.rb +6 -4
- data/lib/arel_extensions/nodes/union.rb +8 -5
- data/lib/arel_extensions/nodes/union_all.rb +7 -4
- data/lib/arel_extensions/nodes/wday.rb +4 -0
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/null_functions.rb +7 -5
- data/lib/arel_extensions/predications.rb +43 -44
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +7 -5
- data/lib/arel_extensions/string_functions.rb +29 -58
- data/lib/arel_extensions/tasks.rb +6 -6
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +31 -24
- data/lib/arel_extensions/visitors/mssql.rb +181 -279
- data/lib/arel_extensions/visitors/mysql.rb +210 -280
- data/lib/arel_extensions/visitors/oracle.rb +180 -201
- data/lib/arel_extensions/visitors/oracle12.rb +31 -18
- data/lib/arel_extensions/visitors/postgresql.rb +173 -252
- data/lib/arel_extensions/visitors/sqlite.rb +126 -140
- data/lib/arel_extensions/visitors/to_sql.rb +237 -272
- data/lib/arel_extensions/visitors.rb +59 -75
- data/lib/arel_extensions.rb +31 -159
- data/test/database.yml +7 -15
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +116 -105
- data/test/support/fake_record.rb +3 -3
- data/test/test_comparators.rb +17 -14
- data/test/visitors/test_bulk_insert_oracle.rb +11 -11
- data/test/visitors/test_bulk_insert_sqlite.rb +13 -12
- data/test/visitors/test_bulk_insert_to_sql.rb +13 -11
- data/test/visitors/test_oracle.rb +55 -55
- data/test/visitors/test_to_sql.rb +226 -419
- data/test/with_ar/all_agnostic_test.rb +361 -578
- data/test/with_ar/insert_agnostic_test.rb +21 -27
- data/test/with_ar/test_bulk_sqlite.rb +16 -17
- data/test/with_ar/test_math_sqlite.rb +26 -26
- data/test/with_ar/test_string_mysql.rb +33 -31
- data/test/with_ar/test_string_sqlite.rb +34 -30
- metadata +22 -29
- data/.github/workflows/ruby.yml +0 -341
- data/gemfiles/rails6.gemfile +0 -30
- data/gemfiles/rails6_1.gemfile +0 -30
- data/gemfiles/rails7.gemfile +0 -23
- data/gemspecs/arel_extensions-v1.gemspec +0 -28
- data/gemspecs/arel_extensions-v2.gemspec +0 -28
- data/generate_gems.sh +0 -15
- data/lib/arel_extensions/aliases.rb +0 -14
- data/lib/arel_extensions/helpers.rb +0 -51
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
- data/lib/arel_extensions/nodes/sum.rb +0 -7
- data/lib/arel_extensions/visitors/convert_format.rb +0 -37
- data/test/arelx_test_helper.rb +0 -71
- data/version_v1.rb +0 -3
- data/version_v2.rb +0 -3
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
class CommonSqlFunctions
|
|
3
|
+
|
|
3
4
|
def initialize(cnx)
|
|
4
5
|
@cnx = cnx
|
|
5
6
|
if cnx && cnx.adapter_name =~ /sqlite/i && !$load_extension_disabled
|
|
6
7
|
begin
|
|
7
8
|
db = cnx.raw_connection
|
|
8
9
|
db.enable_load_extension(1)
|
|
9
|
-
db.load_extension(
|
|
10
|
-
db.load_extension(
|
|
10
|
+
db.load_extension("/usr/lib/sqlite3/pcre.so")
|
|
11
|
+
db.load_extension("/usr/lib/sqlite3/extension-functions.so")
|
|
11
12
|
db.enable_load_extension(0)
|
|
12
13
|
rescue => e
|
|
13
14
|
$load_extension_disabled = true
|
|
14
|
-
puts "
|
|
15
|
+
puts "can not load extensions #{e.inspect}"
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def add_sqlite_functions
|
|
20
21
|
db = @cnx.raw_connection
|
|
21
|
-
db.create_function(
|
|
22
|
+
db.create_function("find_in_set", 1) do |func, val, list|
|
|
22
23
|
case list
|
|
23
24
|
when String
|
|
24
25
|
i = list.split(',').index(val.to_s)
|
|
25
|
-
func.result = i ? (i
|
|
26
|
+
func.result = i ? (i+1) : 0
|
|
26
27
|
when NilClass
|
|
27
28
|
func.result = nil
|
|
28
29
|
else
|
|
29
30
|
i = list.to_s.split(',').index(val.to_s)
|
|
30
|
-
func.result = i ? (i
|
|
31
|
+
func.result = i ? (i+1) : 0
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
|
-
db.create_function(
|
|
34
|
+
db.create_function("instr", 1) do |func, value1, value2|
|
|
34
35
|
i = value1.to_s.index(value2.to_s)
|
|
35
|
-
func.result = i ? (i
|
|
36
|
-
end rescue
|
|
36
|
+
func.result = i ? (i+1) : 0
|
|
37
|
+
end rescue "function instr already here (>= 3.8.5)"
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def add_sql_functions(env_db = nil)
|
|
40
41
|
env_db ||= @cnx.adapter_name
|
|
41
|
-
env_db
|
|
42
|
-
if /sqlite/i.match?(env_db)
|
|
42
|
+
if env_db =~ /sqlite/i
|
|
43
43
|
begin
|
|
44
44
|
add_sqlite_functions
|
|
45
45
|
rescue => e
|
|
46
|
-
puts "
|
|
46
|
+
puts "can not add sqlite functions #{e.inspect}"
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
if File.exist?("init/#{env_db}.sql")
|
|
@@ -52,14 +52,15 @@ module ArelExtensions
|
|
|
52
52
|
sql.split(/^GO\s*$/).each {|str|
|
|
53
53
|
@cnx.execute(str.strip) unless str.blank?
|
|
54
54
|
}
|
|
55
|
-
elsif env_db == 'mysql'
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
elsif env_db == 'mysql'
|
|
56
|
+
sql.split("$$")[1..-2].each { |str|
|
|
57
|
+
@cnx.execute(str.strip) unless str.strip.blank?
|
|
58
|
+
}
|
|
59
59
|
else
|
|
60
60
|
@cnx.execute(sql) unless sql.blank?
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
|
+
|
|
64
65
|
end
|
|
65
66
|
end
|
|
@@ -1,58 +1,59 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Comparators
|
|
3
|
+
|
|
3
4
|
def >(other)
|
|
4
|
-
Arel::Nodes::GreaterThan.new self, Arel.
|
|
5
|
+
Arel::Nodes::GreaterThan.new self, Arel::Nodes.build_quoted(other, self)
|
|
5
6
|
end
|
|
6
7
|
|
|
7
8
|
def >=(other)
|
|
8
|
-
Arel::Nodes::GreaterThanOrEqual.new self, Arel.
|
|
9
|
+
Arel::Nodes::GreaterThanOrEqual.new self, Arel::Nodes.build_quoted(other, self)
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def <(other)
|
|
12
|
-
Arel::Nodes::LessThan.new self, Arel.
|
|
13
|
+
Arel::Nodes::LessThan.new self, Arel::Nodes.build_quoted(other, self)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def <=(other)
|
|
16
|
-
Arel::Nodes::LessThanOrEqual.new self, Arel.
|
|
17
|
+
Arel::Nodes::LessThanOrEqual.new self, Arel::Nodes.build_quoted(other, self)
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
#
|
|
20
|
+
|
|
21
|
+
#REGEXP function
|
|
22
|
+
#Pattern matching using regular expressions
|
|
21
23
|
def =~(other)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
26
|
+
Arel::Nodes::Regexp.new self, convert_regexp(other)
|
|
27
|
+
# end
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
+
#NOT_REGEXP function
|
|
31
|
+
#Negation of Regexp
|
|
30
32
|
def !~(other)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
# arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
|
34
|
+
# if arg == :string || arg == :text
|
|
35
|
+
Arel::Nodes::NotRegexp.new self, convert_regexp(other)
|
|
36
|
+
# end
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
private
|
|
38
|
-
|
|
39
|
-
# Function used for not_regexp.
|
|
40
|
+
#Function use for not_regexp
|
|
40
41
|
def convert_regexp(other)
|
|
41
42
|
case other
|
|
42
43
|
when String
|
|
43
|
-
#
|
|
44
|
+
#Do nothing
|
|
44
45
|
when Regexp
|
|
45
|
-
other = other.source.gsub('\A',
|
|
46
|
-
other.gsub!('\
|
|
47
|
-
other.gsub!('\
|
|
48
|
-
other.gsub!('\
|
|
49
|
-
other.gsub!('\
|
|
50
|
-
other.gsub!('\
|
|
51
|
-
other.gsub!('\W', '[^A-Za-z0-9_]')
|
|
46
|
+
other = other.source.gsub('\A','^')
|
|
47
|
+
other.gsub!('\Z','$')
|
|
48
|
+
other.gsub!('\d','[0-9]')
|
|
49
|
+
other.gsub!('\D','[^0-9]')
|
|
50
|
+
other.gsub!('\w','[0-9A-Za-z]')
|
|
51
|
+
other.gsub!('\W','[^A-Za-z0-9_]')
|
|
52
52
|
else
|
|
53
53
|
raise(ArgumentError)
|
|
54
54
|
end
|
|
55
|
-
Arel.
|
|
55
|
+
Arel::Nodes.build_quoted(other, self)
|
|
56
56
|
end
|
|
57
|
+
|
|
57
58
|
end
|
|
58
59
|
end
|
|
@@ -4,24 +4,24 @@ require 'arel_extensions/nodes/wday'
|
|
|
4
4
|
|
|
5
5
|
module ArelExtensions
|
|
6
6
|
module DateDuration
|
|
7
|
-
#
|
|
7
|
+
#function returns the year (as a number) given a date value.
|
|
8
8
|
def year
|
|
9
|
-
ArelExtensions::Nodes::Duration.new
|
|
9
|
+
ArelExtensions::Nodes::Duration.new "y", self
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
#function returns the month (as a number) given a date value.
|
|
13
13
|
def month
|
|
14
|
-
ArelExtensions::Nodes::Duration.new
|
|
14
|
+
ArelExtensions::Nodes::Duration.new "m", self
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
#function returns the week (as a number) given a date value.
|
|
18
18
|
def week
|
|
19
|
-
ArelExtensions::Nodes::Duration.new
|
|
19
|
+
ArelExtensions::Nodes::Duration.new "w", self
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
#
|
|
22
|
+
#function returns the month (as a number) given a date value.
|
|
23
23
|
def day
|
|
24
|
-
ArelExtensions::Nodes::Duration.new
|
|
24
|
+
ArelExtensions::Nodes::Duration.new "d", self
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def wday
|
|
@@ -29,19 +29,20 @@ module ArelExtensions
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def hour
|
|
32
|
-
ArelExtensions::Nodes::Duration.new
|
|
32
|
+
ArelExtensions::Nodes::Duration.new "h", self
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def minute
|
|
36
|
-
ArelExtensions::Nodes::Duration.new
|
|
36
|
+
ArelExtensions::Nodes::Duration.new "mn", self
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def second
|
|
40
|
-
ArelExtensions::Nodes::Duration.new
|
|
40
|
+
ArelExtensions::Nodes::Duration.new "s", self
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def format(tpl
|
|
44
|
-
ArelExtensions::Nodes::Format.new [self, tpl
|
|
43
|
+
def format(tpl)
|
|
44
|
+
ArelExtensions::Nodes::Format.new [self, tpl]
|
|
45
45
|
end
|
|
46
|
+
|
|
46
47
|
end
|
|
47
48
|
end
|
|
@@ -2,35 +2,32 @@ require 'arel'
|
|
|
2
2
|
|
|
3
3
|
module ArelExtensions
|
|
4
4
|
module InsertManager
|
|
5
|
+
|
|
5
6
|
def bulk_insert(cols, data)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
case cols.first
|
|
8
|
+
when String, Symbol
|
|
9
|
+
cols.each { |c|
|
|
10
|
+
@ast.columns << @ast.relation[c]
|
|
11
|
+
}
|
|
9
12
|
when Array
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
cols.map {|c| [@ast.relation[c.first]] }
|
|
15
|
-
else
|
|
16
|
-
raise ArgumentError, "cols has an invalid type: #{cols.first.first.class}"
|
|
13
|
+
if String === cols.first.first
|
|
14
|
+
@ast.columns = cols.map {|c| [@ast.relation[c.first]] }
|
|
15
|
+
elsif Arel::Attributes::Attribute == cols.first.first
|
|
16
|
+
@ast.columns = cols
|
|
17
17
|
end
|
|
18
|
-
when
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
end
|
|
23
|
-
self.values = BulkValues.new(columns, data)
|
|
24
|
-
@ast.columns = columns
|
|
18
|
+
when NilClass
|
|
19
|
+
@ast.columns = @ast.relation.columns
|
|
20
|
+
end
|
|
21
|
+
self.values = BulkValues.new(@ast.columns, data)
|
|
25
22
|
end
|
|
26
23
|
|
|
27
24
|
class BulkValues < Arel::Nodes::Node
|
|
28
25
|
attr_accessor :left, :cols
|
|
29
|
-
|
|
30
26
|
def initialize(cols, values)
|
|
31
27
|
@left = values
|
|
32
28
|
@cols = cols
|
|
33
29
|
end
|
|
34
30
|
end
|
|
31
|
+
|
|
35
32
|
end
|
|
36
33
|
end
|
data/lib/arel_extensions/math.rb
CHANGED
|
@@ -11,49 +11,48 @@ require 'arel_extensions/nodes/union_all'
|
|
|
11
11
|
|
|
12
12
|
module ArelExtensions
|
|
13
13
|
module Math
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
14
|
+
#function + between
|
|
15
|
+
#String and others (convert in string) allows you to concatenate 2 or more strings together.
|
|
16
|
+
#Date and integer adds or subtracts a specified time interval from a date.
|
|
17
17
|
def +(other)
|
|
18
18
|
case self
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
when Arel::Nodes::Quoted
|
|
20
|
+
return self.concat(other)
|
|
21
|
+
when Arel::Nodes::Grouping
|
|
22
|
+
if self.expr.left.is_a?(String) || self.expr.right.is_a?(String)
|
|
23
|
+
return self.concat(other)
|
|
24
|
+
else
|
|
25
|
+
return Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
|
26
|
+
end
|
|
27
|
+
when ArelExtensions::Nodes::Function,ArelExtensions::Nodes::Case
|
|
28
|
+
return case self.return_type
|
|
29
29
|
when :string, :text
|
|
30
30
|
self.concat(other)
|
|
31
31
|
when :integer, :decimal, :float, :number, :int
|
|
32
|
-
Arel.
|
|
32
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
|
33
33
|
when :date, :datetime
|
|
34
34
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
|
35
35
|
else
|
|
36
36
|
self.concat(other)
|
|
37
37
|
end
|
|
38
|
-
when
|
|
39
|
-
Arel.
|
|
38
|
+
when Arel::Nodes::Function
|
|
39
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
|
40
40
|
else
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Arel.grouping(Arel::Nodes::Addition.new(self, Arel.quoted(other)))
|
|
41
|
+
begin
|
|
42
|
+
col = Arel::Table.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s]
|
|
43
|
+
rescue Exception
|
|
44
|
+
col = nil
|
|
45
|
+
end
|
|
46
|
+
if (!col) #if the column doesn't exist in the database
|
|
47
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new(self, other))
|
|
49
48
|
else
|
|
50
49
|
arg = col.type
|
|
51
|
-
if arg == :integer || !arg
|
|
50
|
+
if arg == :integer || (!arg)
|
|
52
51
|
other = other.to_i if other.is_a?(String)
|
|
53
|
-
Arel.
|
|
52
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
|
54
53
|
elsif arg == :decimal || arg == :float
|
|
55
54
|
other = Arel.sql(other) if other.is_a?(String) # Arel should accept Float & BigDecimal!
|
|
56
|
-
Arel.
|
|
55
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
|
57
56
|
elsif arg == :datetime || arg == :date
|
|
58
57
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
|
59
58
|
elsif arg == :string || arg == :text
|
|
@@ -63,50 +62,48 @@ module ArelExtensions
|
|
|
63
62
|
end
|
|
64
63
|
end
|
|
65
64
|
|
|
66
|
-
#
|
|
67
|
-
#
|
|
65
|
+
#function returns the time between two dates
|
|
66
|
+
#function returns the substraction between two ints
|
|
68
67
|
def -(other)
|
|
69
68
|
case self
|
|
70
69
|
when Arel::Nodes::Grouping
|
|
71
70
|
if self.expr.left.is_a?(Date) || self.expr.left.is_a?(DateTime)
|
|
72
|
-
Arel.
|
|
71
|
+
Arel::Nodes::Grouping.new(ArelExtensions::Nodes::DateSub.new [self, other])
|
|
73
72
|
else
|
|
74
|
-
Arel.
|
|
73
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
|
75
74
|
end
|
|
76
75
|
when ArelExtensions::Nodes::Function, ArelExtensions::Nodes::Case
|
|
77
76
|
case self.return_type
|
|
78
77
|
when :string, :text # ???
|
|
79
|
-
Arel.
|
|
78
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other)) # ??
|
|
80
79
|
when :integer, :decimal, :float, :number
|
|
81
|
-
Arel.
|
|
80
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
|
82
81
|
when :date, :datetime
|
|
83
|
-
ArelExtensions::Nodes::DateSub.new [self,
|
|
82
|
+
ArelExtensions::Nodes::DateSub.new [self, other]
|
|
84
83
|
else
|
|
85
|
-
Arel.
|
|
84
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
|
86
85
|
end
|
|
87
86
|
when Arel::Nodes::Function
|
|
88
|
-
Arel.
|
|
87
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
|
89
88
|
else
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
|
89
|
+
begin
|
|
90
|
+
col = Arel::Table.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s]
|
|
91
|
+
rescue Exception
|
|
92
|
+
col = nil
|
|
93
|
+
end
|
|
94
|
+
if (!col) #if the column doesn't exist in the database
|
|
95
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
|
98
96
|
else
|
|
99
97
|
arg = col.type
|
|
100
98
|
if (arg == :date || arg == :datetime)
|
|
101
99
|
case other
|
|
102
100
|
when Arel::Attributes::Attribute
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if !col2 # if the column doesn't exist in the database
|
|
101
|
+
begin
|
|
102
|
+
col2 = Arel::Table.engine.connection.schema_cache.columns_hash(other.relation.table_name)[other.name.to_s]
|
|
103
|
+
rescue Exception
|
|
104
|
+
col2 = nil
|
|
105
|
+
end
|
|
106
|
+
if (!col2) #if the column doesn't exist in the database
|
|
110
107
|
ArelExtensions::Nodes::DateSub.new [self, other]
|
|
111
108
|
else
|
|
112
109
|
arg2 = col2.type
|
|
@@ -118,7 +115,7 @@ module ArelExtensions
|
|
|
118
115
|
end
|
|
119
116
|
when Arel::Nodes::Node, DateTime, Time, String, Date
|
|
120
117
|
ArelExtensions::Nodes::DateDiff.new [self, other]
|
|
121
|
-
when
|
|
118
|
+
when ArelExtensions::Nodes::Duration, Integer
|
|
122
119
|
ArelExtensions::Nodes::DateSub.new [self, other]
|
|
123
120
|
else # ActiveSupport::Duration
|
|
124
121
|
ArelExtensions::Nodes::DateAdd.new [self, -other]
|
|
@@ -126,15 +123,16 @@ module ArelExtensions
|
|
|
126
123
|
else
|
|
127
124
|
case other
|
|
128
125
|
when Integer, Float, BigDecimal
|
|
129
|
-
Arel.
|
|
126
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, Arel.sql(other.to_s)))
|
|
130
127
|
when String
|
|
131
|
-
Arel.
|
|
128
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, Arel.sql(other)))
|
|
132
129
|
else
|
|
133
|
-
Arel.
|
|
130
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
|
134
131
|
end
|
|
135
132
|
end
|
|
136
133
|
end
|
|
137
134
|
end
|
|
138
135
|
end
|
|
136
|
+
|
|
139
137
|
end
|
|
140
138
|
end
|
|
@@ -7,15 +7,15 @@ require 'arel_extensions/nodes/formatted_number'
|
|
|
7
7
|
require 'arel_extensions/nodes/log10'
|
|
8
8
|
require 'arel_extensions/nodes/power'
|
|
9
9
|
require 'arel_extensions/nodes/std'
|
|
10
|
-
require 'arel_extensions/nodes/sum'
|
|
11
10
|
|
|
12
11
|
module ArelExtensions
|
|
13
12
|
module MathFunctions
|
|
13
|
+
|
|
14
14
|
# Arel does not handle Decimal literal properly
|
|
15
15
|
def * other
|
|
16
16
|
case other
|
|
17
17
|
when Float, BigDecimal
|
|
18
|
-
super(Arel.
|
|
18
|
+
super(Arel::Nodes.build_quoted(other))
|
|
19
19
|
else
|
|
20
20
|
super(other)
|
|
21
21
|
end
|
|
@@ -25,7 +25,7 @@ module ArelExtensions
|
|
|
25
25
|
def / other
|
|
26
26
|
case other
|
|
27
27
|
when Float, BigDecimal
|
|
28
|
-
super(Arel.
|
|
28
|
+
super(Arel::Nodes.build_quoted(other))
|
|
29
29
|
else
|
|
30
30
|
super(other)
|
|
31
31
|
end
|
|
@@ -33,86 +33,79 @@ module ArelExtensions
|
|
|
33
33
|
|
|
34
34
|
# Abs function returns the absolute value of a number passed as argument #
|
|
35
35
|
def abs
|
|
36
|
-
|
|
36
|
+
ArelExtensions::Nodes::Abs.new [self]
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
# will rounded up any positive or negative decimal value within the function upwards #
|
|
40
40
|
def ceil
|
|
41
|
-
|
|
41
|
+
ArelExtensions::Nodes::Ceil.new [self]
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# function rounded up any positive or negative decimal value down to the next least integer
|
|
45
45
|
def floor
|
|
46
|
-
|
|
46
|
+
ArelExtensions::Nodes::Floor.new [self]
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
# function gives the base 10 log
|
|
50
50
|
def log10
|
|
51
|
-
|
|
51
|
+
ArelExtensions::Nodes::Log10.new [self]
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# function gives the power of a number
|
|
55
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
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
|
|
66
|
-
ArelExtensions::Nodes::Std.new self,
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def variance opts = {unbiased: true}
|
|
70
|
-
ArelExtensions::Nodes::Variance.new self, **opts
|
|
65
|
+
def std unbiased = true
|
|
66
|
+
ArelExtensions::Nodes::Std.new [self,unbiased]
|
|
71
67
|
end
|
|
72
68
|
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
Arel::Nodes::Sum.new [self]
|
|
76
|
-
else
|
|
77
|
-
ArelExtensions::Nodes::Sum.new self, **opts
|
|
78
|
-
end
|
|
69
|
+
def variance unbiased = true
|
|
70
|
+
ArelExtensions::Nodes::Variance.new [self,unbiased]
|
|
79
71
|
end
|
|
80
72
|
|
|
81
|
-
#
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
alias_method
|
|
73
|
+
#function that can be invoked to produce random numbers between 0 and 1
|
|
74
|
+
# def rand seed = nil
|
|
75
|
+
# ArelExtensions::Nodes::Rand.new [seed]
|
|
76
|
+
# end
|
|
77
|
+
alias_method :random, :rand
|
|
86
78
|
|
|
87
|
-
#
|
|
79
|
+
#function is used to round a numeric field to the number of decimals specified
|
|
88
80
|
def round precision = nil
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
if precision
|
|
82
|
+
ArelExtensions::Nodes::Round.new [self, precision]
|
|
83
|
+
else
|
|
84
|
+
ArelExtensions::Nodes::Round.new [self]
|
|
85
|
+
end
|
|
94
86
|
end
|
|
95
87
|
|
|
96
88
|
# function returning a number at a specific format
|
|
97
|
-
def format_number format_string, locale
|
|
89
|
+
def format_number format_string, locale=nil
|
|
98
90
|
begin
|
|
99
|
-
sprintf(format_string,
|
|
91
|
+
sprintf(format_string,0) # this line is to get the right error message if the format_string is not correct
|
|
100
92
|
m = /^(.*)%([ #+\-0]*)([1-9][0-9]+|[1-9]?)[.]?([0-9]*)([a-zA-Z])(.*)$/.match(format_string)
|
|
101
93
|
opts = {
|
|
102
|
-
prefix
|
|
103
|
-
flags
|
|
104
|
-
width
|
|
105
|
-
precision
|
|
106
|
-
type
|
|
107
|
-
suffix
|
|
108
|
-
locale
|
|
109
|
-
original_string
|
|
94
|
+
:prefix => m[1],
|
|
95
|
+
:flags => m[2].split(//).uniq.join,
|
|
96
|
+
:width => m[3].to_i,
|
|
97
|
+
:precision => m[4] != '' ? m[4].to_i : 6,
|
|
98
|
+
:type => m[5],
|
|
99
|
+
:suffix => m[6],
|
|
100
|
+
:locale => locale,
|
|
101
|
+
:original_string => format_string
|
|
110
102
|
}
|
|
111
|
-
# opts = {locale
|
|
112
|
-
ArelExtensions::Nodes::FormattedNumber.new [self,
|
|
103
|
+
# opts = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
|
|
104
|
+
ArelExtensions::Nodes::FormattedNumber.new [self,opts]
|
|
113
105
|
rescue Exception
|
|
114
|
-
Arel.
|
|
106
|
+
Arel::Nodes.build_quoted('Wrong Format')
|
|
115
107
|
end
|
|
116
108
|
end
|
|
109
|
+
|
|
117
110
|
end
|
|
118
111
|
end
|