activerecord-postgis-array 0.3.4
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.
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/.travis.yml +18 -0
- data/CHANGELOG.md +99 -0
- data/CONTRIBUTING.md +35 -0
- data/Gemfile +12 -0
- data/LICENSE +22 -0
- data/README.md +87 -0
- data/Rakefile +33 -0
- data/activerecord-postgis-array.gemspec +30 -0
- data/docs/indexes.md +28 -0
- data/docs/migrations.md +92 -0
- data/docs/querying.md +170 -0
- data/docs/type_casting.md +51 -0
- data/lib/activerecord-postgis-array.rb +3 -0
- data/lib/activerecord-postgis-array/active_record.rb +4 -0
- data/lib/activerecord-postgis-array/active_record/connection_adapters.rb +1 -0
- data/lib/activerecord-postgis-array/active_record/connection_adapters/postgres_adapter.rb +346 -0
- data/lib/activerecord-postgis-array/active_record/relation.rb +2 -0
- data/lib/activerecord-postgis-array/active_record/relation/predicate_builder.rb +71 -0
- data/lib/activerecord-postgis-array/active_record/relation/query_methods.rb +84 -0
- data/lib/activerecord-postgis-array/active_record/sanitization.rb +30 -0
- data/lib/activerecord-postgis-array/active_record/schema_dumper.rb +157 -0
- data/lib/activerecord-postgis-array/arel.rb +3 -0
- data/lib/activerecord-postgis-array/arel/nodes.rb +2 -0
- data/lib/activerecord-postgis-array/arel/nodes/array_nodes.rb +9 -0
- data/lib/activerecord-postgis-array/arel/nodes/contained_within.rb +20 -0
- data/lib/activerecord-postgis-array/arel/predications.rb +25 -0
- data/lib/activerecord-postgis-array/arel/visitors.rb +2 -0
- data/lib/activerecord-postgis-array/arel/visitors/to_sql.rb +15 -0
- data/lib/activerecord-postgis-array/arel/visitors/visitor.rb +38 -0
- data/lib/activerecord-postgis-array/version.rb +3 -0
- data/spec/arel/arel_spec.rb +30 -0
- data/spec/arel/array_spec.rb +77 -0
- data/spec/columns/array_spec.rb +120 -0
- data/spec/dummy/.gitignore +15 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/rails.png +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/person.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +6 -0
- data/spec/dummy/config/database.yml.example +14 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +38 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/db/migrate/20120501163758_create_people.rb +12 -0
- data/spec/dummy/db/schema.rb +25 -0
- data/spec/dummy/db/seeds.rb +7 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/lib/tasks/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/index.html +241 -0
- data/spec/dummy/public/robots.txt +5 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/factories/people.rb +7 -0
- data/spec/dummy/test/fixtures/.gitkeep +0 -0
- data/spec/dummy/test/functional/.gitkeep +0 -0
- data/spec/dummy/test/integration/.gitkeep +0 -0
- data/spec/dummy/test/performance/browsing_test.rb +12 -0
- data/spec/dummy/test/test_helper.rb +13 -0
- data/spec/dummy/test/unit/.gitkeep +0 -0
- data/spec/dummy/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/dummy/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/dummy/vendor/plugins/.gitkeep +0 -0
- data/spec/migrations/active_record_migration_spec.rb +29 -0
- data/spec/migrations/array_spec.rb +136 -0
- data/spec/migrations/index_spec.rb +67 -0
- data/spec/models/array_spec.rb +285 -0
- data/spec/queries/array_queries_spec.rb +72 -0
- data/spec/queries/sanity_spec.rb +16 -0
- data/spec/schema_dumper/array_spec.rb +17 -0
- data/spec/schema_dumper/extension_spec.rb +14 -0
- data/spec/schema_dumper/index_spec.rb +46 -0
- data/spec/spec_helper.rb +29 -0
- metadata +318 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'active_record/relation/predicate_builder'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class PredicateBuilder # :nodoc:
|
5
|
+
def self.build_from_hash(engine, attributes, default_table, allow_table_name = true)
|
6
|
+
predicates = attributes.map do |column, value|
|
7
|
+
table = default_table
|
8
|
+
|
9
|
+
if allow_table_name && value.is_a?(Hash)
|
10
|
+
table = Arel::Table.new(column, engine)
|
11
|
+
|
12
|
+
if value.empty?
|
13
|
+
'1 = 2'
|
14
|
+
else
|
15
|
+
build_from_hash(engine, value, table, false)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
column = column.to_s
|
19
|
+
|
20
|
+
if allow_table_name && column.include?('.')
|
21
|
+
table_name, column = column.split('.', 2)
|
22
|
+
table = Arel::Table.new(table_name, engine)
|
23
|
+
end
|
24
|
+
|
25
|
+
attribute = table[column.to_sym]
|
26
|
+
|
27
|
+
case value
|
28
|
+
when ActiveRecord::Relation
|
29
|
+
value = value.select(value.klass.arel_table[value.klass.primary_key]) if value.select_values.empty?
|
30
|
+
attribute.in(value.arel.ast)
|
31
|
+
when Array, ActiveRecord::Associations::CollectionProxy
|
32
|
+
column_definition = engine.columns.find { |col| col.name == column }
|
33
|
+
|
34
|
+
if column_definition.respond_to?(:array) && column_definition.array
|
35
|
+
attribute.eq(value)
|
36
|
+
else
|
37
|
+
values = value.to_a.map {|x| x.is_a?(ActiveRecord::Base) ? x.id : x}
|
38
|
+
ranges, values = values.partition {|v| v.is_a?(Range) || v.is_a?(Arel::Relation)}
|
39
|
+
|
40
|
+
array_predicates = ranges.map {|range| attribute.in(range)}
|
41
|
+
|
42
|
+
if values.include?(nil)
|
43
|
+
values = values.compact
|
44
|
+
if values.empty?
|
45
|
+
array_predicates << attribute.eq(nil)
|
46
|
+
else
|
47
|
+
array_predicates << attribute.in(values.compact).or(attribute.eq(nil))
|
48
|
+
end
|
49
|
+
else
|
50
|
+
array_predicates << attribute.in(values)
|
51
|
+
end
|
52
|
+
|
53
|
+
array_predicates.inject {|composite, predicate| composite.or(predicate)}
|
54
|
+
end
|
55
|
+
when Range, Arel::Relation
|
56
|
+
attribute.in(value)
|
57
|
+
when ActiveRecord::Base
|
58
|
+
attribute.eq(value.id)
|
59
|
+
when Class
|
60
|
+
# FIXME: I think we need to deprecate this behavior
|
61
|
+
attribute.eq(value.name)
|
62
|
+
else
|
63
|
+
attribute.eq(value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
predicates.flatten
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'active_record/relation/query_methods'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module QueryMethods
|
5
|
+
class WhereChain
|
6
|
+
def initialize(scope)
|
7
|
+
@scope = scope
|
8
|
+
end
|
9
|
+
|
10
|
+
def overlap(opts)
|
11
|
+
opts.each do |key, value|
|
12
|
+
@scope = @scope.where(arel_table[key].overlap(value))
|
13
|
+
end
|
14
|
+
@scope
|
15
|
+
end
|
16
|
+
|
17
|
+
def contained_within(opts)
|
18
|
+
opts.each do |key, value|
|
19
|
+
@scope = @scope.where(arel_table[key].contained_within(value))
|
20
|
+
end
|
21
|
+
|
22
|
+
@scope
|
23
|
+
end
|
24
|
+
|
25
|
+
def contained_within_or_equals(opts)
|
26
|
+
opts.each do |key, value|
|
27
|
+
@scope = @scope.where(arel_table[key].contained_within_or_equals(value))
|
28
|
+
end
|
29
|
+
|
30
|
+
@scope
|
31
|
+
end
|
32
|
+
|
33
|
+
def contains(opts)
|
34
|
+
opts.each do |key, value|
|
35
|
+
@scope = @scope.where(arel_table[key].contains(value))
|
36
|
+
end
|
37
|
+
|
38
|
+
@scope
|
39
|
+
end
|
40
|
+
|
41
|
+
def contains_or_equals(opts)
|
42
|
+
opts.each do |key, value|
|
43
|
+
@scope = @scope.where(arel_table[key].contains_or_equals(value))
|
44
|
+
end
|
45
|
+
|
46
|
+
@scope
|
47
|
+
end
|
48
|
+
|
49
|
+
def any(opts)
|
50
|
+
equality_to_function('ANY', opts)
|
51
|
+
end
|
52
|
+
|
53
|
+
def all(opts)
|
54
|
+
equality_to_function('ALL', opts)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def arel_table
|
60
|
+
@arel_table ||= @scope.engine.arel_table
|
61
|
+
end
|
62
|
+
|
63
|
+
def equality_to_function(function_name, opts)
|
64
|
+
opts.each do |key, value|
|
65
|
+
any_function = Arel::Nodes::NamedFunction.new(function_name, [arel_table[key]])
|
66
|
+
predicate = Arel::Nodes::Equality.new(value, any_function)
|
67
|
+
@scope = @scope.where(predicate)
|
68
|
+
end
|
69
|
+
|
70
|
+
@scope
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def where_with_chaining(*opts, &block)
|
75
|
+
if opts.empty? && !block_given?
|
76
|
+
WhereChain.new(self)
|
77
|
+
else
|
78
|
+
where_without_chaining(*opts, &block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
alias_method_chain :where, :chaining
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'active_record/sanitization'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Sanitization
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def sanitize_sql_hash_for_assignment(attrs)
|
9
|
+
attrs.map do |attr, value|
|
10
|
+
"#{connection.quote_column_name(attr)} = #{quote_bound_value(value, attr)}"
|
11
|
+
end.join(', ')
|
12
|
+
end
|
13
|
+
|
14
|
+
def quote_bound_value(value, column = nil, c = connection)
|
15
|
+
if column.present? && column != c
|
16
|
+
record_column = self.columns.select {|col| col.name == column}.first
|
17
|
+
c.quote(value, record_column)
|
18
|
+
elsif value.respond_to?(:map) && !value.acts_like?(:string)
|
19
|
+
if value.respond_to?(:empty?) && value.empty?
|
20
|
+
c.quote(nil)
|
21
|
+
else
|
22
|
+
value.map { |v| c.quote(v) }.join(',')
|
23
|
+
end
|
24
|
+
else
|
25
|
+
c.quote(value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'active_record/schema_dumper'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class SchemaDumper
|
5
|
+
VALID_COLUMN_SPEC_KEYS = [:name, :limit, :precision, :scale, :default, :null, :array]
|
6
|
+
def self.valid_column_spec_keys
|
7
|
+
VALID_COLUMN_SPEC_KEYS
|
8
|
+
end
|
9
|
+
|
10
|
+
def dump(stream)
|
11
|
+
header(stream)
|
12
|
+
# added
|
13
|
+
extensions(stream) if @connection.respond_to?(:supports_extensions?) &&
|
14
|
+
@connection.supports_extensions?
|
15
|
+
# /added
|
16
|
+
tables(stream)
|
17
|
+
trailer(stream)
|
18
|
+
stream
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def extensions(stream)
|
24
|
+
exts = @connection.extensions
|
25
|
+
|
26
|
+
unless exts.empty?
|
27
|
+
stream.puts exts.map { |name| " add_extension \"#{name}\""}.join("\n") + "\n\n"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def table(table, stream)
|
32
|
+
columns = @connection.columns(table)
|
33
|
+
begin
|
34
|
+
tbl = StringIO.new
|
35
|
+
|
36
|
+
# first dump primary key column
|
37
|
+
if @connection.respond_to?(:pk_and_sequence_for)
|
38
|
+
pk, _ = @connection.pk_and_sequence_for(table)
|
39
|
+
elsif @connection.respond_to?(:primary_key)
|
40
|
+
pk = @connection.primary_key(table)
|
41
|
+
end
|
42
|
+
|
43
|
+
tbl.print " create_table #{table.inspect}"
|
44
|
+
if columns.detect { |c| c.name == pk }
|
45
|
+
if pk != 'id'
|
46
|
+
tbl.print %Q(, :primary_key => "#{pk}")
|
47
|
+
end
|
48
|
+
else
|
49
|
+
tbl.print ", :id => false"
|
50
|
+
end
|
51
|
+
tbl.print ", :force => true"
|
52
|
+
tbl.puts " do |t|"
|
53
|
+
|
54
|
+
# then dump all non-primary key columns
|
55
|
+
column_specs = columns.map do |column|
|
56
|
+
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
|
57
|
+
next if column.name == pk
|
58
|
+
spec = column_spec(column)
|
59
|
+
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
|
60
|
+
spec
|
61
|
+
end.compact
|
62
|
+
|
63
|
+
# find all migration keys used in this table
|
64
|
+
keys = self.class.valid_column_spec_keys & column_specs.map{ |k| k.keys }.flatten
|
65
|
+
|
66
|
+
# figure out the lengths for each column based on above keys
|
67
|
+
lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
|
68
|
+
|
69
|
+
# the string we're going to sprintf our values against, with standardized column widths
|
70
|
+
format_string = lengths.map{ |len| "%-#{len}s" }
|
71
|
+
|
72
|
+
# find the max length for the 'type' column, which is special
|
73
|
+
type_length = column_specs.map{ |column| column[:type].length }.max
|
74
|
+
|
75
|
+
# add column type definition to our format string
|
76
|
+
format_string.unshift " t.%-#{type_length}s "
|
77
|
+
|
78
|
+
format_string *= ''
|
79
|
+
|
80
|
+
column_specs.each do |colspec|
|
81
|
+
values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
|
82
|
+
values.unshift colspec[:type]
|
83
|
+
tbl.print((format_string % values).gsub(/,\s*$/, ''))
|
84
|
+
tbl.puts
|
85
|
+
end
|
86
|
+
|
87
|
+
tbl.puts " end"
|
88
|
+
tbl.puts
|
89
|
+
|
90
|
+
indexes(table, tbl)
|
91
|
+
|
92
|
+
tbl.rewind
|
93
|
+
stream.print tbl.read
|
94
|
+
rescue => e
|
95
|
+
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
96
|
+
stream.puts "# #{e.message}"
|
97
|
+
stream.puts
|
98
|
+
end
|
99
|
+
|
100
|
+
stream
|
101
|
+
end
|
102
|
+
|
103
|
+
#mostly rails 3.2 code
|
104
|
+
def indexes(table, stream)
|
105
|
+
if (indexes = @connection.indexes(table)).any?
|
106
|
+
add_index_statements = indexes.map do |index|
|
107
|
+
statement_parts = [
|
108
|
+
('add_index ' + index.table.inspect),
|
109
|
+
index.columns.inspect,
|
110
|
+
(':name => ' + index.name.inspect),
|
111
|
+
]
|
112
|
+
statement_parts << ':unique => true' if index.unique
|
113
|
+
|
114
|
+
index_lengths = (index.lengths || []).compact
|
115
|
+
statement_parts << (':length => ' + Hash[index.columns.zip(index.lengths)].inspect) unless index_lengths.empty?
|
116
|
+
|
117
|
+
index_orders = (index.orders || {})
|
118
|
+
statement_parts << (':order => ' + index.orders.inspect) unless index_orders.empty?
|
119
|
+
|
120
|
+
# changed from rails 2.3
|
121
|
+
statement_parts << (':where => ' + index.where.inspect) if index.where
|
122
|
+
statement_parts << (':using => ' + index.using.inspect) if index.using
|
123
|
+
statement_parts << (':index_opclass => ' + index.index_opclass.inspect) if index.index_opclass.present?
|
124
|
+
# /changed
|
125
|
+
|
126
|
+
' ' + statement_parts.join(', ')
|
127
|
+
end
|
128
|
+
|
129
|
+
stream.puts add_index_statements.sort.join("\n")
|
130
|
+
stream.puts
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
#mostly rails 3.2 code (pulled out of table method)
|
135
|
+
def column_spec(column)
|
136
|
+
spec = {}
|
137
|
+
spec[:name] = column.name.inspect
|
138
|
+
|
139
|
+
# AR has an optimization which handles zero-scale decimals as integers. This
|
140
|
+
# code ensures that the dumper still dumps the column as a decimal.
|
141
|
+
spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
|
142
|
+
'decimal'
|
143
|
+
else
|
144
|
+
column.type.to_s
|
145
|
+
end
|
146
|
+
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && spec[:type] != 'decimal'
|
147
|
+
spec[:precision] = column.precision.inspect if column.precision
|
148
|
+
spec[:scale] = column.scale.inspect if column.scale
|
149
|
+
spec[:null] = 'false' unless column.null
|
150
|
+
spec[:default] = default_string(column.default) if column.has_default?
|
151
|
+
# changed from rails 3.2 code
|
152
|
+
spec[:array] = 'true' if column.respond_to?(:array) && column.array
|
153
|
+
# /changed
|
154
|
+
spec
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'arel/nodes/binary'
|
2
|
+
module Arel
|
3
|
+
module Nodes
|
4
|
+
class ContainedWithin < Arel::Nodes::Binary
|
5
|
+
def operator; :<< end
|
6
|
+
end
|
7
|
+
|
8
|
+
class ContainedWithinEquals < Arel::Nodes::Binary
|
9
|
+
def operator; '<<='.to_sym end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Contains < Arel::Nodes::Binary
|
13
|
+
def operator; :>> end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ContainsEquals < Arel::Nodes::Binary
|
17
|
+
def operator; '>>='.to_sym end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'arel/predications'
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
module Predications
|
5
|
+
def contained_within(other)
|
6
|
+
Nodes::ContainedWithin.new self, other
|
7
|
+
end
|
8
|
+
|
9
|
+
def contained_within_or_equals(other)
|
10
|
+
Nodes::ContainedWithinEquals.new self, other
|
11
|
+
end
|
12
|
+
|
13
|
+
def contains(other)
|
14
|
+
Nodes::Contains.new self, other
|
15
|
+
end
|
16
|
+
|
17
|
+
def contains_or_equals(other)
|
18
|
+
Nodes::ContainsEquals.new self, other
|
19
|
+
end
|
20
|
+
|
21
|
+
def overlap(other)
|
22
|
+
Nodes::Overlap.new self, other
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'arel/visitors/to_sql'
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
module Visitors
|
5
|
+
class ToSql
|
6
|
+
def visit_Array o
|
7
|
+
if last_column.respond_to?(:array) && last_column.array
|
8
|
+
quoted o
|
9
|
+
else
|
10
|
+
o.empty? ? 'NULL' : o.map { |x| visit x }.join(', ')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'arel/visitors/visitor'
|
2
|
+
module Arel
|
3
|
+
module Visitors
|
4
|
+
class Visitor
|
5
|
+
# We are adding our visitors to the main visitor for the time being until the right spot is found to monkey patch
|
6
|
+
private
|
7
|
+
def visit_Arel_Nodes_ContainedWithin o
|
8
|
+
"#{visit o.left} << #{visit o.right}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def visit_Arel_Nodes_ContainedWithinEquals o
|
12
|
+
"#{visit o.left} <<= #{visit o.right}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def visit_Arel_Nodes_Contains o
|
16
|
+
left_column = o.left.relation.engine.columns.find { |col| col.name == o.left.name.to_s }
|
17
|
+
|
18
|
+
if left_column && left_column.respond_to?(:array) && left_column.array
|
19
|
+
"#{visit o.left} @> #{visit o.right}"
|
20
|
+
else
|
21
|
+
"#{visit o.left} >> #{visit o.right}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def visit_Arel_Nodes_ContainsEquals o
|
26
|
+
"#{visit o.left} >>= #{visit o.right}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def visit_Arel_Nodes_Overlap o
|
30
|
+
"#{visit o.left} && #{visit o.right}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_IPAddr value
|
34
|
+
"'#{value.to_s}/#{value.instance_variable_get(:@mask_addr).to_s(2).count('1')}'"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|