arel_extensions 2.0.9 → 2.0.14

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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/Gemfile +10 -10
  4. data/Rakefile +4 -4
  5. data/gemfiles/rails3.gemfile +9 -9
  6. data/gemfiles/rails4.gemfile +13 -13
  7. data/gemfiles/rails5_0.gemfile +13 -13
  8. data/gemfiles/rails5_1_4.gemfile +13 -13
  9. data/gemfiles/rails5_2.gemfile +13 -13
  10. data/gemfiles/rails6.gemfile +13 -13
  11. data/lib/arel_extensions.rb +3 -3
  12. data/lib/arel_extensions/attributes.rb +0 -0
  13. data/lib/arel_extensions/boolean_functions.rb +21 -5
  14. data/lib/arel_extensions/common_sql_functions.rb +2 -4
  15. data/lib/arel_extensions/comparators.rb +11 -14
  16. data/lib/arel_extensions/date_duration.rb +4 -5
  17. data/lib/arel_extensions/insert_manager.rb +16 -17
  18. data/lib/arel_extensions/math.rb +8 -9
  19. data/lib/arel_extensions/math_functions.rb +15 -17
  20. data/lib/arel_extensions/nodes/abs.rb +0 -1
  21. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -1
  22. data/lib/arel_extensions/nodes/blank.rb +0 -1
  23. data/lib/arel_extensions/nodes/case.rb +3 -4
  24. data/lib/arel_extensions/nodes/cast.rb +4 -2
  25. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  26. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  27. data/lib/arel_extensions/nodes/coalesce.rb +0 -1
  28. data/lib/arel_extensions/nodes/collate.rb +0 -1
  29. data/lib/arel_extensions/nodes/concat.rb +1 -3
  30. data/lib/arel_extensions/nodes/date_diff.rb +7 -8
  31. data/lib/arel_extensions/nodes/duration.rb +0 -1
  32. data/lib/arel_extensions/nodes/find_in_set.rb +0 -1
  33. data/lib/arel_extensions/nodes/floor.rb +1 -1
  34. data/lib/arel_extensions/nodes/format.rb +27 -1
  35. data/lib/arel_extensions/nodes/formatted_number.rb +0 -1
  36. data/lib/arel_extensions/nodes/function.rb +18 -15
  37. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  38. data/lib/arel_extensions/nodes/json.rb +39 -30
  39. data/lib/arel_extensions/nodes/length.rb +0 -1
  40. data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
  41. data/lib/arel_extensions/nodes/locate.rb +0 -1
  42. data/lib/arel_extensions/nodes/log10.rb +1 -2
  43. data/lib/arel_extensions/nodes/matches.rb +0 -2
  44. data/lib/arel_extensions/nodes/md5.rb +0 -1
  45. data/lib/arel_extensions/nodes/power.rb +0 -1
  46. data/lib/arel_extensions/nodes/rand.rb +0 -1
  47. data/lib/arel_extensions/nodes/repeat.rb +0 -2
  48. data/lib/arel_extensions/nodes/replace.rb +0 -2
  49. data/lib/arel_extensions/nodes/round.rb +0 -1
  50. data/lib/arel_extensions/nodes/soundex.rb +0 -1
  51. data/lib/arel_extensions/nodes/std.rb +0 -1
  52. data/lib/arel_extensions/nodes/substring.rb +0 -1
  53. data/lib/arel_extensions/nodes/sum.rb +0 -0
  54. data/lib/arel_extensions/nodes/then.rb +0 -0
  55. data/lib/arel_extensions/nodes/trim.rb +0 -2
  56. data/lib/arel_extensions/nodes/union.rb +0 -2
  57. data/lib/arel_extensions/nodes/union_all.rb +0 -2
  58. data/lib/arel_extensions/nodes/wday.rb +0 -4
  59. data/lib/arel_extensions/null_functions.rb +3 -5
  60. data/lib/arel_extensions/predications.rb +5 -6
  61. data/lib/arel_extensions/railtie.rb +5 -5
  62. data/lib/arel_extensions/set_functions.rb +0 -2
  63. data/lib/arel_extensions/string_functions.rb +21 -22
  64. data/lib/arel_extensions/tasks.rb +1 -1
  65. data/lib/arel_extensions/version.rb +1 -1
  66. data/lib/arel_extensions/visitors.rb +9 -7
  67. data/lib/arel_extensions/visitors/convert_format.rb +37 -0
  68. data/lib/arel_extensions/visitors/ibm_db.rb +4 -11
  69. data/lib/arel_extensions/visitors/mssql.rb +48 -44
  70. data/lib/arel_extensions/visitors/mysql.rb +65 -67
  71. data/lib/arel_extensions/visitors/oracle.rb +58 -55
  72. data/lib/arel_extensions/visitors/oracle12.rb +2 -3
  73. data/lib/arel_extensions/visitors/postgresql.rb +41 -34
  74. data/lib/arel_extensions/visitors/sqlite.rb +23 -18
  75. data/lib/arel_extensions/visitors/to_sql.rb +69 -61
  76. data/test/arelx_test_helper.rb +0 -2
  77. data/test/real_db_test.rb +27 -42
  78. data/test/support/fake_record.rb +1 -1
  79. data/test/test_comparators.rb +0 -4
  80. data/test/visitors/test_bulk_insert_oracle.rb +0 -1
  81. data/test/visitors/test_bulk_insert_sqlite.rb +0 -2
  82. data/test/visitors/test_oracle.rb +1 -2
  83. data/test/visitors/test_to_sql.rb +16 -25
  84. data/test/with_ar/all_agnostic_test.rb +135 -139
  85. data/test/with_ar/insert_agnostic_test.rb +0 -2
  86. data/test/with_ar/test_bulk_sqlite.rb +0 -4
  87. data/test/with_ar/test_math_sqlite.rb +4 -8
  88. data/test/with_ar/test_string_mysql.rb +1 -5
  89. data/test/with_ar/test_string_sqlite.rb +1 -5
  90. data/version_v1.rb +1 -1
  91. data/version_v2.rb +1 -1
  92. metadata +3 -2
@@ -4,22 +4,22 @@ require 'arel_extensions/nodes/wday'
4
4
 
5
5
  module ArelExtensions
6
6
  module DateDuration
7
- #function returns the year (as a number) given a date value.
7
+ # function returns the year (as a number) given a date value.
8
8
  def year
9
9
  ArelExtensions::Nodes::Duration.new "y", self
10
10
  end
11
11
 
12
- #function returns the month (as a number) given a date value.
12
+ # function returns the month (as a number) given a date value.
13
13
  def month
14
14
  ArelExtensions::Nodes::Duration.new "m", self
15
15
  end
16
16
 
17
- #function returns the week (as a number) given a date value.
17
+ # function returns the week (as a number) given a date value.
18
18
  def week
19
19
  ArelExtensions::Nodes::Duration.new "w", self
20
20
  end
21
21
 
22
- #function returns the month (as a number) given a date value.
22
+ # function returns the month (as a number) given a date value.
23
23
  def day
24
24
  ArelExtensions::Nodes::Duration.new "d", self
25
25
  end
@@ -43,6 +43,5 @@ module ArelExtensions
43
43
  def format(tpl)
44
44
  ArelExtensions::Nodes::Format.new [self, tpl]
45
45
  end
46
-
47
46
  end
48
47
  end
@@ -2,34 +2,33 @@ require 'arel'
2
2
 
3
3
  module ArelExtensions
4
4
  module InsertManager
5
-
6
5
  def bulk_insert(cols, data)
7
6
  res_columns = []
8
- case cols.first
9
- when String, Symbol
10
- cols.each { |c|
11
- res_columns << @ast.relation[c]
12
- }
13
- when Array
14
- if String === cols.first.first
15
- res_columns = cols.map {|c| [@ast.relation[c.first]] }
16
- elsif Arel::Attributes::Attribute == cols.first.first
17
- res_columns = cols
18
- end
19
- when NilClass
20
- res_columns = @ast.relation.columns
7
+ case cols.first
8
+ when String, Symbol
9
+ cols.each { |c|
10
+ res_columns << @ast.relation[c]
11
+ }
12
+ when Array
13
+ if String === cols.first.first
14
+ res_columns = cols.map {|c| [@ast.relation[c.first]] }
15
+ elsif Arel::Attributes::Attribute == cols.first.first
16
+ res_columns = cols
21
17
  end
22
- self.values = BulkValues.new(res_columns, data)
23
- @ast.columns = res_columns
18
+ when NilClass
19
+ res_columns = @ast.relation.columns
20
+ end
21
+ self.values = BulkValues.new(res_columns, data)
22
+ @ast.columns = res_columns
24
23
  end
25
24
 
26
25
  class BulkValues < Arel::Nodes::Node
27
26
  attr_accessor :left, :cols
27
+
28
28
  def initialize(cols, values)
29
29
  @left = values
30
30
  @cols = cols
31
31
  end
32
32
  end
33
-
34
33
  end
35
34
  end
@@ -11,9 +11,9 @@ require 'arel_extensions/nodes/union_all'
11
11
 
12
12
  module ArelExtensions
13
13
  module Math
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.
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
19
  when Arel::Nodes::Quoted
@@ -43,7 +43,7 @@ module ArelExtensions
43
43
  rescue Exception
44
44
  col = nil
45
45
  end
46
- if (!col) #if the column doesn't exist in the database
46
+ if (!col) # if the column doesn't exist in the database
47
47
  Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new(self, other))
48
48
  else
49
49
  arg = col.type
@@ -62,8 +62,8 @@ module ArelExtensions
62
62
  end
63
63
  end
64
64
 
65
- #function returns the time between two dates
66
- #function returns the substraction between two ints
65
+ # function returns the time between two dates
66
+ # function returns the substraction between two ints
67
67
  def -(other)
68
68
  case self
69
69
  when Arel::Nodes::Grouping
@@ -91,7 +91,7 @@ module ArelExtensions
91
91
  rescue Exception
92
92
  col = nil
93
93
  end
94
- if (!col) #if the column doesn't exist in the database
94
+ if (!col) # if the column doesn't exist in the database
95
95
  Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
96
96
  else
97
97
  arg = col.type
@@ -103,7 +103,7 @@ module ArelExtensions
103
103
  rescue Exception
104
104
  col2 = nil
105
105
  end
106
- if (!col2) #if the column doesn't exist in the database
106
+ if (!col2) # if the column doesn't exist in the database
107
107
  ArelExtensions::Nodes::DateSub.new [self, other]
108
108
  else
109
109
  arg2 = col2.type
@@ -133,6 +133,5 @@ module ArelExtensions
133
133
  end
134
134
  end
135
135
  end
136
-
137
136
  end
138
137
  end
@@ -11,7 +11,6 @@ require 'arel_extensions/nodes/sum'
11
11
 
12
12
  module ArelExtensions
13
13
  module MathFunctions
14
-
15
14
  # Arel does not handle Decimal literal properly
16
15
  def * other
17
16
  case other
@@ -47,7 +46,7 @@ module ArelExtensions
47
46
  ArelExtensions::Nodes::Floor.new [self]
48
47
  end
49
48
 
50
- # function gives the base 10 log
49
+ # function gives the base 10 log
51
50
  def log10
52
51
  ArelExtensions::Nodes::Log10.new [self]
53
52
  end
@@ -75,13 +74,13 @@ module ArelExtensions
75
74
  ArelExtensions::Nodes::Sum.new self, opts
76
75
  end
77
76
 
78
- #function that can be invoked to produce random numbers between 0 and 1
79
- # def rand seed = nil
80
- # ArelExtensions::Nodes::Rand.new [seed]
81
- # end
82
- alias_method :random, :rand
77
+ # function that can be invoked to produce random numbers between 0 and 1
78
+ # def rand seed = nil
79
+ # ArelExtensions::Nodes::Rand.new [seed]
80
+ # end
81
+ alias_method(:random, :rand) rescue nil
83
82
 
84
- #function is used to round a numeric field to the number of decimals specified
83
+ # function is used to round a numeric field to the number of decimals specified
85
84
  def round precision = nil
86
85
  if precision
87
86
  ArelExtensions::Nodes::Round.new [self, precision]
@@ -96,14 +95,14 @@ module ArelExtensions
96
95
  sprintf(format_string,0) # this line is to get the right error message if the format_string is not correct
97
96
  m = /^(.*)%([ #+\-0]*)([1-9][0-9]+|[1-9]?)[.]?([0-9]*)([a-zA-Z])(.*)$/.match(format_string)
98
97
  opts = {
99
- :prefix => m[1],
100
- :flags => m[2].split(//).uniq.join,
101
- :width => m[3].to_i,
102
- :precision => m[4] != '' ? m[4].to_i : 6,
103
- :type => m[5],
104
- :suffix => m[6],
105
- :locale => locale,
106
- :original_string => format_string
98
+ prefix: m[1],
99
+ flags: m[2].split(//).uniq.join,
100
+ width: m[3].to_i,
101
+ precision: m[4] != '' ? m[4].to_i : 6,
102
+ type: m[5],
103
+ suffix: m[6],
104
+ locale: locale,
105
+ original_string: format_string
107
106
  }
108
107
  # opts = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
109
108
  ArelExtensions::Nodes::FormattedNumber.new [self,opts]
@@ -111,6 +110,5 @@ module ArelExtensions
111
110
  Arel::Nodes.build_quoted('Wrong Format')
112
111
  end
113
112
  end
114
-
115
113
  end
116
114
  end
@@ -2,7 +2,6 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Abs < Function
4
4
  RETURN_TYPE = :number
5
-
6
5
  end
7
6
  end
8
7
  end
@@ -9,6 +9,5 @@ module ArelExtensions
9
9
  super [node]
10
10
  end
11
11
  end
12
-
13
12
  end
14
13
  end
@@ -19,6 +19,5 @@ module ArelExtensions
19
19
  super expr.first
20
20
  end
21
21
  end
22
-
23
22
  end
24
23
  end
@@ -19,7 +19,6 @@ module ArelExtensions
19
19
 
20
20
  class Else < Arel::Nodes::Unary # :nodoc:
21
21
  end
22
-
23
22
  end
24
23
  else
25
24
  class Case < Arel::Nodes::Case
@@ -96,9 +95,9 @@ module ArelExtensions
96
95
 
97
96
  def eql? other
98
97
  self.class == other.class &&
99
- self.case == other.case &&
100
- self.conditions == other.conditions &&
101
- self.default == other.default
98
+ self.case == other.case &&
99
+ self.conditions == other.conditions &&
100
+ self.default == other.default
102
101
  end
103
102
  alias :== :eql?
104
103
 
@@ -14,7 +14,10 @@ module ArelExtensions
14
14
  @return_type = :decimal
15
15
  when :number
16
16
  @return_type = :number
17
- when 'char', 'varchar', 'text', 'nchar', 'nvarchar', 'ntext'
17
+ when 'char', 'varchar', 'nchar', 'nvarchar'
18
+ @return_type = :string
19
+ when 'text', :text, 'ntext', :ntext
20
+ @as_attr = expr[1].to_sym
18
21
  @return_type = :string
19
22
  when :datetime, 'datetime','smalldatetime'
20
23
  @return_type = :datetime
@@ -46,7 +49,6 @@ module ArelExtensions
46
49
  def return_type
47
50
  @return_type
48
51
  end
49
-
50
52
  end
51
53
  end
52
54
  end
@@ -1,7 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
3
  class Ceil < Function
4
- RETURN_TYPE = :number
4
+ RETURN_TYPE = :number
5
5
  end
6
6
  end
7
7
  end
File without changes
@@ -29,7 +29,6 @@ module ArelExtensions
29
29
  end
30
30
  return super(tab)
31
31
  end
32
-
33
32
  end
34
33
  end
35
34
  end
@@ -12,7 +12,6 @@ module ArelExtensions
12
12
  tab = [convert_to_node(left)]
13
13
  return super(tab)
14
14
  end
15
-
16
15
  end
17
16
  end
18
17
  end
@@ -11,7 +11,7 @@ module ArelExtensions::Nodes
11
11
  else
12
12
  node
13
13
  end
14
- }.flatten.reduce([]) { | res, b |
14
+ }.flatten.reduce([]) { |res, b|
15
15
  # concatenate successive literal strings.
16
16
  if b.is_a?(Arel::Nodes::Quoted) && b.expr == ""
17
17
  res
@@ -37,7 +37,6 @@ module ArelExtensions::Nodes
37
37
  def concat(other)
38
38
  Concat.new(self.expressions + [other])
39
39
  end
40
-
41
40
  end
42
41
 
43
42
  class GroupConcat < AggregateFunction
@@ -49,6 +48,5 @@ module ArelExtensions::Nodes
49
48
  @separator = convert_to_node(separator)
50
49
  super node, opts
51
50
  end
52
-
53
51
  end
54
52
  end
@@ -2,7 +2,7 @@ require 'date'
2
2
 
3
3
  module ArelExtensions
4
4
  module Nodes
5
- class DateDiff < Function #difference entre colonne date et date string/date
5
+ class DateDiff < Function # difference entre colonne date et date string/date
6
6
  attr_accessor :left_node_type
7
7
  attr_accessor :right_node_type
8
8
 
@@ -97,7 +97,7 @@ module ArelExtensions
97
97
  v ||= self.expressions.last
98
98
  if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === v
99
99
  if @date_type == :ruby_date
100
- Arel.sql("(INTERVAL '1' DAY) * %s" % v.inspect.to_i )
100
+ Arel.sql("(INTERVAL '1' DAY) * %s" % v.inspect.to_i)
101
101
  else
102
102
  Arel.sql("(INTERVAL '1' SECOND) * %s" % v.to_i)
103
103
  end
@@ -150,6 +150,7 @@ module ArelExtensions
150
150
  end
151
151
 
152
152
  private
153
+
153
154
  def convert(object)
154
155
  case object
155
156
  when Arel::Attributes::Attribute, Arel::Nodes::Node, ActiveSupport::Duration
@@ -157,16 +158,16 @@ module ArelExtensions
157
158
  when Integer
158
159
  object.days
159
160
  when DateTime, Time, Date
160
- raise(ArgumentError, "#{object.class} can not be converted to Integer")
161
+ raise(ArgumentError, "#{object.class} cannot be converted to Integer")
161
162
  when String
162
163
  Arel::Nodes.build_quoted(object)
163
164
  else
164
- raise(ArgumentError, "#{object.class} can not be converted to Integer")
165
+ raise(ArgumentError, "#{object.class} cannot be converted to Integer")
165
166
  end
166
167
  end
167
168
  end
168
169
 
169
- class DateSub < Function #difference entre colonne date et date string/date
170
+ class DateSub < Function # difference entre colonne date et date string/date
170
171
  RETURN_TYPE = :integer
171
172
 
172
173
  def initialize(expr)
@@ -183,12 +184,10 @@ module ArelExtensions
183
184
  if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === object
184
185
  object.to_i
185
186
  else
186
- raise(ArgumentError, "#{object.class} can not be converted to Number")
187
+ raise(ArgumentError, "#{object.class} cannot be converted to Number")
187
188
  end
188
189
  end
189
190
  end
190
-
191
191
  end
192
-
193
192
  end
194
193
  end
@@ -20,7 +20,6 @@ module ArelExtensions
20
20
  def right
21
21
  @expressions[1]
22
22
  end
23
-
24
23
  end
25
24
  end
26
25
  end
@@ -2,7 +2,6 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class FindInSet < Function
4
4
  RETURN_TYPE = :integer
5
-
6
5
  end
7
6
  end
8
7
  end
@@ -1,7 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
3
  class Floor < Function
4
- RETURN_TYPE = :number
4
+ RETURN_TYPE = :number
5
5
  end
6
6
  end
7
7
  end
@@ -1,15 +1,41 @@
1
+ require 'strscan'
2
+
1
3
  module ArelExtensions
2
4
  module Nodes
3
5
  class Format < Function
4
6
  RETURN_TYPE = :string
5
7
 
6
8
  attr_accessor :col_type, :iso_format
9
+
7
10
  def initialize expr
8
11
  col = expr.first
9
- @iso_format = expr[1]
12
+ @iso_format = convert_format(expr[1])
10
13
  @col_type = type_of_attribute(col)
11
14
  super [col, convert_to_string_node(@iso_format)]
12
15
  end
16
+
17
+ private
18
+
19
+ # Address portability issues with some of the formats.
20
+ def convert_format(fmt)
21
+ s = StringScanner.new fmt
22
+ res = StringIO.new
23
+ while !s.eos?
24
+ res <<
25
+ case
26
+ when s.scan(/%D/) then '%m/%d/%y'
27
+ when s.scan(/%F/) then '%Y-%m-%d'
28
+ when s.scan(/%R/) then '%H:%M'
29
+ when s.scan(/%r/) then '%I:%M:%S %p'
30
+ when s.scan(/%T/) then '%H:%M:%S'
31
+ when s.scan(/%v/) then '%e-%b-%Y'
32
+
33
+ when s.scan(/[^%]+/) then s.matched
34
+ when s.scan(/./) then s.matched
35
+ end
36
+ end
37
+ res.string
38
+ end
13
39
  end
14
40
  end
15
41
  end