norikra 0.0.13-java → 0.0.14-java

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