pggraphql 0.0.1 → 0.0.2

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 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