arel-pg-json 0.0.9
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 +7 -0
- data/.gitignore +14 -0
- data/Appraisals +7 -0
- data/Gemfile +7 -0
- data/LICENSE +22 -0
- data/LICENSE.txt +22 -0
- data/README.md +2 -0
- data/Rakefile +11 -0
- data/arel-pg-json.gemspec +18 -0
- data/gemfiles/arel_5.gemfile +8 -0
- data/gemfiles/arel_5.gemfile.lock +40 -0
- data/gemfiles/arel_6.gemfile +8 -0
- data/gemfiles/arel_6.gemfile.lock +40 -0
- data/lib/arel/nodes/pg_json.rb +51 -0
- data/lib/arel/pg_json/build_info.rb +62 -0
- data/lib/arel/visitors/pg_json.rb +64 -0
- data/lib/arel_pg_json.rb +3 -0
- data/test/helper.rb +55 -0
- data/test/nodes/pg_json_test.rb +82 -0
- data/test/nodes/shared_node_examples.rb +17 -0
- data/test/support/fake_record.rb +135 -0
- metadata +120 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 1ed5c1bec6bf9d94d572ff680d02cda7d2796a89
|
|
4
|
+
data.tar.gz: ed6f018677b9fafeace578ae66b1f279347f26b5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 704aefe3cf4185fff19bc897b5ff475bbbbd3683945d78b374ef9d9e5061701fe905260f7b239673e375f93480824a6e2413a0bd0c8aa6d8a67d0cfe36a984d6
|
|
7
|
+
data.tar.gz: d6d9516b81547559319673543c4798c266f98668b8fc218412198688d903a0d7808eff3640425f8cfd4a102188cf5750688b2f46eb4d0a85bad2c2247759512f
|
data/.gitignore
ADDED
data/Appraisals
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015 Guy Boertje
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 Guy Boertje
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'arel/pg_json/build_info'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "arel-pg-json"
|
|
8
|
+
spec.homepage = ''
|
|
9
|
+
spec.require_paths = ['lib']
|
|
10
|
+
|
|
11
|
+
Arel::PgJson::BuildInfo.new.add_to_gemspec(spec)
|
|
12
|
+
|
|
13
|
+
spec.add_runtime_dependency 'arel'
|
|
14
|
+
|
|
15
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
|
16
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
17
|
+
spec.add_development_dependency "minitest", "~> 5.7.0"
|
|
18
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: ../
|
|
3
|
+
specs:
|
|
4
|
+
arel-pg-json (0.0.9)
|
|
5
|
+
arel
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
activesupport (4.2.2)
|
|
11
|
+
i18n (~> 0.7)
|
|
12
|
+
json (~> 1.7, >= 1.7.7)
|
|
13
|
+
minitest (~> 5.1)
|
|
14
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
|
15
|
+
tzinfo (~> 1.1)
|
|
16
|
+
appraisal (2.0.1)
|
|
17
|
+
activesupport (>= 3.2.21)
|
|
18
|
+
bundler
|
|
19
|
+
rake
|
|
20
|
+
thor (>= 0.14.0)
|
|
21
|
+
arel (5.0.1.20140414130214)
|
|
22
|
+
i18n (0.7.0)
|
|
23
|
+
json (1.8.3)
|
|
24
|
+
minitest (5.7.0)
|
|
25
|
+
rake (10.4.2)
|
|
26
|
+
thor (0.19.1)
|
|
27
|
+
thread_safe (0.3.5)
|
|
28
|
+
tzinfo (1.2.2)
|
|
29
|
+
thread_safe (~> 0.1)
|
|
30
|
+
|
|
31
|
+
PLATFORMS
|
|
32
|
+
ruby
|
|
33
|
+
|
|
34
|
+
DEPENDENCIES
|
|
35
|
+
appraisal
|
|
36
|
+
arel (= 5.0.1.20140414130214)
|
|
37
|
+
arel-pg-json!
|
|
38
|
+
bundler (~> 1.7)
|
|
39
|
+
minitest (~> 5.7.0)
|
|
40
|
+
rake (~> 10.0)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: ../
|
|
3
|
+
specs:
|
|
4
|
+
arel-pg-json (0.0.9)
|
|
5
|
+
arel
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
activesupport (4.2.2)
|
|
11
|
+
i18n (~> 0.7)
|
|
12
|
+
json (~> 1.7, >= 1.7.7)
|
|
13
|
+
minitest (~> 5.1)
|
|
14
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
|
15
|
+
tzinfo (~> 1.1)
|
|
16
|
+
appraisal (2.0.1)
|
|
17
|
+
activesupport (>= 3.2.21)
|
|
18
|
+
bundler
|
|
19
|
+
rake
|
|
20
|
+
thor (>= 0.14.0)
|
|
21
|
+
arel (6.0.0)
|
|
22
|
+
i18n (0.7.0)
|
|
23
|
+
json (1.8.3)
|
|
24
|
+
minitest (5.7.0)
|
|
25
|
+
rake (10.4.2)
|
|
26
|
+
thor (0.19.1)
|
|
27
|
+
thread_safe (0.3.5)
|
|
28
|
+
tzinfo (1.2.2)
|
|
29
|
+
thread_safe (~> 0.1)
|
|
30
|
+
|
|
31
|
+
PLATFORMS
|
|
32
|
+
ruby
|
|
33
|
+
|
|
34
|
+
DEPENDENCIES
|
|
35
|
+
appraisal
|
|
36
|
+
arel (= 6.0.0)
|
|
37
|
+
arel-pg-json!
|
|
38
|
+
bundler (~> 1.7)
|
|
39
|
+
minitest (~> 5.7.0)
|
|
40
|
+
rake (~> 10.0)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Arel
|
|
2
|
+
module Nodes
|
|
3
|
+
%w{
|
|
4
|
+
JsonDashArrow
|
|
5
|
+
JsonDashDoubleArrow
|
|
6
|
+
JsonHashArrow
|
|
7
|
+
JsonHashDoubleArrow
|
|
8
|
+
JsonbAtArrow
|
|
9
|
+
JsonbArrowAt
|
|
10
|
+
JsonbQuestion
|
|
11
|
+
JsonbQuestionAnd
|
|
12
|
+
JsonbQuestionOr
|
|
13
|
+
CastJson
|
|
14
|
+
}.each do |name|
|
|
15
|
+
const_set name, Class.new(Binary)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
=begin
|
|
21
|
+
|
|
22
|
+
Arel::Nodes::JsonDashArrow
|
|
23
|
+
|
|
24
|
+
support for CAST("table"."json_data" ->> 'start_i' AS int8) between 1428926200 AND 1428926600
|
|
25
|
+
will be
|
|
26
|
+
Between.new(
|
|
27
|
+
CastJson.new(JsonDashDoubleArrow.new(field, path),'int8'),
|
|
28
|
+
[1428926200, 1428926600]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
JsonbAtArrow
|
|
32
|
+
"table"."json_data" @> '{"field1": "value1", "field2": "value2"}'
|
|
33
|
+
|
|
34
|
+
JsonbArrowAt
|
|
35
|
+
"table"."json_data" <@ '{"field1": "value1", "field2": "value2"}'
|
|
36
|
+
|
|
37
|
+
JsonbQuestionOr
|
|
38
|
+
path ?| text e.g. "table"."json_data" -> 'tags' ?| array['fruit','vegetable']
|
|
39
|
+
|
|
40
|
+
JsonbQuestionAnd
|
|
41
|
+
path ?& text e.g. "foods"."json_data" -> 'tags' ?& array['red','fruit']
|
|
42
|
+
|
|
43
|
+
Operator Right Operand Type Description Example Example Result
|
|
44
|
+
-> int Get JSON array element (indexed from zero) '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 {"c":"baz"}
|
|
45
|
+
-> text Get JSON object field by key '{"a": {"b":"foo"}}'::json->'a' {"b":"foo"}
|
|
46
|
+
->> int Get JSON array element as text '[1,2,3]'::json->>2 3
|
|
47
|
+
->> text Get JSON object field as text '{"a":1,"b":2}'::json->>'b' 2
|
|
48
|
+
#> text[] Get JSON object at specified path '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}' {"c": "foo"}
|
|
49
|
+
#>> text[] Get JSON object at specified path as text '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}' 3
|
|
50
|
+
|
|
51
|
+
=end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Arel
|
|
2
|
+
module PgJson
|
|
3
|
+
class BuildInfo
|
|
4
|
+
def initialize
|
|
5
|
+
@files = `git ls-files -z`.split("\x0")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def add_to_gemspec(spec)
|
|
9
|
+
spec.version = version
|
|
10
|
+
spec.authors = authors
|
|
11
|
+
spec.email = emails
|
|
12
|
+
spec.summary = summary
|
|
13
|
+
spec.description = description
|
|
14
|
+
|
|
15
|
+
spec.files = files
|
|
16
|
+
spec.executables = executables
|
|
17
|
+
spec.test_files = test_files
|
|
18
|
+
spec.license = license
|
|
19
|
+
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def version
|
|
26
|
+
'0.0.9'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def authors
|
|
30
|
+
['Guy Boertje']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def emails
|
|
34
|
+
['guyboertje@gmail.com']
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def summary
|
|
38
|
+
%q{Arel nodes and vistor methods for Postgres Json datatype}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def description
|
|
42
|
+
%q{Arel nodes and vistor methods for Postgres Json datatype}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def files
|
|
46
|
+
@files
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def executables
|
|
50
|
+
@files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_files
|
|
54
|
+
@files.grep(%r{^(spec|features)/})
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def license
|
|
58
|
+
'MIT'
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Arel
|
|
2
|
+
module Visitors
|
|
3
|
+
module PgJson
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def visit_Arel_Nodes_CastJson o, collector
|
|
7
|
+
if !collector.respond_to?('<<') # for arel < 6.0.0
|
|
8
|
+
return visit(o.left, collector)
|
|
9
|
+
.prepend('CAST(')
|
|
10
|
+
.concat(' AS ')
|
|
11
|
+
.concat(o.right)
|
|
12
|
+
.concat(?))
|
|
13
|
+
else
|
|
14
|
+
collector << 'CAST('
|
|
15
|
+
collector = visit(o.left, collector)
|
|
16
|
+
collector << " AS #{o.right})"
|
|
17
|
+
end
|
|
18
|
+
collector
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def visit_Arel_Nodes_JsonDashArrow o, a
|
|
22
|
+
json_infix o, a, '->'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def visit_Arel_Nodes_JsonDashDoubleArrow o, a
|
|
26
|
+
json_infix o, a, '->>'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def visit_Arel_Nodes_JsonHashArrow o, a
|
|
30
|
+
json_infix o, a, '#>'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def visit_Arel_Nodes_JsonHashDoubleArrow o, a
|
|
34
|
+
json_infix o, a, '#>>'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def visit_Arel_Nodes_JsonbAtArrow o, a
|
|
38
|
+
json_infix o, a, '@>'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def visit_Arel_Nodes_JsonbArrowAt o, a
|
|
42
|
+
json_infix o, a, '<@'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def visit_Arel_Nodes_JsonbQuestion o, a
|
|
46
|
+
json_infix o, a, '?'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def visit_Arel_Nodes_JsonbQuestionAnd o, a
|
|
50
|
+
json_infix o, a, '?&'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def visit_Arel_Nodes_JsonbQuestionOr o, a
|
|
54
|
+
json_infix o, a, '?|'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def json_infix(o, a, opr)
|
|
58
|
+
visit(Nodes::InfixOperation.new(opr, o.left, o.right), a)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
PostgreSQL.send :include, PgJson
|
|
63
|
+
end
|
|
64
|
+
end
|
data/lib/arel_pg_json.rb
ADDED
data/test/helper.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
$:.unshift File.expand_path("../lib", File.dirname(__FILE__))
|
|
2
|
+
$:.unshift File.expand_path(File.dirname(__FILE__))
|
|
3
|
+
|
|
4
|
+
require 'arel_pg_json'
|
|
5
|
+
require 'minitest/autorun'
|
|
6
|
+
|
|
7
|
+
if !Arel::Nodes.respond_to?(:build_quoted)
|
|
8
|
+
module Arel
|
|
9
|
+
module Nodes
|
|
10
|
+
def self.build_quoted(val)
|
|
11
|
+
SqlLiteral.new("'#{val}'")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'support/fake_record'
|
|
18
|
+
Arel::Table.engine = FakeRecord::Base.new
|
|
19
|
+
|
|
20
|
+
PgVisitor = Arel::Visitors::PostgreSQL.new Arel::Table.engine.connection
|
|
21
|
+
|
|
22
|
+
TestTable = Arel::Table.new(:foobars)
|
|
23
|
+
|
|
24
|
+
MiniTest::Spec.class_eval do
|
|
25
|
+
def self.shared_examples
|
|
26
|
+
@shared_examples ||= Hash.new.tap{ |h| h.default = ->(*){} }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def shared_examples_for(desc, &block)
|
|
31
|
+
MiniTest::Spec.shared_examples[desc] = block
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def it_behaves_like(desc, *args, &block)
|
|
35
|
+
describe desc do
|
|
36
|
+
self.instance_exec(*args, &MiniTest::Spec.shared_examples[desc])
|
|
37
|
+
self.instance_exec(*args, &block) if block_given?
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def compile node
|
|
42
|
+
if defined?(Arel::Collectors::SQLString)
|
|
43
|
+
PgVisitor.accept(node, Arel::Collectors::SQLString.new).value
|
|
44
|
+
else
|
|
45
|
+
PgVisitor.accept(node)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def field_for(str)
|
|
50
|
+
TestTable[str.to_sym]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def equality_wrap(left, right)
|
|
54
|
+
Arel::Nodes::Equality.new(left, Arel::Nodes.build_quoted(right))
|
|
55
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'nodes/shared_node_examples'
|
|
2
|
+
|
|
3
|
+
module Arel
|
|
4
|
+
module Nodes
|
|
5
|
+
describe 'Postgres Json Nodes' do
|
|
6
|
+
|
|
7
|
+
it_behaves_like 'A Binary Node', JsonDashArrow do |node|
|
|
8
|
+
it "#{node} generates some sql" do
|
|
9
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('bar'))
|
|
10
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" -> 'bar'})
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it_behaves_like 'A Binary Node', JsonDashDoubleArrow do |node|
|
|
15
|
+
it "#{node} generates some sql" do
|
|
16
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('bar'))
|
|
17
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" ->> 'bar'})
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it_behaves_like 'A Binary Node', JsonHashArrow do |node|
|
|
22
|
+
it "#{node} generates some sql" do
|
|
23
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('{bar, baz}'))
|
|
24
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" #> '{bar, baz}'})
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it_behaves_like 'A Binary Node', JsonHashDoubleArrow do |node|
|
|
29
|
+
it "#{node} generates some sql" do
|
|
30
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('{bar, baz}'))
|
|
31
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" #>> '{bar, baz}'})
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it_behaves_like 'A Binary Node', JsonbAtArrow do |node|
|
|
36
|
+
it "#{node} generates some sql" do
|
|
37
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('{"bar": "baz"}'))
|
|
38
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" @> '{"bar": "baz"}'})
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it_behaves_like 'A Binary Node', JsonbArrowAt do |node|
|
|
43
|
+
it "#{node} generates some sql" do
|
|
44
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('{"bar": "baz"}'))
|
|
45
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" <@ '{"bar": "baz"}'})
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it_behaves_like 'A Binary Node', JsonbQuestion do |node|
|
|
50
|
+
it "#{node} generates some sql" do
|
|
51
|
+
sut = node.new(field_for(:jdata), Nodes.build_quoted('bar'))
|
|
52
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" ? 'bar'})
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it_behaves_like 'A Binary Node', JsonbQuestionAnd do |node|
|
|
57
|
+
it "#{node} generates some sql" do
|
|
58
|
+
sut = node.new(field_for(:jdata), SqlLiteral.new("array['b', 'c']"))
|
|
59
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" ?& array['b', 'c']})
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it_behaves_like 'A Binary Node', JsonbQuestionOr do |node|
|
|
64
|
+
it "#{node} generates some sql" do
|
|
65
|
+
sut = node.new(field_for(:jdata), SqlLiteral.new("array['b', 'c']"))
|
|
66
|
+
expect(compile(sut)).must_equal(%{"foobars"."jdata" ?| array['b', 'c']})
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it_behaves_like 'A Binary Node', CastJson do |node|
|
|
71
|
+
it "#{node} generates some sql" do
|
|
72
|
+
expected = %{CAST("foobars"."jdata" ->> 'age' AS int8) BETWEEN 18 AND 30}
|
|
73
|
+
inner = JsonDashDoubleArrow.new(field_for(:jdata), Nodes.build_quoted('age'))
|
|
74
|
+
sut = node.new(inner, SqlLiteral.new('int8'))
|
|
75
|
+
outer = Between.new(sut, And.new([18, 30]))
|
|
76
|
+
expect(compile(outer)).must_equal(expected)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
shared_examples_for 'A Binary Node' do |node|
|
|
4
|
+
describe 'construction' do
|
|
5
|
+
it 'requires two arguments' do
|
|
6
|
+
err = ->{ node.new }.must_raise ArgumentError
|
|
7
|
+
err.message.must_match %r{wrong number of arguments \(0 for 2\)}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'creates a new instance' do
|
|
11
|
+
instance = node.new('foo', 'bar')
|
|
12
|
+
expect(instance.left).must_equal('foo')
|
|
13
|
+
expect(instance.right).must_equal('bar')
|
|
14
|
+
expect(instance).must_be_kind_of(Arel::Nodes::Binary)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
module FakeRecord
|
|
2
|
+
class Column < Struct.new(:name, :type)
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
class Connection
|
|
6
|
+
attr_reader :tables
|
|
7
|
+
attr_accessor :visitor
|
|
8
|
+
|
|
9
|
+
def initialize(visitor = nil)
|
|
10
|
+
@tables = %w{ users photos developers products}
|
|
11
|
+
@columns = {
|
|
12
|
+
'users' => [
|
|
13
|
+
Column.new('id', :integer),
|
|
14
|
+
Column.new('name', :string),
|
|
15
|
+
Column.new('bool', :boolean),
|
|
16
|
+
Column.new('created_at', :date)
|
|
17
|
+
],
|
|
18
|
+
'products' => [
|
|
19
|
+
Column.new('id', :integer),
|
|
20
|
+
Column.new('price', :decimal)
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
@columns_hash = {
|
|
24
|
+
'users' => Hash[@columns['users'].map { |x| [x.name, x] }],
|
|
25
|
+
'products' => Hash[@columns['products'].map { |x| [x.name, x] }]
|
|
26
|
+
}
|
|
27
|
+
@primary_keys = {
|
|
28
|
+
'users' => 'id',
|
|
29
|
+
'products' => 'id'
|
|
30
|
+
}
|
|
31
|
+
@visitor = visitor
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def columns_hash table_name
|
|
35
|
+
@columns_hash[table_name]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def primary_key name
|
|
39
|
+
@primary_keys[name.to_s]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def table_exists? name
|
|
43
|
+
@tables.include? name.to_s
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def columns name, message = nil
|
|
47
|
+
@columns[name.to_s]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def quote_table_name name
|
|
51
|
+
"\"#{name.to_s}\""
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def quote_column_name name
|
|
55
|
+
"\"#{name.to_s}\""
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def schema_cache
|
|
59
|
+
self
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def quote thing, column = nil
|
|
63
|
+
if column && !thing.nil?
|
|
64
|
+
case column.type
|
|
65
|
+
when :integer
|
|
66
|
+
thing = thing.to_i
|
|
67
|
+
when :string
|
|
68
|
+
thing = thing.to_s
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
case thing
|
|
73
|
+
when DateTime
|
|
74
|
+
"'#{thing.strftime("%Y-%m-%d %H:%M:%S")}'"
|
|
75
|
+
when Date
|
|
76
|
+
"'#{thing.strftime("%Y-%m-%d")}'"
|
|
77
|
+
when true
|
|
78
|
+
"'t'"
|
|
79
|
+
when false
|
|
80
|
+
"'f'"
|
|
81
|
+
when nil
|
|
82
|
+
'NULL'
|
|
83
|
+
when Numeric
|
|
84
|
+
thing
|
|
85
|
+
else
|
|
86
|
+
"'#{thing.to_s.gsub("'", "\\\\'")}'"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class ConnectionPool
|
|
92
|
+
class Spec < Struct.new(:config)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
attr_reader :spec, :connection
|
|
96
|
+
|
|
97
|
+
def initialize
|
|
98
|
+
@spec = Spec.new(:adapter => 'postgresql')
|
|
99
|
+
@connection = Connection.new
|
|
100
|
+
@connection.visitor = Arel::Visitors::PostgreSQL.new(connection)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def with_connection
|
|
104
|
+
yield connection
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def table_exists? name
|
|
108
|
+
connection.tables.include? name.to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def columns_hash
|
|
112
|
+
connection.columns_hash
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def schema_cache
|
|
116
|
+
connection
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def quote thing, column = nil
|
|
120
|
+
connection.quote thing, column
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class Base
|
|
125
|
+
attr_accessor :connection_pool
|
|
126
|
+
|
|
127
|
+
def initialize
|
|
128
|
+
@connection_pool = ConnectionPool.new
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def connection
|
|
132
|
+
connection_pool.connection
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: arel-pg-json
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.9
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Guy Boertje
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-06-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: arel
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.7'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.7'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '10.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '10.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: 5.7.0
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 5.7.0
|
|
69
|
+
description: Arel nodes and vistor methods for Postgres Json datatype
|
|
70
|
+
email:
|
|
71
|
+
- guyboertje@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- Appraisals
|
|
78
|
+
- Gemfile
|
|
79
|
+
- LICENSE
|
|
80
|
+
- LICENSE.txt
|
|
81
|
+
- README.md
|
|
82
|
+
- Rakefile
|
|
83
|
+
- arel-pg-json.gemspec
|
|
84
|
+
- gemfiles/arel_5.gemfile
|
|
85
|
+
- gemfiles/arel_5.gemfile.lock
|
|
86
|
+
- gemfiles/arel_6.gemfile
|
|
87
|
+
- gemfiles/arel_6.gemfile.lock
|
|
88
|
+
- lib/arel/nodes/pg_json.rb
|
|
89
|
+
- lib/arel/pg_json/build_info.rb
|
|
90
|
+
- lib/arel/visitors/pg_json.rb
|
|
91
|
+
- lib/arel_pg_json.rb
|
|
92
|
+
- test/helper.rb
|
|
93
|
+
- test/nodes/pg_json_test.rb
|
|
94
|
+
- test/nodes/shared_node_examples.rb
|
|
95
|
+
- test/support/fake_record.rb
|
|
96
|
+
homepage: ''
|
|
97
|
+
licenses:
|
|
98
|
+
- MIT
|
|
99
|
+
metadata: {}
|
|
100
|
+
post_install_message:
|
|
101
|
+
rdoc_options: []
|
|
102
|
+
require_paths:
|
|
103
|
+
- lib
|
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: '0'
|
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - ">="
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: '0'
|
|
114
|
+
requirements: []
|
|
115
|
+
rubyforge_project:
|
|
116
|
+
rubygems_version: 2.4.5
|
|
117
|
+
signing_key:
|
|
118
|
+
specification_version: 4
|
|
119
|
+
summary: Arel nodes and vistor methods for Postgres Json datatype
|
|
120
|
+
test_files: []
|