piggly 1.2.1 → 2.0.0

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.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +163 -0
  3. data/Rakefile +29 -15
  4. data/bin/piggly +4 -244
  5. data/lib/piggly.rb +19 -17
  6. data/lib/piggly/command.rb +9 -0
  7. data/lib/piggly/command/base.rb +148 -0
  8. data/lib/piggly/command/report.rb +162 -0
  9. data/lib/piggly/command/test.rb +157 -0
  10. data/lib/piggly/command/trace.rb +90 -0
  11. data/lib/piggly/command/untrace.rb +78 -0
  12. data/lib/piggly/compiler.rb +7 -5
  13. data/lib/piggly/compiler/cache_dir.rb +119 -0
  14. data/lib/piggly/compiler/coverage_report.rb +63 -0
  15. data/lib/piggly/compiler/trace_compiler.rb +105 -0
  16. data/lib/piggly/config.rb +47 -22
  17. data/lib/piggly/dumper.rb +9 -0
  18. data/lib/piggly/dumper/index.rb +121 -0
  19. data/lib/piggly/dumper/qualified_name.rb +36 -0
  20. data/lib/piggly/dumper/qualified_type.rb +81 -0
  21. data/lib/piggly/dumper/reified_procedure.rb +142 -0
  22. data/lib/piggly/dumper/skeleton_procedure.rb +102 -0
  23. data/lib/piggly/installer.rb +84 -42
  24. data/lib/piggly/parser.rb +43 -49
  25. data/lib/piggly/parser/grammar.tt +289 -313
  26. data/lib/piggly/parser/nodes.rb +270 -211
  27. data/lib/piggly/parser/traversal.rb +35 -33
  28. data/lib/piggly/parser/treetop_ruby19_patch.rb +1 -1
  29. data/lib/piggly/profile.rb +81 -60
  30. data/lib/piggly/reporter.rb +5 -18
  31. data/lib/piggly/reporter/base.rb +103 -0
  32. data/lib/piggly/reporter/html_dsl.rb +63 -0
  33. data/lib/piggly/reporter/index.rb +108 -0
  34. data/lib/piggly/reporter/procedure.rb +104 -0
  35. data/lib/piggly/reporter/resources/highlight.js +21 -0
  36. data/lib/piggly/reporter/{piggly.css → resources/piggly.css} +52 -12
  37. data/lib/piggly/reporter/{sortable.js → resources/sortable.js} +0 -0
  38. data/lib/piggly/tags.rb +280 -0
  39. data/lib/piggly/task.rb +191 -40
  40. data/lib/piggly/util.rb +8 -27
  41. data/lib/piggly/util/blankslate.rb +114 -0
  42. data/lib/piggly/util/cacheable.rb +19 -0
  43. data/lib/piggly/util/enumerable.rb +44 -0
  44. data/lib/piggly/util/file.rb +17 -0
  45. data/lib/piggly/util/process_queue.rb +96 -0
  46. data/lib/piggly/util/thunk.rb +39 -0
  47. data/lib/piggly/version.rb +8 -8
  48. data/spec/examples/compiler/cacheable_spec.rb +190 -0
  49. data/spec/examples/compiler/report_spec.rb +25 -0
  50. data/spec/{compiler → examples/compiler}/trace_spec.rb +7 -57
  51. data/spec/examples/config_spec.rb +61 -0
  52. data/spec/examples/dumper/index_spec.rb +197 -0
  53. data/spec/examples/dumper/procedure_spec.rb +116 -0
  54. data/spec/{grammar → examples/grammar}/expression_spec.rb +60 -60
  55. data/spec/{grammar → examples/grammar}/statements/assignment_spec.rb +15 -15
  56. data/spec/examples/grammar/statements/declaration_spec.rb +21 -0
  57. data/spec/{grammar → examples/grammar}/statements/exception_spec.rb +10 -10
  58. data/spec/{grammar → examples/grammar}/statements/if_spec.rb +47 -34
  59. data/spec/{grammar → examples/grammar}/statements/loop_spec.rb +5 -5
  60. data/spec/{grammar → examples/grammar}/statements/sql_spec.rb +11 -11
  61. data/spec/{grammar → examples/grammar}/tokens/comment_spec.rb +11 -11
  62. data/spec/{grammar → examples/grammar}/tokens/datatype_spec.rb +14 -8
  63. data/spec/{grammar → examples/grammar}/tokens/identifier_spec.rb +26 -10
  64. data/spec/{grammar → examples/grammar}/tokens/keyword_spec.rb +5 -5
  65. data/spec/{grammar → examples/grammar}/tokens/label_spec.rb +7 -7
  66. data/spec/{grammar → examples/grammar}/tokens/literal_spec.rb +1 -1
  67. data/spec/examples/grammar/tokens/lval_spec.rb +50 -0
  68. data/spec/{grammar → examples/grammar}/tokens/number_spec.rb +1 -1
  69. data/spec/{grammar → examples/grammar}/tokens/sqlkeywords_spec.rb +1 -1
  70. data/spec/{grammar → examples/grammar}/tokens/string_spec.rb +9 -9
  71. data/spec/{grammar → examples/grammar}/tokens/whitespace_spec.rb +1 -1
  72. data/spec/examples/installer_spec.rb +59 -0
  73. data/spec/examples/parser/nodes_spec.rb +73 -0
  74. data/spec/examples/parser/traversal_spec.rb +14 -0
  75. data/spec/examples/parser_spec.rb +115 -0
  76. data/spec/examples/profile_spec.rb +153 -0
  77. data/spec/{reporter/html_spec.rb → examples/reporter/html/dsl_spec.rb} +0 -0
  78. data/spec/examples/reporter/html/index_spec.rb +0 -0
  79. data/spec/examples/reporter/html_spec.rb +1 -0
  80. data/spec/examples/reporter_spec.rb +0 -0
  81. data/spec/{compiler → examples}/tags_spec.rb +10 -10
  82. data/spec/examples/task_spec.rb +0 -0
  83. data/spec/examples/util/cacheable_spec.rb +41 -0
  84. data/spec/examples/util/enumerable_spec.rb +64 -0
  85. data/spec/examples/util/file_spec.rb +40 -0
  86. data/spec/examples/util/process_queue_spec.rb +16 -0
  87. data/spec/examples/util/thunk_spec.rb +58 -0
  88. data/spec/examples/version_spec.rb +0 -0
  89. data/spec/issues/007_spec.rb +25 -0
  90. data/spec/issues/008_spec.rb +73 -0
  91. data/spec/issues/018_spec.rb +25 -0
  92. data/spec/spec_helper.rb +253 -9
  93. metadata +136 -93
  94. data/README.markdown +0 -116
  95. data/lib/piggly/compiler/cache.rb +0 -151
  96. data/lib/piggly/compiler/pretty.rb +0 -67
  97. data/lib/piggly/compiler/queue.rb +0 -46
  98. data/lib/piggly/compiler/tags.rb +0 -244
  99. data/lib/piggly/compiler/trace.rb +0 -91
  100. data/lib/piggly/filecache.rb +0 -40
  101. data/lib/piggly/parser/parser.rb +0 -11794
  102. data/lib/piggly/reporter/html.rb +0 -207
  103. data/spec/compiler/cache_spec.rb +0 -9
  104. data/spec/compiler/pretty_spec.rb +0 -9
  105. data/spec/compiler/queue_spec.rb +0 -3
  106. data/spec/compiler/rewrite_spec.rb +0 -3
  107. data/spec/config_spec.rb +0 -58
  108. data/spec/filecache_spec.rb +0 -70
  109. data/spec/fixtures/snippets.sql +0 -158
  110. data/spec/grammar/tokens/lval_spec.rb +0 -50
  111. data/spec/parser_spec.rb +0 -8
  112. data/spec/profile_spec.rb +0 -5
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly
4
+
5
+ describe Config do
6
+ before do
7
+ @config = Config.new
8
+ end
9
+
10
+ it "has class accessors and mutators" do
11
+ @config.should respond_to(:cache_root)
12
+ @config.should respond_to(:cache_root=)
13
+ @config.should respond_to(:report_root)
14
+ @config.should respond_to(:report_root=)
15
+ @config.should respond_to(:trace_prefix)
16
+ @config.should respond_to(:trace_prefix=)
17
+ end
18
+
19
+ it "has default values" do
20
+ @config.cache_root = nil
21
+ @config.cache_root.should_not be_nil
22
+ @config.cache_root.should =~ /cache$/
23
+
24
+ @config.report_root = nil
25
+ @config.report_root.should_not be_nil
26
+ @config.report_root.should =~ /reports$/
27
+
28
+ @config.trace_prefix = nil
29
+ @config.trace_prefix.should_not be_nil
30
+ @config.trace_prefix.should == 'PIGGLY'
31
+ end
32
+
33
+ describe "path" do
34
+ it "doesn't reparent absolute paths" do
35
+ @config.path('/tmp', '/usr/bin/ps').should == '/usr/bin/ps'
36
+ @config.path('A:/data/tmp', 'C:/USER/tmp').should == 'C:/USER/tmp'
37
+ @config.path('/tmp/data', '../data.txt').should == '../data.txt'
38
+ end
39
+
40
+ it "reparents relative paths" do
41
+ @config.path('/tmp', 'note.txt').should == '/tmp/note.txt'
42
+ end
43
+
44
+ it "doesn't require path parameter" do
45
+ @config.path('/tmp').should == '/tmp'
46
+ end
47
+ end
48
+
49
+ describe "mkpath" do
50
+ it "creates root if doesn't exist" do
51
+ FileUtils.should_receive(:makedirs).with('x/y').once.and_return(true)
52
+ @config.mkpath('x/y', 'z')
53
+ end
54
+
55
+ it "throws an error on path components that exist as files" do
56
+ lambda { @config.mkpath('/etc/passwd/file') }.should raise_error(Errno::EEXIST)
57
+ end
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,197 @@
1
+ require "spec_helper"
2
+
3
+ module Piggly
4
+
5
+ describe Dumper::Index do
6
+ before do
7
+ # make sure not to create directories all over the file system during the test
8
+ Config.stub(:mkpath).and_return{|root, file| File.join(root, file) }
9
+
10
+ @config = Config.new
11
+ @index = Dumper::Index.new(@config)
12
+ end
13
+
14
+ context "when cache file doesn't exist" do
15
+ it "is empty" do
16
+ File.should_receive(:exists?).with(@index.path).and_return(false)
17
+ @index.procedures.should be_empty
18
+ end
19
+ end
20
+
21
+ context "when cache file exists" do
22
+ before do
23
+ File.stub(:exists?).with(@index.path).and_return(true)
24
+ end
25
+
26
+ context "when the cache index file is empty" do
27
+ it "is empty" do
28
+ File.should_receive(:read).with(@index.path).and_return([].to_yaml)
29
+ @index.procedures.should be_empty
30
+ end
31
+ end
32
+
33
+ context "when the cache index file has two entries" do
34
+ before do
35
+ @first = Dumper::ReifiedProcedure.from_hash \
36
+ "oid" => "1000",
37
+ "name" => "iterate",
38
+ "source" => "FIRST PROCEDURE SOURCE CODE"
39
+
40
+ @second = Dumper::ReifiedProcedure.from_hash \
41
+ "oid" => "2000",
42
+ "name" => "login",
43
+ "source" => "SECOND PROCEDURE SOURCE CODE"
44
+
45
+ File.stub(:read).with(@first.source_path(@config)).
46
+ and_return(@first.source(@config))
47
+
48
+ File.stub(:read).with(@second.source_path(@config)).
49
+ and_return(@second.source(@config))
50
+
51
+ File.stub(:read).with(@index.path).
52
+ and_return(YAML.dump([@first, @second]))
53
+ end
54
+
55
+ it "has two procedures" do
56
+ @index.procedures.should have(2).things
57
+ end
58
+
59
+ it "is indexed by identifier" do
60
+ @index[@first.identifier].identifier.should == @first.identifier
61
+ @index[@second.identifier].identifier.should == @second.identifier
62
+ end
63
+
64
+ it "reads each procedure's source_path" do
65
+ @index[@first.identifier].source(@config).should == @first.source(@config)
66
+ @index[@second.identifier].source(@config).should == @second.source(@config)
67
+ end
68
+
69
+ context "when the procedures used to be identified using another method" do
70
+ it "renames each procedure using the current identifier"
71
+ it "updates the index with the current identified_using"
72
+ it "writes the updated index to disk"
73
+ end
74
+ end
75
+ end
76
+
77
+ describe "update" do
78
+ it "caches the source of new procedures"
79
+ it "updates the cached source of updated procedures"
80
+ it "purges the cached source of outdated procedures"
81
+ it "writes the cache index to disk"
82
+ it "does not write procedure source code within the cache index"
83
+ end
84
+
85
+ describe "label" do
86
+ def q(*ns)
87
+ Dumper::QualifiedName.new(*ns)
88
+ end
89
+
90
+ before do
91
+ @procedure = mock(:oid => 1,
92
+ :name => q("public", "foo"),
93
+ :type => q("private", "int"),
94
+ :arg_modes => ["in", "in"],
95
+ :arg_names => [],
96
+ :arg_types => [q("private", "int"), q("private", "varchar")])
97
+ end
98
+
99
+ context "when name is unique" do
100
+ context "and there is only one schema" do
101
+ before do
102
+ @index.stub(:procedures =>
103
+ [ @procedure,
104
+ mock(:oid => 2,
105
+ :name => q("public", "bar"),
106
+ :type => q("private", "int"),
107
+ :arg_modes => ["in"],
108
+ :arg_names => [],
109
+ :arg_types => []) ])
110
+ end
111
+
112
+ it "specifies schema.name" do
113
+ @index.label(@procedure).should == "foo"
114
+ end
115
+ end
116
+
117
+ context "and there is more than one schema" do
118
+ before do
119
+ @index.stub(:procedures =>
120
+ [ @procedure,
121
+ mock(:oid => 2,
122
+ :name => q("schema", "foo"),
123
+ :type => q("private", "int"),
124
+ :arg_modes => ["in"],
125
+ :arg_names => [],
126
+ :arg_types => []) ])
127
+ end
128
+
129
+ it "specifies schema.name" do
130
+ @index.label(@procedure).should == "public.foo"
131
+ end
132
+ end
133
+ end
134
+
135
+ context "when name is not unique" do
136
+ context "and schema.name is unique" do
137
+ before do
138
+ @index.stub(:procedures =>
139
+ [ @procedure,
140
+ mock(:oid => 2,
141
+ :name => q("schema", "foo"),
142
+ :type => q("private", "int"),
143
+ :arg_modes => ["in"],
144
+ :arg_names => [],
145
+ :arg_types => []) ])
146
+ end
147
+
148
+ it "specifies schema.name" do
149
+ @index.label(@procedure).should == "public.foo"
150
+ end
151
+ end
152
+
153
+ context "and schema.name is not unique" do
154
+ context "but argument types are unique" do
155
+ before do
156
+ @index.stub(:procedures =>
157
+ [ @procedure,
158
+ mock(:oid => 2,
159
+ :name => q("public", "foo"),
160
+ :type => q("private", "int"),
161
+ :arg_modes => ["in"],
162
+ :arg_names => [],
163
+ :arg_types => []) ])
164
+ end
165
+
166
+ it "specifies schema.name(types)" do
167
+ @index.label(@procedure).should ==
168
+ "foo(private.int, private.varchar)"
169
+ end
170
+ end
171
+
172
+ context "and argument types are not unique" do
173
+ context "but argument modes are unique" do
174
+ before do
175
+ @index.stub(:procedures =>
176
+ [ @procedure,
177
+ mock(:oid => 2,
178
+ :name => q("public", "foo"),
179
+ :type => q("private", "int"),
180
+ :arg_modes => ["out", "out"],
181
+ :arg_names => [],
182
+ :arg_types => [q("private", "int"), q("private", "varchar")]) ])
183
+ end
184
+
185
+ it "specifies schema.name(types and modes)" do
186
+ @index.label(@procedure).should ==
187
+ "foo(in private.int, in private.varchar)"
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ end
196
+
197
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ module Piggly
4
+
5
+ describe Dumper::ReifiedProcedure do
6
+ describe "all" do
7
+ before do
8
+ # stub connection
9
+ end
10
+ end
11
+
12
+ describe "from_hash" do
13
+ it "abbreviates known return types"
14
+ it "leaves alone unknown argument types"
15
+
16
+ it "abbreviates known return types"
17
+ it "leaves alone unknown argument types"
18
+
19
+ it "maps known volatilities"
20
+ it "leaves alone unknown volatilities"
21
+
22
+ it "maps known argument modes"
23
+ it "leaves alone unknown argument modes"
24
+ end
25
+
26
+ describe "store_source" do
27
+ context "when source is already instrumented" do
28
+ it "raises an error"
29
+ end
30
+
31
+ context "when the procedure was identified using the current configuration setting" do
32
+ it "does not attempt to remove any files"
33
+ it "writes to the current location"
34
+ it "has the current identified_using property"
35
+ end
36
+
37
+ context "when the procedure was identified using some other configuration setting" do
38
+ it "removes any old report files"
39
+ it "removes any old trace cache files"
40
+ it "removes the old source cache files"
41
+ it "writes to the current location"
42
+ it "updates the identified_using property"
43
+ end
44
+ end
45
+ end
46
+
47
+ describe Dumper::SkeletonProcedure do
48
+ describe "definition" do
49
+ it "specifies namespace and function name"
50
+ it "specifies source code between dollar-quoted string tags"
51
+
52
+ context "with argument modes" do
53
+ it "specifies argument modes"
54
+ end
55
+
56
+ context "without argument modes" do
57
+ it "doesn't specify argument modes"
58
+ end
59
+
60
+ context "with strict modifier" do
61
+ it "specifies STRICT token"
62
+ end
63
+
64
+ context "without strict modifier" do
65
+ it "doesn't specify STRICT token"
66
+ end
67
+
68
+ context "with security definer modifier" do
69
+ it "specifies SECURITY DEFINER token"
70
+ end
71
+
72
+ context "without security definer modifier" do
73
+ it "doesn't specify SECURITY DEFINER token"
74
+ end
75
+
76
+ context "with set-returning type" do
77
+ it "specifies SETOF token"
78
+ end
79
+
80
+ context "without non set-returning type" do
81
+ it "doesn't specify SETOF token"
82
+ end
83
+
84
+ context "with stable volatility" do
85
+ it "specifies STABLE token"
86
+ end
87
+ end
88
+
89
+ describe "source_path" do
90
+ it "has a .plpgsql extension"
91
+ it "is within the Dumper directory"
92
+ end
93
+
94
+ describe "purge_source" do
95
+ context "when the procedure was identified using the current configuration setting" do
96
+ it "removes any old report files"
97
+ it "removes any old trace cache files"
98
+ it "removes the old source cache files"
99
+ it "removes the current report files"
100
+ it "removes the current trace cache files"
101
+ it "removes the current source cache files"
102
+ it "doesn't attempt to remove any other files"
103
+ end
104
+
105
+ context "when the procedure was identified using some other configuration setting" do
106
+ it "removes the current report files"
107
+ it "removes the current trace cache files"
108
+ it "removes the current source cache files"
109
+ it "doesn't attempt to remove any other files"
110
+ end
111
+ end
112
+
113
+ describe "equality operator"
114
+ end
115
+
116
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  module Piggly
4
4
  describe Parser, "expressions" do
@@ -15,39 +15,39 @@ module Piggly
15
15
 
16
16
  it "can be a blank expression" do
17
17
  node, rest = parse_some(:expressionUntilSemiColon, ';')
18
- node.should be_a(Expression)
18
+ node.should be_expression
19
19
  node.source_text.should == ''
20
20
  rest.should == ';'
21
21
  end
22
22
 
23
23
  it "can be a comment" do
24
24
  node, rest = parse_some(:expressionUntilSemiColon, "/* comment */;")
25
- node.should be_a(Expression)
26
- node.count{|e| e.is_a?(TComment) }.should == 1
25
+ node.should be_expression
26
+ node.count{|e| e.comment? }.should == 1
27
27
 
28
28
  node, rest = parse_some(:expressionUntilSemiColon, "-- comment\n;")
29
- node.should be_a(Expression)
30
- node.count{|e| e.is_a?(TComment) }.should == 1
29
+ node.should be_expression
30
+ node.count{|e| e.comment? }.should == 1
31
31
  end
32
32
 
33
33
  it "can be a string" do
34
34
  node, rest = parse_some(:expressionUntilSemiColon, "'string';")
35
- node.should be_a(Expression)
36
- node.count{|e| e.is_a?(TString) }.should == 1
35
+ node.should be_expression
36
+ node.count{|e| e.string? }.should == 1
37
37
 
38
38
  node, rest = parse_some(:expressionUntilSemiColon, "$$ string $$;")
39
- node.should be_a(Expression)
40
- node.count{|e| e.is_a?(TString) }.should == 1
39
+ node.should be_expression
40
+ node.count{|e| e.string? }.should == 1
41
41
  end
42
42
 
43
43
  it "can be an arithmetic expression" do
44
44
  node, rest = parse_some(:expressionUntilSemiColon, "10 * (3 + x);")
45
- node.should be_a(Expression)
45
+ node.should be_expression
46
46
  end
47
47
 
48
48
  it "can be an SQL statement" do
49
49
  node, rest = parse_some(:expressionUntilSemiColon, "SELECT id FROM dataset;")
50
- node.should be_a(Expression)
50
+ node.should be_expression
51
51
  end
52
52
 
53
53
  it "can be an expression with comments embedded" do
@@ -56,8 +56,8 @@ module Piggly
56
56
  FROM "dataset" /* ; */ -- previous comments shouldn't terminate expression
57
57
  WHERE value IS /*NOT*/ NULL;
58
58
  SQL
59
- node.should be_a(Expression)
60
- node.count{|e| e.is_a?(TComment) }.should == 4
59
+ node.should be_expression
60
+ node.count{|e| e.comment? }.should == 4
61
61
  end
62
62
 
63
63
  it "can be an expression with strings and comments embedded" do
@@ -68,9 +68,9 @@ module Piggly
68
68
  AND length(value) > 10 -- 3. this comment in tail doesn't contain any 'string's
69
69
  /* 4. farewell comment in tail */;
70
70
  SQL
71
- node.should be_a(Expression)
72
- node.count{|e| e.is_a?(TComment) }.should == 4
73
- node.count{|e| e.is_a?(TString) }.should == 1
71
+ node.should be_expression
72
+ node.count{|e| e.comment? }.should == 4
73
+ node.count{|e| e.string? }.should == 1
74
74
  end
75
75
 
76
76
  it "can be an expression with strings embedded" do
@@ -81,19 +81,19 @@ module Piggly
81
81
  AND value <> '; this should not terminate expression'
82
82
  AND created_at = '2001-01-01';
83
83
  SQL
84
- node.should be_a(Expression)
85
- node.count{|e| e.is_a?(TString) }.should == 2
84
+ node.should be_expression
85
+ node.count{|e| e.string? }.should == 2
86
86
  end
87
87
 
88
- it "should combine trailing whitespace into 'tail' node" do
88
+ it "combines trailing whitespace into 'tail' node" do
89
89
  node, rest = parse_some(:expressionUntilSemiColon, "a := x + y \t;")
90
- node.should be_a(Expression)
90
+ node.should be_expression
91
91
  node.tail.source_text.should == " \t"
92
92
  end
93
93
 
94
- it "should combine trailing comments into 'tail' node" do
94
+ it "combines trailing comments into 'tail' node" do
95
95
  node, rest = parse_some(:expressionUntilSemiColon, "a := x + y /* note -- comment */;")
96
- node.should be_a(Expression)
96
+ node.should be_expression
97
97
  node.tail.source_text.should == ' /* note -- comment */'
98
98
 
99
99
  node, rest = parse_some(:expressionUntilSemiColon, <<-SQL)
@@ -103,7 +103,7 @@ module Piggly
103
103
  AND length(value) > 10 -- 3. this comment in tail doesn't contain any 'string's
104
104
  /* 4. farewell comment in tail */;
105
105
  SQL
106
- node.tail.count{|e| e.is_a?(TComment) }.should == 2
106
+ node.tail.count{|e| e.comment? }.should == 2
107
107
  end
108
108
  end
109
109
 
@@ -127,22 +127,22 @@ module Piggly
127
127
 
128
128
  it "can be a string" do
129
129
  node, rest = parse_some(:expressionUntilThen, "'string' THEN")
130
- node.should be_a(Expression)
131
- node.count{|e| e.is_a?(TString) }.should == 1
130
+ node.should be_expression
131
+ node.count{|e| e.string? }.should == 1
132
132
 
133
133
  node, rest = parse_some(:expressionUntilThen, "$$ string $$ THEN")
134
- node.should be_a(Expression)
135
- node.count{|e| e.is_a?(TString) }.should == 1
134
+ node.should be_expression
135
+ node.count{|e| e.string? }.should == 1
136
136
  end
137
137
 
138
138
  it "can be an arithmetic expression" do
139
139
  node, rest = parse_some(:expressionUntilThen, "10 * (3 + x) THEN")
140
- node.should be_a(Expression)
140
+ node.should be_expression
141
141
  end
142
142
 
143
143
  it "can be an SQL statement" do
144
144
  node, rest = parse_some(:expressionUntilThen, "SELECT id FROM dataset THEN")
145
- node.should be_a(Expression)
145
+ node.should be_expression
146
146
  end
147
147
 
148
148
  it "can be an expression with comments embedded" do
@@ -151,8 +151,8 @@ module Piggly
151
151
  FROM "dataset" /* THEN */ -- previous comments shouldn't terminate expression
152
152
  WHERE value IS /*NOT*/ NULL THEN
153
153
  SQL
154
- node.should be_a(Expression)
155
- node.count{|e| e.is_a?(TComment) }.should == 4
154
+ node.should be_expression
155
+ node.count{|e| e.comment? }.should == 4
156
156
  end
157
157
 
158
158
  it "can be an expression with strings and comments embedded" do
@@ -163,9 +163,9 @@ module Piggly
163
163
  AND length(value) > 10 -- 3. this comment in tail doesn't contain any 'string's
164
164
  /* 4. farewell comment in tail */ THEN
165
165
  SQL
166
- node.should be_a(Expression)
167
- node.count{|e| e.is_a?(TComment) }.should == 4
168
- node.count{|e| e.is_a?(TString) }.should == 1
166
+ node.should be_expression
167
+ node.count{|e| e.comment? }.should == 4
168
+ node.count{|e| e.string? }.should == 1
169
169
  end
170
170
 
171
171
  it "can be an expression with strings embedded" do
@@ -176,19 +176,19 @@ module Piggly
176
176
  AND value <> ' THEN this should not terminate expression'
177
177
  AND created_at = '2001-01-01' THEN
178
178
  SQL
179
- node.should be_a(Expression)
180
- node.count{|e| e.is_a?(TString) }.should == 2
179
+ node.should be_expression
180
+ node.count{|e| e.string? }.should == 2
181
181
  end
182
182
 
183
- it "should combine trailing whitespace into 'tail' node" do
183
+ it "combines trailing whitespace into 'tail' node" do
184
184
  node, rest = parse_some(:expressionUntilThen, "a := x + y \tTHEN")
185
- node.should be_a(Expression)
185
+ node.should be_expression
186
186
  node.tail.source_text.should == " \t"
187
187
  end
188
188
 
189
- it "should combine trailing comments into 'tail' node" do
189
+ it "combines trailing comments into 'tail' node" do
190
190
  node, rest = parse_some(:expressionUntilThen, "a := x + y /* note -- comment */THEN")
191
- node.should be_a(Expression)
191
+ node.should be_expression
192
192
  node.tail.source_text.should == ' /* note -- comment */'
193
193
 
194
194
  node, rest = parse_some(:expressionUntilThen, <<-SQL)
@@ -198,7 +198,7 @@ module Piggly
198
198
  AND length(value) > 10 -- 3. this comment in tail doesn't contain any 'string's
199
199
  /* 4. farewell comment in tail */THEN
200
200
  SQL
201
- node.tail.count{|e| e.is_a?(TComment) }.should == 2
201
+ node.tail.count{|e| e.comment? }.should == 2
202
202
  end
203
203
  end
204
204
 
@@ -222,22 +222,22 @@ module Piggly
222
222
 
223
223
  it "can be a string" do
224
224
  node, rest = parse_some(:expressionUntilLoop, "'string' LOOP")
225
- node.should be_a(Expression)
226
- node.count{|e| e.is_a?(TString) }.should == 1
225
+ node.should be_expression
226
+ node.count{|e| e.string? }.should == 1
227
227
 
228
228
  node, rest = parse_some(:expressionUntilLoop, "$$ string $$ LOOP")
229
- node.should be_a(Expression)
230
- node.count{|e| e.is_a?(TString) }.should == 1
229
+ node.should be_expression
230
+ node.count{|e| e.string? }.should == 1
231
231
  end
232
232
 
233
233
  it "can be an arithmetic expression" do
234
234
  node, rest = parse_some(:expressionUntilLoop, "10 * (3 + x) LOOP")
235
- node.should be_a(Expression)
235
+ node.should be_expression
236
236
  end
237
237
 
238
238
  it "can be an SQL statement" do
239
239
  node, rest = parse_some(:expressionUntilLoop, "SELECT id FROM dataset LOOP")
240
- node.should be_a(Expression)
240
+ node.should be_expression
241
241
  end
242
242
 
243
243
  it "can be an expression with comments embedded" do
@@ -246,8 +246,8 @@ module Piggly
246
246
  FROM "dataset" /* LOOP */ -- previous comments shouldn't terminate expression
247
247
  WHERE value IS /*NOT*/ NULL LOOP
248
248
  SQL
249
- node.should be_a(Expression)
250
- node.count{|e| e.is_a?(TComment) }.should == 4
249
+ node.should be_expression
250
+ node.count{|e| e.comment? }.should == 4
251
251
  end
252
252
 
253
253
  it "can be an expression with strings and comments embedded" do
@@ -258,9 +258,9 @@ module Piggly
258
258
  AND length(value) > 10 -- 3. this comment in tail doesn't contain any 'string's
259
259
  /* 4. farewell comment in tail */ LOOP
260
260
  SQL
261
- node.should be_a(Expression)
262
- node.count{|e| e.is_a?(TComment) }.should == 4
263
- node.count{|e| e.is_a?(TString) }.should == 1
261
+ node.should be_expression
262
+ node.count{|e| e.comment? }.should == 4
263
+ node.count{|e| e.string? }.should == 1
264
264
  end
265
265
 
266
266
  it "can be an expression with strings embedded" do
@@ -271,19 +271,19 @@ module Piggly
271
271
  AND value <> ' LOOP this should not terminate expression'
272
272
  AND created_at = '2001-01-01' LOOP
273
273
  SQL
274
- node.should be_a(Expression)
275
- node.count{|e| e.is_a?(TString) }.should == 2
274
+ node.should be_expression
275
+ node.count{|e| e.string? }.should == 2
276
276
  end
277
277
 
278
- it "should combine trailing whitespace into 'tail' node" do
278
+ it "combines trailing whitespace into 'tail' node" do
279
279
  node, rest = parse_some(:expressionUntilLoop, "a := x + y \tLOOP")
280
- node.should be_a(Expression)
280
+ node.should be_expression
281
281
  node.tail.source_text.should == " \t"
282
282
  end
283
283
 
284
- it "should combine trailing comments into 'tail' node" do
284
+ it "combines trailing comments into 'tail' node" do
285
285
  node, rest = parse_some(:expressionUntilLoop, "a := x + y /* note -- comment */LOOP")
286
- node.should be_a(Expression)
286
+ node.should be_expression
287
287
  node.tail.source_text.should == ' /* note -- comment */'
288
288
 
289
289
  node, rest = parse_some(:expressionUntilLoop, <<-SQL)
@@ -293,7 +293,7 @@ module Piggly
293
293
  AND length(value) > 10 -- 3. this comment in tail doesn't contain any 'string's
294
294
  /* 4. farewell comment in tail */LOOP
295
295
  SQL
296
- node.tail.count{|e| e.is_a?(TComment) }.should == 2
296
+ node.tail.count{|e| e.comment? }.should == 2
297
297
  end
298
298
  end
299
299