pggraphql 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d1e6b2c6fed6ff27d8df6c047a1a7a00da92d82b
4
- data.tar.gz: fae12d3c2d83579341ca9d9703bef24c89db4808
3
+ metadata.gz: 6b77f4fa17f6d73f558fa894e56b662a4226c5ea
4
+ data.tar.gz: 66fcd016a628c740e127968d054dd0bbeec29ce3
5
5
  SHA512:
6
- metadata.gz: fee51a6659a3b61afb46cb3f435450214c1b7a878dc625362b8a1f0196e1e14a7f1d402f1a458fe9625279518bdf4aef6ff45e30287a431c15e96d75c769b571
7
- data.tar.gz: e8bd53a6028edf19f10a4db5524cc03a2f3fcef3acf027260abb0e97b49b8cbc02956b7dd5bf41ed17ced8bbe325b4bc5fdd8633beb1fe0a22e71c2d6681fc96
6
+ metadata.gz: 52e5bdbdd564c508160e4688e87b66ef9e3fa9cb74fe9d21c977ca2ff9436fcb25c5e94768b346ffe4540b71a61e500ca50c17a4358f12e66e5e3587aaf39746
7
+ data.tar.gz: 437d33d4175c3ac772eae462e65d3ec08156a266f30f479264a47cfdc3e1303aa6efbf80aef8a62ad6fbb8edb31886c5da1bb71fbe9df1379d2ecc0890f5f5c1
data/.gitignore CHANGED
@@ -32,3 +32,4 @@ build/
32
32
 
33
33
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
34
34
  .rvmrc
35
+ .DS_Store
@@ -1,3 +1,3 @@
1
1
  module Pggraphql
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/pggraphql.rb CHANGED
@@ -1,126 +1,146 @@
1
- require "json"
2
1
  require "active_support/all"
3
2
  require "pggraphql/version"
4
3
 
5
4
  module PgGraphQl
6
5
 
7
6
  class Schema
8
- attr_accessor :roots
9
-
7
+ attr_reader :types, :roots
10
8
  def initialize
11
- @roots = {}
12
9
  @types = {}
10
+ @roots = []
13
11
  yield(self) if block_given?
14
12
 
15
- @types = @types.inject({}) do |memo, e|
16
- t = memo[e[0]] = Type.new(e[0])
17
-
18
- e[1].each_pair do |key, val|
19
- t.send("#{key}=", val) unless key == :block
20
- end
21
-
22
- e[1][:block].call(t) if e[1][:block]
23
- memo
24
- end
13
+ @roots = @roots.map{|r| @types[r]}
25
14
  end
26
15
 
27
- def root(name, opts={})
28
- opts[:type] = name.to_s.singularize.to_sym unless opts[:type]
29
- @roots[name] = opts
16
+ def root(name)
17
+ @roots << name
30
18
  end
31
19
 
32
- def type(name, opts={}, &block)
33
- opts[:block] = block
34
- @types[name] = opts
20
+ def type(name, opts={})
21
+ type = @types[name] = Type.new(self, name)
22
+ opts.each_pair{|key, val| type.send(:"#{key}=", val) }
23
+ yield(type) if block_given?
35
24
  end
36
25
 
37
- def query(query, level=0, parent_link=nil, parent_type=nil)
38
- requested_type = @types[query[0][0].to_sym]
39
- requested_ids = query[0][1].is_a?(Array) ? query[0][1] : [query[0][1]].reject{|e| !e}
26
+ def to_sql(query, level=0, parent=nil, link_name=nil)
27
+ if level > 0
28
+ query.map do |e|
29
+ link = parent ? parent.links[link_name] : nil
30
+ type = link ? link.type : self.types[e[0].to_s.singularize.to_sym]
31
+ ids = e[1][:id]
40
32
 
41
- sql = requested_type.sql
33
+ columns = e[1].map do |f|
34
+ column_name = f[0]
42
35
 
43
- where_conditions = []
44
-
45
- if parent_link
46
- if parent_link[:fk].is_a?(Symbol)
47
- where_conditions << (parent_link[:invert] ? " #{requested_type.pk} = #{parent_type.as}.#{parent_link[:fk]}" : " #{parent_link[:fk]} = #{parent_type.pk!}")
48
- elsif parent_link[:fk].is_a?(Proc)
49
- where_conditions << (" #{requested_type.pk} in (" + parent_link[:fk].call(parent_link) + ")")
50
- else
51
- raise "unsupported"
52
- end
53
-
54
- where_conditions << parent_link[:filter] if parent_link[:filter]
55
- end
36
+ raise "unknown field #{column_name.inspect} on type #{type.name.inspect}" if !f[1].is_a?(Hash) && !type.fields.include?(column_name)
37
+ raise "unknown link #{column_name.inspect} on type #{type.name.inspect}" if f[1].is_a?(Hash) && !type.links.include?(column_name)
56
38
 
57
- requested_columns = query[1..-1].map do |field|
39
+ (f[1].is_a?(Hash) ? "(" + to_sql([f].to_h, level + 1, type, column_name) + ") as #{column_name}" : column_name.to_s)
40
+ end.join(",")
58
41
 
59
- if field.is_a?(Symbol)
60
- raise "unknown field" unless requested_type.fields.include?(field)
61
- field.to_s
62
- elsif field.is_a?(Array)
42
+ is_many = (link && link.many?) || !ids || ids.is_a?(Array)
43
+ order_by = link.try(:order_by) || type.try(:order_by)
63
44
 
64
- requested_link_field = field[0][0]
65
- requested_link = requested_type.links[requested_link_field][1]
66
- requested_link_ids = field[0][1]
67
- requested_link_type = @types[requested_link[:type]]
45
+ wheres = []
68
46
 
69
- requested_link_query = field.each_with_index.map do |e2, idx|
70
- idx == 0 ? [requested_link_type.name, requested_link_ids] : e2
47
+ if ids && ids.to_s != "id"
48
+ if ids.is_a?(Array)
49
+ wheres << "id in (#{ids.join(',')})" unless ids.empty?
50
+ else
51
+ wheres << "id = #{ids}"
52
+ end
71
53
  end
72
54
 
73
- "(" + self.query(requested_link_query, level + 1, requested_link, requested_type) + ") as #{requested_link_field}"
74
- else
75
- raise "unsupported"
76
- end
55
+ wheres << ("(" + type.filter + ")") if type.filter
77
56
 
78
- end
57
+ if link
58
+ wheres << if link.invert
59
+ "id = #{parent.table}.#{link.fk}"
60
+ else
61
+ "#{link.fk} = #{parent.table}.id"
62
+ end
79
63
 
80
- is_many = parent_type && parent_type.links[parent_link[:name]][0] == :many
64
+ wheres << ("(" + link.filter + ")") if link.filter
65
+ end
81
66
 
82
- inner_sql = sql.gsub("*", requested_columns.join(", "))
67
+ sql = "select to_json("
68
+ sql += "coalesce(json_agg(" if is_many
69
+ sql += "x.*"
70
+ sql += "), '[]'::json)" if is_many
71
+ sql += ") from (select #{columns} from #{type.table}"
72
+ sql += " where #{wheres.join(' and ')}" unless wheres.empty?
73
+ sql += " order by #{order_by}" if order_by
74
+ sql += " limit 1" if !is_many
75
+ sql += ") x"
76
+
77
+ end.join
78
+ else
79
+ wrap_root(query.map do |e|
80
+ sql = to_sql([e].to_h, 1)
81
+ "select '#{e[0]}'::text as key, (#{sql}) as value"
82
+ end.join("\nunion all\n"))
83
+ end
84
+ end
83
85
 
84
- where_conditions << " #{requested_type.pk} in (#{requested_ids.map(&:to_s).join(',')})" unless requested_ids.empty?
85
- where_conditions << (" " + requested_type.filter) if requested_type.filter
86
+ def wrap_root(sql)
87
+ "select ('{'||string_agg(to_json(t1.key)||':'||coalesce(to_json(t1.value), 'null'), ',')||'}')::json res from (\n" + sql + ") t1"
88
+ end
86
89
 
87
- unless where_conditions.empty?
88
- inner_sql += " where"
89
- inner_sql += where_conditions.join(" and ")
90
+ class Type
91
+ attr_accessor :name, :table, :filter, :links, :order_by, :fields
92
+ attr_reader :schema
93
+ def initialize(schema, name)
94
+ @schema = schema
95
+ @name = name
96
+ @table = name.to_s.pluralize.to_sym
97
+ @fields = [:id]
98
+ @filter = nil
99
+ @order_by = nil
100
+ @links = {}
90
101
  end
102
+ def one(name, opts={})
103
+ create_link(name, false, opts)
104
+ end
105
+ def many(name, opts={})
106
+ create_link(name, true, opts)
107
+ end
108
+ def create_link(name, many, opts)
109
+ link = @links[name] = Link.new(self, name, many)
110
+ opts.each_pair do |key, val|
111
+ link.send(:"#{key}=", val)
112
+ end
113
+ link
114
+ end
115
+ end
91
116
 
92
- inner_sql += (is_many ? "" : " limit 1")
93
-
94
- "select to_json(" + (is_many ? "coalesce(json_agg(x.*), '[]'::json)" : "x.*" ) + ") res from (#{inner_sql}) x"
117
+ class Link
118
+ attr_accessor :name, :invert, :filter, :order_by
119
+ def initialize(owner, name, many)
120
+ @owner = owner
121
+ @name = name
122
+ @many = many
123
+ @invert = false
124
+ @order_by = nil
125
+ end
126
+ def fk=(_fk)
127
+ @_fk = fk
128
+ end
129
+ def fk
130
+ @invert ? "#{@name.to_s.singularize}_id" : "#{@owner.name}_id"
131
+ end
132
+ def type=(_type)
133
+ @_type = _type
134
+ end
135
+ def type
136
+ @owner.schema.types[@_type||@name.to_s.singularize.to_sym]
137
+ end
138
+ def many?
139
+ !!@many
140
+ end
95
141
  end
96
142
 
97
143
  end
98
144
 
99
- class Type
100
- attr_accessor :pk, :sql, :fields, :as, :filter
101
- attr_reader :links, :name
102
- def initialize(name)
103
- @name = name
104
- @links = {}
105
- @fields = [:id]
106
- @as = name.to_s.pluralize.to_sym
107
- @sql = "select * from #{name.to_s.pluralize}"
108
- @pk = :id
109
- end
110
- def pk!
111
- :"#{@as}.#{@pk}"
112
- end
113
- def one(name, opts={})
114
- opts[:fk] = :"#{@name}_id" unless opts[:fk]
115
- opts[:type] = name.to_s.singularize.to_sym unless opts[:type]
116
- opts[:name] = name
117
- @links[name] = [:one, opts]
118
- end
119
- def many(name, opts={})
120
- opts[:fk] = :"#{@name}_id" unless opts[:fk]
121
- opts[:type] = name.to_s.singularize.to_sym unless opts[:type]
122
- opts[:name] = name
123
- @links[name] = [:many, opts]
124
- end
125
- end
145
+
126
146
  end
@@ -9,154 +9,491 @@ module PgGraphQl
9
9
  sql.strip.split(" ").map{|e| e.strip}.reject{|e| e.empty?}
10
10
  end
11
11
 
12
- def query(*args, &block)
13
- Schema.new(&block).query(*args)
12
+ def to_sql(query, print_sql=nil, &block)
13
+ s = Schema.new(&block)
14
+ s.class.send(:define_method, :wrap_root) do |unwrapped_sql|
15
+ unwrapped_sql
16
+ end
17
+
18
+ sql = s.to_sql(query)
19
+ puts sql if print_sql
20
+ sql
14
21
  end
15
22
 
16
- # schema
23
+ def test_simple
24
+ res = to_sql({user: {id: 1, email: "email"}}) do |s|
25
+ s.root :user
26
+ s.type :user, fields: [:id, :email]
27
+ end
17
28
 
18
- def test_schema_root_type
19
- assert_equal :sometype, Schema.new{|e| e.root(:sometype)}.roots[:sometype][:type]
20
- assert_equal :person, Schema.new{|e| e.root(:people)}.roots[:people][:type]
29
+ assert_equal token(<<-SQL
30
+ select 'user'::text as key,
31
+ (select to_json(x.*)
32
+ from (select id,
33
+ email
34
+ from users
35
+ where id = 1 limit 1) x) as value
36
+ SQL
37
+ ), token(res)
21
38
  end
22
39
 
23
- # type
40
+ def test_simple_pk_array_empty
41
+ res = to_sql({user: {id: [], email: "email"}}) do |s|
42
+ s.root :user
43
+ s.type :user, fields: [:id, :email]
44
+ end
24
45
 
25
- def test_pk_prefixed_by_as
26
- assert_equal :"sometypes.id", Type.new(:sometype).pk!
46
+ assert_equal token(<<-SQL
47
+ select 'user'::text as key,
48
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
49
+ from (select id,
50
+ email
51
+ from users) x) as value
52
+ SQL
53
+ ), token(res)
27
54
  end
28
55
 
29
- # type - defaults
56
+ def test_simple_pk_array_one
57
+ res = to_sql({user: {id: [1], email: "email"}}) do |s|
58
+ s.root :user
59
+ s.type :user, fields: [:id, :email]
60
+ end
30
61
 
31
- def test_type_default_fields
32
- assert_equal [:id], Type.new(:sometype).fields
62
+ assert_equal token(<<-SQL
63
+ select 'user'::text as key,
64
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
65
+ from (select id,
66
+ email
67
+ from users where id in (1)) x) as value
68
+ SQL
69
+ ), token(res)
33
70
  end
34
71
 
35
- def test_type_default_as
36
- assert_equal :sometypes, Type.new(:sometype).as
37
- assert_equal :people, Type.new(:person).as
38
- end
72
+ def test_simple_pk_array_multiple
73
+ res = to_sql({user: {id: [1,2], email: "email"}}) do |s|
74
+ s.root :user
75
+ s.type :user, fields: [:id, :email]
76
+ end
39
77
 
40
- def test_type_default_sql
41
- assert_equal "select * from houses", Type.new(:house).sql
42
- assert_equal "select * from people", Type.new(:person).sql
78
+ assert_equal token(<<-SQL
79
+ select 'user'::text as key,
80
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
81
+ from (select id,
82
+ email
83
+ from users where id in (1,2)) x) as value
84
+ SQL
85
+ ), token(res)
43
86
  end
44
87
 
45
- def test_type_default_pk
46
- assert_equal :id, Type.new(:sometype).pk
88
+ def test_simple_filter
89
+ res = to_sql({user: {id: 1, email: "email"}}) do |s|
90
+ s.root :user
91
+ s.type :user, fields: [:id, :email], filter: "id > 100"
92
+ end
93
+
94
+ assert_equal token(<<-SQL
95
+ select 'user'::text as key,
96
+ (select to_json(x.*)
97
+ from (select id,
98
+ email
99
+ from users
100
+ where id = 1 and (id > 100) limit 1) x) as value
101
+ SQL
102
+ ), token(res)
47
103
  end
48
104
 
49
- def test_type_link_default_fk
50
- assert_equal :sometype_id, Type.new(:sometype).tap{|e| e.one(:somelink) }.links[:somelink][1][:fk]
51
- assert_equal :sometype_id, Type.new(:sometype).tap{|e| e.many(:somelink) }.links[:somelink][1][:fk]
52
- assert_equal :other_fk, Type.new(:sometype).tap{|e| e.one(:somelink, fk: :other_fk) }.links[:somelink][1][:fk]
53
- assert_equal :other_fk, Type.new(:sometype).tap{|e| e.many(:somelink, fk: :other_fk) }.links[:somelink][1][:fk]
105
+ def test_simple_multiple
106
+ res = to_sql({user: {id: 1, email: "email"}, educator: {id: "id"}}) do |s|
107
+ s.root :user
108
+ s.type :user, fields: [:id, :email]
109
+ s.type :educator
110
+ end
111
+
112
+ assert_equal token(<<-SQL
113
+ select 'user'::text as key,
114
+ (select to_json(x.*)
115
+ from (select id,
116
+ email
117
+ from users
118
+ where id = 1 limit 1) x) as value
119
+ union all
120
+ select 'educator'::text as key,
121
+ (select to_json(x.*)
122
+ from (select id
123
+ from educators limit 1) x) as value
124
+ SQL
125
+ ), token(res)
54
126
  end
55
127
 
56
- def test_type_link_default_type
57
- assert_equal :somelink, Type.new(:sometype).tap{|e| e.one(:somelink) }.links[:somelink][1][:type]
58
- assert_equal :somelink, Type.new(:sometype).tap{|e| e.many(:somelink) }.links[:somelink][1][:type]
128
+ #####################
129
+ # one
130
+ #####################
59
131
 
60
- assert_equal :person, Type.new(:sometype).tap{|e| e.one(:people) }.links[:people][1][:type]
61
- assert_equal :person, Type.new(:sometype).tap{|e| e.many(:people) }.links[:people][1][:type]
62
132
 
63
- assert_equal :other_type, Type.new(:sometype).tap{|e| e.one(:somelink, type: :other_type) }.links[:somelink][1][:type]
64
- assert_equal :other_type, Type.new(:sometype).tap{|e| e.many(:somelink, type: :other_type) }.links[:somelink][1][:type]
133
+ def test_link_one
134
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id"}}}) do |s|
135
+ s.root :user
136
+ s.type :user, fields: [:id, :email] do |t|
137
+ t.one :address
138
+ end
139
+ s.type :address
140
+ end
141
+
142
+ assert_equal token(<<-SQL
143
+ select 'user'::text as key,
144
+ (select to_json(x.*)
145
+ from (select id,
146
+ email,
147
+ (select to_json(x.*)
148
+ from (select id
149
+ from addresses
150
+ where user_id = users.id limit 1) x) as address
151
+ from users
152
+ where id = 1 limit 1) x) as value
153
+ SQL
154
+ ), token(res)
65
155
  end
66
156
 
67
- def test_unknown_field
68
- assert_raise_message "unknown field" do
69
- query([[:user, 1], :id, :name]) do |s|
70
- s.root :user
71
- s.type :user
157
+ def test_link_one_invert
158
+ res = to_sql({address: {id: 1, user: {id: "id", email: "email"}}}) do |s|
159
+ s.root :address
160
+ s.type :address do |t|
161
+ t.one :user, invert: true
72
162
  end
163
+ s.type :user, fields: [:id, :email]
73
164
  end
165
+
166
+ assert_equal token(<<-SQL
167
+ select 'address'::text as key,
168
+ (select to_json(x.*)
169
+ from (select id,
170
+ (select to_json(x.*)
171
+ from (select id,
172
+ email
173
+ from users
174
+ where id = addresses.user_id limit 1) x) as user
175
+ from addresses
176
+ where id = 1 limit 1) x) as value
177
+ SQL
178
+ ), token(res)
74
179
  end
75
180
 
76
- def test_simple
77
- res = query([[:user, 1], :id, :name]) do |s|
181
+ def test_link_one_filter
182
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id"}}}) do |s|
78
183
  s.root :user
79
- s.type :user, fields: [:id, :name]
184
+ s.type :user, fields: [:id, :email] do |t|
185
+ t.one :address, filter: "id > 100"
186
+ end
187
+ s.type :address
80
188
  end
81
189
 
82
- assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) limit 1) x"), token(res)
190
+ assert_equal token(<<-SQL
191
+ select 'user'::text as key,
192
+ (select to_json(x.*)
193
+ from (select id,
194
+ email,
195
+ (select to_json(x.*)
196
+ from (select id
197
+ from addresses
198
+ where user_id = users.id and (id > 100) limit 1) x) as address
199
+ from users
200
+ where id = 1 limit 1) x) as value
201
+ SQL
202
+ ), token(res)
83
203
  end
84
204
 
85
- def test_simple_filter
86
- res = query([[:user, 1], :id, :name]) do |s|
205
+ def test_link_one_order_by
206
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id"}}}) do |s|
87
207
  s.root :user
88
- s.type :user, fields: [:id, :name], filter: "id % 2 = 0"
208
+ s.type :user, fields: [:id, :email] do |t|
209
+ t.one :address, order_by: "id desc"
210
+ end
211
+ s.type :address
89
212
  end
90
213
 
91
- assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) and id % 2 = 0 limit 1) x"), token(res)
214
+ assert_equal token(<<-SQL
215
+ select 'user'::text as key,
216
+ (select to_json(x.*)
217
+ from (select id,
218
+ email,
219
+ (select to_json(x.*)
220
+ from (select id
221
+ from addresses
222
+ where user_id = users.id order by id desc limit 1) x) as address
223
+ from users
224
+ where id = 1 limit 1) x) as value
225
+ SQL
226
+ ), token(res)
227
+ end
228
+
229
+ #####################
230
+ # one-in-one
231
+ #####################
92
232
 
93
- res = query([[:user, 1], :id, :name]) do |s|
233
+ def test_link_one_in_one
234
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id", country: {id: "id"}}}}) do |s|
94
235
  s.root :user
95
- s.type :user, fields: [:id, :name], filter: "id % 2 = 0 and id > 10"
236
+ s.type :user, fields: [:id, :email] do |t|
237
+ t.one :address
238
+ end
239
+ s.type :address do |t|
240
+ t.one :country
241
+ end
242
+ s.type :country
96
243
  end
97
244
 
98
- assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) and id % 2 = 0 and id > 10 limit 1) x"), token(res)
245
+ assert_equal token(<<-SQL
246
+ select 'user'::text as key,
247
+ (select to_json(x.*)
248
+ from (select id,
249
+ email,
250
+ (select to_json(x.*)
251
+ from (select id,
252
+ (select to_json(x.*)
253
+ from (select id
254
+ from countries
255
+ where address_id = addresses.id limit 1) x) as country
256
+ from addresses
257
+ where user_id = users.id limit 1) x) as address
258
+ from users
259
+ where id = 1 limit 1) x) as value
260
+ SQL
261
+ ), token(res)
99
262
  end
100
263
 
101
- def test_one
102
- res = query([[:user, 1], :id, [[:address], :id]]) do |s|
264
+ def test_link_one_in_one_invert
265
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id", country: {id: "id"}}}}) do |s|
103
266
  s.root :user
104
- s.type :user do |t|
267
+ s.type :user, fields: [:id, :email] do |t|
105
268
  t.one :address
106
269
  end
270
+ s.type :address do |t|
271
+ t.one :country, invert: true
272
+ end
273
+ s.type :country
274
+ end
275
+
276
+ assert_equal token(<<-SQL
277
+ select 'user'::text as key,
278
+ (select to_json(x.*)
279
+ from (select id,
280
+ email,
281
+ (select to_json(x.*)
282
+ from (select id,
283
+ (select to_json(x.*)
284
+ from (select id
285
+ from countries
286
+ where id = addresses.country_id limit 1) x) as country
287
+ from addresses
288
+ where user_id = users.id limit 1) x) as address
289
+ from users
290
+ where id = 1 limit 1) x) as value
291
+ SQL
292
+ ), token(res)
293
+ end
294
+
295
+ #####################
296
+ # many
297
+ #####################
298
+
299
+
300
+ def test_link_many
301
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id"}}}) do |s|
302
+ s.root :user
303
+ s.type :user, fields: [:id, :email] do |t|
304
+ t.many :address
305
+ end
107
306
  s.type :address
108
307
  end
109
308
 
110
- expected = <<-SQL
111
- select
112
- to_json(x.*) res
113
- from (
114
- select
115
- id,
116
- (select to_json(x.*) res from (select id from addresses where user_id = users.id limit 1) x) as address
117
- from users
118
- where id in (1)
119
- limit 1
120
- ) x
309
+ assert_equal token(<<-SQL
310
+ select 'user'::text as key,
311
+ (select to_json(x.*)
312
+ from (select id,
313
+ email,
314
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
315
+ from (select id
316
+ from addresses
317
+ where user_id = users.id) x) as address
318
+ from users
319
+ where id = 1 limit 1) x) as value
121
320
  SQL
321
+ ), token(res)
322
+ end
323
+
324
+ def test_link_many_invert
325
+ res = to_sql({address: {id: "id", users: {id: "id", email: "email"}}}) do |s|
326
+ s.root :address
327
+ s.type :address do |t|
328
+ t.many :users, invert: true
329
+ end
330
+ s.type :user, fields: [:id, :email]
331
+ end
122
332
 
123
- assert_equal token(expected), token(res)
333
+ assert_equal token(<<-SQL
334
+ select 'address'::text as key,
335
+ (select to_json(x.*)
336
+ from (select id,
337
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
338
+ from (select id,
339
+ email
340
+ from users
341
+ where id = addresses.user_id) x) as users
342
+ from addresses limit 1) x) as value
343
+ SQL
344
+ ), token(res)
124
345
  end
125
346
 
126
- def test_one_fk_invert
127
- res = query([[:user, 1], :id, [[:address], :id]]) do |s|
347
+ def test_link_many_filter
348
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id"}}}) do |s|
128
349
  s.root :user
129
- s.type :user do |t|
130
- t.one :address, fk: :address_id, invert: true
350
+ s.type :user, fields: [:id, :email] do |t|
351
+ t.many :address, filter: "id % 2 = 0"
131
352
  end
132
353
  s.type :address
133
354
  end
134
355
 
135
- expected = <<-SQL
136
- select
137
- to_json(x.*) res
138
- from (
139
- select
140
- id,
141
- (select to_json(x.*) res from (select id from addresses where id = users.address_id limit 1) x) as address
142
- from users
143
- where id in (1)
144
- limit 1
145
- ) x
356
+ assert_equal token(<<-SQL
357
+ select 'user'::text as key,
358
+ (select to_json(x.*)
359
+ from (select id,
360
+ email,
361
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
362
+ from (select id
363
+ from addresses
364
+ where user_id = users.id and (id % 2 = 0)) x) as address
365
+ from users
366
+ where id = 1 limit 1) x) as value
146
367
  SQL
368
+ ), token(res)
369
+ end
147
370
 
148
- assert_equal token(expected), token(res)
371
+ def test_link_many_order_by
372
+ res = to_sql({user: {id: 1, email: "email", address: {id: "id"}}}) do |s|
373
+ s.root :user
374
+ s.type :user, fields: [:id, :email] do |t|
375
+ t.many :address, order_by: "id desc"
376
+ end
377
+ s.type :address
378
+ end
379
+
380
+ assert_equal token(<<-SQL
381
+ select 'user'::text as key,
382
+ (select to_json(x.*)
383
+ from (select id,
384
+ email,
385
+ (select to_json(coalesce(json_agg(x.*), '[]'::json))
386
+ from (select id
387
+ from addresses
388
+ where user_id = users.id order by id desc) x) as address
389
+ from users
390
+ where id = 1 limit 1) x) as value
391
+ SQL
392
+ ), token(res)
149
393
  end
150
394
 
151
- # def test_one_polymorph
395
+
396
+ # # schema
397
+
398
+ # def test_schema_root_type
399
+ # assert_equal :sometype, Schema.new{|e| e.root(:sometype)}.roots[:sometype][:type]
400
+ # assert_equal :person, Schema.new{|e| e.root(:people)}.roots[:people][:type]
401
+ # end
402
+
403
+ # # type
404
+
405
+ # def test_pk_prefixed_by_as
406
+ # assert_equal :"sometypes.id", Type.new(:sometype).pk!
407
+ # end
408
+
409
+ # type - defaults
410
+
411
+ # def test_type_default_fields
412
+ # assert_equal [:id], Schema::Type.new(:sometype).fields
413
+ # end
414
+
415
+ # def test_type_default_as
416
+ # assert_equal :sometypes, Type.new(:sometype).as
417
+ # assert_equal :people, Type.new(:person).as
418
+ # end
419
+
420
+ # def test_type_default_sql
421
+ # assert_equal "select * from houses", Type.new(:house).sql
422
+ # assert_equal "select * from people", Type.new(:person).sql
423
+ # end
424
+
425
+ # def test_type_default_pk
426
+ # assert_equal :id, Type.new(:sometype).pk
427
+ # end
428
+
429
+ # def test_type_link_default_fk
430
+ # assert_equal :sometype_id, Type.new(:sometype).tap{|e| e.one(:somelink) }.links[:somelink][1][:fk]
431
+ # assert_equal :sometype_id, Type.new(:sometype).tap{|e| e.many(:somelink) }.links[:somelink][1][:fk]
432
+ # assert_equal :other_fk, Type.new(:sometype).tap{|e| e.one(:somelink, fk: :other_fk) }.links[:somelink][1][:fk]
433
+ # assert_equal :other_fk, Type.new(:sometype).tap{|e| e.many(:somelink, fk: :other_fk) }.links[:somelink][1][:fk]
434
+ # end
435
+
436
+ # def test_type_link_default_type
437
+ # assert_equal :somelink, Type.new(:sometype).tap{|e| e.one(:somelink) }.links[:somelink][1][:type]
438
+ # assert_equal :somelink, Type.new(:sometype).tap{|e| e.many(:somelink) }.links[:somelink][1][:type]
439
+
440
+ # assert_equal :person, Type.new(:sometype).tap{|e| e.one(:people) }.links[:people][1][:type]
441
+ # assert_equal :person, Type.new(:sometype).tap{|e| e.many(:people) }.links[:people][1][:type]
442
+
443
+ # assert_equal :other_type, Type.new(:sometype).tap{|e| e.one(:somelink, type: :other_type) }.links[:somelink][1][:type]
444
+ # assert_equal :other_type, Type.new(:sometype).tap{|e| e.many(:somelink, type: :other_type) }.links[:somelink][1][:type]
445
+ # end
446
+
447
+ # def test_unknown_field
448
+ # assert_raise_message "unknown field" do
449
+ # query([[:user, 1], :id, :name]) do |s|
450
+ # s.root :user
451
+ # s.type :user
452
+ # end
453
+ # end
454
+ # end
455
+
456
+ # def test_simple_object_query
457
+ # res = query({user: [[:user, 1], :id, :name]}) do |s|
458
+ # s.root :user
459
+ # s.type :user, fields: [:id, :name]
460
+ # end
461
+
462
+ # assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) limit 1) x"), token(res)
463
+ # end
464
+
465
+ # def test_simple
466
+ # res = query([[:user, 1], :id, :name]) do |s|
467
+ # s.root :user
468
+ # s.type :user, fields: [:id, :name]
469
+ # end
470
+
471
+ # assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) limit 1) x"), token(res)
472
+ # end
473
+
474
+ # def test_simple_filter
475
+ # res = query([[:user, 1], :id, :name]) do |s|
476
+ # s.root :user
477
+ # s.type :user, fields: [:id, :name], filter: "id % 2 = 0"
478
+ # end
479
+
480
+ # assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) and id % 2 = 0 limit 1) x"), token(res)
481
+
482
+ # res = query([[:user, 1], :id, :name]) do |s|
483
+ # s.root :user
484
+ # s.type :user, fields: [:id, :name], filter: "id % 2 = 0 and id > 10"
485
+ # end
486
+
487
+ # assert_equal token("select to_json(x.*) res from (select id, name from users where id in (1) and id % 2 = 0 and id > 10 limit 1) x"), token(res)
488
+ # end
489
+
490
+ # def test_one
152
491
  # res = query([[:user, 1], :id, [[:address], :id]]) do |s|
153
492
  # s.root :user
154
493
  # s.type :user do |t|
155
- # t.one :address, polymorph: [:primary, :secondary]
494
+ # t.one :address
156
495
  # end
157
496
  # s.type :address
158
- # s.type :address_primary
159
- # s.type :address_secondary
160
497
  # end
161
498
 
162
499
  # expected = <<-SQL
@@ -165,11 +502,7 @@ module PgGraphQl
165
502
  # from (
166
503
  # select
167
504
  # id,
168
- # (select to_json(x.*) res from (
169
- # select 'primary' as type, id from addresses join addresses_primary using (id) where user_id = users.id and addresses.type = 'primary'
170
- # union
171
- # select 'secondary' as type, id from addresses join addresses_secondary using (id) where user_id = users.id and addresses.type = 'secondary'
172
- # ) x) as address
505
+ # (select to_json(x.*) res from (select id from addresses where user_id = users.id limit 1) x) as address
173
506
  # from users
174
507
  # where id in (1)
175
508
  # limit 1
@@ -179,168 +512,224 @@ module PgGraphQl
179
512
  # assert_equal token(expected), token(res)
180
513
  # end
181
514
 
182
- def test_one_filter
183
- res = query([[:user, 1], :id, [[:address], :id]]) do |s|
184
- s.root :user
185
- s.type :user do |t|
186
- t.one :address, filter: "is_default = true"
187
- end
188
- s.type :address
189
- end
515
+ # def test_one_fk_invert
516
+ # res = query([[:user, 1], :id, [[:address], :id]]) do |s|
517
+ # s.root :user
518
+ # s.type :user do |t|
519
+ # t.one :address, fk: :address_id, invert: true
520
+ # end
521
+ # s.type :address
522
+ # end
190
523
 
191
- expected = <<-SQL
192
- select
193
- to_json(x.*) res
194
- from (
195
- select
196
- id,
197
- (select to_json(x.*) res from (select id from addresses where user_id = users.id and is_default = true limit 1) x) as address
198
- from users
199
- where id in (1)
200
- limit 1
201
- ) x
202
- SQL
524
+ # expected = <<-SQL
525
+ # select
526
+ # to_json(x.*) res
527
+ # from (
528
+ # select
529
+ # id,
530
+ # (select to_json(x.*) res from (select id from addresses where id = users.address_id limit 1) x) as address
531
+ # from users
532
+ # where id in (1)
533
+ # limit 1
534
+ # ) x
535
+ # SQL
203
536
 
204
- assert_equal token(expected), token(res)
205
- end
537
+ # assert_equal token(expected), token(res)
538
+ # end
206
539
 
207
- def test_one_fk_through
208
- res = query([[:user, 1], :id, [[:address], :id]]) do |s|
209
- s.root :user
210
- s.type :user do |t|
211
- t.one :address, fk: ->(l) do
212
- "select id from some_address_table where user_id = #{t.pk!}"
213
- end
214
- end
215
- s.type :address
216
- end
540
+ # # def test_one_polymorph
541
+ # # res = query([[:user, 1], :id, [[:address], :id]]) do |s|
542
+ # # s.root :user
543
+ # # s.type :user do |t|
544
+ # # t.one :address, polymorph: [:primary, :secondary]
545
+ # # end
546
+ # # s.type :address
547
+ # # s.type :address_primary
548
+ # # s.type :address_secondary
549
+ # # end
550
+
551
+ # # expected = <<-SQL
552
+ # # select
553
+ # # to_json(x.*) res
554
+ # # from (
555
+ # # select
556
+ # # id,
557
+ # # (select to_json(x.*) res from (
558
+ # # select 'primary' as type, id from addresses join addresses_primary using (id) where user_id = users.id and addresses.type = 'primary'
559
+ # # union
560
+ # # select 'secondary' as type, id from addresses join addresses_secondary using (id) where user_id = users.id and addresses.type = 'secondary'
561
+ # # ) x) as address
562
+ # # from users
563
+ # # where id in (1)
564
+ # # limit 1
565
+ # # ) x
566
+ # # SQL
567
+
568
+ # # assert_equal token(expected), token(res)
569
+ # # end
570
+
571
+ # def test_one_filter
572
+ # res = query([[:user, 1], :id, [[:address], :id]]) do |s|
573
+ # s.root :user
574
+ # s.type :user do |t|
575
+ # t.one :address, filter: "is_default = true"
576
+ # end
577
+ # s.type :address
578
+ # end
217
579
 
218
- expected = <<-SQL
219
- select
220
- to_json(x.*) res
221
- from (
222
- select
223
- id,
224
- (select to_json(x.*) res from (select id from addresses where id in (select id from some_address_table where user_id = users.id) limit 1) x) as address
225
- from users
226
- where id in (1)
227
- limit 1
228
- ) x
229
- SQL
580
+ # expected = <<-SQL
581
+ # select
582
+ # to_json(x.*) res
583
+ # from (
584
+ # select
585
+ # id,
586
+ # (select to_json(x.*) res from (select id from addresses where user_id = users.id and is_default = true limit 1) x) as address
587
+ # from users
588
+ # where id in (1)
589
+ # limit 1
590
+ # ) x
591
+ # SQL
230
592
 
231
- assert_equal token(expected), token(res)
232
- end
593
+ # assert_equal token(expected), token(res)
594
+ # end
233
595
 
234
- def test_one_in_one
235
- res = query([[:user, 1], :id, [[:address], :id, [[:person], :id]]]) do |s|
236
- s.root :user
237
- s.type :user do |t|
238
- t.one :address
239
- end
240
- s.type :address do |t|
241
- t.one :person
242
- end
243
- s.type :person
244
- end
596
+ # def test_one_fk_through
597
+ # res = query([[:user, 1], :id, [[:address], :id]]) do |s|
598
+ # s.root :user
599
+ # s.type :user do |t|
600
+ # t.one :address, fk: ->(l) do
601
+ # "select id from some_address_table where user_id = #{t.pk!}"
602
+ # end
603
+ # end
604
+ # s.type :address
605
+ # end
245
606
 
246
- expected = <<-SQL
247
- select
248
- to_json(x.*) res
249
- from (
250
- select
251
- id,
252
- (select to_json(x.*) res from (
253
- select
254
- id,
255
- (select to_json(x.*) res from (select id from people where address_id = addresses.id limit 1) x) as person
256
- from addresses where user_id = users.id limit 1
257
- ) x) as address
258
- from users
259
- where id in (1)
260
- limit 1
261
- ) x
262
- SQL
607
+ # expected = <<-SQL
608
+ # select
609
+ # to_json(x.*) res
610
+ # from (
611
+ # select
612
+ # id,
613
+ # (select to_json(x.*) res from (select id from addresses where id in (select id from some_address_table where user_id = users.id) limit 1) x) as address
614
+ # from users
615
+ # where id in (1)
616
+ # limit 1
617
+ # ) x
618
+ # SQL
263
619
 
264
- assert_equal token(expected), token(res)
265
- end
620
+ # assert_equal token(expected), token(res)
621
+ # end
266
622
 
267
- def test_many
268
- res = query([[:user, 1], :id, [[:addresses], :id]]) do |s|
269
- s.root :user
270
- s.type :user do |t|
271
- t.many :addresses
272
- end
273
- s.type :address
274
- end
623
+ # def test_one_in_one
624
+ # res = query([[:user, 1], :id, [[:address], :id, [[:person], :id]]]) do |s|
625
+ # s.root :user
626
+ # s.type :user do |t|
627
+ # t.one :address
628
+ # end
629
+ # s.type :address do |t|
630
+ # t.one :person
631
+ # end
632
+ # s.type :person
633
+ # end
275
634
 
276
- expected = <<-SQL
277
- select
278
- to_json(x.*) res
279
- from (
280
- select id,
281
- (select to_json(coalesce(json_agg(x.*), '[]'::json)) res from (select id from addresses where user_id = users.id) x) as addresses
282
- from users
283
- where id in (1) limit 1
284
- ) x
285
- SQL
635
+ # expected = <<-SQL
636
+ # select
637
+ # to_json(x.*) res
638
+ # from (
639
+ # select
640
+ # id,
641
+ # (select to_json(x.*) res from (
642
+ # select
643
+ # id,
644
+ # (select to_json(x.*) res from (select id from people where address_id = addresses.id limit 1) x) as person
645
+ # from addresses where user_id = users.id limit 1
646
+ # ) x) as address
647
+ # from users
648
+ # where id in (1)
649
+ # limit 1
650
+ # ) x
651
+ # SQL
286
652
 
287
- assert_equal token(expected), token(res)
288
- end
653
+ # assert_equal token(expected), token(res)
654
+ # end
289
655
 
290
- def test_many_with_ids
291
- res = query([[:user, 1], :id, [[:addresses, 100], :id]]) do |s|
292
- s.root :user
293
- s.type :user do |t|
294
- t.many :addresses
295
- end
296
- s.type :address
297
- end
656
+ # def test_many
657
+ # res = query([[:user, 1], :id, [[:addresses], :id]]) do |s|
658
+ # s.root :user
659
+ # s.type :user do |t|
660
+ # t.many :addresses
661
+ # end
662
+ # s.type :address
663
+ # end
298
664
 
299
- expected = <<-SQL
300
- select
301
- to_json(x.*) res
302
- from (
303
- select id,
304
- (select to_json(coalesce(json_agg(x.*), '[]'::json)) res from (select id from addresses where user_id = users.id and id in (100)) x) as addresses
305
- from users
306
- where id in (1) limit 1
307
- ) x
308
- SQL
665
+ # expected = <<-SQL
666
+ # select
667
+ # to_json(x.*) res
668
+ # from (
669
+ # select id,
670
+ # (select to_json(coalesce(json_agg(x.*), '[]'::json)) res from (select id from addresses where user_id = users.id) x) as addresses
671
+ # from users
672
+ # where id in (1) limit 1
673
+ # ) x
674
+ # SQL
309
675
 
310
- assert_equal token(expected), token(res)
311
- end
676
+ # assert_equal token(expected), token(res)
677
+ # end
312
678
 
313
- def test_one_in_many
314
- res = query([[:user, 1], :id, [[:addresses], :id, [[:person], :id]]]) do |s|
315
- s.root :user
316
- s.type :user do |t|
317
- t.many :addresses
318
- end
319
- s.type :address do |t|
320
- t.one :person
321
- end
322
- s.type :person
323
- end
679
+ # def test_many_with_ids
680
+ # res = query([[:user, 1], :id, [[:addresses, 100], :id]]) do |s|
681
+ # s.root :user
682
+ # s.type :user do |t|
683
+ # t.many :addresses
684
+ # end
685
+ # s.type :address
686
+ # end
324
687
 
325
- expected = <<-SQL
326
- select
327
- to_json(x.*) res
328
- from (
329
- select
330
- id,
331
- (select to_json(coalesce(json_agg(x.*), '[]'::json)) res from (
332
- select
333
- id,
334
- (select to_json(x.*) res from (select id from people where address_id = addresses.id limit 1) x) as person
335
- from addresses where user_id = users.id
336
- ) x) as addresses
337
- from users
338
- where id in (1)
339
- limit 1
340
- ) x
341
- SQL
688
+ # expected = <<-SQL
689
+ # select
690
+ # to_json(x.*) res
691
+ # from (
692
+ # select id,
693
+ # (select to_json(coalesce(json_agg(x.*), '[]'::json)) res from (select id from addresses where user_id = users.id and id in (100)) x) as addresses
694
+ # from users
695
+ # where id in (1) limit 1
696
+ # ) x
697
+ # SQL
342
698
 
343
- assert_equal token(expected), token(res)
344
- end
699
+ # assert_equal token(expected), token(res)
700
+ # end
701
+
702
+ # def test_one_in_many
703
+ # res = query([[:user, 1], :id, [[:addresses], :id, [[:person], :id]]]) do |s|
704
+ # s.root :user
705
+ # s.type :user do |t|
706
+ # t.many :addresses
707
+ # end
708
+ # s.type :address do |t|
709
+ # t.one :person
710
+ # end
711
+ # s.type :person
712
+ # end
713
+
714
+ # expected = <<-SQL
715
+ # select
716
+ # to_json(x.*) res
717
+ # from (
718
+ # select
719
+ # id,
720
+ # (select to_json(coalesce(json_agg(x.*), '[]'::json)) res from (
721
+ # select
722
+ # id,
723
+ # (select to_json(x.*) res from (select id from people where address_id = addresses.id limit 1) x) as person
724
+ # from addresses where user_id = users.id
725
+ # ) x) as addresses
726
+ # from users
727
+ # where id in (1)
728
+ # limit 1
729
+ # ) x
730
+ # SQL
731
+
732
+ # assert_equal token(expected), token(res)
733
+ # end
345
734
  end
346
735
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pggraphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Zimmek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-05 00:00:00.000000000 Z
11
+ date: 2015-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json