arel_extensions 1.2.23 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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/gemfiles/rails6.gemfile
CHANGED
@@ -8,23 +8,22 @@ group :development, :test do
|
|
8
8
|
gem 'activemodel', '~> 6.0.0'
|
9
9
|
gem 'activerecord', '~> 6.0.0'
|
10
10
|
|
11
|
-
gem "sqlite3", '~> 1.4', platforms: [:mri
|
12
|
-
gem "mysql2", '0.5.2', platforms: [:mri
|
13
|
-
gem "pg",'< 1.0.0', platforms: [:mri
|
11
|
+
gem "sqlite3", '~> 1.4', platforms: [:mri]
|
12
|
+
gem "mysql2", '0.5.2', platforms: [:mri]
|
13
|
+
gem "pg",'< 1.0.0', platforms: [:mri]
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
gem "tiny_tds", platforms: [:mri, :mingw, :x64_mingw, :mswin]
|
16
|
+
gem "activerecord-sqlserver-adapter", '~> 6.0', platforms: [:mri, :mingw, :x64_mingw, :mswin]
|
17
17
|
|
18
18
|
gem 'ruby-oci8', platforms: [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
19
|
gem 'activerecord-oracle_enhanced-adapter', '~> 6.0.0' if ENV.has_key? 'ORACLE_HOME'
|
20
20
|
|
21
21
|
# for JRuby
|
22
|
-
gem 'activerecord-jdbc-adapter', platforms: :jruby
|
22
|
+
gem 'activerecord-jdbc-adapter', github: 'jruby/activerecord-jdbc-adapter', tag: 'v60.4', platforms: :jruby
|
23
23
|
gem "jdbc-sqlite3", platforms: :jruby
|
24
24
|
gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
|
25
25
|
gem "activerecord-jdbcmysql-adapter", platforms: :jruby
|
26
26
|
gem "activerecord-jdbcpostgresql-adapter", platforms: :jruby
|
27
|
-
gem "activerecord-jdbcmssql-adapter", platforms: :jruby
|
28
27
|
end
|
29
28
|
|
30
|
-
gemspec path: "../"
|
29
|
+
gemspec path: "../"
|
data/gemfiles/rails6_1.gemfile
CHANGED
@@ -8,23 +8,22 @@ group :development, :test do
|
|
8
8
|
gem 'activemodel', '~> 6.1.0'
|
9
9
|
gem 'activerecord', '~> 6.1.0'
|
10
10
|
|
11
|
-
gem "sqlite3", '~> 1.4', platforms: [:mri
|
12
|
-
gem "mysql2", '0.5.2', platforms: [:mri
|
13
|
-
gem "pg",'~> 1.1', platforms: [:mri
|
11
|
+
gem "sqlite3", '~> 1.4', platforms: [:mri]
|
12
|
+
gem "mysql2", '0.5.2', platforms: [:mri]
|
13
|
+
gem "pg",'~> 1.1', platforms: [:mri]
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
gem "tiny_tds", platforms: [:mri, :mingw, :x64_mingw, :mswin]
|
16
|
+
gem "activerecord-sqlserver-adapter", '~> 6.1.0', platforms: [:mri, :mingw, :x64_mingw, :mswin]
|
17
17
|
|
18
18
|
gem 'ruby-oci8', platforms: [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
19
|
gem 'activerecord-oracle_enhanced-adapter', '~> 6.0.0' if ENV.has_key? 'ORACLE_HOME'
|
20
20
|
|
21
21
|
# for JRuby
|
22
|
-
gem 'activerecord-jdbc-adapter', platforms: :jruby
|
22
|
+
gem 'activerecord-jdbc-adapter', github: 'jruby/activerecord-jdbc-adapter', tag: 'v61.1', platforms: :jruby
|
23
23
|
gem "jdbc-sqlite3", platforms: :jruby
|
24
24
|
gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
|
25
25
|
gem "activerecord-jdbcmysql-adapter", platforms: :jruby
|
26
26
|
gem "activerecord-jdbcpostgresql-adapter", platforms: :jruby
|
27
|
-
gem "activerecord-jdbcmssql-adapter", platforms: :jruby
|
28
27
|
end
|
29
28
|
|
30
29
|
gemspec path: "../"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'rails', '~> 7.0.1'
|
4
|
+
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem 'activesupport', '~> 7.0.1'
|
8
|
+
gem 'activemodel', '~> 7.0.1'
|
9
|
+
gem 'activerecord', '~> 7.0.1'
|
10
|
+
|
11
|
+
gem "sqlite3", '~> 1.4', platforms: [:mri]
|
12
|
+
gem "mysql2", '0.5.2', platforms: [:mri]
|
13
|
+
gem "pg",'~> 1.1', platforms: [:mri]
|
14
|
+
|
15
|
+
gem "tiny_tds", platforms: [:mri, :mingw, :x64_mingw, :mswin]
|
16
|
+
gem "activerecord-sqlserver-adapter", '~> 7.0.0.0', platforms: [:mri, :mingw, :x64_mingw, :mswin]
|
17
|
+
|
18
|
+
gem 'ruby-oci8', platforms: [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
|
+
gem 'activerecord-oracle_enhanced-adapter', '~> 6.0.0' if ENV.has_key? 'ORACLE_HOME'
|
20
|
+
end
|
21
|
+
|
22
|
+
gemspec path: "../"
|
@@ -23,6 +23,6 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_dependency('arel', '>= 6.0')
|
24
24
|
|
25
25
|
s.add_development_dependency('minitest', '~> 5.9')
|
26
|
-
s.add_development_dependency('rdoc', '
|
26
|
+
s.add_development_dependency('rdoc', '>= 6.3.1')
|
27
27
|
s.add_development_dependency('rake', '~> 12.3.3')
|
28
28
|
end
|
@@ -23,6 +23,6 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_dependency('activerecord', '>= 6.0')
|
24
24
|
|
25
25
|
s.add_development_dependency('minitest', '~> 5.9')
|
26
|
-
s.add_development_dependency('rdoc', '
|
26
|
+
s.add_development_dependency('rdoc', '>= 6.3.1')
|
27
27
|
s.add_development_dependency('rake', '~> 12.3.3')
|
28
28
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'arel_extensions/aliases'
|
1
2
|
require 'arel_extensions/math'
|
2
3
|
require 'arel_extensions/comparators'
|
3
4
|
require 'arel_extensions/date_duration'
|
@@ -8,6 +9,7 @@ require 'arel_extensions/predications'
|
|
8
9
|
|
9
10
|
module ArelExtensions
|
10
11
|
module Attributes
|
12
|
+
include ArelExtensions::Aliases
|
11
13
|
include ArelExtensions::Math
|
12
14
|
include ArelExtensions::Comparators
|
13
15
|
include ArelExtensions::DateDuration
|
@@ -40,8 +40,8 @@ module ArelExtensions
|
|
40
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, time_zone = nil)
|
44
|
+
ArelExtensions::Nodes::Format.new [self, tpl, time_zone]
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ArelExtensions
|
2
|
+
|
3
|
+
#
|
4
|
+
# column_of
|
5
|
+
#
|
6
|
+
# Before the creation of these methods, getting the column name was done
|
7
|
+
# uniquely through the code found in `column_of_via_arel_table`.
|
8
|
+
#
|
9
|
+
# This turned out to be unreliable, most notably when using adapters that do
|
10
|
+
# not come with activerecord standard batteries. SQL Server is the most
|
11
|
+
# notorious example.
|
12
|
+
#
|
13
|
+
# Currently, we're using a needlessly complicated way to address this issue.
|
14
|
+
# Different versions of activerecord are behaving differently; the public APIs
|
15
|
+
# do not seem to come with any guarantees, so we need to be sure that we're
|
16
|
+
# coveing all these cases.
|
17
|
+
|
18
|
+
def self.column_of_via_arel_table(table_name, column_name)
|
19
|
+
begin
|
20
|
+
Arel::Table.engine.connection.schema_cache.columns_hash(table_name)[column_name]
|
21
|
+
rescue NoMethodError
|
22
|
+
nil
|
23
|
+
rescue Exception => e
|
24
|
+
puts "Failed to fetch column info for #{table_name}.#{column_name} ."
|
25
|
+
puts "This should never be reached."
|
26
|
+
puts "#{e.class}: #{e}"
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.column_of(table_name, column_name)
|
32
|
+
use_arel_table = !ActiveRecord::Base.connected? || \
|
33
|
+
(ActiveRecord::Base.connection.pool.respond_to?(:schema_cache) && ActiveRecord::Base.connection.pool.schema_cache.nil?)
|
34
|
+
|
35
|
+
if use_arel_table
|
36
|
+
column_of_via_arel_table(table_name, column_name)
|
37
|
+
else
|
38
|
+
if ActiveRecord::Base.connection.pool.respond_to?(:pool_config)
|
39
|
+
ActiveRecord::Base.connection.pool.pool_config.schema_cache.columns_hash(table_name)[column_name]
|
40
|
+
elsif ActiveRecord::Base.connection.pool.respond_to?(:schema_cache)
|
41
|
+
ActiveRecord::Base.connection.pool.schema_cache.columns_hash(table_name)[column_name]
|
42
|
+
else
|
43
|
+
puts ">>> We really shouldn't be here #{table_name}.#{column_name}"
|
44
|
+
column_of_via_arel_table(table_name, column_name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -3,23 +3,25 @@ require 'arel'
|
|
3
3
|
module ArelExtensions
|
4
4
|
module InsertManager
|
5
5
|
def bulk_insert(cols, data)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
6
|
+
raise ArgumentError, "cols must be present" if cols.blank?
|
7
|
+
columns =
|
8
|
+
case cols.first
|
9
|
+
when Array
|
10
|
+
case cols.first.first
|
11
|
+
when Arel::Attributes::Attribute
|
12
|
+
cols
|
13
|
+
when String, Symbol
|
14
|
+
cols.map {|c| [@ast.relation[c.first]] }
|
15
|
+
else
|
16
|
+
raise ArgumentError, "cols has an invalid type: #{cols.first.first.class}"
|
17
|
+
end
|
18
|
+
when String, Symbol
|
19
|
+
cols.map { |c| @ast.relation[c] }
|
20
|
+
else
|
21
|
+
raise ArgumentError, "cols has an invalid type: #{cols.first.class}"
|
22
|
+
end
|
23
|
+
self.values = BulkValues.new(columns, data)
|
24
|
+
@ast.columns = columns
|
23
25
|
end
|
24
26
|
|
25
27
|
class BulkValues < Arel::Nodes::Node
|
data/lib/arel_extensions/math.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'arel_extensions/helpers'
|
2
|
+
|
1
3
|
require 'arel_extensions/nodes'
|
2
4
|
require 'arel_extensions/nodes/function'
|
3
5
|
require 'arel_extensions/nodes/concat'
|
@@ -22,37 +24,33 @@ module ArelExtensions
|
|
22
24
|
if self.expr.left.is_a?(String) || self.expr.right.is_a?(String)
|
23
25
|
return self.concat(other)
|
24
26
|
else
|
25
|
-
return Arel
|
27
|
+
return Arel.grouping(Arel::Nodes::Addition.new self, other)
|
26
28
|
end
|
27
29
|
when ArelExtensions::Nodes::Function,ArelExtensions::Nodes::Case
|
28
30
|
return case self.return_type
|
29
31
|
when :string, :text
|
30
32
|
self.concat(other)
|
31
33
|
when :integer, :decimal, :float, :number, :int
|
32
|
-
Arel
|
34
|
+
Arel.grouping(Arel::Nodes::Addition.new self, other)
|
33
35
|
when :date, :datetime
|
34
36
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
35
37
|
else
|
36
38
|
self.concat(other)
|
37
39
|
end
|
38
40
|
when Arel::Nodes::Function
|
39
|
-
Arel
|
41
|
+
Arel.grouping(Arel::Nodes::Addition.new self, other)
|
40
42
|
else
|
41
|
-
|
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
|
43
|
+
col = self.respond_to?(:relation)? ArelExtensions::column_of(self.relation.table_name, self.name.to_s) : nil
|
46
44
|
if (!col) # if the column doesn't exist in the database
|
47
|
-
Arel
|
45
|
+
Arel.grouping(Arel::Nodes::Addition.new(self, Arel::Nodes.build_quoted(other)))
|
48
46
|
else
|
49
47
|
arg = col.type
|
50
48
|
if arg == :integer || (!arg)
|
51
49
|
other = other.to_i if other.is_a?(String)
|
52
|
-
Arel
|
50
|
+
Arel.grouping(Arel::Nodes::Addition.new self, Arel::Nodes.build_quoted(other))
|
53
51
|
elsif arg == :decimal || arg == :float
|
54
52
|
other = Arel.sql(other) if other.is_a?(String) # Arel should accept Float & BigDecimal!
|
55
|
-
Arel
|
53
|
+
Arel.grouping(Arel::Nodes::Addition.new self, Arel::Nodes.build_quoted(other))
|
56
54
|
elsif arg == :datetime || arg == :date
|
57
55
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
58
56
|
elsif arg == :string || arg == :text
|
@@ -68,41 +66,33 @@ module ArelExtensions
|
|
68
66
|
case self
|
69
67
|
when Arel::Nodes::Grouping
|
70
68
|
if self.expr.left.is_a?(Date) || self.expr.left.is_a?(DateTime)
|
71
|
-
Arel
|
69
|
+
Arel.grouping(ArelExtensions::Nodes::DateSub.new [self, Arel::Nodes.build_quoted(other)])
|
72
70
|
else
|
73
|
-
Arel
|
71
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other)))
|
74
72
|
end
|
75
73
|
when ArelExtensions::Nodes::Function, ArelExtensions::Nodes::Case
|
76
74
|
case self.return_type
|
77
75
|
when :string, :text # ???
|
78
|
-
Arel
|
76
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other))) # ??
|
79
77
|
when :integer, :decimal, :float, :number
|
80
|
-
Arel
|
78
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other)))
|
81
79
|
when :date, :datetime
|
82
|
-
ArelExtensions::Nodes::DateSub.new [self, other]
|
80
|
+
ArelExtensions::Nodes::DateSub.new [self, Arel::Nodes.build_quoted(other)]
|
83
81
|
else
|
84
|
-
Arel
|
82
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other)))
|
85
83
|
end
|
86
84
|
when Arel::Nodes::Function
|
87
|
-
Arel
|
85
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other)))
|
88
86
|
else
|
89
|
-
|
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
|
87
|
+
col = ArelExtensions::column_of(self.relation.table_name, self.name.to_s)
|
94
88
|
if (!col) # if the column doesn't exist in the database
|
95
|
-
Arel
|
89
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other)))
|
96
90
|
else
|
97
91
|
arg = col.type
|
98
92
|
if (arg == :date || arg == :datetime)
|
99
93
|
case other
|
100
94
|
when Arel::Attributes::Attribute
|
101
|
-
|
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
|
95
|
+
col2 = ArelExtensions::column_of(other.relation.table_name, other.name.to_s)
|
106
96
|
if (!col2) # if the column doesn't exist in the database
|
107
97
|
ArelExtensions::Nodes::DateSub.new [self, other]
|
108
98
|
else
|
@@ -123,11 +113,11 @@ module ArelExtensions
|
|
123
113
|
else
|
124
114
|
case other
|
125
115
|
when Integer, Float, BigDecimal
|
126
|
-
Arel
|
116
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.sql(other.to_s)))
|
127
117
|
when String
|
128
|
-
Arel
|
118
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.sql(other)))
|
129
119
|
else
|
130
|
-
Arel
|
120
|
+
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel::Nodes.build_quoted(other)))
|
131
121
|
end
|
132
122
|
end
|
133
123
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'arel_extensions/helpers'
|
2
|
+
|
1
3
|
module ArelExtensions
|
2
4
|
module Nodes
|
3
5
|
if Gem::Version.new(Arel::VERSION) < Gem::Version.new("7.1.0")
|
@@ -34,6 +36,7 @@ module ArelExtensions
|
|
34
36
|
include Arel::Math
|
35
37
|
include Arel::Predications
|
36
38
|
include Arel::OrderPredications
|
39
|
+
include ArelExtensions::Aliases
|
37
40
|
include ArelExtensions::Math
|
38
41
|
include ArelExtensions::Comparators
|
39
42
|
include ArelExtensions::Predications
|
@@ -56,11 +59,7 @@ module ArelExtensions
|
|
56
59
|
when Date, DateTime,Time
|
57
60
|
:datetime
|
58
61
|
when Arel::Attributes::Attribute
|
59
|
-
|
60
|
-
Arel::Table.engine.connection.schema_cache.columns_hash(obj.relation.table_name)[obj.name.to_s].type
|
61
|
-
rescue Exception
|
62
|
-
:string
|
63
|
-
end
|
62
|
+
ArelExtensions::column_of(obj.relation.table_name, obj.name.to_s)&.type || :string
|
64
63
|
else
|
65
64
|
:string
|
66
65
|
end
|
@@ -102,7 +101,7 @@ module ArelExtensions
|
|
102
101
|
alias :== :eql?
|
103
102
|
|
104
103
|
def as other
|
105
|
-
Arel::Nodes::As.new self, Arel
|
104
|
+
Arel::Nodes::As.new self, Arel.sql(other)
|
106
105
|
end
|
107
106
|
end
|
108
107
|
end
|
@@ -117,7 +117,16 @@ module ArelExtensions
|
|
117
117
|
if @date_type == :date
|
118
118
|
v.to_i / (24*3600)
|
119
119
|
elsif @date_type == :datetime
|
120
|
-
v.
|
120
|
+
if v.parts.size == 1
|
121
|
+
# first entry in the dict v.parts; one of [:years, :months, :weeks, :days, :hours, :minutes, :seconds]
|
122
|
+
# | the value
|
123
|
+
# | |
|
124
|
+
# | |
|
125
|
+
# v v
|
126
|
+
v.parts.first.second
|
127
|
+
else
|
128
|
+
v.to_i
|
129
|
+
end
|
121
130
|
end
|
122
131
|
else
|
123
132
|
v
|
@@ -130,7 +139,17 @@ module ArelExtensions
|
|
130
139
|
if @date_type == :date
|
131
140
|
Arel.sql('day')
|
132
141
|
elsif @date_type == :datetime
|
133
|
-
|
142
|
+
res = if v.parts.size == 1
|
143
|
+
# first entry in the dict v.parts; one of [:years, :months, :weeks, :days, :hours, :minutes, :seconds]
|
144
|
+
# | the key
|
145
|
+
# | | convert symbol to string
|
146
|
+
# | | | remove the plural suffix `s`
|
147
|
+
# v v v v
|
148
|
+
v.parts.first.first.to_s[0..-2]
|
149
|
+
else
|
150
|
+
'second'
|
151
|
+
end
|
152
|
+
Arel.sql(res)
|
134
153
|
end
|
135
154
|
else
|
136
155
|
if ArelExtensions::Nodes::Duration === v
|
@@ -141,9 +160,9 @@ module ArelExtensions
|
|
141
160
|
when 'h','mn','s'
|
142
161
|
Arel.sql('second')
|
143
162
|
when /i\z/
|
144
|
-
Arel.sql(
|
163
|
+
Arel.sql(ArelExtensions::Visitors::MSSQL::LOADED_VISITOR::DATE_MAPPING[v.left[0..-2]])
|
145
164
|
else
|
146
|
-
Arel.sql(
|
165
|
+
Arel.sql(ArelExtensions::Visitors::MSSQL::LOADED_VISITOR::DATE_MAPPING[v.left])
|
147
166
|
end
|
148
167
|
end
|
149
168
|
end
|
@@ -5,11 +5,12 @@ module ArelExtensions
|
|
5
5
|
class Format < Function
|
6
6
|
RETURN_TYPE = :string
|
7
7
|
|
8
|
-
attr_accessor :col_type, :iso_format
|
8
|
+
attr_accessor :col_type, :iso_format, :time_zone
|
9
9
|
|
10
10
|
def initialize expr
|
11
|
-
col = expr
|
11
|
+
col = expr[0]
|
12
12
|
@iso_format = convert_format(expr[1])
|
13
|
+
@time_zone = Arel::Nodes.build_quoted(expr[2]) if expr[2]
|
13
14
|
@col_type = type_of_attribute(col)
|
14
15
|
super [col, convert_to_string_node(@iso_format)]
|
15
16
|
end
|
@@ -51,11 +51,7 @@ module ArelExtensions
|
|
51
51
|
def type_of_attribute(att)
|
52
52
|
case att
|
53
53
|
when Arel::Attributes::Attribute
|
54
|
-
|
55
|
-
Arel::Table.engine.connection.schema_cache.columns_hash(att.relation.table_name)[att.name.to_s].type
|
56
|
-
rescue
|
57
|
-
att
|
58
|
-
end
|
54
|
+
ArelExtensions::column_of(att.relation.table_name, att.name.to_s)&.type || att
|
59
55
|
when ArelExtensions::Nodes::Function
|
60
56
|
att.return_type
|
61
57
|
# else
|
@@ -80,7 +76,7 @@ module ArelExtensions
|
|
80
76
|
when ActiveSupport::Duration
|
81
77
|
Arel.sql(object.to_i)
|
82
78
|
when Array
|
83
|
-
Arel
|
79
|
+
Arel.grouping(object.map{|e| convert_to_node(e)})
|
84
80
|
else
|
85
81
|
raise(ArgumentError, "#{object.class} cannot be converted to CONCAT arg")
|
86
82
|
end
|
@@ -10,10 +10,6 @@ module ArelExtensions
|
|
10
10
|
@substitute = convert_to_node(substitute)
|
11
11
|
super([@left,@pattern,@substitute])
|
12
12
|
end
|
13
|
-
|
14
|
-
def +(other)
|
15
|
-
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
16
|
-
end
|
17
13
|
end
|
18
14
|
|
19
15
|
class RegexpReplace < Function
|
@@ -26,10 +22,6 @@ module ArelExtensions
|
|
26
22
|
@substitute = convert_to_node(substitute)
|
27
23
|
super([@left,@pattern,@substitute])
|
28
24
|
end
|
29
|
-
|
30
|
-
def +(other)
|
31
|
-
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
32
|
-
end
|
33
25
|
end
|
34
26
|
end
|
35
27
|
end
|
@@ -14,7 +14,7 @@ module ArelExtensions
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def as other
|
17
|
-
Arel::Nodes::TableAlias.new Arel
|
17
|
+
Arel::Nodes::TableAlias.new Arel.grouping(self), Arel::Nodes::SqlLiteral.new(other.to_s)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -10,7 +10,7 @@ module ArelExtensions
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def as other
|
13
|
-
Arel::Nodes::TableAlias.new Arel
|
13
|
+
Arel::Nodes::TableAlias.new Arel.grouping(self), Arel::Nodes::SqlLiteral.new(other.to_s)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -24,9 +24,17 @@ module ArelExtensions
|
|
24
24
|
ArelExtensions::Nodes::FindInSet.new [other, self]
|
25
25
|
end
|
26
26
|
|
27
|
-
# LENGTH function returns the length of the value in a text field.
|
27
|
+
# LENGTH function returns the length (bytewise) of the value in a text field.
|
28
28
|
def length
|
29
|
-
ArelExtensions::Nodes::Length.new
|
29
|
+
ArelExtensions::Nodes::Length.new self, true
|
30
|
+
end
|
31
|
+
|
32
|
+
def byte_length
|
33
|
+
ArelExtensions::Nodes::Length.new self, true
|
34
|
+
end
|
35
|
+
|
36
|
+
def char_length
|
37
|
+
ArelExtensions::Nodes::Length.new self, false
|
30
38
|
end
|
31
39
|
|
32
40
|
# LOCATE function returns the first starting position of a string in another string.
|