arel_extensions 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +46 -0
- data/Gemfile +10 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +101 -0
- data/Rakefile +14 -0
- data/arel_extensions.gemspec +32 -0
- data/functions.html +344 -0
- data/gemfiles/Gemfile.rails3 +10 -0
- data/gemfiles/Gemfile.rails5 +10 -0
- data/init/mssql.sql +6 -0
- data/init/mysql.sql +0 -0
- data/init/oracle.sql +31 -0
- data/init/postgresql.sql +12 -0
- data/init/sqlite.sql +1 -0
- data/lib/arel_extensions.rb +84 -0
- data/lib/arel_extensions/attributes.rb +26 -0
- data/lib/arel_extensions/comparators.rb +59 -0
- data/lib/arel_extensions/date_duration.rb +28 -0
- data/lib/arel_extensions/insert_manager.rb +33 -0
- data/lib/arel_extensions/math.rb +48 -0
- data/lib/arel_extensions/math_functions.rb +35 -0
- data/lib/arel_extensions/nodes.rb +27 -0
- data/lib/arel_extensions/nodes/abs.rb +6 -0
- data/lib/arel_extensions/nodes/ceil.rb +6 -0
- data/lib/arel_extensions/nodes/coalesce.rb +22 -0
- data/lib/arel_extensions/nodes/concat.rb +33 -0
- data/lib/arel_extensions/nodes/date_diff.rb +106 -0
- data/lib/arel_extensions/nodes/duration.rb +30 -0
- data/lib/arel_extensions/nodes/find_in_set.rb +16 -0
- data/lib/arel_extensions/nodes/floor.rb +6 -0
- data/lib/arel_extensions/nodes/function.rb +17 -0
- data/lib/arel_extensions/nodes/isnull.rb +30 -0
- data/lib/arel_extensions/nodes/length.rb +6 -0
- data/lib/arel_extensions/nodes/locate.rb +33 -0
- data/lib/arel_extensions/nodes/ltrim.rb +28 -0
- data/lib/arel_extensions/nodes/matches.rb +22 -0
- data/lib/arel_extensions/nodes/rand.rb +23 -0
- data/lib/arel_extensions/nodes/replace.rb +36 -0
- data/lib/arel_extensions/nodes/round.rb +15 -0
- data/lib/arel_extensions/nodes/rtrim.rb +29 -0
- data/lib/arel_extensions/nodes/soundex.rb +23 -0
- data/lib/arel_extensions/nodes/sum.rb +23 -0
- data/lib/arel_extensions/nodes/trim.rb +26 -0
- data/lib/arel_extensions/nodes/wday.rb +23 -0
- data/lib/arel_extensions/null_functions.rb +16 -0
- data/lib/arel_extensions/string_functions.rb +68 -0
- data/lib/arel_extensions/version.rb +4 -0
- data/lib/arel_extensions/visitors.rb +6 -0
- data/lib/arel_extensions/visitors/ibm_db.rb +206 -0
- data/lib/arel_extensions/visitors/mssql.rb +213 -0
- data/lib/arel_extensions/visitors/mysql.rb +184 -0
- data/lib/arel_extensions/visitors/oracle.rb +267 -0
- data/lib/arel_extensions/visitors/postgresql.rb +258 -0
- data/lib/arel_extensions/visitors/sqlite.rb +218 -0
- data/lib/arel_extensions/visitors/to_sql.rb +199 -0
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +251 -0
- data/test/support/fake_record.rb +137 -0
- data/test/test_comparators.rb +49 -0
- data/test/visitors/test_bulk_insert_oracle.rb +30 -0
- data/test/visitors/test_bulk_insert_sqlite.rb +31 -0
- data/test/visitors/test_bulk_insert_to_sql.rb +32 -0
- data/test/visitors/test_oracle.rb +105 -0
- data/test/visitors/test_to_sql.rb +148 -0
- data/test/with_ar/test_bulk_sqlite.rb +44 -0
- data/test/with_ar/test_math_sqlite.rb +59 -0
- data/test/with_ar/test_string_sqlite.rb +69 -0
- metadata +230 -0
data/init/mssql.sql
ADDED
data/init/mysql.sql
ADDED
File without changes
|
data/init/oracle.sql
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
CREATE OR REPLACE FUNCTION find_in_set(
|
2
|
+
i_value IN VARCHAR2,
|
3
|
+
i_list IN VARCHAR2,
|
4
|
+
i_delim IN VARCHAR2 DEFAULT ','
|
5
|
+
) RETURN INT DETERMINISTIC
|
6
|
+
AS
|
7
|
+
p_result INT := 0;
|
8
|
+
p_start NUMBER(5) := 1;
|
9
|
+
p_end NUMBER(5);
|
10
|
+
c_len CONSTANT NUMBER(5) := LENGTH( i_list );
|
11
|
+
c_ld CONSTANT NUMBER(5) := LENGTH( i_delim );
|
12
|
+
BEGIN
|
13
|
+
IF c_len > 0 THEN
|
14
|
+
p_end := INSTR( i_list, i_delim, p_start );
|
15
|
+
WHILE p_end > 0 LOOP
|
16
|
+
p_result := p_result + 1;
|
17
|
+
IF ( SUBSTR( i_list, p_start, p_end - p_start ) = i_value )
|
18
|
+
THEN
|
19
|
+
RETURN p_result;
|
20
|
+
END IF;
|
21
|
+
p_start := p_end + c_ld;
|
22
|
+
p_end := INSTR( i_list, i_delim, p_start );
|
23
|
+
END LOOP;
|
24
|
+
IF p_start <= c_len + 1
|
25
|
+
AND SUBSTR( i_list, p_start, c_len - p_start + 1 ) = i_value
|
26
|
+
THEN
|
27
|
+
RETURN p_result + 1;
|
28
|
+
END IF;
|
29
|
+
END IF;
|
30
|
+
RETURN 0;
|
31
|
+
END;
|
data/init/postgresql.sql
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
CREATE OR REPLACE FUNCTION public.find_in_set(n INTEGER, s TEXT)
|
2
|
+
RETURNS BOOLEAN
|
3
|
+
LANGUAGE sql
|
4
|
+
AS $function$
|
5
|
+
select bool(int4(z.row_number))
|
6
|
+
from
|
7
|
+
(
|
8
|
+
select row_number() over(), y.x
|
9
|
+
from (select unnest(('{' || $2 || '}')::int[]) as x) as y
|
10
|
+
) as z
|
11
|
+
where z.x = $1
|
12
|
+
$function$
|
data/init/sqlite.sql
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'arel'
|
2
|
+
|
3
|
+
# UnaryOperation|Grouping|Extract < Unary < Arel::Nodes::Node
|
4
|
+
# Equality|Regexp|Matches < Binary < Arel::Nodes::Node
|
5
|
+
# Count|NamedFunction < Function < Arel::Nodes::Node
|
6
|
+
|
7
|
+
# pure Arel internals improvements
|
8
|
+
Arel::Nodes::Binary.class_eval do
|
9
|
+
include Arel::AliasPredication
|
10
|
+
end
|
11
|
+
|
12
|
+
Arel::Nodes::Unary.class_eval do
|
13
|
+
include Arel::Math
|
14
|
+
include Arel::AliasPredication
|
15
|
+
include Arel::Expressions
|
16
|
+
end
|
17
|
+
|
18
|
+
Arel::Nodes::Grouping.class_eval do
|
19
|
+
include Arel::Math
|
20
|
+
include Arel::AliasPredication
|
21
|
+
include Arel::Expressions
|
22
|
+
end
|
23
|
+
|
24
|
+
Arel::Nodes::Function.class_eval do
|
25
|
+
include Arel::Math
|
26
|
+
include Arel::Expressions
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'arel_extensions/version'
|
30
|
+
require 'arel_extensions/attributes'
|
31
|
+
require 'arel_extensions/visitors'
|
32
|
+
require 'arel_extensions/nodes'
|
33
|
+
require 'arel_extensions/comparators'
|
34
|
+
require 'arel_extensions/date_duration'
|
35
|
+
require 'arel_extensions/null_functions'
|
36
|
+
require 'arel_extensions/math'
|
37
|
+
require 'arel_extensions/math_functions'
|
38
|
+
require 'arel_extensions/string_functions'
|
39
|
+
|
40
|
+
require 'arel_extensions/insert_manager'
|
41
|
+
|
42
|
+
module Arel
|
43
|
+
def self.rand
|
44
|
+
ArelExtensions::Nodes::Rand.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Arel::Attributes::Attribute.class_eval do
|
49
|
+
include Arel::Math
|
50
|
+
include ArelExtensions::Attributes
|
51
|
+
end
|
52
|
+
|
53
|
+
Arel::Nodes::Function.class_eval do
|
54
|
+
include ArelExtensions::Comparators
|
55
|
+
include ArelExtensions::DateDuration
|
56
|
+
include ArelExtensions::MathFunctions
|
57
|
+
include ArelExtensions::StringFunctions
|
58
|
+
end
|
59
|
+
|
60
|
+
Arel::Nodes::Unary.class_eval do
|
61
|
+
include ArelExtensions::Math
|
62
|
+
include ArelExtensions::Attributes
|
63
|
+
include ArelExtensions::MathFunctions
|
64
|
+
include ArelExtensions::Comparators
|
65
|
+
end
|
66
|
+
|
67
|
+
Arel::Nodes::Binary.class_eval do
|
68
|
+
include ArelExtensions::Math
|
69
|
+
include ArelExtensions::Attributes
|
70
|
+
include ArelExtensions::MathFunctions
|
71
|
+
include ArelExtensions::Comparators
|
72
|
+
end
|
73
|
+
|
74
|
+
Arel::Nodes::Equality.class_eval do
|
75
|
+
include ArelExtensions::Comparators
|
76
|
+
include ArelExtensions::DateDuration
|
77
|
+
include ArelExtensions::MathFunctions
|
78
|
+
include ArelExtensions::StringFunctions
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
Arel::InsertManager.class_eval do
|
83
|
+
include ArelExtensions::InsertManager
|
84
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'arel_extensions/comparators'
|
2
|
+
require 'arel_extensions/date_duration'
|
3
|
+
require 'arel_extensions/math'
|
4
|
+
require 'arel_extensions/math_functions'
|
5
|
+
require 'arel_extensions/null_functions'
|
6
|
+
require 'arel_extensions/string_functions'
|
7
|
+
|
8
|
+
module ArelExtensions
|
9
|
+
module Attributes
|
10
|
+
include ArelExtensions::Comparators
|
11
|
+
include ArelExtensions::DateDuration
|
12
|
+
include ArelExtensions::Math
|
13
|
+
include ArelExtensions::MathFunctions
|
14
|
+
include ArelExtensions::NullFunctions
|
15
|
+
include ArelExtensions::StringFunctions
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def !=(other)
|
22
|
+
Arel::Nodes::NotEqual.new self, Arel::Nodes.build_quoted(other, self)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ArelExtensions
|
2
|
+
module Comparators
|
3
|
+
|
4
|
+
def >(other)
|
5
|
+
Arel::Nodes::GreaterThan.new self, Arel::Nodes.build_quoted(other, self)
|
6
|
+
end
|
7
|
+
|
8
|
+
def >=(other)
|
9
|
+
Arel::Nodes::GreaterThanOrEqual.new self, Arel::Nodes.build_quoted(other, self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def <(other)
|
13
|
+
Arel::Nodes::LessThan.new self, Arel::Nodes.build_quoted(other, self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def <=(other)
|
17
|
+
Arel::Nodes::LessThanOrEqual.new self, Arel::Nodes.build_quoted(other, self)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
#REGEXP function
|
22
|
+
#Pattern matching using regular expressions
|
23
|
+
def =~(other)
|
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
|
28
|
+
end
|
29
|
+
|
30
|
+
#NOT_REGEXP function
|
31
|
+
#Negation of Regexp
|
32
|
+
def !~(other)
|
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
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
#Function use for not_regexp
|
41
|
+
def convert_regexp(other)
|
42
|
+
case other
|
43
|
+
when String
|
44
|
+
#Do nothing
|
45
|
+
when Regexp
|
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
|
+
else
|
53
|
+
raise(ArgumentError)
|
54
|
+
end
|
55
|
+
Arel::Nodes.build_quoted(other, self)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ArelExtensions
|
2
|
+
module DateDuration
|
3
|
+
#function returns the year (as a number) given a date value.
|
4
|
+
def year
|
5
|
+
ArelExtensions::Nodes::Duration.new "y",self
|
6
|
+
end
|
7
|
+
|
8
|
+
#function returns the month (as a number) given a date value.
|
9
|
+
def month
|
10
|
+
ArelExtensions::Nodes::Duration.new "m",self
|
11
|
+
end
|
12
|
+
|
13
|
+
#function returns the week (as a number) given a date value.
|
14
|
+
def week
|
15
|
+
ArelExtensions::Nodes::Duration.new "w",self
|
16
|
+
end
|
17
|
+
|
18
|
+
#function returns the month (as a number) given a date value.
|
19
|
+
def day
|
20
|
+
ArelExtensions::Nodes::Duration.new "d",self
|
21
|
+
end
|
22
|
+
|
23
|
+
def wday
|
24
|
+
ArelExtensions::Nodes::Wday.new self
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'arel'
|
2
|
+
|
3
|
+
module ArelExtensions
|
4
|
+
module InsertManager
|
5
|
+
|
6
|
+
def bulk_insert(cols, data)
|
7
|
+
case cols.first
|
8
|
+
when String, Symbol
|
9
|
+
cols.each { |c|
|
10
|
+
@ast.columns << @ast.relation[c]
|
11
|
+
}
|
12
|
+
when Array
|
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
|
+
end
|
18
|
+
when NilClass
|
19
|
+
@ast.columns = @ast.relation.columns
|
20
|
+
end
|
21
|
+
self.values = BulkValues.new(@ast.columns, data)
|
22
|
+
end
|
23
|
+
|
24
|
+
class BulkValues < Arel::Nodes::Node
|
25
|
+
attr_accessor :left, :cols
|
26
|
+
def initialize(cols, values)
|
27
|
+
@left = values
|
28
|
+
@cols = cols
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ArelExtensions
|
2
|
+
module Math
|
3
|
+
#function + between
|
4
|
+
#String and others (convert in string) allows you to concatenate 2 or more strings together.
|
5
|
+
#Date and integer adds or subtracts a specified time interval from a date.
|
6
|
+
def +(other)
|
7
|
+
return ArelExtensions::Nodes::Concat.new(self.expressions + [other]) if self.is_a?(ArelExtensions::Nodes::Concat)
|
8
|
+
arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
9
|
+
if arg == :integer || arg == :decimal || arg == :float
|
10
|
+
if other.is_a?(String)
|
11
|
+
other = other.to_i
|
12
|
+
end
|
13
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
14
|
+
elsif arg == :datetime || arg == :date
|
15
|
+
ArelExtensions::Nodes::DateAdd.new [self, other]
|
16
|
+
elsif arg == :string
|
17
|
+
ArelExtensions::Nodes::Concat.new [self, other]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#function returns the time between two dates
|
22
|
+
#function returns the susbration between two int
|
23
|
+
def -(other)
|
24
|
+
arg = self.relation.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s].type
|
25
|
+
if (arg == :date || arg == :datetime)
|
26
|
+
case other
|
27
|
+
when Arel::Attributes::Attribute
|
28
|
+
arg2 = other.relation.engine.connection.schema_cache.columns_hash(other.relation.table_name)[other.name.to_s].type
|
29
|
+
if arg2 == :date || arg2 == :datetime
|
30
|
+
ArelExtensions::Nodes::DateDiff.new self, other
|
31
|
+
else
|
32
|
+
ArelExtensions::Nodes::DateSub.new self, other
|
33
|
+
end
|
34
|
+
when Arel::Nodes::Node, DateTime, Time, String, Date
|
35
|
+
ArelExtensions::Nodes::DateDiff.new self, other
|
36
|
+
when Fixnum
|
37
|
+
ArelExtensions::Nodes::DateSub.new self, other
|
38
|
+
end
|
39
|
+
else
|
40
|
+
if other.is_a?(String)
|
41
|
+
other = other.to_i
|
42
|
+
end
|
43
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ArelExtensions
|
2
|
+
module MathFunctions
|
3
|
+
|
4
|
+
# Abs function returns the absolute value of a number passed as argument #
|
5
|
+
def abs
|
6
|
+
ArelExtensions::Nodes::Abs.new [self]
|
7
|
+
end
|
8
|
+
|
9
|
+
# will rounded up any positive or negative decimal value within the function upwards #
|
10
|
+
def ceil
|
11
|
+
ArelExtensions::Nodes::Ceil.new [self]
|
12
|
+
end
|
13
|
+
|
14
|
+
# function rounded up any positive or negative decimal value down to the next least integer
|
15
|
+
def floor
|
16
|
+
ArelExtensions::Nodes::Floor.new [self]
|
17
|
+
end
|
18
|
+
|
19
|
+
#function that can be invoked to produce random numbers between 0 and 1
|
20
|
+
# def rand seed = nil
|
21
|
+
# ArelExtensions::Nodes::Rand.new [seed]
|
22
|
+
# end
|
23
|
+
alias_method :random, :rand
|
24
|
+
|
25
|
+
#function is used to round a numeric field to the number of decimals specified
|
26
|
+
def round precision = nil
|
27
|
+
if precision
|
28
|
+
ArelExtensions::Nodes::Round.new [self, Arel::Nodes.build_quoted(precision)]
|
29
|
+
else
|
30
|
+
ArelExtensions::Nodes::Round.new [self]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'arel_extensions/nodes/function'
|
2
|
+
# Math functions
|
3
|
+
require 'arel_extensions/nodes/abs'
|
4
|
+
require 'arel_extensions/nodes/ceil'
|
5
|
+
require 'arel_extensions/nodes/floor'
|
6
|
+
require 'arel_extensions/nodes/round'
|
7
|
+
require 'arel_extensions/nodes/rand'
|
8
|
+
require 'arel_extensions/nodes/sum'
|
9
|
+
|
10
|
+
# String functions
|
11
|
+
require 'arel_extensions/nodes/concat' if Arel::VERSION.to_i < 7
|
12
|
+
require 'arel_extensions/nodes/length'
|
13
|
+
require 'arel_extensions/nodes/locate'
|
14
|
+
require 'arel_extensions/nodes/matches'
|
15
|
+
require 'arel_extensions/nodes/find_in_set'
|
16
|
+
require 'arel_extensions/nodes/replace'
|
17
|
+
require 'arel_extensions/nodes/soundex'
|
18
|
+
require 'arel_extensions/nodes/trim'
|
19
|
+
require 'arel_extensions/nodes/ltrim'
|
20
|
+
require 'arel_extensions/nodes/rtrim'
|
21
|
+
|
22
|
+
|
23
|
+
require 'arel_extensions/nodes/coalesce'
|
24
|
+
require 'arel_extensions/nodes/date_diff'
|
25
|
+
require 'arel_extensions/nodes/duration'
|
26
|
+
require 'arel_extensions/nodes/isnull'
|
27
|
+
require 'arel_extensions/nodes/wday'
|