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