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.
- data/lib/norikra/engine.rb +101 -80
- data/lib/norikra/field.rb +204 -0
- data/lib/norikra/fieldset.rb +167 -0
- data/lib/norikra/logger.rb +37 -22
- data/lib/norikra/query.rb +152 -14
- data/lib/norikra/query/ast.rb +65 -22
- data/lib/norikra/rpc/handler.rb +10 -3
- data/lib/norikra/server.rb +8 -2
- data/lib/norikra/target.rb +24 -0
- data/lib/norikra/typedef.rb +117 -234
- data/lib/norikra/typedef_manager.rb +22 -16
- data/lib/norikra/version.rb +1 -1
- data/norikra.gemspec +1 -1
- data/script/spec_server_pry +31 -0
- data/spec/field_spec.rb +131 -2
- data/spec/fieldset_spec.rb +92 -23
- data/spec/query_spec.rb +204 -29
- data/spec/spec_helper.rb +39 -3
- data/spec/target_spec.rb +18 -0
- data/spec/typedef_manager_spec.rb +35 -12
- data/spec/typedef_spec.rb +235 -24
- metadata +6 -4
@@ -13,7 +13,8 @@ module Norikra
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def field_list(target)
|
16
|
-
@typedefs[target].
|
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 =
|
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(
|
137
|
-
@typedefs[
|
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
|
145
|
-
@typedefs.
|
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
|
data/lib/norikra/version.rb
CHANGED
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.
|
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"
|
data/script/spec_server_pry
CHANGED
@@ -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/
|
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
|
data/spec/fieldset_spec.rb
CHANGED
@@ -1,33 +1,11 @@
|
|
1
1
|
require_relative './spec_helper'
|
2
2
|
|
3
|
-
require 'norikra/
|
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 '
|
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 = '
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
expect(
|
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
|