piglet 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/README.rdoc +24 -4
  2. data/lib/piglet/field/binary_conditional.rb +15 -0
  3. data/lib/piglet/field/call_expression.rb +21 -0
  4. data/lib/piglet/field/infix_expression.rb +19 -0
  5. data/lib/piglet/field/literal.rb +20 -0
  6. data/lib/piglet/field/operators.rb +80 -0
  7. data/lib/piglet/field/prefix_expression.rb +23 -0
  8. data/lib/piglet/field/reference.rb +41 -0
  9. data/lib/piglet/field/rename.rb +13 -0
  10. data/lib/piglet/field/suffix_expression.rb +19 -0
  11. data/lib/piglet/inout/describe.rb +7 -0
  12. data/lib/piglet/inout/dump.rb +7 -0
  13. data/lib/piglet/inout/explain.rb +15 -0
  14. data/lib/piglet/inout/illustrate.rb +7 -0
  15. data/lib/piglet/inout/load.rb +31 -0
  16. data/lib/piglet/inout/output.rb +15 -0
  17. data/lib/piglet/inout/storage_types.rb +18 -0
  18. data/lib/piglet/inout/store.rb +19 -0
  19. data/lib/piglet/interpreter.rb +39 -7
  20. data/lib/piglet/relation/cogroup.rb +33 -0
  21. data/lib/piglet/relation/cross.rb +24 -0
  22. data/lib/piglet/relation/distinct.rb +18 -0
  23. data/lib/piglet/relation/filter.rb +15 -0
  24. data/lib/piglet/relation/foreach.rb +21 -0
  25. data/lib/piglet/relation/group.rb +23 -0
  26. data/lib/piglet/relation/join.rb +22 -0
  27. data/lib/piglet/relation/limit.rb +15 -0
  28. data/lib/piglet/relation/order.rb +31 -0
  29. data/lib/piglet/relation/relation.rb +179 -0
  30. data/lib/piglet/relation/sample.rb +15 -0
  31. data/lib/piglet/relation/split.rb +45 -0
  32. data/lib/piglet/relation/stream.rb +7 -0
  33. data/lib/piglet/relation/union.rb +21 -0
  34. data/lib/piglet.rb +40 -38
  35. data/spec/piglet/{field_spec.rb → field/reference_spec.rb} +22 -6
  36. data/spec/piglet/interpreter_spec.rb +51 -5
  37. data/spec/piglet/{relation_spec.rb → relation/relation_spec.rb} +6 -6
  38. data/spec/piglet/{split_spec.rb → relation/split_spec.rb} +8 -8
  39. data/spec/spec_helper.rb +0 -2
  40. metadata +39 -40
  41. data/examples/spike1.rb +0 -43
  42. data/examples/spike2.rb +0 -40
  43. data/lib/piglet/assignment.rb +0 -13
  44. data/lib/piglet/cogroup.rb +0 -31
  45. data/lib/piglet/cross.rb +0 -22
  46. data/lib/piglet/describe.rb +0 -5
  47. data/lib/piglet/distinct.rb +0 -16
  48. data/lib/piglet/dump.rb +0 -5
  49. data/lib/piglet/explain.rb +0 -13
  50. data/lib/piglet/field.rb +0 -40
  51. data/lib/piglet/field_expression_functions.rb +0 -62
  52. data/lib/piglet/field_function_expression.rb +0 -19
  53. data/lib/piglet/field_infix_expression.rb +0 -17
  54. data/lib/piglet/field_prefix_expression.rb +0 -21
  55. data/lib/piglet/field_rename.rb +0 -11
  56. data/lib/piglet/field_suffix_expression.rb +0 -17
  57. data/lib/piglet/filter.rb +0 -13
  58. data/lib/piglet/foreach.rb +0 -19
  59. data/lib/piglet/group.rb +0 -21
  60. data/lib/piglet/illustrate.rb +0 -5
  61. data/lib/piglet/join.rb +0 -20
  62. data/lib/piglet/limit.rb +0 -13
  63. data/lib/piglet/load.rb +0 -31
  64. data/lib/piglet/load_and_store.rb +0 -16
  65. data/lib/piglet/order.rb +0 -29
  66. data/lib/piglet/relation.rb +0 -177
  67. data/lib/piglet/sample.rb +0 -13
  68. data/lib/piglet/split.rb +0 -41
  69. data/lib/piglet/store.rb +0 -17
  70. data/lib/piglet/storing.rb +0 -13
  71. data/lib/piglet/stream.rb +0 -5
  72. data/lib/piglet/union.rb +0 -19
@@ -0,0 +1,22 @@
1
+ module Piglet
2
+ module Relation
3
+ class Join # :nodoc:
4
+ include Relation
5
+
6
+ def initialize(relation, description)
7
+ @join_fields = Hash[*description.select { |k, v| k.is_a?(Relation) }.flatten]
8
+ @sources = @join_fields.keys
9
+ @using = description[:using]
10
+ @parallel = description[:parallel]
11
+ end
12
+
13
+ def to_s
14
+ joins = @sources.map { |s| "#{s.alias} BY #{@join_fields[s]}" }.join(', ')
15
+ str = "JOIN #{joins}"
16
+ str << " USING \"#{@using.to_s}\"" if @using
17
+ str << " PARALLEL #{@parallel}" if @parallel
18
+ str
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Piglet
2
+ module Relation
3
+ class Limit # :nodoc:
4
+ include Relation
5
+
6
+ def initialize(relation, n)
7
+ @sources, @n = [relation], n
8
+ end
9
+
10
+ def to_s
11
+ "LIMIT #{@sources.first.alias} #{@n}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ module Piglet
2
+ module Relation
3
+ class Order # :nodoc:
4
+ include Relation
5
+
6
+ def initialize(relation, fields, options)
7
+ options ||= {}
8
+ @sources, @parallel = [relation], options[:parallel]
9
+ @fields = fields.is_a?(Enumerable) ? fields : [fields]
10
+ end
11
+
12
+ def to_s
13
+ "ORDER #{@sources.first.alias} BY #{field_strings}"
14
+ end
15
+
16
+ private
17
+
18
+ def field_strings
19
+ @fields.map { |f| field_string(f) }.join(', ')
20
+ end
21
+
22
+ def field_string(f)
23
+ if f.is_a?(Enumerable)
24
+ "#{f[0]} #{f[1].to_s.upcase}"
25
+ else
26
+ f.to_s
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,179 @@
1
+ module Piglet
2
+ module Relation
3
+ module Relation
4
+ attr_reader :sources
5
+
6
+ # The name this relation will get in Pig Latin. Then name is generated when
7
+ # the relation is outputed by the interpreter, and will be unique.
8
+ def alias
9
+ @alias ||= Relation.next_alias
10
+ end
11
+
12
+ # GROUP
13
+ #
14
+ # x.group(:a) # => GROUP x By a
15
+ # x.group(:a, :b, :c) # => GROUP x BY (a, b, c)
16
+ # x.group([:a, :b, :c], :parallel => 3) # => GROUP x BY (a, b, c) PARALLEL 3
17
+ def group(*args)
18
+ grouping, options = split_at_options(args)
19
+ Group.new(self, [grouping].flatten, options)
20
+ end
21
+
22
+ # DISTINCT
23
+ #
24
+ # x.distinct # => DISTINCT x
25
+ # x.distinct(:parallel => 5) # => DISTINCT x PARALLEL 5
26
+ def distinct(options={})
27
+ Distinct.new(self, options)
28
+ end
29
+
30
+ # COGROUP
31
+ #
32
+ # x.cogroup(x => :a, y => :b) # => COGROUP x BY a, y BY b
33
+ # x.cogroup(x => :a, y => :b, z => :c) # => COGROUP x BY a, y BY b, z BY c
34
+ # x.cogroup(x => [:a, :b], y => [:c, :d]) # => COGROUP x BY (a, b), y BY (c, d)
35
+ # x.cogroup(x => :a, y => [:b, :inner]) # => COGROUP x BY a, y BY b INNER
36
+ # x.cogroup(x => :a, y => :b, :parallel => 5) # => COGROUP x BY a, y BY b PARALLEL 5
37
+ def cogroup(description)
38
+ Cogroup.new(self, description)
39
+ end
40
+
41
+ # CROSS
42
+ #
43
+ # x.cross(y) # => CROSS x, y
44
+ # x.cross(y, z, w) # => CROSS x, y, z, w
45
+ # x.cross([y, z], :parallel => 5) # => CROSS x, y, z, w PARALLEL 5
46
+ def cross(*args)
47
+ relations, options = split_at_options(args)
48
+ Cross.new(([self] + relations).flatten, options)
49
+ end
50
+
51
+ # FILTER
52
+ #
53
+ # x.filter { |r| r.a == r.b } # => FILTER x BY a == b
54
+ # x.filter { |r| r.a > r.b && r.c != 3 } # => FILTER x BY a > b AND c != 3
55
+ def filter
56
+ Filter.new(self, yield(self))
57
+ end
58
+
59
+ # FOREACH ... GENERATE
60
+ #
61
+ # x.foreach { |r| r.a } # => FOREACH x GENERATE a
62
+ # x.foreach { |r| [r.a, r.b] } # => FOREACH x GENERATE a, b
63
+ # x.foreach { |r| r.a.max } # => FOREACH x GENERATE MAX(a)
64
+ # x.foreach { |r| r.a.avg.as(:b) } # => FOREACH x GENERATE AVG(a) AS b
65
+ #
66
+ #--
67
+ #
68
+ # TODO: FOREACH a { b GENERATE c }
69
+ def foreach
70
+ Foreach.new(self, yield(self))
71
+ end
72
+
73
+ # JOIN
74
+ #
75
+ # x.join(x => :a, y => :b) # => JOIN x BY a, y BY b
76
+ # x.join(x => :a, y => :b, z => :c) # => JOIN x BY a, y BY b, z BY c
77
+ # x.join(x => :a, y => :b, :using => :replicated) # => JOIN x BY a, y BY b USING "replicated"
78
+ # x.join(x => :a, y => :b, :parallel => 5) # => JOIN x BY a, y BY b PARALLEL 5
79
+ def join(description)
80
+ Join.new(self, description)
81
+ end
82
+
83
+ # LIMIT
84
+ #
85
+ # x.limit(10) # => LIMIT x 10
86
+ def limit(n)
87
+ Limit.new(self, n)
88
+ end
89
+
90
+ # ORDER
91
+ #
92
+ # x.order(:a) # => ORDER x BY a
93
+ # x.order(:a, :b) # => ORDER x BY a, b
94
+ # x.order([:a, :asc], [:b, :desc]) # => ORDER x BY a ASC, b DESC
95
+ # x.order(:a, :parallel => 5) # => ORDER x BY a PARALLEL 5
96
+ #
97
+ #--
98
+ #
99
+ # NOTE: the syntax x.order(:a => :asc, :b => :desc) would be nice, but in
100
+ # Ruby 1.8 the order of the keys cannot be guaranteed.
101
+ def order(*args)
102
+ fields, options = split_at_options(args)
103
+ fields = *fields
104
+ Order.new(self, fields, options)
105
+ end
106
+
107
+ # SAMPLE
108
+ #
109
+ # x.sample(5) # => SAMPLE x 5;
110
+ def sample(n)
111
+ Sample.new(self, n)
112
+ end
113
+
114
+ # SPLIT
115
+ #
116
+ # y, z = x.split { |r| [r.a <= 3, r.b > 4]} # => SPLIT x INTO y IF a <= 3, z IF a > 4
117
+ def split
118
+ Split.new(self, yield(self)).shards
119
+ end
120
+
121
+ # STREAM
122
+ #
123
+ # x.stream(x, 'cut -f 3') # => STREAM x THROUGH `cut -f 3`
124
+ # x.stream([x, y], 'cut -f 3') # => STREAM x, y THROUGH `cut -f 3`
125
+ # x.stream(x, 'cut -f 3', :schema => [%w(a int)]) # => STREAM x THROUGH `cut -f 3` AS (a:int)
126
+ #
127
+ #--
128
+ #
129
+ # TODO: how to handle DEFINE'd commands?
130
+ def stream(relations, command, options={})
131
+ raise NotSupportedError
132
+ end
133
+
134
+ # UNION
135
+ #
136
+ # x.union(y) # => UNION x, y
137
+ # x.union(y, z) # => UNION x, y, z
138
+ def union(*relations)
139
+ Union.new(*([self] + relations))
140
+ end
141
+
142
+ def method_missing(name, *args)
143
+ if name.to_s =~ /^\w+$/ && args.empty?
144
+ Field::Reference.new(name, self)
145
+ else
146
+ super
147
+ end
148
+ end
149
+
150
+ def [](n)
151
+ Field::Reference.new("\$#{n}", self)
152
+ end
153
+
154
+ def hash
155
+ self.alias.hash
156
+ end
157
+
158
+ def eql?(other)
159
+ other.is_a?(Relation) && other.alias == self.alias
160
+ end
161
+
162
+ private
163
+
164
+ def split_at_options(parameters)
165
+ if parameters.last.is_a? Hash
166
+ [parameters[0..-2], parameters.last]
167
+ else
168
+ [parameters, nil]
169
+ end
170
+ end
171
+
172
+ def self.next_alias
173
+ @counter ||= 0
174
+ @counter += 1
175
+ "relation_#{@counter}"
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,15 @@
1
+ module Piglet
2
+ module Relation
3
+ class Sample # :nodoc:
4
+ include Relation
5
+
6
+ def initialize(relation, n)
7
+ @sources, @n = [relation], n
8
+ end
9
+
10
+ def to_s
11
+ "SAMPLE #{@sources.first.alias} #{@n}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+ module Piglet
2
+ module Relation
3
+ class Split # :nodoc:
4
+ include Relation
5
+
6
+ def initialize(relation, expressions)
7
+ @sources, @expressions = [relation], expressions
8
+ @shard_map = create_shards
9
+ end
10
+
11
+ def shards
12
+ @shard_map.values_at(*@expressions)
13
+ end
14
+
15
+ def to_s
16
+ split_strings = @expressions.map do |expression|
17
+ "#{@shard_map[expression].alias} IF #{expression}"
18
+ end
19
+
20
+ "SPLIT #{@sources.first.alias} INTO #{split_strings.join(', ')}"
21
+ end
22
+
23
+ private
24
+
25
+ def create_shards
26
+ @expressions.inject({}) do |map, expr|
27
+ map[expr] = RelationShard.new(self)
28
+ map
29
+ end
30
+ end
31
+ end
32
+
33
+ class RelationShard # :nodoc:
34
+ include Relation
35
+
36
+ def initialize(split)
37
+ @sources = [split]
38
+ end
39
+
40
+ def to_s
41
+ self.alias
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ module Piglet
2
+ module Relation
3
+ class Stream # :nodoc:
4
+ include Relation
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ module Piglet
2
+ module Relation
3
+ class Union # :nodoc:
4
+ include Relation
5
+
6
+ def initialize(*relations)
7
+ @sources = relations
8
+ end
9
+
10
+ def to_s
11
+ "UNION #{source_aliases.join(', ')}"
12
+ end
13
+
14
+ private
15
+
16
+ def source_aliases
17
+ @sources.map { |s| s.alias }
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/piglet.rb CHANGED
@@ -1,45 +1,47 @@
1
1
  # :main: README.rdoc
2
2
  module Piglet # :nodoc:
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
 
5
- autoload_files = %w(
6
- assignment
7
- cogroup
8
- cross
9
- describe
10
- distinct
11
- dump
12
- explain
13
- field
14
- field_expression_functions
15
- field_function_expression
16
- field_infix_expression
17
- field_prefix_expression
18
- field_rename
19
- field_suffix_expression
20
- filter
21
- foreach
22
- group
23
- illustrate
24
- interpreter
25
- join
26
- limit
27
- load
28
- load_and_store
29
- order
30
- relation
31
- sample
32
- split
33
- store
34
- storing
35
- stream
36
- union
37
- )
5
+ autoload :Interpreter, 'piglet/interpreter'
38
6
 
39
- autoload_files.each do |f|
40
- c = f.split('_').map { |s| s.capitalize }.join.to_sym
41
- p = "piglet/#{f}"
42
- autoload c, p
7
+ module Inout
8
+ autoload :Describe, 'piglet/inout/describe'
9
+ autoload :Dump, 'piglet/inout/dump'
10
+ autoload :Explain, 'piglet/inout/explain'
11
+ autoload :Illustrate, 'piglet/inout/illustrate'
12
+ autoload :Load, 'piglet/inout/load'
13
+ autoload :Output, 'piglet/inout/output'
14
+ autoload :StorageTypes, 'piglet/inout/storage_types'
15
+ autoload :Store, 'piglet/inout/store'
16
+ end
17
+
18
+ module Relation
19
+ autoload :Cogroup, 'piglet/relation/cogroup'
20
+ autoload :Cross, 'piglet/relation/cross'
21
+ autoload :Distinct, 'piglet/relation/distinct'
22
+ autoload :Filter, 'piglet/relation/filter'
23
+ autoload :Foreach, 'piglet/relation/foreach'
24
+ autoload :Group, 'piglet/relation/group'
25
+ autoload :Join, 'piglet/relation/join'
26
+ autoload :Limit, 'piglet/relation/limit'
27
+ autoload :Order, 'piglet/relation/order'
28
+ autoload :Relation, 'piglet/relation/relation'
29
+ autoload :Sample, 'piglet/relation/sample'
30
+ autoload :Split, 'piglet/relation/split'
31
+ autoload :Stream, 'piglet/relation/stream'
32
+ autoload :Union, 'piglet/relation/union'
33
+ end
34
+
35
+ module Field
36
+ autoload :BinaryConditional, 'piglet/field/binary_conditional'
37
+ autoload :CallExpression, 'piglet/field/call_expression'
38
+ autoload :InfixExpression, 'piglet/field/infix_expression'
39
+ autoload :Literal, 'piglet/field/literal'
40
+ autoload :Operators, 'piglet/field/operators'
41
+ autoload :PrefixExpression, 'piglet/field/prefix_expression'
42
+ autoload :Reference, 'piglet/field/reference'
43
+ autoload :Rename, 'piglet/field/rename'
44
+ autoload :SuffixExpression, 'piglet/field/suffix_expression'
43
45
  end
44
46
 
45
47
  class NotSupportedError < StandardError; end
@@ -1,10 +1,10 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
 
4
- describe Piglet::Field do
4
+ describe Piglet::Field::Reference do
5
5
 
6
6
  before do
7
- @field = Piglet::Field.new('field')
7
+ @field = Piglet::Field::Reference.new('field')
8
8
  end
9
9
 
10
10
  describe '#to_s' do
@@ -13,7 +13,7 @@ describe Piglet::Field do
13
13
  end
14
14
 
15
15
  it 'returns a string with the field name (as a symbol)' do
16
- @field = Piglet::Field.new(:field)
16
+ @field = Piglet::Field::Reference.new(:field)
17
17
  @field.to_s.should eql("field")
18
18
  end
19
19
  end
@@ -52,8 +52,8 @@ describe Piglet::Field do
52
52
 
53
53
  context 'infix and unary operators' do
54
54
  before do
55
- @field1 = Piglet::Field.new('field1')
56
- @field2 = Piglet::Field.new('field2')
55
+ @field1 = Piglet::Field::Reference.new('field1')
56
+ @field2 = Piglet::Field::Reference.new('field2')
57
57
  end
58
58
 
59
59
  [:==, :>, :<, :>=, :<=, :%, :+, :-, :*, :/].each do |op|
@@ -125,6 +125,22 @@ describe Piglet::Field do
125
125
  it 'supports casts on an expression' do
126
126
  (@field1 + @field2).cast(:chararray).to_s.should eql("(chararray) (field1 + field2)")
127
127
  end
128
+
129
+ it 'supports AND though #and on fields' do
130
+ @field1.and(@field2).to_s.should eql("field1 AND field2")
131
+ end
132
+
133
+ it 'supports AND through #and on expressions' do
134
+ (@field1 + @field2).and(@field1 - @field2).to_s.should eql("(field1 + field2) AND (field1 - field2)")
135
+ end
136
+
137
+ it 'supports OR though #or on fields' do
138
+ @field1.or(@field2).to_s.should eql("field1 OR field2")
139
+ end
140
+
141
+ it 'supports OR through #or on expressions' do
142
+ (@field1 + @field2).or(@field1 - @field2).to_s.should eql("(field1 + field2) OR (field1 - field2)")
143
+ end
128
144
  end
129
145
 
130
146
  end
@@ -40,7 +40,7 @@ describe Piglet::Interpreter do
40
40
  @interpreter.to_pig_latin.should include("LOAD 'some/path' USING XYZ;")
41
41
  end
42
42
 
43
- Piglet::LoadAndStore::LOAD_STORE_FUNCTIONS.each do |symbolic_name, function|
43
+ Piglet::Inout::StorageTypes::LOAD_STORE_FUNCTIONS.each do |symbolic_name, function|
44
44
  it "knows that the load method :#{symbolic_name} means #{function}" do
45
45
  @interpreter.interpret { store(load('some/path', :using => symbolic_name), 'out') }
46
46
  @interpreter.to_pig_latin.should include("LOAD 'some/path' USING #{function};")
@@ -267,10 +267,10 @@ describe Piglet::Interpreter do
267
267
  @interpreter.to_pig_latin.should match(/FILTER \w+ BY a == 3/)
268
268
  end
269
269
 
270
- # it 'outputs a FILTER statement with a complex test' do
271
- # @interpreter.interpret { dump(load('in').filter { |r| r.a > r.b && r.c != 3 }) }
272
- # @interpreter.to_pig_latin.should match(/FILTER \w+ BY a > b AND c != 3/)
273
- # end
270
+ it 'outputs a FILTER statement with a complex test' do
271
+ @interpreter.interpret { dump(load('in').filter { |r| (r.a > r.b).and(r.c.ne(3)) }) }
272
+ @interpreter.to_pig_latin.should match(/FILTER \w+ BY \(a > b\) AND \(c != 3\)/)
273
+ end
274
274
  end
275
275
 
276
276
  describe 'SPLIT' do
@@ -410,4 +410,50 @@ describe Piglet::Interpreter do
410
410
  end
411
411
  end
412
412
 
413
+ context 'misc. operators' do
414
+ it 'outputs a binary conditional when using #test' do
415
+ @interpreter.interpret do
416
+ dump(load('in').foreach { |r| [test(r.a == r.b, r.a, r.b)]})
417
+ end
418
+ @interpreter.to_pig_latin.should include('(a == b ? a : b)')
419
+ end
420
+ end
421
+
422
+ context 'literals' do
423
+ it 'outputs a literal string when passing a string to #literal' do
424
+ @interpreter.interpret do
425
+ dump(load('in').foreach { |r| [literal('hello').as(:world)]})
426
+ end
427
+ @interpreter.to_pig_latin.should include("'hello' AS world")
428
+ end
429
+
430
+ it 'outputs a literal integer when passing an integer to #literal' do
431
+ @interpreter.interpret do
432
+ dump(load('in').foreach { |r| [literal(3).as(:n)]})
433
+ end
434
+ @interpreter.to_pig_latin.should include("3 AS n")
435
+ end
436
+
437
+ it 'outputs a literal float when passing a float to #literal' do
438
+ @interpreter.interpret do
439
+ dump(load('in').foreach { |r| [literal(3.14).as(:pi)]})
440
+ end
441
+ @interpreter.to_pig_latin.should include("3.14 AS pi")
442
+ end
443
+
444
+ it 'outputs a literal string when passing an arbitrary object to #literal' do
445
+ @interpreter.interpret do
446
+ dump(load('in').foreach { |r| [literal(self).as(:interpreter)]})
447
+ end
448
+ @interpreter.to_pig_latin.should match(/'[^']+' AS interpreter/)
449
+ end
450
+
451
+ it 'escapes single quotes in literal strings' do
452
+ @interpreter.interpret do
453
+ dump(load('in').foreach { |r| [literal("hello 'world'").as(:str)]})
454
+ end
455
+ @interpreter.to_pig_latin.should include("'hello \\'world\\'' AS str")
456
+ end
457
+ end
458
+
413
459
  end
@@ -1,11 +1,11 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
 
4
- describe Piglet::Relation do
4
+ describe Piglet::Relation::Relation do
5
5
 
6
6
  before do
7
7
  @relation = Object.new
8
- @relation.extend Piglet::Relation
8
+ @relation.extend Piglet::Relation::Relation
9
9
  end
10
10
 
11
11
  it 'has a alias' do
@@ -16,7 +16,7 @@ describe Piglet::Relation do
16
16
  aliases = { }
17
17
  1000.times do
18
18
  @relation = Object.new
19
- @relation.extend Piglet::Relation
19
+ @relation.extend Piglet::Relation::Relation
20
20
  aliases.should_not have_key(@relation.alias)
21
21
  aliases[@relation.alias] = @relation
22
22
  end
@@ -37,7 +37,7 @@ describe Piglet::Relation do
37
37
  describe '#cross' do
38
38
  it 'returns a new relation with the target relation as one of the sources' do
39
39
  other = Object.new
40
- other.extend Piglet::Relation
40
+ other.extend Piglet::Relation::Relation
41
41
  @relation.cross(other).sources.should include(@relation)
42
42
  end
43
43
  end
@@ -45,7 +45,7 @@ describe Piglet::Relation do
45
45
  describe '#union' do
46
46
  it 'returns a new relation with the target relation as one of the sources' do
47
47
  other = Object.new
48
- other.extend Piglet::Relation
48
+ other.extend Piglet::Relation::Relation
49
49
  @relation.union(other).sources.should include(@relation)
50
50
  end
51
51
  end
@@ -1,27 +1,27 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
3
 
4
- describe Piglet::Split do
4
+ describe Piglet::Relation::Split do
5
5
 
6
6
  before do
7
7
  @relation = mock('source')
8
8
  @expr1 = mock('expr1')
9
9
  @expr2 = mock('expr2')
10
10
  @relation.stub!(:alias).and_return('rel')
11
- @expr1.stub!(:to_s).and_return('y')
12
- @expr2.stub!(:to_s).and_return('w')
13
- @split = Piglet::Split.new(@relation, [@expr1, @expr2])
11
+ @expr1.stub!(:to_s).and_return('expr1')
12
+ @expr2.stub!(:to_s).and_return('expr2')
13
+ @split = Piglet::Relation::Split.new(@relation, [@expr1, @expr2])
14
14
  end
15
15
 
16
16
  describe '#to_s' do
17
17
  it 'outputs all x IF y expressions' do
18
- @split.to_s.should match(/SPLIT rel INTO \w+ IF [yw], \w+ IF [yw]/)
18
+ @split.to_s.should match(/SPLIT rel INTO \w+ IF expr[12], \w+ IF expr[12]/)
19
19
  end
20
20
 
21
21
  it 'contains the names of all the shard relations' do
22
22
  @shards = @split.shards
23
- @split.to_s.should include("#{@shards[0].alias} IF y")
24
- @split.to_s.should include("#{@shards[1].alias} IF w")
23
+ @split.to_s.should include("#{@shards[0].alias} IF expr1")
24
+ @split.to_s.should include("#{@shards[1].alias} IF expr2")
25
25
  end
26
26
  end
27
27
 
data/spec/spec_helper.rb CHANGED
@@ -7,8 +7,6 @@ require 'spec'
7
7
  require 'spec/autorun'
8
8
 
9
9
 
10
- require 'piglet/interpreter'
11
-
12
10
  Spec::Runner.configure do |config|
13
11
 
14
12
  end