groupdate 4.1.2 → 6.0.1
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/CHANGELOG.md +97 -34
- data/CONTRIBUTING.md +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +41 -48
- data/lib/groupdate/adapters/base_adapter.rb +51 -0
- data/lib/groupdate/adapters/mysql_adapter.rb +63 -0
- data/lib/groupdate/adapters/postgresql_adapter.rb +46 -0
- data/lib/groupdate/adapters/sqlite_adapter.rb +51 -0
- data/lib/groupdate/enumerable.rb +9 -15
- data/lib/groupdate/magic.rb +111 -12
- data/lib/groupdate/query_methods.rb +3 -10
- data/lib/groupdate/relation.rb +3 -0
- data/lib/groupdate/series_builder.rb +112 -76
- data/lib/groupdate/version.rb +1 -1
- data/lib/groupdate.rb +29 -7
- metadata +15 -110
- data/lib/groupdate/relation_builder.rb +0 -186
data/lib/groupdate.rb
CHANGED
@@ -1,20 +1,28 @@
|
|
1
|
+
# dependencies
|
2
|
+
require "active_support"
|
1
3
|
require "active_support/core_ext/module/attribute_accessors"
|
2
4
|
require "active_support/time"
|
3
|
-
|
4
|
-
|
5
|
-
require "groupdate/series_builder"
|
5
|
+
|
6
|
+
# modules
|
6
7
|
require "groupdate/magic"
|
8
|
+
require "groupdate/series_builder"
|
9
|
+
require "groupdate/version"
|
10
|
+
|
11
|
+
# adapters
|
12
|
+
require "groupdate/adapters/base_adapter"
|
13
|
+
require "groupdate/adapters/mysql_adapter"
|
14
|
+
require "groupdate/adapters/postgresql_adapter"
|
15
|
+
require "groupdate/adapters/sqlite_adapter"
|
7
16
|
|
8
17
|
module Groupdate
|
9
18
|
class Error < RuntimeError; end
|
10
19
|
|
11
|
-
PERIODS = [:second, :minute, :hour, :day, :week, :month, :quarter, :year, :day_of_week, :hour_of_day, :minute_of_hour, :day_of_month, :month_of_year]
|
20
|
+
PERIODS = [:second, :minute, :hour, :day, :week, :month, :quarter, :year, :day_of_week, :hour_of_day, :minute_of_hour, :day_of_month, :day_of_year, :month_of_year]
|
12
21
|
METHODS = PERIODS.map { |v| :"group_by_#{v}" } + [:group_by_period]
|
13
22
|
|
14
|
-
mattr_accessor :week_start, :day_start, :time_zone
|
15
|
-
self.week_start = :
|
23
|
+
mattr_accessor :week_start, :day_start, :time_zone
|
24
|
+
self.week_start = :sunday
|
16
25
|
self.day_start = 0
|
17
|
-
self.dates = true
|
18
26
|
|
19
27
|
# api for gems like ActiveMedian
|
20
28
|
def self.process_result(relation, result, **options)
|
@@ -23,8 +31,22 @@ module Groupdate
|
|
23
31
|
end
|
24
32
|
result
|
25
33
|
end
|
34
|
+
|
35
|
+
def self.adapters
|
36
|
+
@adapters ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.register_adapter(name, adapter)
|
40
|
+
Array(name).each do |n|
|
41
|
+
adapters[n] = adapter
|
42
|
+
end
|
43
|
+
end
|
26
44
|
end
|
27
45
|
|
46
|
+
Groupdate.register_adapter ["Mysql2", "Mysql2Spatial", "Mysql2Rgeo"], Groupdate::Adapters::MySQLAdapter
|
47
|
+
Groupdate.register_adapter ["PostgreSQL", "PostGIS", "Redshift"], Groupdate::Adapters::PostgreSQLAdapter
|
48
|
+
Groupdate.register_adapter "SQLite", Groupdate::Adapters::SQLiteAdapter
|
49
|
+
|
28
50
|
require "groupdate/enumerable"
|
29
51
|
|
30
52
|
ActiveSupport.on_load(:active_record) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groupdate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -16,114 +16,16 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
-
|
28
|
-
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rake
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: minitest
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: activerecord
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: pg
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "<"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "<"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '1'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: mysql2
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "<"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0.5'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "<"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0.5'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: sqlite3
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - "~>"
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 1.3.0
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: 1.3.0
|
125
|
-
description:
|
126
|
-
email: andrew@chartkick.com
|
26
|
+
version: '5.2'
|
27
|
+
description:
|
28
|
+
email: andrew@ankane.org
|
127
29
|
executables: []
|
128
30
|
extensions: []
|
129
31
|
extra_rdoc_files: []
|
@@ -134,18 +36,21 @@ files:
|
|
134
36
|
- README.md
|
135
37
|
- lib/groupdate.rb
|
136
38
|
- lib/groupdate/active_record.rb
|
39
|
+
- lib/groupdate/adapters/base_adapter.rb
|
40
|
+
- lib/groupdate/adapters/mysql_adapter.rb
|
41
|
+
- lib/groupdate/adapters/postgresql_adapter.rb
|
42
|
+
- lib/groupdate/adapters/sqlite_adapter.rb
|
137
43
|
- lib/groupdate/enumerable.rb
|
138
44
|
- lib/groupdate/magic.rb
|
139
45
|
- lib/groupdate/query_methods.rb
|
140
46
|
- lib/groupdate/relation.rb
|
141
|
-
- lib/groupdate/relation_builder.rb
|
142
47
|
- lib/groupdate/series_builder.rb
|
143
48
|
- lib/groupdate/version.rb
|
144
49
|
homepage: https://github.com/ankane/groupdate
|
145
50
|
licenses:
|
146
51
|
- MIT
|
147
52
|
metadata: {}
|
148
|
-
post_install_message:
|
53
|
+
post_install_message:
|
149
54
|
rdoc_options: []
|
150
55
|
require_paths:
|
151
56
|
- lib
|
@@ -153,15 +58,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
58
|
requirements:
|
154
59
|
- - ">="
|
155
60
|
- !ruby/object:Gem::Version
|
156
|
-
version: '2.
|
61
|
+
version: '2.6'
|
157
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
63
|
requirements:
|
159
64
|
- - ">="
|
160
65
|
- !ruby/object:Gem::Version
|
161
66
|
version: '0'
|
162
67
|
requirements: []
|
163
|
-
rubygems_version: 3.
|
164
|
-
signing_key:
|
68
|
+
rubygems_version: 3.2.32
|
69
|
+
signing_key:
|
165
70
|
specification_version: 4
|
166
71
|
summary: The simplest way to group temporal data
|
167
72
|
test_files: []
|
@@ -1,186 +0,0 @@
|
|
1
|
-
module Groupdate
|
2
|
-
class RelationBuilder
|
3
|
-
attr_reader :period, :column, :day_start, :week_start
|
4
|
-
|
5
|
-
def initialize(relation, column:, period:, time_zone:, time_range:, week_start:, day_start:)
|
6
|
-
@relation = relation
|
7
|
-
@column = resolve_column(relation, column)
|
8
|
-
@period = period
|
9
|
-
@time_zone = time_zone
|
10
|
-
@time_range = time_range
|
11
|
-
@week_start = week_start
|
12
|
-
@day_start = day_start
|
13
|
-
|
14
|
-
if relation.default_timezone == :local
|
15
|
-
raise Groupdate::Error, "ActiveRecord::Base.default_timezone must be :utc to use Groupdate"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def generate
|
20
|
-
@relation.group(group_clause).where(*where_clause)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def group_clause
|
26
|
-
time_zone = @time_zone.tzinfo.name
|
27
|
-
adapter_name = @relation.connection.adapter_name
|
28
|
-
query =
|
29
|
-
case adapter_name
|
30
|
-
when "MySQL", "Mysql2", "Mysql2Spatial", 'Mysql2Rgeo'
|
31
|
-
case period
|
32
|
-
when :day_of_week
|
33
|
-
["DAYOFWEEK(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} second), '+00:00', ?)) - 1", time_zone]
|
34
|
-
when :hour_of_day
|
35
|
-
["(EXTRACT(HOUR from CONVERT_TZ(#{column}, '+00:00', ?)) + 24 - #{day_start / 3600}) % 24", time_zone]
|
36
|
-
when :minute_of_hour
|
37
|
-
["(EXTRACT(MINUTE from CONVERT_TZ(#{column}, '+00:00', ?)))", time_zone]
|
38
|
-
when :day_of_month
|
39
|
-
["DAYOFMONTH(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} second), '+00:00', ?))", time_zone]
|
40
|
-
when :month_of_year
|
41
|
-
["MONTH(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} second), '+00:00', ?))", time_zone]
|
42
|
-
when :week
|
43
|
-
["CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL ((#{7 - week_start} + WEEKDAY(CONVERT_TZ(#{column}, '+00:00', ?) - INTERVAL #{day_start} second)) % 7) DAY) - INTERVAL #{day_start} second, '+00:00', ?), '%Y-%m-%d 00:00:00') + INTERVAL #{day_start} second, ?, '+00:00')", time_zone, time_zone, time_zone]
|
44
|
-
when :quarter
|
45
|
-
["DATE_ADD(CONVERT_TZ(DATE_FORMAT(DATE(CONCAT(EXTRACT(YEAR FROM CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} second), '+00:00', ?)), '-', LPAD(1 + 3 * (QUARTER(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} second), '+00:00', ?)) - 1), 2, '00'), '-01')), '%Y-%m-%d %H:%i:%S'), ?, '+00:00'), INTERVAL #{day_start} second)", time_zone, time_zone, time_zone]
|
46
|
-
else
|
47
|
-
format =
|
48
|
-
case period
|
49
|
-
when :second
|
50
|
-
"%Y-%m-%d %H:%i:%S"
|
51
|
-
when :minute
|
52
|
-
"%Y-%m-%d %H:%i:00"
|
53
|
-
when :hour
|
54
|
-
"%Y-%m-%d %H:00:00"
|
55
|
-
when :day
|
56
|
-
"%Y-%m-%d 00:00:00"
|
57
|
-
when :month
|
58
|
-
"%Y-%m-01 00:00:00"
|
59
|
-
else # year
|
60
|
-
"%Y-01-01 00:00:00"
|
61
|
-
end
|
62
|
-
|
63
|
-
["DATE_ADD(CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} second), '+00:00', ?), '#{format}'), ?, '+00:00'), INTERVAL #{day_start} second)", time_zone, time_zone]
|
64
|
-
end
|
65
|
-
when "PostgreSQL", "PostGIS"
|
66
|
-
case period
|
67
|
-
when :day_of_week
|
68
|
-
["EXTRACT(DOW from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} second')::integer", time_zone]
|
69
|
-
when :hour_of_day
|
70
|
-
["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} second')::integer", time_zone]
|
71
|
-
when :minute_of_hour
|
72
|
-
["EXTRACT(MINUTE from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} second')::integer", time_zone]
|
73
|
-
when :day_of_month
|
74
|
-
["EXTRACT(DAY from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} second')::integer", time_zone]
|
75
|
-
when :month_of_year
|
76
|
-
["EXTRACT(MONTH from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} second')::integer", time_zone]
|
77
|
-
when :week # start on Sunday, not PostgreSQL default Monday
|
78
|
-
["(DATE_TRUNC('#{period}', (#{column}::timestamptz - INTERVAL '#{week_start} day' - INTERVAL '#{day_start} second') AT TIME ZONE ?) + INTERVAL '#{week_start} day' + INTERVAL '#{day_start} second') AT TIME ZONE ?", time_zone, time_zone]
|
79
|
-
else
|
80
|
-
["(DATE_TRUNC('#{period}', (#{column}::timestamptz - INTERVAL '#{day_start} second') AT TIME ZONE ?) + INTERVAL '#{day_start} second') AT TIME ZONE ?", time_zone, time_zone]
|
81
|
-
end
|
82
|
-
when "SQLite"
|
83
|
-
raise Groupdate::Error, "Time zones not supported for SQLite" unless @time_zone.utc_offset.zero?
|
84
|
-
raise Groupdate::Error, "day_start not supported for SQLite" unless day_start.zero?
|
85
|
-
raise Groupdate::Error, "week_start not supported for SQLite" unless week_start == 6
|
86
|
-
|
87
|
-
if period == :week
|
88
|
-
["strftime('%%Y-%%m-%%d 00:00:00 UTC', #{column}, '-6 days', 'weekday 0')"]
|
89
|
-
else
|
90
|
-
format =
|
91
|
-
case period
|
92
|
-
when :hour_of_day
|
93
|
-
"%H"
|
94
|
-
when :minute_of_hour
|
95
|
-
"%M"
|
96
|
-
when :day_of_week
|
97
|
-
"%w"
|
98
|
-
when :day_of_month
|
99
|
-
"%d"
|
100
|
-
when :month_of_year
|
101
|
-
"%m"
|
102
|
-
when :second
|
103
|
-
"%Y-%m-%d %H:%M:%S UTC"
|
104
|
-
when :minute
|
105
|
-
"%Y-%m-%d %H:%M:00 UTC"
|
106
|
-
when :hour
|
107
|
-
"%Y-%m-%d %H:00:00 UTC"
|
108
|
-
when :day
|
109
|
-
"%Y-%m-%d 00:00:00 UTC"
|
110
|
-
when :month
|
111
|
-
"%Y-%m-01 00:00:00 UTC"
|
112
|
-
when :quarter
|
113
|
-
raise Groupdate::Error, "Quarter not supported for SQLite"
|
114
|
-
else # year
|
115
|
-
"%Y-01-01 00:00:00 UTC"
|
116
|
-
end
|
117
|
-
|
118
|
-
["strftime('#{format.gsub(/%/, '%%')}', #{column})"]
|
119
|
-
end
|
120
|
-
when "Redshift"
|
121
|
-
case period
|
122
|
-
when :day_of_week
|
123
|
-
["EXTRACT(DOW from CONVERT_TIMEZONE(?, #{column}::timestamp) - INTERVAL '#{day_start} second')::integer", time_zone]
|
124
|
-
when :hour_of_day
|
125
|
-
["EXTRACT(HOUR from CONVERT_TIMEZONE(?, #{column}::timestamp) - INTERVAL '#{day_start} second')::integer", time_zone]
|
126
|
-
when :minute_of_hour
|
127
|
-
["EXTRACT(MINUTE from CONVERT_TIMEZONE(?, #{column}::timestamp) - INTERVAL '#{day_start} second')::integer", time_zone]
|
128
|
-
when :day_of_month
|
129
|
-
["EXTRACT(DAY from CONVERT_TIMEZONE(?, #{column}::timestamp) - INTERVAL '#{day_start} second')::integer", time_zone]
|
130
|
-
when :month_of_year
|
131
|
-
["EXTRACT(MONTH from CONVERT_TIMEZONE(?, #{column}::timestamp) - INTERVAL '#{day_start} second')::integer", time_zone]
|
132
|
-
when :week # start on Sunday, not Redshift default Monday
|
133
|
-
# Redshift does not return timezone information; it
|
134
|
-
# always says it is in UTC time, so we must convert
|
135
|
-
# back to UTC to play properly with the rest of Groupdate.
|
136
|
-
#
|
137
|
-
["CONVERT_TIMEZONE(?, 'Etc/UTC', DATE_TRUNC(?, CONVERT_TIMEZONE(?, #{column}) - INTERVAL '#{week_start} day' - INTERVAL '#{day_start} second'))::timestamp + INTERVAL '#{week_start} day' + INTERVAL '#{day_start} second'", time_zone, period, time_zone]
|
138
|
-
else
|
139
|
-
["CONVERT_TIMEZONE(?, 'Etc/UTC', DATE_TRUNC(?, CONVERT_TIMEZONE(?, #{column}) - INTERVAL '#{day_start} second'))::timestamp + INTERVAL '#{day_start} second'", time_zone, period, time_zone]
|
140
|
-
end
|
141
|
-
else
|
142
|
-
raise Groupdate::Error, "Connection adapter not supported: #{adapter_name}"
|
143
|
-
end
|
144
|
-
|
145
|
-
if adapter_name == "MySQL" && period == :week
|
146
|
-
query[0] = "CAST(#{query[0]} AS DATETIME)"
|
147
|
-
end
|
148
|
-
|
149
|
-
clause = @relation.send(:sanitize_sql_array, query)
|
150
|
-
|
151
|
-
# cleaner queries in logs
|
152
|
-
clause = clean_group_clause_postgresql(clause)
|
153
|
-
clean_group_clause_mysql(clause)
|
154
|
-
end
|
155
|
-
|
156
|
-
def clean_group_clause_postgresql(clause)
|
157
|
-
clause.gsub(/ (\-|\+) INTERVAL '0 second'/, "")
|
158
|
-
end
|
159
|
-
|
160
|
-
def clean_group_clause_mysql(clause)
|
161
|
-
clause = clause.gsub("DATE_SUB(#{column}, INTERVAL 0 second)", "#{column}")
|
162
|
-
if clause.start_with?("DATE_ADD(") && clause.end_with?(", INTERVAL 0 second)")
|
163
|
-
clause = clause[9..-21]
|
164
|
-
end
|
165
|
-
clause
|
166
|
-
end
|
167
|
-
|
168
|
-
def where_clause
|
169
|
-
if @time_range.is_a?(Range)
|
170
|
-
op = @time_range.exclude_end? ? "<" : "<="
|
171
|
-
["#{column} >= ? AND #{column} #{op} ?", @time_range.first, @time_range.last]
|
172
|
-
else
|
173
|
-
["#{column} IS NOT NULL"]
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
# resolves eagerly
|
178
|
-
# need to convert both where_clause (easy)
|
179
|
-
# and group_clause (not easy) if want to avoid this
|
180
|
-
def resolve_column(relation, column)
|
181
|
-
node = relation.send(:relation).send(:arel_columns, [column]).first
|
182
|
-
node = Arel::Nodes::SqlLiteral.new(node) if node.is_a?(String)
|
183
|
-
relation.connection.visitor.accept(node, Arel::Collectors::SQLString.new).value
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|