norikra 1.1.2-java → 1.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Changes.md +4 -0
- data/Gemfile +4 -0
- data/README.md +3 -6
- data/lib/norikra/cli.rb +54 -54
- data/lib/norikra/engine.rb +91 -44
- data/lib/norikra/field.rb +12 -7
- data/lib/norikra/fieldset.rb +26 -13
- data/lib/norikra/listener.rb +192 -61
- data/lib/norikra/logger.rb +34 -10
- data/lib/norikra/output_pool.rb +1 -1
- data/lib/norikra/query/ast.rb +240 -20
- data/lib/norikra/query.rb +103 -46
- data/lib/norikra/rpc/handler.rb +3 -3
- data/lib/norikra/rpc/http.rb +1 -1
- data/lib/norikra/server.rb +34 -28
- data/lib/norikra/stats.rb +3 -3
- data/lib/norikra/target.rb +1 -1
- data/lib/norikra/typedef.rb +22 -17
- data/lib/norikra/typedef_manager.rb +9 -6
- data/lib/norikra/udf.rb +6 -2
- data/lib/norikra/version.rb +1 -1
- data/lib/norikra/webui/api.rb +3 -3
- data/lib/norikra/webui/handler.rb +6 -6
- data/norikra.gemspec +0 -1
- data/script/{spec_server_pry → pry} +0 -24
- data/spec/field_spec.rb +14 -0
- data/spec/fieldset_spec.rb +111 -0
- data/spec/listener_spec.rb +64 -26
- data/spec/query_spec.rb +171 -25
- data/spec/spec_helper.rb +0 -46
- data/spec/typedef_manager_spec.rb +15 -9
- data/spec/typedef_spec.rb +11 -11
- metadata +3 -19
- data/lib/norikra/rpc/error.rb +0 -0
- data/lib/norikra/rubyudf.rb +0 -49
data/lib/norikra/query/ast.rb
CHANGED
@@ -717,6 +717,125 @@ module Norikra
|
|
717
717
|
# ")"]]]]]]]]],
|
718
718
|
# "<EOF>"]
|
719
719
|
|
720
|
+
#### SELECT a,NULLABLE(b),COUNT(DISTINCT NULLABLE(c)) FROM t GROUP BY a,NULLABLE(b)
|
721
|
+
|
722
|
+
# ["startEPLExpressionRule",
|
723
|
+
# ["eplExpression",
|
724
|
+
# ["selectExpr",
|
725
|
+
# "SELECT",
|
726
|
+
# ["selectClause",
|
727
|
+
# ["selectionList",
|
728
|
+
# ["selectionListElement",
|
729
|
+
# ["selectionListElementExpr",
|
730
|
+
# ["expression",
|
731
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
732
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
733
|
+
# ["multiplyExpression",["unaryExpression",
|
734
|
+
# ["eventPropertyOrLibFunction",
|
735
|
+
# ["eventProperty",
|
736
|
+
# ["eventPropertyAtomic", ["eventPropertyIdent", ["keywordAllowedIdent", "a"]]]]]]]]]]]]]]]]]]],
|
737
|
+
# ",",
|
738
|
+
# ["selectionListElement",
|
739
|
+
# ["selectionListElementExpr",
|
740
|
+
# ["expression",
|
741
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
742
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
743
|
+
# ["multiplyExpression",["unaryExpression",
|
744
|
+
# ["eventPropertyOrLibFunction",
|
745
|
+
# ["libFunction",
|
746
|
+
# ["libFunctionWithClass",
|
747
|
+
# ["funcIdentTop", ["escapableIdent", "NULLABLE"]],
|
748
|
+
# "(",
|
749
|
+
# ["libFunctionArgs",
|
750
|
+
# ["libFunctionArgItem",
|
751
|
+
# ["expressionWithTime",
|
752
|
+
# ["expressionQualifyable",
|
753
|
+
# ["expression",
|
754
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",
|
755
|
+
# ["negatedExpression",["evalEqualsExpression",["evalRelationalExpression",
|
756
|
+
# ["concatenationExpr",["additiveExpression",["multiplyExpression",["unaryExpression",
|
757
|
+
# ["eventPropertyOrLibFunction",
|
758
|
+
# ["eventProperty",
|
759
|
+
# ["eventPropertyAtomic",
|
760
|
+
# ["eventPropertyIdent", ["keywordAllowedIdent", "b"]]]]]]]]]]]]]]]]]]]]],
|
761
|
+
# ")"]]]]]]]]]]]]]]]]],
|
762
|
+
# ",",
|
763
|
+
# ["selectionListElement",
|
764
|
+
# ["selectionListElementExpr",
|
765
|
+
# ["expression",
|
766
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
767
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
768
|
+
# ["multiplyExpression",["unaryExpression",
|
769
|
+
# ["builtinFunc",
|
770
|
+
# "COUNT",
|
771
|
+
# "(",
|
772
|
+
# "DISTINCT",
|
773
|
+
# ["expression",
|
774
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",
|
775
|
+
# ["negatedExpression",["evalEqualsExpression",["evalRelationalExpression",
|
776
|
+
# ["concatenationExpr",["additiveExpression",["multiplyExpression",["unaryExpression",
|
777
|
+
# ["eventPropertyOrLibFunction",
|
778
|
+
# ["libFunction",
|
779
|
+
# ["libFunctionWithClass",
|
780
|
+
# ["funcIdentTop", ["escapableIdent", "NULLABLE"]],
|
781
|
+
# "(",
|
782
|
+
# ["libFunctionArgs",
|
783
|
+
# ["libFunctionArgItem",
|
784
|
+
# ["expressionWithTime",
|
785
|
+
# ["expressionQualifyable",
|
786
|
+
# ["expression",
|
787
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",
|
788
|
+
# ["negatedExpression",["evalEqualsExpression",["evalRelationalExpression",
|
789
|
+
# ["concatenationExpr",["additiveExpression",["multiplyExpression",
|
790
|
+
# ["unaryExpression",
|
791
|
+
# ["eventPropertyOrLibFunction",
|
792
|
+
# ["eventProperty",
|
793
|
+
# ["eventPropertyAtomic",
|
794
|
+
# ["eventPropertyIdent",
|
795
|
+
# ["keywordAllowedIdent", "c"]]]]]]]]]]]]]]]]]]]]],
|
796
|
+
# ")"]]]]]]]]]]]]]]],
|
797
|
+
# ")"]]]]]]]]]]]]]]]]],
|
798
|
+
# "FROM",
|
799
|
+
# ["fromClause",
|
800
|
+
# ["streamExpression", ["eventFilterExpression", ["classIdentifier", ["escapableStr", "t"]]]],
|
801
|
+
# "regularJoin"],
|
802
|
+
# "GROUP",
|
803
|
+
# "BY",
|
804
|
+
# ["groupByListExpr",
|
805
|
+
# ["groupByListChoice",
|
806
|
+
# ["expression",
|
807
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
808
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
809
|
+
# ["multiplyExpression",["unaryExpression",
|
810
|
+
# ["eventPropertyOrLibFunction",
|
811
|
+
# ["eventProperty",
|
812
|
+
# ["eventPropertyAtomic", ["eventPropertyIdent", ["keywordAllowedIdent", "a"]]]]]]]]]]]]]]]]]],
|
813
|
+
# ",",
|
814
|
+
# ["groupByListChoice",
|
815
|
+
# ["expression",
|
816
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
817
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
818
|
+
# ["multiplyExpression",["unaryExpression",
|
819
|
+
# ["eventPropertyOrLibFunction",
|
820
|
+
# ["libFunction",
|
821
|
+
# ["libFunctionWithClass",
|
822
|
+
# ["funcIdentTop", ["escapableIdent", "NULLABLE"]],
|
823
|
+
# "(",
|
824
|
+
# ["libFunctionArgs",
|
825
|
+
# ["libFunctionArgItem",
|
826
|
+
# ["expressionWithTime",
|
827
|
+
# ["expressionQualifyable",
|
828
|
+
# ["expression",
|
829
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",
|
830
|
+
# ["negatedExpression",["evalEqualsExpression",["evalRelationalExpression",
|
831
|
+
# ["concatenationExpr",["additiveExpression",["multiplyExpression",["unaryExpression",
|
832
|
+
# ["eventPropertyOrLibFunction",
|
833
|
+
# ["eventProperty",
|
834
|
+
# ["eventPropertyAtomic",
|
835
|
+
# ["eventPropertyIdent", ["keywordAllowedIdent", "b"]]]]]]]]]]]]]]]]]]]]],
|
836
|
+
# ")"]]]]]]]]]]]]]]]]]]],
|
837
|
+
# "<EOF>"]
|
838
|
+
|
720
839
|
def astnode(tree)
|
721
840
|
# com.espertech.esper.epl.generated.EsperEPL2GrammarParser.ruleNames[ast.ruleIndex] #=> "startEPLExpressionRule"
|
722
841
|
# com.espertech.esper.epl.generated.EsperEPL2GrammarParser.ruleNames[ast.getChild(0).ruleIndex] #=> "eplExpression"
|
@@ -745,9 +864,11 @@ module Norikra
|
|
745
864
|
end
|
746
865
|
|
747
866
|
cls = case name
|
867
|
+
when 'expression' then ASTExpression
|
748
868
|
when 'eventProperty' then ASTEventPropNode
|
749
869
|
when 'selectionListElementExpr' then ASTSelectionElementNode
|
750
870
|
when 'libFunction' then ASTLibFunctionNode
|
871
|
+
when 'libFunctionArgItem' then ASTLibFunctionArgItemNode
|
751
872
|
when 'streamExpression', 'subSelectFilterExpr' then ASTStreamNode
|
752
873
|
when 'patternFilterExpression' then ASTPatternNode
|
753
874
|
when 'subQueryExpr' then ASTSubSelectNode
|
@@ -769,6 +890,14 @@ module Norikra
|
|
769
890
|
@tree = tree
|
770
891
|
end
|
771
892
|
|
893
|
+
def has_a?(name)
|
894
|
+
@children.size == 1 && (@children.first.name == name || @children.first.nodetype?(name))
|
895
|
+
end
|
896
|
+
|
897
|
+
def chain(*nodes)
|
898
|
+
nodes.reduce(self){|n, next_node| n && n.has_a?(next_node) ? n.child : nil }
|
899
|
+
end
|
900
|
+
|
772
901
|
def nodetype?(*sym)
|
773
902
|
false
|
774
903
|
end
|
@@ -813,6 +942,28 @@ module Norikra
|
|
813
942
|
end
|
814
943
|
end
|
815
944
|
|
945
|
+
class ASTExpression < ASTNode
|
946
|
+
# ["expression",
|
947
|
+
# ["caseExpression", ["evalOrExpression", ["evalAndExpression", ["bitWiseExpression", ["negatedExpression",
|
948
|
+
# ["evalEqualsExpression", ["evalRelationalExpression", ["concatenationExpr", ["additiveExpression",
|
949
|
+
# ["multiplyExpression", ["unaryExpression", ["eventPropertyOrLibFunction",
|
950
|
+
# ["eventProperty",
|
951
|
+
# ["eventPropertyAtomic", ["eventPropertyIdent", ["keywordAllowedIdent", "s"]]]]]]]]]]]]]]]]]]]
|
952
|
+
def nodetype?(*sym)
|
953
|
+
sym.include?(:expression)
|
954
|
+
end
|
955
|
+
|
956
|
+
SIMPLE_PROPERTY_REFERENCE_NODES = [
|
957
|
+
"caseExpression", "evalOrExpression", "evalAndExpression", "bitWiseExpression", "negatedExpression",
|
958
|
+
"evalEqualsExpression", "evalRelationalExpression", "concatenationExpr", "additiveExpression",
|
959
|
+
"multiplyExpression", "unaryExpression", "eventPropertyOrLibFunction", "eventProperty"
|
960
|
+
]
|
961
|
+
def propertyReference?
|
962
|
+
end_node = self.chain(*SIMPLE_PROPERTY_REFERENCE_NODES)
|
963
|
+
end_node && end_node.nodetype?(:property)
|
964
|
+
end
|
965
|
+
end
|
966
|
+
|
816
967
|
class ASTEventPropNode < ASTNode # eventProperty
|
817
968
|
### "a"
|
818
969
|
# ["eventProperty", ["eventPropertyAtomic", ["eventPropertyIdent", ["keywordAllowedIdent", "a"]]]
|
@@ -870,13 +1021,13 @@ module Norikra
|
|
870
1021
|
if props.size > 1 # alias.fieldname or container_fieldname.key.$1 or fieldname.method(...)
|
871
1022
|
non_calls = props.select{|p| p.children.size == 1 }.map{|p| p.find('eventPropertyIdent').find('keywordAllowedIdent').child.name }
|
872
1023
|
if known_targets_aliases.include?(leading_name)
|
873
|
-
[ {:
|
1024
|
+
[ {f: non_calls[1..-1].join("."), t: leading_name} ]
|
874
1025
|
else
|
875
|
-
[ {:
|
1026
|
+
[ {f: non_calls.join("."), t: default_target} ]
|
876
1027
|
end
|
877
1028
|
else # fieldname (default target)
|
878
1029
|
# ["eventProperty", ["eventPropertyAtomic", ["eventPropertyIdent", ["keywordAllowedIdent", "a"]]]
|
879
|
-
[ {:
|
1030
|
+
[ {f: leading_name, t: default_target } ]
|
880
1031
|
end
|
881
1032
|
end
|
882
1033
|
end
|
@@ -892,7 +1043,7 @@ module Norikra
|
|
892
1043
|
# ["eventProperty",
|
893
1044
|
# ["eventPropertyAtomic", ["eventPropertyIdent", ["keywordAllowedIdent", "s"]]]]]]]]]]]]]]]]]]]
|
894
1045
|
|
895
|
-
### "count(*) AS cnt"
|
1046
|
+
### "count(*) AS cnt"
|
896
1047
|
# ["selectionListElementExpr",
|
897
1048
|
# ["expression",
|
898
1049
|
# ["caseExpression", ["evalOrExpression", ["evalAndExpression", ["bitWiseExpression", ["negatedExpression",
|
@@ -925,6 +1076,22 @@ module Norikra
|
|
925
1076
|
end
|
926
1077
|
|
927
1078
|
class ASTLibFunctionNode < ASTNode # LIB_FUNCTION
|
1079
|
+
### NULLABLE field!
|
1080
|
+
# ["libFunction",
|
1081
|
+
# ["libFunctionWithClass",
|
1082
|
+
# ["funcIdentTop", ["escapableIdent", "NULLABLE"]],
|
1083
|
+
# "(",
|
1084
|
+
# ["libFunctionArgs",["libFunctionArgItem",["expressionWithTime",["expressionQualifyable",
|
1085
|
+
# ["expression",
|
1086
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
1087
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
1088
|
+
# ["multiplyExpression",["unaryExpression",
|
1089
|
+
# ["eventPropertyOrLibFunction",
|
1090
|
+
# ["eventProperty",
|
1091
|
+
# ["eventPropertyAtomic",
|
1092
|
+
# ["eventPropertyIdent", ["keywordAllowedIdent", "b"]]]]]]]]]]]]]]]]]]]]],
|
1093
|
+
# ")"]]]
|
1094
|
+
|
928
1095
|
### foo is function
|
929
1096
|
# "foo()" => ["libFunction", ["libFunctionWithClass", ["funcIdentTop", ["escapableIdent", "foo"]], "(", ")"]]
|
930
1097
|
|
@@ -948,6 +1115,25 @@ module Norikra
|
|
948
1115
|
# ["libFunctionArgItem", ["expressionWithTime", ["expressionQualifyable", ["expression", EXPRESSION... ]]]]],
|
949
1116
|
# ")"]]
|
950
1117
|
|
1118
|
+
### foo(value)
|
1119
|
+
# ["libFunction",
|
1120
|
+
# ["libFunctionWithClass",
|
1121
|
+
# ["funcIdentTop", ["escapableIdent", "FOO"]],
|
1122
|
+
# "(",
|
1123
|
+
# ["libFunctionArgs",
|
1124
|
+
# ["libFunctionArgItem",
|
1125
|
+
# ["expressionWithTime",
|
1126
|
+
# ["expressionQualifyable",
|
1127
|
+
# ["expression",
|
1128
|
+
# ["caseExpression",["evalOrExpression",["evalAndExpression",["bitWiseExpression",["negatedExpression",
|
1129
|
+
# ["evalEqualsExpression",["evalRelationalExpression",["concatenationExpr",["additiveExpression",
|
1130
|
+
# ["multiplyExpression",["unaryExpression",
|
1131
|
+
# ["eventPropertyOrLibFunction",
|
1132
|
+
# ["eventProperty",
|
1133
|
+
# ["eventPropertyAtomic",
|
1134
|
+
# ["eventPropertyIdent", ["keywordAllowedIdent", "value"]]]]]]]]]]]]]]]]]]]]],
|
1135
|
+
# ")"]]
|
1136
|
+
|
951
1137
|
### foo is property
|
952
1138
|
### "foo.bar()"
|
953
1139
|
# ["libFunction",
|
@@ -1067,33 +1253,67 @@ module Norikra
|
|
1067
1253
|
# "(",
|
1068
1254
|
# ")"]]
|
1069
1255
|
|
1256
|
+
def function_name
|
1257
|
+
f = self.find("funcIdentTop")
|
1258
|
+
if e = f.find("escapableIdent")
|
1259
|
+
e.child.name
|
1260
|
+
else
|
1261
|
+
f.child.name
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
|
1070
1265
|
def nodetype?(*sym)
|
1071
1266
|
sym.include?(:lib) || sym.include?(:libfunc)
|
1072
1267
|
end
|
1073
1268
|
|
1074
1269
|
def fields(default_target=nil, known_targets_aliases=[])
|
1270
|
+
# class identifier is receiver: "IDENT.func()"
|
1075
1271
|
identifier = self.find("classIdentifier")
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1272
|
+
if identifier
|
1273
|
+
if identifier.children.size == 1 && Norikra::Query.imported_java_class?(identifier.find("escapableStr").child.name)
|
1274
|
+
# Java imported class name (ex: 'Math.abs(-1)')
|
1275
|
+
self.listup(:prop).map{|c| c.fields(default_target, known_targets_aliases)}.reduce(&:+) || []
|
1276
|
+
else
|
1277
|
+
parts = identifier.listup('escapableStr').map{|node| node.child.name }
|
1278
|
+
target, fieldname = if parts.size == 1
|
1279
|
+
[ default_target, parts.first ]
|
1280
|
+
elsif known_targets_aliases.include?( parts.first )
|
1281
|
+
[ parts[0], parts[1..-1].join(".") ]
|
1282
|
+
else
|
1283
|
+
[ default_target, parts.join(".") ]
|
1284
|
+
end
|
1285
|
+
children_list = self.listup(:prop).map{|c| c.fields(default_target, known_targets_aliases)}.reduce(&:+) || []
|
1286
|
+
[{f: fieldname, t: target}] + children_list
|
1287
|
+
end
|
1082
1288
|
else
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
[{:f => fieldname, :t => target}] + children_list
|
1289
|
+
if self.function_name.upcase == 'NULLABLE'
|
1290
|
+
props = self.listup(:prop).map{|c| c.fields(default_target, known_targets_aliases)}.reduce(&:+) || []
|
1291
|
+
props.each do |def_item|
|
1292
|
+
def_item[:n] = true # nullable: true
|
1293
|
+
end
|
1294
|
+
props
|
1295
|
+
else
|
1296
|
+
self.listup(:prop).map{|c| c.fields(default_target, known_targets_aliases)}.reduce(&:+) || []
|
1297
|
+
end
|
1093
1298
|
end
|
1094
1299
|
end
|
1095
1300
|
end
|
1096
1301
|
|
1302
|
+
class ASTLibFunctionArgItemNode < ASTNode
|
1303
|
+
# ["libFunctionArgs",
|
1304
|
+
# ["libFunctionArgItem",
|
1305
|
+
# ["expressionWithTime",
|
1306
|
+
# ["expressionQualifyable",
|
1307
|
+
# ["expression", ... ]]]]
|
1308
|
+
def nodetype?(*sym)
|
1309
|
+
sym.include?(:libarg)
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
def expression
|
1313
|
+
self.chain("expressionWithTime", "expressionQualifyable", "expression")
|
1314
|
+
end
|
1315
|
+
end
|
1316
|
+
|
1097
1317
|
class ASTStreamNode < ASTNode # streamExpression, subSelectFilterExpr
|
1098
1318
|
def self.generate(name, children, tree)
|
1099
1319
|
if children.first.name == 'eventFilterExpression'
|
data/lib/norikra/query.rb
CHANGED
@@ -27,6 +27,12 @@ module Norikra
|
|
27
27
|
@aliases = nil
|
28
28
|
@subqueries = nil
|
29
29
|
@fields = nil
|
30
|
+
@nullable_fields = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
internal = ['name', 'group', 'expression', 'statement_name', 'targets', 'aliases', 'fields', 'nullable_fields', 'subqueries', 'fieldsets'].map{|x| "@#{x}=" + self.send(x.to_sym).inspect }.join(", ")
|
35
|
+
"<#Norikra::Query:#{self.object_id} #{internal}>"
|
30
36
|
end
|
31
37
|
|
32
38
|
def <=>(other)
|
@@ -45,16 +51,8 @@ module Norikra
|
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
48
|
-
def self.loopback(group)
|
49
|
-
group && group =~ /^LOOPBACK\((.+)\)$/ && $1
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.stdout?(group)
|
53
|
-
group && group == "STDOUT()"
|
54
|
-
end
|
55
|
-
|
56
54
|
def dup
|
57
|
-
self.class.new(:
|
55
|
+
self.class.new(name: @name, group: @group, expression: @expression.dup)
|
58
56
|
end
|
59
57
|
|
60
58
|
def to_hash
|
@@ -70,8 +68,26 @@ module Norikra
|
|
70
68
|
end
|
71
69
|
|
72
70
|
def invalid?
|
73
|
-
# check query is invalid as Norikra query or not
|
74
|
-
|
71
|
+
# check query is invalid as Norikra query or not, and return invalid reason (or nil for valid queries)
|
72
|
+
|
73
|
+
# "SELECT *" is prohibited because each Norikra targets does not have all fields users expect
|
74
|
+
if self.ast.listup('selectionListElement').any?{|node| node.children.map(&:name).any?{|name| name == '*' } }
|
75
|
+
# '*' is a direct child of selectionListElement, not selectionListElementExpr
|
76
|
+
return "'SELECT *' is prohibited in query"
|
77
|
+
end
|
78
|
+
|
79
|
+
# NULLABLE(...) can have "a" single field reference only
|
80
|
+
nullables = self.ast.listup(:libfunc).select{|node| node.function_name.upcase == "NULLABLE" }
|
81
|
+
if nullables.size > 0
|
82
|
+
unless nullables.all?{|node| args = node.find("libFunctionArgs"); args && args.has_a?(:libarg) }
|
83
|
+
return "NULLABLE(...) must have a field argument"
|
84
|
+
end
|
85
|
+
unless nullables.all?{|node| exp = node.find(:libarg).expression; exp && exp.propertyReference? }
|
86
|
+
return "NULLABLE(...) can get a field, not expression"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
nil
|
75
91
|
end
|
76
92
|
|
77
93
|
def targets
|
@@ -93,74 +109,85 @@ module Norikra
|
|
93
109
|
end
|
94
110
|
|
95
111
|
def explore(outer_targets=[], alias_overridden={})
|
96
|
-
fields = {
|
97
|
-
|
112
|
+
fields = {
|
113
|
+
defs: { all: [], unknown: [], target: {} },
|
114
|
+
nullables: { all: [], unknown: [], target: {} },
|
115
|
+
}
|
116
|
+
|
117
|
+
alias_map = alias_overridden.dup
|
98
118
|
|
99
|
-
all = []
|
100
|
-
unknowns = []
|
101
119
|
self.ast.listup(:stream).each do |node|
|
102
120
|
node.aliases.each do |alias_name, target|
|
103
121
|
alias_map[alias_name] = target
|
104
122
|
end
|
105
123
|
node.targets.each do |target|
|
106
|
-
fields[target]
|
124
|
+
fields[:defs][:target][target] = []
|
125
|
+
fields[:nullables][:target][target] = []
|
107
126
|
end
|
108
127
|
end
|
109
128
|
|
110
|
-
|
111
|
-
|
112
|
-
raise Norikra::ClientError, "Invalid alias '#{dup_aliases.join(',')}', same with target name"
|
113
|
-
end
|
114
|
-
|
115
|
-
default_target = fields.keys.size == 1 ? fields.keys.first : nil
|
129
|
+
# default target should be out of effect of outer_targets
|
130
|
+
default_target = fields[:defs][:target].keys.size == 1 ? fields[:defs][:target].keys.first : nil
|
116
131
|
|
117
132
|
outer_targets.each do |t|
|
118
|
-
fields[t] ||= []
|
133
|
+
fields[:defs][:target][t] ||= []
|
134
|
+
fields[:nullables][:target][t] ||= []
|
119
135
|
end
|
120
136
|
|
121
|
-
|
122
|
-
|
123
|
-
|
137
|
+
dup_aliases = (alias_map.keys & fields[:defs][:target].keys)
|
138
|
+
unless dup_aliases.empty?
|
139
|
+
raise Norikra::ClientError, "Invalid alias '#{dup_aliases.join(',')}', same with target name"
|
124
140
|
end
|
125
141
|
|
126
142
|
# names of 'AS'
|
127
143
|
field_aliases = self.ast.listup(:selection).map(&:alias).compact
|
128
144
|
|
129
|
-
known_targets_aliases = fields.keys + alias_map.keys
|
145
|
+
known_targets_aliases = fields[:defs][:target].keys + alias_map.keys
|
130
146
|
self.ast.fields(default_target, known_targets_aliases).each do |field_def|
|
131
147
|
f = field_def[:f]
|
132
148
|
next if field_aliases.include?(f)
|
133
149
|
|
134
|
-
all.push(f)
|
150
|
+
fields[:defs][:all].push(f)
|
151
|
+
fields[:nullables][:all].push(f) if field_def[:n]
|
135
152
|
|
136
153
|
if field_def[:t]
|
137
154
|
t = alias_map[field_def[:t]] || field_def[:t]
|
138
|
-
unless fields[t]
|
155
|
+
unless fields[:defs][:target][t]
|
139
156
|
raise Norikra::ClientError, "unknown target alias name for: #{field_def[:t]}.#{field_def[:f]}"
|
140
157
|
end
|
141
|
-
fields[t].push(f)
|
142
|
-
|
158
|
+
fields[:defs][:target][t].push(f)
|
159
|
+
fields[:nullables][:target][t].push(f) if field_def[:n]
|
143
160
|
else
|
144
|
-
|
161
|
+
fields[:defs][:unknown].push(f)
|
162
|
+
fields[:nullables][:unknown].push(f) if field_def[:n]
|
145
163
|
end
|
146
164
|
end
|
147
165
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
fields[
|
166
|
+
self.subqueries.each do |subquery|
|
167
|
+
sub = {}
|
168
|
+
sub[:defs], sub[:nullables] = subquery.explore(fields[:defs][:target].keys, alias_map)
|
169
|
+
|
170
|
+
[:defs, :nullables].each do |group|
|
171
|
+
fields[group][:all] += sub[group].delete('')
|
172
|
+
fields[group][:unknown] += sub[group].delete(nil)
|
173
|
+
sub[group].keys.each do |t|
|
174
|
+
fields[group][:target][t] ||= []
|
175
|
+
fields[group][:target][t] += sub[group][t]
|
176
|
+
end
|
154
177
|
end
|
155
178
|
end
|
156
179
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
180
|
+
compact = ->(data){
|
181
|
+
r = {}
|
182
|
+
data[:target].keys.each do |t|
|
183
|
+
r[t] = data[:target][t].sort.uniq
|
184
|
+
end
|
185
|
+
r[''] = data[:all].sort.uniq
|
186
|
+
r[nil] = data[:unknown].sort.uniq
|
187
|
+
r
|
188
|
+
}
|
162
189
|
|
163
|
-
fields
|
190
|
+
[ compact.(fields[:defs]), compact.(fields[:nullables]) ]
|
164
191
|
end
|
165
192
|
|
166
193
|
def fields(target='')
|
@@ -168,10 +195,18 @@ module Norikra
|
|
168
195
|
# target nil: fields for unknown targets
|
169
196
|
return @fields[target] if @fields
|
170
197
|
|
171
|
-
@fields = explore()
|
198
|
+
@fields, @nullable_fields = explore()
|
172
199
|
@fields[target]
|
173
200
|
end
|
174
201
|
|
202
|
+
def nullable_fields(target='')
|
203
|
+
# argument target is same with #fields
|
204
|
+
return @nullable_fields[target] if @nullable_fields
|
205
|
+
|
206
|
+
@fields, @nullable_fields = explore()
|
207
|
+
@nullable_fields[target]
|
208
|
+
end
|
209
|
+
|
175
210
|
class ParseRuleSelectorImpl
|
176
211
|
include Java::ComEspertechEsperEplParse::ParseRuleSelector
|
177
212
|
def invokeParseRule(parser)
|
@@ -218,10 +253,32 @@ module Norikra
|
|
218
253
|
end
|
219
254
|
|
220
255
|
def self.rewrite_query(statement_model, mapping)
|
256
|
+
rewrite_nullable_fields(statement_model)
|
221
257
|
rewrite_event_type_name(statement_model, mapping)
|
222
258
|
rewrite_event_field_name(statement_model, mapping)
|
223
259
|
end
|
224
260
|
|
261
|
+
def self.rewrite_nullable_fields(statement_model)
|
262
|
+
# NULLABLE(field) -> field
|
263
|
+
## NOTICE: NULLABLE(...) cannot be used in view parameters. ex: target.std:unique(NULLABLE(a)) -> x
|
264
|
+
rewriter = lambda {|node|
|
265
|
+
if node.respond_to?(:getExpression)
|
266
|
+
exp = node.getExpression
|
267
|
+
if exp && exp.is_a?(Java::ComEspertechEsperClientSoda::DotExpression) && exp.getChain.size == 1
|
268
|
+
# top-level lib function
|
269
|
+
# exp.getChain[0] #=> Java::ComEspertechEsperClientSoda::DotExpressionItem
|
270
|
+
if exp.getChain[0].name.upcase == 'NULLABLE'
|
271
|
+
node.setExpression(exp.getChain[0].getParameters[0])
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
}
|
276
|
+
recaller = lambda {|node|
|
277
|
+
Norikra::Query.rewrite_nullable_fields(node.getModel)
|
278
|
+
}
|
279
|
+
traverse_fields(rewriter, recaller, statement_model)
|
280
|
+
end
|
281
|
+
|
225
282
|
def self.rewrite_event_field_name(statement_model, mapping)
|
226
283
|
# mapping: {target_name => query_event_type_name}
|
227
284
|
# mapping is for target name rewriting of fully qualified field name access
|
@@ -235,7 +292,7 @@ module Norikra
|
|
235
292
|
# model.getWhereClause.getChildren[1].getChildren[0].getPropertyName #=> 'field.key1.$1'
|
236
293
|
# model.getWhereClause.getChildren[2].getChildren[0].getChain[0].getName #=> 'opts.num.$0' from opts.num.$0.length()
|
237
294
|
|
238
|
-
query = Norikra::Query.new(:
|
295
|
+
query = Norikra::Query.new(name: 'dummy name by .rewrite_event_field_name', expression: statement_model.toEPL)
|
239
296
|
targets = query.targets
|
240
297
|
fqfs_prefixes = targets + query.aliases
|
241
298
|
|
data/lib/norikra/rpc/handler.rb
CHANGED
@@ -13,9 +13,9 @@ class Norikra::RPC::Handler
|
|
13
13
|
|
14
14
|
def logging(type, handler, args=[])
|
15
15
|
if type == :manage
|
16
|
-
debug
|
16
|
+
debug("RPC"){ { handler: handler.to_s, args: args } }
|
17
17
|
else
|
18
|
-
trace
|
18
|
+
trace("RPC"){ { handler: handler.to_s, args: args } }
|
19
19
|
end
|
20
20
|
|
21
21
|
begin
|
@@ -67,7 +67,7 @@ class Norikra::RPC::Handler
|
|
67
67
|
|
68
68
|
def register(query_name, query_group, expression)
|
69
69
|
logging(:manage, :register, [query_name, query_group, expression]){
|
70
|
-
r = @engine.register(Norikra::Query.new(:
|
70
|
+
r = @engine.register(Norikra::Query.new(name: query_name, group: query_group, expression: expression))
|
71
71
|
!!r
|
72
72
|
}
|
73
73
|
end
|
data/lib/norikra/rpc/http.rb
CHANGED
@@ -35,7 +35,7 @@ module Norikra::RPC
|
|
35
35
|
info "RPC server #{@host}:#{@port}, #{@threads} threads"
|
36
36
|
@thread = Thread.new do
|
37
37
|
@mizuno = Mizuno::Server.new
|
38
|
-
@mizuno.run(@app, :
|
38
|
+
@mizuno.run(@app, embedded: true, threads: @threads, port: @port, host: @host)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|