norikra 0.0.13-java → 0.0.14-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,7 +13,8 @@ module Norikra
13
13
  end
14
14
 
15
15
  def field_list(target)
16
- @typedefs[target].fields.values.sort{|a,b| a.name <=> b.name}.map(&:to_hash)
16
+ @typedefs[target].dump.map{|key,hash_value| hash_value}
17
+ # @typedefs[target].fields.values.sort{|a,b| a.name <=> b.name}.map(&:to_hash)
17
18
  end
18
19
 
19
20
  def add_target(target, fields)
@@ -45,15 +46,26 @@ module Norikra
45
46
  @typedefs[target].reserve(field, type)
46
47
  end
47
48
 
48
- def fields_defined?(target, field_name_list)
49
- @typedefs[target].field_defined?(field_name_list)
50
- end
51
-
52
49
  def ready?(query)
53
50
  query.targets.all?{|t| @typedefs[t] && ! @typedefs[t].lazy? && @typedefs[t].field_defined?(query.fields(t))} &&
54
51
  query.fields(nil).all?{|f| query.targets.any?{|t| @typedefs[t].field_defined?([f])}}
55
52
  end
56
53
 
54
+ def register_waiting_fields(query)
55
+ query.targets.each do |t|
56
+ next if t.nil?
57
+
58
+ typedef = @typedefs[t]
59
+ fields = typedef.fields
60
+
61
+ query.fields(t).each do |fieldname|
62
+ if !fields.has_key?(fieldname) && !typedef.waiting_fields.include?(fieldname)
63
+ typedef.waiting_fields.push(fieldname)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
57
69
  def generate_fieldset_mapping(query)
58
70
  fields_set = {}
59
71
 
@@ -89,7 +101,7 @@ module Norikra
89
101
  end
90
102
 
91
103
  def generate_base_fieldset(target, event)
92
- guessed = Norikra::FieldSet.simple_guess(event, false) # all fields are non-optional
104
+ guessed = @typedefs[target].simple_guess(event, false, false) # all fields are non-optional
93
105
  guessed.update(@typedefs[target].fields, false)
94
106
  guessed
95
107
  end
@@ -133,18 +145,12 @@ module Norikra
133
145
  sets
134
146
  end
135
147
 
136
- def refer(target, event)
137
- @typedefs[target].refer(event)
138
- end
139
-
140
- def format(target, event)
141
- @typedefs[target].format(event)
148
+ def refer(target_name, event, strict=false)
149
+ @typedefs[target_name].refer(event, strict)
142
150
  end
143
151
 
144
- def dump
145
- @typedefs.keys.map{|target|
146
- {:name => target, :fields => @typedefs[target].dump}
147
- }
152
+ def dump_target(name)
153
+ @typedefs[name].dump_all
148
154
  end
149
155
  end
150
156
  end
@@ -1,3 +1,3 @@
1
1
  module Norikra
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
data/norikra.gemspec CHANGED
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency "rack"
24
24
  spec.add_runtime_dependency "msgpack-rpc-over-http-jruby", ">= 0.0.5"
25
25
  spec.add_runtime_dependency "thor"
26
- spec.add_runtime_dependency "norikra-client-jruby", ">= 0.0.6"
26
+ spec.add_runtime_dependency "norikra-client-jruby", ">= 0.0.7"
27
27
 
28
28
  spec.add_development_dependency "bundler", "~> 1.3"
29
29
  spec.add_development_dependency "rake"
@@ -22,6 +22,37 @@ def rspec(file=nil)
22
22
  end
23
23
  end
24
24
 
25
+ $service = nil
26
+ def service
27
+ $service ||= com.espertech.esper.client.EPServiceProviderManager.getDefaultProvider
28
+ end
29
+
30
+ $administrator = nil
31
+ def administrator
32
+ $administrator ||= service.getEPAdministrator
33
+ end
34
+
35
+ def compileEPL(query_str)
36
+ administrator.compileEPL(query_str)
37
+ end
38
+
39
+ def query_string(model)
40
+ writer = java.io.StringWriter.new
41
+ formatter = com.espertech.esper.client.soda.EPStatementFormatter.new
42
+ if model.respond_to?(:toEPLElement)
43
+ model.toEPLElement(writer)
44
+ writer.toString
45
+ elsif model.respond_to?(:toPrecedenceFreeEPL)
46
+ model.toPrecedenceFreeEPL(writer)
47
+ writer.toString
48
+ elsif model.is_a?(Java::ComEspertechEsperClientSoda::EPStatementObjectModel)
49
+ model.toEPL
50
+ else
51
+ model.toEPL(writer, formatter)
52
+ writer.toString
53
+ end
54
+ end
55
+
25
56
  puts <<DESC
26
57
 
27
58
  Example:
data/spec/field_spec.rb CHANGED
@@ -1,12 +1,73 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require_relative './spec_helper'
2
3
 
3
- require 'norikra/typedef'
4
- # require 'norikra/error'
4
+ require 'norikra/field'
5
5
 
6
6
  require 'json'
7
7
  require 'digest'
8
8
 
9
9
  describe Norikra::Field do
10
+ describe '.escape_name' do
11
+ it 'escapes chars not alphabetic and numeric chars, with "_"' do
12
+ expect(Norikra::Field.escape_name("part1 part2")).to eql('part1_part2')
13
+ expect(Norikra::Field.escape_name("part1^part2")).to eql('part1_part2')
14
+ expect(Norikra::Field.escape_name("part1|part2")).to eql('part1_part2')
15
+ expect(Norikra::Field.escape_name("part1\"part2")).to eql('part1_part2')
16
+ expect(Norikra::Field.escape_name("part1'part2")).to eql('part1_part2')
17
+ expect(Norikra::Field.escape_name("part1@part2")).to eql('part1_part2')
18
+ expect(Norikra::Field.escape_name("part1#part2")).to eql('part1_part2')
19
+ expect(Norikra::Field.escape_name("part1あpart2")).to eql('part1_part2')
20
+ end
21
+
22
+ it 'escape "." in field name with "$"' do
23
+ expect(Norikra::Field.escape_name("part1.part2")).to eql('part1$part2')
24
+ end
25
+
26
+ it 'escape additional "." which specify string-dot of key chain escaped with "_"' do
27
+ expect(Norikra::Field.escape_name("part1..part2")).to eql('part1$_part2')
28
+ end
29
+
30
+ it 'escape numeric-only part with prefix "$"' do
31
+ expect(Norikra::Field.escape_name("part1.0")).to eql('part1$$0')
32
+ end
33
+ end
34
+
35
+ describe '.regulate_key_chain' do
36
+ it 'escape String chain items and returns by array which started with numeric, with "$$", and joins keys with separator "$"' do
37
+ expect(Norikra::Field.regulate_key_chain(["part1", "part2"])).to eql(['part1','part2'])
38
+ expect(Norikra::Field.regulate_key_chain(["part.1", "2"])).to eql(['part_1', '$$2'])
39
+ expect(Norikra::Field.regulate_key_chain(["part1", 2])).to eql(['part1', '$2'])
40
+ expect(Norikra::Field.regulate_key_chain(["part1", 2, "2"])).to eql(['part1', '$2', '$$2'])
41
+ expect(Norikra::Field.regulate_key_chain(["part1", ".part2"])).to eql(['part1', '_part2'])
42
+ expect(Norikra::Field.regulate_key_chain(["part1", 2, ".part2"])).to eql(['part1', '$2', '_part2'])
43
+ end
44
+ end
45
+
46
+ describe '.escape_key_chain' do
47
+ it 'escape String chain items which started with numeric, with "$$", and joins keys with separator "$"' do
48
+ expect(Norikra::Field.escape_key_chain("part1", "part2")).to eql('part1$part2')
49
+ expect(Norikra::Field.escape_key_chain("part.1", "2")).to eql('part_1$$$2')
50
+ expect(Norikra::Field.escape_key_chain("part1", 2)).to eql('part1$$2')
51
+ expect(Norikra::Field.escape_key_chain("part1", 2, "2")).to eql('part1$$2$$$2')
52
+ expect(Norikra::Field.escape_key_chain("part1", ".part2")).to eql('part1$_part2')
53
+ expect(Norikra::Field.escape_key_chain("part1", 2, ".part2")).to eql('part1$$2$_part2')
54
+ end
55
+ end
56
+
57
+ describe '.container_type?' do
58
+ it 'returns true for only "hash" and "array"' do
59
+ expect(Norikra::Field.container_type?('')).to be_false
60
+ expect(Norikra::Field.container_type?('string')).to be_false
61
+ expect(Norikra::Field.container_type?('int')).to be_false
62
+ expect(Norikra::Field.container_type?('long')).to be_false
63
+
64
+ expect(Norikra::Field.container_type?('Hash')).to be_true
65
+ expect(Norikra::Field.container_type?('hash')).to be_true
66
+ expect(Norikra::Field.container_type?('Array')).to be_true
67
+ expect(Norikra::Field.container_type?('array')).to be_true
68
+ end
69
+ end
70
+
10
71
  describe '.valid_type?' do
11
72
  it 'returns normalized type strings' do
12
73
  expect(Norikra::Field.valid_type?('String')).to eql('string')
@@ -139,4 +200,72 @@ describe Norikra::Field do
139
200
  end
140
201
  end
141
202
  end
203
+
204
+ describe '#define_value_accessor' do
205
+ it 'defines value accessor method for simple single field name' do
206
+ f = Norikra::Field.new('foo', 'string')
207
+
208
+ f.define_value_accessor('foo', false)
209
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2', 'baz' => 'value3'})).to eql('value1')
210
+ end
211
+
212
+ it 'defines chain value accessor for 2-depth hash access chain' do
213
+ f = Norikra::Field.new('foo', 'hash')
214
+ f.define_value_accessor('foo.bar', true)
215
+ expect(f.value({'foo' => {'bar' => 'value1'}, 'bar' => 'value2'})).to eql('value1')
216
+ expect(f.value({'foo' => ['value1'], 'bar' => 'value2'})).to be_nil
217
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2'})).to be_nil
218
+ end
219
+
220
+ it 'defines chain value accessor for 2-depth array access chain' do
221
+ f = Norikra::Field.new('foo', 'array')
222
+ f.define_value_accessor('foo.0', true)
223
+ expect(f.value({'foo' => {'bar' => 'value1'}, 'bar' => 'value2'})).to be_nil
224
+ expect(f.value({'foo' => ['value1'], 'bar' => 'value2'})).to eql('value1')
225
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2'})).to be_nil
226
+ end
227
+
228
+ it 'defines chain value accessor for 2-depth array access chain' do
229
+ f = Norikra::Field.new('foo', 'array')
230
+ f.define_value_accessor('foo.$0', true)
231
+ expect(f.value({'foo' => {0 => 'value1'}, 'bar' => 'value2'})).to eql('value1')
232
+ expect(f.value({'foo' => {'bar' => 'value1'}, 'bar' => 'value2'})).to be_nil
233
+ expect(f.value({'foo' => ['value1'], 'bar' => 'value2'})).to eql('value1')
234
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2'})).to be_nil
235
+ end
236
+
237
+ it 'defines chain value accessor for 2-depth hash access chain, with numeric string' do
238
+ f = Norikra::Field.new('foo', 'hash')
239
+ f.define_value_accessor('foo.$$0', true)
240
+ expect(f.value({'foo' => {0 => 'value1'}, 'bar' => 'value2'})).to be_nil
241
+ expect(f.value({'foo' => {'0' => 'value1'}, 'bar' => 'value2'})).to eql('value1')
242
+ expect(f.value({'foo' => ['value1'], 'bar' => 'value2'})).to be_nil
243
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2'})).to be_nil
244
+ end
245
+
246
+ it 'defines chain value accessor for 2-depth access chain, with integer key' do
247
+ f = Norikra::Field.new('foo', 'hash')
248
+ f.define_value_accessor('foo.0', true)
249
+ expect(f.value({'foo' => {0 => 'value1'}, 'bar' => 'value2'})).to eql('value1')
250
+ expect(f.value({'foo' => {'0' => 'value1'}, 'bar' => 'value2'})).to eql('value1')
251
+ expect(f.value({'foo' => ['value1'], 'bar' => 'value2'})).to eql('value1')
252
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2'})).to be_nil
253
+ end
254
+
255
+ it 'defines chain value accessor for 2-depth chain with dots' do
256
+ f = Norikra::Field.new('foo', 'hash')
257
+ f.define_value_accessor('foo..data', true)
258
+ expect(f.value({'foo' => {'.data' => 'value1'}, 'bar' => 'value2'})).to eql('value1')
259
+ expect(f.value({'foo' => ['value1'], 'bar' => 'value2'})).to be_nil
260
+ expect(f.value({'foo' => 'value1', 'bar' => 'value2'})).to be_nil
261
+ end
262
+
263
+ it 'defines chain value accessor for N-depth hash and array' do
264
+ f = Norikra::Field.new('foo', 'hash')
265
+ f.define_value_accessor('foo.bar.$0.baz', true)
266
+ expect(f.value({'foo' => {'bar' => [{'baz' => 'value1'}, {'baz' => 'value2'}]}})).to eql('value1')
267
+ f.define_value_accessor('foo.bar.1.baz', true)
268
+ expect(f.value({'foo' => {'bar' => [{'baz' => 'value1'}, {'baz' => 'value2'}]}})).to eql('value2')
269
+ end
270
+ end
142
271
  end
@@ -1,33 +1,11 @@
1
1
  require_relative './spec_helper'
2
2
 
3
- require 'norikra/typedef'
3
+ require 'norikra/fieldset'
4
4
 
5
5
  require 'json'
6
6
  require 'digest'
7
7
 
8
8
  describe Norikra::FieldSet do
9
- describe '.simple_guess' do
10
- it 'can guess field definitions with class of values' do
11
- t = Norikra::FieldSet.simple_guess({'key1' => true, 'key2' => false, 'key3' => 10, 'key4' => 3.1415, 'key5' => 'foobar'})
12
- r = t.definition
13
- expect(r['key1']).to eql('boolean')
14
- expect(r['key2']).to eql('boolean')
15
- expect(r['key3']).to eql('long')
16
- expect(r['key4']).to eql('double')
17
- expect(r['key5']).to eql('string')
18
- end
19
-
20
- it 'does not guess with content of string values' do
21
- t = Norikra::FieldSet.simple_guess({'key1' => 'TRUE', 'key2' => 'false', 'key3' => "10", 'key4' => '3.1415', 'key5' => {:a => 1}})
22
- r = t.definition
23
- expect(r['key1']).to eql('string')
24
- expect(r['key2']).to eql('string')
25
- expect(r['key3']).to eql('string')
26
- expect(r['key4']).to eql('string')
27
- expect(r['key5']).to eql('string')
28
- end
29
- end
30
-
31
9
  describe 'can be initialized with both of Hash parameter and String' do
32
10
  it 'accepts String as type' do
33
11
  set = Norikra::FieldSet.new({'x' => 'string', 'y' => 'long'})
@@ -71,6 +49,40 @@ describe Norikra::FieldSet do
71
49
  end
72
50
  end
73
51
 
52
+ describe '.leaves' do
53
+ it 'returns field access chains to all keys of 1-depth Hash container' do
54
+ leaves = Norikra::FieldSet.leaves({'field1' => 1, 'field2' => 2})
55
+ expect(leaves.size).to eql(2)
56
+ expect(leaves).to eql([['field1', 1], ['field2', 2]])
57
+ end
58
+
59
+ it 'returns field access chains to all indexes of 1-depth Array container' do
60
+ leaves = Norikra::FieldSet.leaves([1, 2, 3])
61
+ expect(leaves.size).to eql(3)
62
+ expect(leaves).to eql([[0, 1], [1, 2], [2, 3]])
63
+ end
64
+
65
+ it 'returns field access chains of 2-depth array' do
66
+ leaves = Norikra::FieldSet.leaves([[0, 1, 2], 3, 4])
67
+ expect(leaves.size).to eql(5)
68
+ expect(leaves[0]).to eql([0, 0, 0])
69
+ expect(leaves[1]).to eql([0, 1, 1])
70
+ expect(leaves[2]).to eql([0, 2, 2])
71
+ expect(leaves[3]).to eql([1, 3])
72
+ expect(leaves[4]).to eql([2, 4])
73
+ end
74
+
75
+ it 'returns field access chains of deep containers' do
76
+ leaves = Norikra::FieldSet.leaves({'f1' => [{'fz1' => 1, 'fz2' => {'fz3' => 2, 'fz4' => 3}}, 4], 'f2' => 5})
77
+ expect(leaves.size).to eql(5)
78
+ expect(leaves[0]).to eql(['f1', 0, 'fz1', 1])
79
+ expect(leaves[1]).to eql(['f1', 0, 'fz2', 'fz3', 2])
80
+ expect(leaves[2]).to eql(['f1', 0, 'fz2', 'fz4', 3])
81
+ expect(leaves[3]).to eql(['f1', 1, 4])
82
+ expect(leaves[4]).to eql(['f2', 5])
83
+ end
84
+ end
85
+
74
86
  describe '.field_names_key' do
75
87
  it 'returns comma-separated sorted field names of argument hash' do
76
88
  expect(Norikra::FieldSet.field_names_key({'x1'=>1,'y3'=>2,'xx'=>3,'xx1'=>4,'a'=>5})).to eql('a,x1,xx,xx1,y3')
@@ -79,6 +91,32 @@ describe Norikra::FieldSet do
79
91
  it 'returns comma-separated sorted field names of argument hash AND non-optional fields of 2nd argument fieldset instance' do
80
92
  expect(Norikra::FieldSet.field_names_key({'x1'=>1,'y3'=>2,'xx'=>3,'xx1'=>4}, set)).to eql('a,x,x1,xx,xx1,y,y3')
81
93
  end
94
+
95
+ it 'returns only fields with defined previously in strict-mode' do
96
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'xx'=>3,'xx1'=>4}, set, true)).to eql('a,x,y')
97
+ end
98
+
99
+ it 'returns fields also in additional_fields in strict-mode and additional_fields' do
100
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'xx'=>3,'xx1'=>4,'xx2'=>5,'yy'=>6,'yy1'=>7}, set, true, ['xx2','yy1'])).to eql('a,x,xx2,y,yy1')
101
+ end
102
+
103
+ it 'returns result w/o chained field accesses not reserved (also in non-strict mode)' do
104
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'z'=>{'x1'=>1,'x2'=>2}}, set, true, [])).to eql('a,x,y')
105
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'z'=>{'x1'=>1,'x2'=>2}}, set, false, [])).to eql('a,x,y')
106
+ end
107
+
108
+ it 'returns result w/ reserved chained field accesses' do
109
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'z'=>{'x1'=>1,'x2'=>2}}, set, false, ['z.x2'])).to eql('a,x,y,z.x2')
110
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'z'=>{'x1'=>1,'x2'=>2}}, set, true, ['z.x1'])).to eql('a,x,y,z.x1')
111
+ end
112
+
113
+ it 'returns result w/ newly founded fields in non-strict mode, only for non-chained field accesses' do
114
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'z'=>{'x1'=>1,'x2'=>2},'p'=>true}, set, false, [])).to eql('a,p,x,y')
115
+ end
116
+
117
+ it 'returns result w/ regulared names for chained field accesses' do
118
+ expect(Norikra::FieldSet.field_names_key({'x'=>1,'y'=>2,'z'=>['a','b','c']}, set, false, ['z.$0'])).to eql('a,x,y,z.$0')
119
+ end
82
120
  end
83
121
 
84
122
  describe '#field_names_key' do
@@ -208,5 +246,36 @@ describe Norikra::FieldSet do
208
246
  expect(x.event_type_name).to eql(internal)
209
247
  end
210
248
  end
249
+
250
+ describe '#format' do
251
+ it 'returns hash value with formatted fields as defined' do
252
+ t = Norikra::FieldSet.new({'a' => 'string', 'b' => 'long', 'c' => 'boolean', 'd' => 'double'})
253
+
254
+ d = t.format({'a'=>'hoge','b'=>'2000','c'=>'true','d'=>'3.14'})
255
+ expect(d['a']).to be_instance_of(String)
256
+ expect(d['a']).to eql('hoge')
257
+ expect(d['b']).to be_instance_of(Fixnum)
258
+ expect(d['b']).to eql(2000)
259
+ expect(d['c']).to be_instance_of(TrueClass)
260
+ expect(d['c']).to eql(true)
261
+ expect(d['d']).to be_instance_of(Float)
262
+ expect(d['d']).to eql(3.14)
263
+ end
264
+
265
+ it 'returns data with keys encoded for chained field accesses' do
266
+ t = Norikra::FieldSet.new({'a' => 'string', 'b' => 'long', 'e.$0' => 'string', 'f.foo.$$0' => 'string'})
267
+
268
+ d = t.format({'a'=>'hoge','b'=>'2000','c'=>'true','d'=>'3.14','e'=>['moris','tago'],'f'=>{'foo'=>{'0'=>'zero','1'=>'one'},'bar'=>{'0'=>'ZERO','1'=>'ONE'}}})
269
+ expect(d.size).to eql(4)
270
+ expect(d['a']).to be_instance_of(String)
271
+ expect(d['a']).to eql('hoge')
272
+ expect(d['b']).to be_instance_of(Fixnum)
273
+ expect(d['b']).to eql(2000)
274
+ expect(d['e$$0']).to be_instance_of(String)
275
+ expect(d['e$$0']).to eql('moris')
276
+ expect(d['f$foo$$$0']).to be_instance_of(String)
277
+ expect(d['f$foo$$$0']).to eql('zero')
278
+ end
279
+ end
211
280
  end
212
281
  end
data/spec/query_spec.rb CHANGED
@@ -2,6 +2,8 @@ require_relative './spec_helper'
2
2
 
3
3
  require 'norikra/query'
4
4
 
5
+ include Norikra::SpecHelper
6
+
5
7
  describe Norikra::Query do
6
8
  context 'when instanciate' do
7
9
  describe '#initialize' do
@@ -106,6 +108,40 @@ describe Norikra::Query do
106
108
  expect(q.fields(nil)).to eql([])
107
109
  end
108
110
  end
111
+
112
+ context 'with simple query including container field accesses' do
113
+ it 'returns query instances collectly parsed' do
114
+ expression = 'SELECT count(*) AS cnt FROM TestTable.win:time_batch(10 sec) WHERE params.path="/" AND size > 100 and opts.$0 > 0'
115
+ q = Norikra::Query.new(
116
+ :name => 'TestTable query7', :expression => expression
117
+ )
118
+ expect(q.name).to eql('TestTable query7')
119
+ expect(q.group).to be_nil
120
+ expect(q.expression).to eql(expression)
121
+ expect(q.targets).to eql(['TestTable'])
122
+
123
+ expect(q.fields).to eql(['params.path', 'size', 'opts.$0'].sort)
124
+ expect(q.fields('TestTable')).to eql(['params.path', 'size', 'opts.$0'].sort)
125
+ expect(q.fields(nil)).to eql([])
126
+ end
127
+ end
128
+
129
+ context 'with simple query including deep depth container field accesses and function calls' do
130
+ it 'returns query instances collectly parsed' do
131
+ expression = 'SELECT count(*) AS cnt FROM TestTable.win:time_batch(10 sec) WHERE params.$$path.$1="/" AND size.$0.bytes > 100 and opts.num.$0.length() > 0'
132
+ q = Norikra::Query.new(
133
+ :name => 'TestTable query8', :expression => expression
134
+ )
135
+ expect(q.name).to eql('TestTable query8')
136
+ expect(q.group).to be_nil
137
+ expect(q.expression).to eql(expression)
138
+ expect(q.targets).to eql(['TestTable'])
139
+
140
+ expect(q.fields).to eql(['params.$$path.$1', 'size.$0.bytes', 'opts.num.$0'].sort)
141
+ expect(q.fields('TestTable')).to eql(['params.$$path.$1', 'size.$0.bytes', 'opts.num.$0'].sort)
142
+ expect(q.fields(nil)).to eql([])
143
+ end
144
+ end
109
145
  end
110
146
 
111
147
  describe '#dup' do
@@ -132,39 +168,178 @@ describe Norikra::Query do
132
168
  end
133
169
  end
134
170
 
135
- describe '#dup_with_stream_name' do
171
+ describe '.rewrite_event_field_name' do
172
+ context 'without any container field access' do
173
+ expression = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and size > 100 and (param.length()) > 0'
174
+ it 'returns same query with original' do
175
+ with_engine do
176
+ model = administrator.compileEPL(expression)
177
+ expect(Norikra::Query.rewrite_event_field_name(model, {'TestTable' => 'T1'}).toEPL).to eql(expression)
178
+ end
179
+ end
180
+ end
181
+
182
+ context 'with container field access' do
183
+ expression = 'select max(result.$0.size) as cnt from TestTable.win:time_batch(10 seconds) where req.path = "/" and result.$0.size > 100 and (req.param.length()) > 0'
184
+ expected = 'select max(result$$0$size) as cnt from TestTable.win:time_batch(10 seconds) where req$path = "/" and result$$0$size > 100 and (req$param.length()) > 0'
185
+ it 'returns query with encoded container fields' do
186
+ with_engine do
187
+ model = administrator.compileEPL(expression)
188
+ expect(Norikra::Query.rewrite_event_field_name(model, {'TestTable' => 'T1'}).toEPL).to eql(expected)
189
+ end
190
+ end
191
+ end
192
+
193
+ context 'with container field access with joins' do
194
+ expression = 'select product, max(sta.param.size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data.$0.$$body.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
195
+ expected = 'select product, max(sta.param$size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data$$0$$$body.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
196
+ it 'returns query with encoded container fields' do
197
+ with_engine do
198
+ model = administrator.compileEPL(expression)
199
+ expect(Norikra::Query.rewrite_event_field_name(model, {'StreamA' => 'S1', 'StreamB' => 'S2'}).toEPL).to eql(expected)
200
+ end
201
+ end
202
+ end
203
+
204
+ context 'without any container field access, but with alias specification, without joins' do
205
+ expression = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and TestTable.size > 100 and (param.length()) > 0'
206
+ expected = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and T1.size > 100 and (param.length()) > 0'
207
+ it 'returns query expression' do
208
+ with_engine do
209
+ model = administrator.compileEPL(expression)
210
+ expect(Norikra::Query.rewrite_event_field_name(model, {'TestTable' => 'T1'}).toEPL).to eql(expected)
211
+ end
212
+ end
213
+ end
214
+
215
+ context 'with subquery in select clause' do
216
+ expression = 'select RfidEvent.zoneId.$0, (select name.x from Zones.std:unique(zoneName) where zoneId = RfidEvent.zoneId.$0) as name from RfidEvent'
217
+ expected = 'select Z2.zoneId$$0, (select name$x from Zones.std:unique(zoneName) where zoneId = Z2.zoneId$$0) as name from RfidEvent'
218
+ it 'returns query model which have replaced stream name, for only targets of fully qualified field name access' do
219
+ with_engine do
220
+ model = administrator.compileEPL(expression)
221
+ expect(Norikra::Query.rewrite_event_field_name(model, {'Zones' => 'Z1', 'RfidEvent' => 'Z2'}).toEPL).to eql(expected)
222
+ end
223
+ end
224
+ end
225
+
226
+ context 'with container field accesses, with targets, aliases and joins' do
227
+ expression = 'select StreamA.product, max(sta.param.size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data.$0.$$body.substr(0, 8)) = StreamB.header.$0 and (Math.abs(StreamA.size.$0.$$abs)) > 3'
228
+ expected = 'select S1.product, max(sta.param$size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data$$0$$$body.substr(0, 8)) = S2.header$$0 and (Math.abs(S1.size$$0$$$abs)) > 3'
229
+ it 'returns query model which have replaced stream name, for only targets of fully qualified field name access' do
230
+ with_engine do
231
+ model = administrator.compileEPL(expression)
232
+ expect(Norikra::Query.rewrite_event_field_name(model, {'StreamA' => 'S1', 'StreamB' => 'S2'}).toEPL).to eql(expected)
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ describe '.rewrite_event_type_name' do
136
239
  context 'with simple query' do
137
- expression = 'SELECT count(*) AS cnt FROM TestTable.win:time_batch(10 sec) WHERE path="/" AND size > 100 and param.length() > 0'
138
- it 'returns duplicated object, with replaced ' do
139
- query = Norikra::Query.new(
140
- :name => 'TestTable query1', :expression => expression
141
- )
142
- expect(query.dup_with_stream_name('hoge').expression).to eql(
143
- 'SELECT count(*) AS cnt FROM hoge.win:time_batch(10 sec) WHERE path="/" AND size > 100 and param.length() > 0'
144
- )
240
+ expression = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and size > 100 and (param.length()) > 0'
241
+
242
+ it 'returns query model which have replaced stream name' do
243
+ with_engine do
244
+ model = administrator.compileEPL(expression)
245
+ expect(Norikra::Query.rewrite_event_type_name(model, {'TestTable' => 'hoge'}).toEPL).to eql(expression.sub('TestTable','hoge'))
246
+ end
247
+ end
248
+ end
249
+ context 'with subquery in select clause' do
250
+ expression = 'select zoneId.$0, (select name.x from Zones.std:unique(zoneName) where zoneId = RfidEvent.zoneId.$0) as name from RfidEvent'
251
+ expected = 'select zoneId.$0, (select name.x from Z1.std:unique(zoneName) where zoneId = RfidEvent.zoneId.$0) as name from Z2'
252
+ it 'returns query model which have replaced stream name, for only From clause' do
253
+ with_engine do
254
+ model = administrator.compileEPL(expression)
255
+ expect(Norikra::Query.rewrite_event_type_name(model, {'Zones' => 'Z1', 'RfidEvent' => 'Z2'}).toEPL).to eql(expected)
256
+ end
145
257
  end
146
258
  end
259
+ context 'with subquery in from clause' do
260
+ expression = "select * from BarData(ticker='MSFT', sub(closePrice, (select movAgv from SMA20Stream(ticker='MSFT').std:lastevent())) > 0)"
261
+ expected = 'select * from B1(ticker = "MSFT" and (sub(closePrice, (select movAgv from B2(ticker = "MSFT").std:lastevent()))) > 0)'
262
+ it 'returns query model which have replaced stream name' do
263
+ with_engine do
264
+ model = administrator.compileEPL(expression)
265
+ expect(Norikra::Query.rewrite_event_type_name(model, {'BarData' => 'B1', 'SMA20Stream' => 'B2'}).toEPL).to eql(expected)
266
+ end
267
+ end
268
+ end
269
+ context 'with joins' do
270
+ expression = 'select product, max(sta.size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
271
+ it 'returns query model which have replaced stream name' do
272
+ with_engine do
273
+ model = administrator.compileEPL(expression)
274
+ mapping = {'StreamA' => 'sa', 'StreamB' => 'sb'}
275
+ expect(Norikra::Query.rewrite_event_type_name(model, mapping).toEPL).to eql(expression.sub('StreamA','sa').sub('StreamB','sb'))
276
+ end
277
+ end
278
+ end
279
+ end
147
280
 
148
- context 'with query with newlines' do
149
- expression = <<EOQ
150
- SELECT
151
- count(*) AS cnt
152
- FROM TestTable.win:time_batch(10 sec)
153
- WHERE path="/" AND size > 100
154
- AND param.length() > 0
155
- EOQ
156
- expected_query = <<EOQ
157
- SELECT
158
- count(*) AS cnt
159
- FROM hoge.win:time_batch(10 sec)
160
- WHERE path="/" AND size > 100
161
- AND param.length() > 0
162
- EOQ
163
- it 'returns duplicated object, with replaced ' do
164
- query = Norikra::Query.new(
165
- :name => 'TestTable query1', :expression => expression
166
- )
167
- expect(query.dup_with_stream_name('hoge').expression).to eql(expected_query)
281
+ describe '.rewrite_query' do
282
+ it 'rewrites all of targets and container-field-accesses' do
283
+ with_engine do
284
+ e1 = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and size > 100 and (param.length()) > 0'
285
+ x1 = 'select count(*) as cnt from T1.win:time_batch(10 seconds) where path = "/" and size > 100 and (param.length()) > 0'
286
+ model = administrator.compileEPL(e1)
287
+ mapping = {'TestTable' => 'T1'}
288
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x1)
289
+
290
+ e2 = 'select max(result.$0.size) as cnt from TestTable.win:time_batch(10 seconds) where req.path = "/" and result.$0.size > 100 and (req.param.length()) > 0'
291
+ x2 = 'select max(result$$0$size) as cnt from T1.win:time_batch(10 seconds) where req$path = "/" and result$$0$size > 100 and (req$param.length()) > 0'
292
+ model = administrator.compileEPL(e2)
293
+ mapping = {'TestTable' => 'T1'}
294
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x2)
295
+
296
+ e3 = 'select product, max(sta.param.size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data.$0.$$body.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
297
+ x3 = 'select product, max(sta.param$size) as maxsize from S1.win:keepall() as sta, S2(size > 10).win:time(20 seconds) as stb where (sta.data$$0$$$body.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
298
+ model = administrator.compileEPL(e3)
299
+ mapping = {'StreamA' => 'S1', 'StreamB' => 'S2'}
300
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x3)
301
+
302
+ e4 = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and TestTable.size > 100 and (param.length()) > 0'
303
+ x4 = 'select count(*) as cnt from T1.win:time_batch(10 seconds) where path = "/" and T1.size > 100 and (param.length()) > 0'
304
+ model = administrator.compileEPL(e4)
305
+ mapping = {'TestTable' => 'T1'}
306
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x4)
307
+
308
+ e5 = 'select RfidEvent.zoneId.$0, (select name.x from Zones.std:unique(zoneName) where zoneId = RfidEvent.zoneId.$0) as name from RfidEvent'
309
+ x5 = 'select R1.zoneId$$0, (select name$x from Z1.std:unique(zoneName) where zoneId = R1.zoneId$$0) as name from R1'
310
+ model = administrator.compileEPL(e5)
311
+ mapping = {'RfidEvent' => 'R1', 'Zones' => 'Z1'}
312
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x5)
313
+
314
+ e6 = 'select StreamA.product, max(sta.param.size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data.$0.$$body.substr(0, 8)) = StreamB.header.$0 and (Math.abs(StreamA.size.$0.$$abs)) > 3'
315
+ x6 = 'select S1.product, max(sta.param$size) as maxsize from S1.win:keepall() as sta, S2(size > 10).win:time(20 seconds) as stb where (sta.data$$0$$$body.substr(0, 8)) = S2.header$$0 and (Math.abs(S1.size$$0$$$abs)) > 3'
316
+ model = administrator.compileEPL(e6)
317
+ mapping = {'StreamA' => 'S1', 'StreamB' => 'S2'}
318
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x6)
319
+
320
+ e7 = 'select count(*) as cnt from TestTable.win:time_batch(10 seconds) where path = "/" and size > 100 and (param.length()) > 0'
321
+ x7 = 'select count(*) as cnt from T1.win:time_batch(10 seconds) where path = "/" and size > 100 and (param.length()) > 0'
322
+ model = administrator.compileEPL(e7)
323
+ mapping = {'TestTable' => 'T1'}
324
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x7)
325
+
326
+ e8 = 'select RfidEvent.zoneId.$0, (select name.x from Zones.std:unique(zoneName) where zoneId = RfidEvent.zoneId.$0) as name from RfidEvent'
327
+ x8 = 'select R1.zoneId$$0, (select name$x from Z1.std:unique(zoneName) where zoneId = R1.zoneId$$0) as name from R1'
328
+ model = administrator.compileEPL(e8)
329
+ mapping = {'Zones' => 'Z1', 'RfidEvent' => 'R1'}
330
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x8)
331
+
332
+ e9 = 'select * from BarData(ticker = "MSFT" and (sub(closePrice, (select movAgv from SMA20Stream(ticker = "MSFT").std:lastevent())) > 0))'
333
+ x9 = 'select * from B1(ticker = "MSFT" and (sub(closePrice, (select movAgv from S1(ticker = "MSFT").std:lastevent()))) > 0)'
334
+ model = administrator.compileEPL(e9)
335
+ mapping = {'BarData' => 'B1', 'SMA20Stream' => 'S1'}
336
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x9)
337
+
338
+ e10 = 'select product, max(sta.size) as maxsize from StreamA.win:keepall() as sta, StreamB(size > 10).win:time(20 seconds) as stb where (sta.data.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
339
+ x10 = 'select product, max(sta.size) as maxsize from S1.win:keepall() as sta, S2(size > 10).win:time(20 seconds) as stb where (sta.data.substr(0, 8)) = stb.header and (Math.abs(sta.size)) > 3'
340
+ model = administrator.compileEPL(e10)
341
+ mapping = {'StreamA' => 'S1', 'StreamB' => 'S2'}
342
+ expect(Norikra::Query.rewrite_query(model, mapping).toEPL).to eql(x10)
168
343
  end
169
344
  end
170
345
  end