axiom-arango-adapter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +5 -0
  3. data/.travis.yml +25 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.devtools +57 -0
  6. data/Guardfile +18 -0
  7. data/LICENSE +20 -0
  8. data/README.md +92 -0
  9. data/Rakefile +2 -0
  10. data/TODO +1 -0
  11. data/axiom-arango-adapter.gemspec +26 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/roodi.yml +18 -0
  16. data/config/site.reek +102 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/axiom-arango-adapter.rb +2 -0
  19. data/lib/axiom/adapter/arango.rb +40 -0
  20. data/lib/axiom/adapter/arango/adapter.rb +68 -0
  21. data/lib/axiom/adapter/arango/gateway.rb +356 -0
  22. data/lib/axiom/adapter/arango/reader.rb +98 -0
  23. data/lib/axiom/adapter/arango/visitor.rb +100 -0
  24. data/lib/axiom/adapter/arango/visitor/aggregate.rb +132 -0
  25. data/lib/axiom/adapter/arango/visitor/attribute.rb +26 -0
  26. data/lib/axiom/adapter/arango/visitor/binary.rb +77 -0
  27. data/lib/axiom/adapter/arango/visitor/for.rb +75 -0
  28. data/lib/axiom/adapter/arango/visitor/for/base.rb +40 -0
  29. data/lib/axiom/adapter/arango/visitor/for/binary.rb +108 -0
  30. data/lib/axiom/adapter/arango/visitor/for/binary/join.rb +131 -0
  31. data/lib/axiom/adapter/arango/visitor/for/binary/product.rb +48 -0
  32. data/lib/axiom/adapter/arango/visitor/for/summarization.rb +113 -0
  33. data/lib/axiom/adapter/arango/visitor/for/unary.rb +29 -0
  34. data/lib/axiom/adapter/arango/visitor/for/unary/extension.rb +72 -0
  35. data/lib/axiom/adapter/arango/visitor/for/unary/limit.rb +31 -0
  36. data/lib/axiom/adapter/arango/visitor/for/unary/offset.rb +34 -0
  37. data/lib/axiom/adapter/arango/visitor/for/unary/order.rb +63 -0
  38. data/lib/axiom/adapter/arango/visitor/for/unary/projection.rb +32 -0
  39. data/lib/axiom/adapter/arango/visitor/for/unary/rename.rb +88 -0
  40. data/lib/axiom/adapter/arango/visitor/for/unary/restriction.rb +42 -0
  41. data/lib/axiom/adapter/arango/visitor/function.rb +33 -0
  42. data/lib/axiom/adapter/arango/visitor/header.rb +55 -0
  43. data/lib/axiom/adapter/arango/visitor/literal.rb +26 -0
  44. data/lib/axiom/adapter/arango/visitor/reverse.rb +27 -0
  45. data/spec/fuzzer.rb +53 -0
  46. data/spec/integration/arango/read_spec.rb +166 -0
  47. data/spec/setup/arangodb.sh +61 -0
  48. data/spec/setup/run.sh +23 -0
  49. data/spec/shared/aql_behavior.rb +7 -0
  50. data/spec/shared/binary_relation_method_behaviour.rb +53 -0
  51. data/spec/shared/unary_relation_method_behaviour.rb +21 -0
  52. data/spec/spec_helper.rb +51 -0
  53. data/spec/support/ice_nine_config.rb +6 -0
  54. data/spec/unit/axiom/adapter/arango/adapter/class_methods/new_spec.rb +24 -0
  55. data/spec/unit/axiom/adapter/arango/adapter/gateway_spec.rb +11 -0
  56. data/spec/unit/axiom/adapter/arango/adapter/reader_spec.rb +12 -0
  57. data/spec/unit/axiom/adapter/arango/gateway/class_methods/new_spec.rb +15 -0
  58. data/spec/unit/axiom/adapter/arango/gateway/difference_spec.rb +16 -0
  59. data/spec/unit/axiom/adapter/arango/gateway/drop_spec.rb +20 -0
  60. data/spec/unit/axiom/adapter/arango/gateway/each_spec.rb +78 -0
  61. data/spec/unit/axiom/adapter/arango/gateway/extend_spec.rb +26 -0
  62. data/spec/unit/axiom/adapter/arango/gateway/intersect_spec.rb +16 -0
  63. data/spec/unit/axiom/adapter/arango/gateway/join_spec.rb +43 -0
  64. data/spec/unit/axiom/adapter/arango/gateway/materialize_spec.rb +26 -0
  65. data/spec/unit/axiom/adapter/arango/gateway/optimize_spec.rb +22 -0
  66. data/spec/unit/axiom/adapter/arango/gateway/product_spec.rb +16 -0
  67. data/spec/unit/axiom/adapter/arango/gateway/project_spec.rb +20 -0
  68. data/spec/unit/axiom/adapter/arango/gateway/remove_spec.rb +20 -0
  69. data/spec/unit/axiom/adapter/arango/gateway/rename_spec.rb +20 -0
  70. data/spec/unit/axiom/adapter/arango/gateway/respond_to_predicate_spec.rb +28 -0
  71. data/spec/unit/axiom/adapter/arango/gateway/restrict_spec.rb +26 -0
  72. data/spec/unit/axiom/adapter/arango/gateway/reverse_spec.rb +20 -0
  73. data/spec/unit/axiom/adapter/arango/gateway/sort_by_spec.rb +26 -0
  74. data/spec/unit/axiom/adapter/arango/gateway/summarize_spec.rb +150 -0
  75. data/spec/unit/axiom/adapter/arango/gateway/take_spec.rb +20 -0
  76. data/spec/unit/axiom/adapter/arango/gateway/unhandled_message_spec.rb +17 -0
  77. data/spec/unit/axiom/adapter/arango/gateway/union_spec.rb +16 -0
  78. data/spec/unit/axiom/adapter/arango/reader/each_spec.rb +43 -0
  79. data/spec/unit/axiom/adapter/arango/visitor/aggregate/count/root_spec.rb +15 -0
  80. data/spec/unit/axiom/adapter/arango/visitor/aggregate/count_spec.rb +15 -0
  81. data/spec/unit/axiom/adapter/arango/visitor/aggregate/maximum/root_spec.rb +15 -0
  82. data/spec/unit/axiom/adapter/arango/visitor/aggregate/maximum_spec.rb +15 -0
  83. data/spec/unit/axiom/adapter/arango/visitor/aggregate/minimum/root_spec.rb +15 -0
  84. data/spec/unit/axiom/adapter/arango/visitor/aggregate/minimum_spec.rb +15 -0
  85. data/spec/unit/axiom/adapter/arango/visitor/aggregate/sum/root_spec.rb +15 -0
  86. data/spec/unit/axiom/adapter/arango/visitor/aggregate/sum_spec.rb +15 -0
  87. data/spec/unit/axiom/adapter/arango/visitor/attribute/root_spec.rb +12 -0
  88. data/spec/unit/axiom/adapter/arango/visitor/binary/root_spec.rb +15 -0
  89. data/spec/unit/axiom/adapter/arango/visitor/class_methods/build_spec.rb +37 -0
  90. data/spec/unit/axiom/adapter/arango/visitor/class_methods/run_spec.rb +26 -0
  91. data/spec/unit/axiom/adapter/arango/visitor/for/base/root_spec.rb +13 -0
  92. data/spec/unit/axiom/adapter/arango/visitor/for/binary/join/local_name_spec.rb +20 -0
  93. data/spec/unit/axiom/adapter/arango/visitor/for/binary/join/right/root_spec.rb +14 -0
  94. data/spec/unit/axiom/adapter/arango/visitor/for/binary/join/root_spec.rb +14 -0
  95. data/spec/unit/axiom/adapter/arango/visitor/for/binary/join_spec.rb +14 -0
  96. data/spec/unit/axiom/adapter/arango/visitor/for/binary/local_name_spec.rb +14 -0
  97. data/spec/unit/axiom/adapter/arango/visitor/for/binary/product/right/root_spec.rb +13 -0
  98. data/spec/unit/axiom/adapter/arango/visitor/for/binary/product/root_spec.rb +13 -0
  99. data/spec/unit/axiom/adapter/arango/visitor/for/binary/product_spec.rb +13 -0
  100. data/spec/unit/axiom/adapter/arango/visitor/for/binary/right/join_spec.rb +14 -0
  101. data/spec/unit/axiom/adapter/arango/visitor/for/binary/right/local_name_spec.rb +13 -0
  102. data/spec/unit/axiom/adapter/arango/visitor/for/binary/right/product_spec.rb +13 -0
  103. data/spec/unit/axiom/adapter/arango/visitor/for/local_name_spec.rb +21 -0
  104. data/spec/unit/axiom/adapter/arango/visitor/for/root_spec.rb +29 -0
  105. data/spec/unit/axiom/adapter/arango/visitor/for/summarization/root_spec.rb +53 -0
  106. data/spec/unit/axiom/adapter/arango/visitor/for/unary/extension/root_spec.rb +13 -0
  107. data/spec/unit/axiom/adapter/arango/visitor/for/unary/extension_spec.rb +13 -0
  108. data/spec/unit/axiom/adapter/arango/visitor/for/unary/limit/root_spec.rb +17 -0
  109. data/spec/unit/axiom/adapter/arango/visitor/for/unary/limit_spec.rb +17 -0
  110. data/spec/unit/axiom/adapter/arango/visitor/for/unary/offset/root_spec.rb +17 -0
  111. data/spec/unit/axiom/adapter/arango/visitor/for/unary/offset_spec.rb +17 -0
  112. data/spec/unit/axiom/adapter/arango/visitor/for/unary/order/root_spec.rb +14 -0
  113. data/spec/unit/axiom/adapter/arango/visitor/for/unary/order_spec.rb +14 -0
  114. data/spec/unit/axiom/adapter/arango/visitor/for/unary/projection/root_spec.rb +13 -0
  115. data/spec/unit/axiom/adapter/arango/visitor/for/unary/projection_spec.rb +13 -0
  116. data/spec/unit/axiom/adapter/arango/visitor/for/unary/rename/root_spec.rb +13 -0
  117. data/spec/unit/axiom/adapter/arango/visitor/for/unary/rename_spec.rb +13 -0
  118. data/spec/unit/axiom/adapter/arango/visitor/for/unary/restriction/root_spec.rb +14 -0
  119. data/spec/unit/axiom/adapter/arango/visitor/for/unary/restriction_spec.rb +14 -0
  120. data/spec/unit/axiom/adapter/arango/visitor/header/root_spec.rb +12 -0
  121. data/spec/unit/axiom/adapter/arango/visitor/literal/root_spec.rb +10 -0
  122. data/spec/unit/axiom/adapter/arango/visitor/static/root_spec.rb +19 -0
  123. data/spec/unit/axiom/adapter/arango/visitor/visit_spec.rb +52 -0
  124. data/spec/unit/axiom/adapter/arango/visitor/visitor_spec.rb +39 -0
  125. metadata +379 -0
@@ -0,0 +1,68 @@
1
+ module Axiom
2
+ module Adapter
3
+ module Arango
4
+
5
+ # Adapter to read tuples from remote ArangoDB
6
+ class Adapter
7
+ include Adamantium::Flat, Concord.new(:database, :logger)
8
+
9
+ # Return new adapter
10
+ #
11
+ # @param [Ashikawa::Core::Database] _database
12
+ # @param [NullLogger] _logger
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @example
17
+ #
18
+ # database = Ashikawa::Core::Database.new('http://localhost:8529')
19
+ # adapter = Axiom::Adapter::Arango::Adapter.new(database, Logger.new($stderr, :debug))
20
+ #
21
+ # @api public
22
+ #
23
+ def self.new(_database, _logger = NullLogger.instance)
24
+ super
25
+ end
26
+
27
+ # Return reader for base relation
28
+ #
29
+ # @param [Relation::Base] base_relation
30
+ # the relation to read from
31
+ #
32
+ # @return [Reader]
33
+ # the reader
34
+ #
35
+ # @api private
36
+ #
37
+ def reader(base_relation)
38
+ Reader.new(self, base_relation)
39
+ end
40
+
41
+ # Return gateway for the ArangoDB adapter
42
+ #
43
+ # @param [Relation::Base] base_relation
44
+ #
45
+ # @return [Gateway]
46
+ #
47
+ # @example
48
+ #
49
+ # gateway = adapter.gateway(base_relation)
50
+ #
51
+ # # Perform restriction on gateway
52
+ # relation = gateway.restrict { |r| r.foo.eql('bar') }
53
+ #
54
+ # # Enumerate tuples
55
+ # relation.each do |tuple|
56
+ # p tuple.to_ary
57
+ # end
58
+ #
59
+ # @api public
60
+ #
61
+ def gateway(base_relation)
62
+ Gateway.new(self, base_relation)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,356 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module Adapter
5
+ module Arango
6
+ # A relation backed by an adapter
7
+ class Gateway < Relation
8
+ include Concord.new(:adapter, :relation)
9
+
10
+ DECORATED_CLASS = superclass
11
+
12
+ # remove methods so they can be proxied
13
+ undef_method *DECORATED_CLASS.public_instance_methods(false).map(&:to_s) - %w[ materialize ]
14
+ undef_method :project, :remove, :extend, :rename, :restrict, :sort_by, :reverse, :drop, :take
15
+
16
+ # Iterate over each row in the results
17
+ #
18
+ # @example
19
+ # gateway = Gateway.new(adapter, relation)
20
+ # gateway.each { |tuple| ... }
21
+ #
22
+ # @yield [tuple]
23
+ #
24
+ # @yieldparam [Tuple] tuple
25
+ # each tuple in the results
26
+ #
27
+ # @return [self]
28
+ #
29
+ # @api public
30
+ def each
31
+ return to_enum unless block_given?
32
+ tuples.each { |tuple| yield tuple }
33
+ self
34
+ end
35
+
36
+ # Return a relation that is the join of two relations
37
+ #
38
+ # @example natural join
39
+ # join = relation.join(other)
40
+ #
41
+ # @example theta-join using a block
42
+ # join = relation.join(other) { |r| r.a.gte(r.b) }
43
+ #
44
+ # @param [Relation] other
45
+ # the other relation to join
46
+ #
47
+ # @yield [relation]
48
+ # optional block to restrict the tuples with
49
+ #
50
+ # @yieldparam [Relation] relation
51
+ # the context to evaluate the restriction with
52
+ #
53
+ # @yieldreturn [Function, #call]
54
+ # predicate to restrict the tuples with
55
+ #
56
+ # @return [Gateway]
57
+ # return a gateway if the adapters are equal
58
+ # @return [Algebra::Join]
59
+ # return a normal join when the adapters are not equal
60
+ # @return [Algebra::Restriction]
61
+ # return a normal restriction when the adapters are not equal
62
+ # for a theta-join
63
+ #
64
+ # @api public
65
+ def join(other)
66
+ if block_given?
67
+ super
68
+ else
69
+ binary_operation(__method__, other, Algebra::Join)
70
+ end
71
+ end
72
+
73
+ # Return a relation that is the Cartesian product of two relations
74
+ #
75
+ # @example
76
+ # product = gateway.product(other)
77
+ #
78
+ # @param [Relation] other
79
+ # the other relation to find the product with
80
+ #
81
+ # @return [Gateway]
82
+ # return a gateway if the adapters are equal
83
+ # @return [Algebra::Product]
84
+ # return a normal product when the adapters are not equal
85
+ #
86
+ # @api public
87
+ def product(other)
88
+ binary_operation(__method__, other, Algebra::Product)
89
+ end
90
+
91
+ # Return the union between relations
92
+ #
93
+ # @example
94
+ # union = gateway.union(other)
95
+ #
96
+ # @param [Relation] other
97
+ # the other relation to find the union with
98
+ #
99
+ # @return [Gateway]
100
+ # return a gateway if the adapters are equal
101
+ # @return [Algebra::Union]
102
+ # return a normal union when the adapters are not equal
103
+ #
104
+ # @api public
105
+ def union(other)
106
+ binary_operation(__method__, other, Algebra::Union)
107
+ end
108
+
109
+ # Return the intersection between relations
110
+ #
111
+ # @example
112
+ # intersect = gateway.intersect(other)
113
+ #
114
+ # @param [Relation] other
115
+ # the other relation to find the intersect with
116
+ #
117
+ # @return [Gateway]
118
+ # return a gateway if the adapters are equal
119
+ # @return [Algebra::Intersection]
120
+ # return a normal intersection when the adapters are not equal
121
+ #
122
+ # @api public
123
+ def intersect(other)
124
+ binary_operation(__method__, other, Algebra::Intersection)
125
+ end
126
+
127
+ # Return the difference between relations
128
+ #
129
+ # @example
130
+ # difference = gateway.difference(other)
131
+ #
132
+ # @param [Relation] other
133
+ # the other relation to find the difference with
134
+ #
135
+ # @return [Gateway]
136
+ # return a gateway if the adapters are equal
137
+ # @return [Algebra::Difference]
138
+ # return a normal dfference when the adapters are not equal
139
+ #
140
+ # @api public
141
+ def difference(other)
142
+ binary_operation(__method__, other, Algebra::Difference)
143
+ end
144
+
145
+ # Return a summarized relation
146
+ #
147
+ # @example with no arguments
148
+ # summarization = gateway.summarize do |context|
149
+ # context.add(:count, context[:id].count)
150
+ # end
151
+ #
152
+ # @example with a relation
153
+ # summarization = gateway.summarize(relation) do |context|
154
+ # context.add(:count, context[:id].count)
155
+ # end
156
+ #
157
+ # @example with a header
158
+ # summarization = gateway.summarize([ :name ]) do |context|
159
+ # context.add(:count, context[:id].count)
160
+ # end
161
+ #
162
+ # @example with another gateway
163
+ # summarization = gateway.summarize(other_gateway) do |context|
164
+ # context.add(:count, context[:id].count)
165
+ # end
166
+ #
167
+ # @param [Gateway, Relation, Header, #to_ary] summarize_with
168
+ #
169
+ # @yield [function]
170
+ # Evaluate a summarization function
171
+ #
172
+ # @yieldparam [Evaluator::Context] context
173
+ # the context to evaluate the function within
174
+ #
175
+ # @return [Gateway]
176
+ # return a gateway if the adapters are equal, or there is no adapter
177
+ # @return [Algebra::Summarization]
178
+ # return a normal summarization when the adapters are not equal
179
+ #
180
+ # @api public
181
+ def summarize(summarize_with = TABLE_DEE, &block)
182
+ if summarize_merge?(summarize_with)
183
+ summarize_merge(summarize_with, &block)
184
+ else
185
+ summarize_split(summarize_with, &block)
186
+ end
187
+ end
188
+
189
+ # Test if the method is supported on this object
190
+ #
191
+ # @param [Symbol] method
192
+ #
193
+ # @return [Boolean]
194
+ #
195
+ # @api private
196
+ def respond_to?(method, *)
197
+ super || forwardable?(method)
198
+ end
199
+
200
+ private
201
+
202
+ # Proxy the message to the relation
203
+ #
204
+ # @param [Symbol] method
205
+ #
206
+ # @param [Array] args
207
+ #
208
+ # @return [self]
209
+ # return self for all command methods
210
+ # @return [Object]
211
+ # return response from all query methods
212
+ #
213
+ # @api private
214
+ def method_missing(method, *args, &block)
215
+ forwardable?(method) ? forward(method, *args, &block) : super
216
+ end
217
+
218
+ # Test if the method can be forwarded to the relation
219
+ #
220
+ # @param [Symbol] method
221
+ #
222
+ # @return [Boolean]
223
+ #
224
+ # @api private
225
+ def forwardable?(method)
226
+ relation.respond_to?(method)
227
+ end
228
+
229
+ # Forward the message to the relation
230
+ #
231
+ # @param [Array] args
232
+ #
233
+ # @return [self]
234
+ # return self for all command methods
235
+ # @return [Object]
236
+ # return response from all query methods
237
+ #
238
+ # @api private
239
+ def forward(*args, &block)
240
+ inner_relation = relation
241
+ response = inner_relation.public_send(*args, &block)
242
+ if response.equal?(inner_relation)
243
+ self
244
+ elsif response.kind_of?(DECORATED_CLASS)
245
+ self.class.new(adapter, response)
246
+ else
247
+ response
248
+ end
249
+ end
250
+
251
+ # Return a list of tuples to iterate over
252
+ #
253
+ # @return [#each]
254
+ #
255
+ # @api private
256
+ def tuples
257
+ inner_relation = relation
258
+ if materialized?
259
+ inner_relation
260
+ else
261
+ read_tuples
262
+ end
263
+ end
264
+
265
+ # Return a tuple reader
266
+ #
267
+ # @return [Enumerable<Tuple>]
268
+ #
269
+ # @api private
270
+ #
271
+ def read_tuples
272
+ adapter.reader(relation)
273
+ end
274
+
275
+ # Return a binary relation
276
+ #
277
+ # @param [Relation] other
278
+ #
279
+ # @return [Gateway]
280
+ # return a gateway if the adapters are equal
281
+ # @return [Relation]
282
+ # return a binary relation when the adapters are not equal
283
+ #
284
+ # @api private
285
+ def binary_operation(method, other, factory)
286
+ if same_adapter?(other)
287
+ forward(method, other.relation)
288
+ else
289
+ factory.new(self, other)
290
+ end
291
+ end
292
+
293
+ # Test if the other object is a Gateway
294
+ #
295
+ # @param [Gateway, Relation] other
296
+ #
297
+ # @return [Boolean]
298
+ #
299
+ # @api private
300
+ def gateway?(other)
301
+ other.kind_of?(Gateway)
302
+ end
303
+
304
+ # Test if the other object uses the same adapter
305
+ #
306
+ # @param [Gateway, Relation] other
307
+ #
308
+ # @return [Boolean]
309
+ #
310
+ # @api private
311
+ def same_adapter?(other)
312
+ gateway?(other) && adapter.eql?(other.adapter)
313
+ end
314
+
315
+ # Test if the summarize_with object can be merged into the summarization
316
+ #
317
+ # @param [Gateway, Relation, Header] summarize_with
318
+ #
319
+ # @return [Boolean]
320
+ #
321
+ # @api private
322
+ def summarize_merge?(summarize_with)
323
+ !summarize_with.respond_to?(:header) ||
324
+ summarize_with.equal?(TABLE_DEE) ||
325
+ same_adapter?(summarize_with)
326
+ end
327
+
328
+ # Merge the summarize_with into the summarization
329
+ #
330
+ # @param [Gateway, Relation, Header] summarize_with
331
+ #
332
+ # @return [Gateway]
333
+ #
334
+ # @api private
335
+ def summarize_merge(summarize_with, &block)
336
+ summarize_with = summarize_with.relation if gateway?(summarize_with)
337
+ forward(:summarize, summarize_with, &block)
338
+ end
339
+
340
+ # Split the summarize_with into a separate relation, wrapped in a summarization
341
+ #
342
+ # @param [Gateway, Relation, Header] summarize_with
343
+ #
344
+ # @return [Algebra::Summarization]
345
+ #
346
+ # @api private
347
+ def summarize_split(summarize_with, &block)
348
+ # evaluate the gateway, then summarize with the provided relation
349
+ context = Evaluator::Context.new(header - summarize_with.header, &block)
350
+ Algebra::Summarization.new(self, summarize_with, context.functions)
351
+ end
352
+
353
+ end
354
+ end
355
+ end
356
+ end
@@ -0,0 +1,98 @@
1
+ module Axiom
2
+ module Adapter
3
+ module Arango
4
+ # A reader to read tuples from the database
5
+ class Reader
6
+ include Adamantium::Flat, Enumerable, Concord.new(:adapter, :relation)
7
+
8
+ # Enumerate tuples
9
+ #
10
+ # @return [self]
11
+ # if block given
12
+ #
13
+ # @return [Enumerable<Tuple>]
14
+ # otherwise
15
+ #
16
+ # @api private
17
+ #
18
+ def each
19
+ return to_enum unless block_given?
20
+
21
+ cursor.each do |document|
22
+ yield tuple(document)
23
+ end
24
+
25
+ self
26
+ end
27
+
28
+ private
29
+
30
+ # Coerce document to tuple
31
+ #
32
+ # @param [Ashikawa::Core::Document] document
33
+ #
34
+ # @return [Tuple]
35
+ #
36
+ # @api private
37
+ #
38
+ def tuple(document)
39
+ Tuple.new(header, document.to_hash.values_at(*document_keys))
40
+ end
41
+
42
+ # Return header
43
+ #
44
+ # @return [Relation::Header]
45
+ #
46
+ # @api private
47
+ #
48
+ def header
49
+ relation.header
50
+ end
51
+
52
+ # Return attribute names
53
+ #
54
+ # @return [Enumerable<Symbol>]
55
+ #
56
+ # @api private
57
+ #
58
+ def attribute_names
59
+ header.map(&:name)
60
+ end
61
+
62
+ # Return document keys
63
+ #
64
+ # @return [Enumerable<String>]
65
+ #
66
+ # @api private
67
+ #
68
+ def document_keys
69
+ attribute_names.map(&:to_s)
70
+ end
71
+ memoize :document_keys
72
+
73
+ # Return cursor
74
+ #
75
+ # @return [Ashikawa::Core::Cursor]
76
+ #
77
+ # @api private
78
+ #
79
+ def cursor
80
+ adapter.database.query.execute(aql)
81
+ end
82
+
83
+ # Return AQL to query with
84
+ #
85
+ # @return [String]
86
+ #
87
+ # @api private
88
+ #
89
+ def aql
90
+ aql = Visitor.run(relation).aql
91
+ adapter.logger.debug { "AQL: #{aql}" }
92
+ aql
93
+ end
94
+
95
+ end
96
+ end
97
+ end
98
+ end