From fcbf96add6929834715ed4d3efd43adcd80632d4 Mon Sep 17 00:00:00 2001 From: Alejandro Lopez Date: Mon, 5 Jun 2023 13:38:15 +0300 Subject: [PATCH] [#76] Add UNIQUE keyword Signed-off-by: Alejandro Lopez --- netmap/context.go | 12 + netmap/netmap.go | 35 ++- netmap/parser/Query.g4 | 2 +- netmap/parser/Query.interp | Bin 4477 -> 4611 bytes netmap/parser/Query.tokens | Bin 350 -> 372 bytes netmap/parser/QueryLexer.g4 | 1 + netmap/parser/QueryLexer.interp | Bin 7164 -> 7459 bytes netmap/parser/QueryLexer.tokens | Bin 350 -> 372 bytes netmap/parser/generate.go | 4 +- netmap/parser/query_base_visitor.go | 2 + netmap/parser/query_lexer.go | 235 ++++++++++--------- netmap/parser/query_parser.go | 343 +++++++++++++++------------- netmap/parser/query_visitor.go | 2 + netmap/policy.go | 21 ++ netmap/policy_test.go | 4 + netmap/selector.go | 3 + netmap/selector_test.go | 38 +++ 17 files changed, 423 insertions(+), 279 deletions(-) diff --git a/netmap/context.go b/netmap/context.go index e1c426a8..00942e5d 100644 --- a/netmap/context.go +++ b/netmap/context.go @@ -35,6 +35,11 @@ type context struct { // container backup factor cbf uint32 + + // nodes already used in previous selections, which is needed when the placement + // policy uses the UNIQUE flag. Nodes marked as used are not used in subsequent + // base selections. + usedNodes map[uint64]bool } // Various validation errors. @@ -58,6 +63,7 @@ func newContext(nm NetMap) *context { numCache: make(map[string]uint64), weightFunc: defaultWeightFunc(nm.nodes), + usedNodes: make(map[uint64]bool), } } @@ -76,6 +82,12 @@ func (c *context) setCBF(cbf uint32) { } } +func (c *context) addUsedNodes(ns ...NodeInfo) { + for _, n := range ns { + c.usedNodes[n.hash] = true + } +} + func defaultWeightFunc(ns nodes) weightFunc { mean := newMeanAgg() min := newMinAgg() diff --git a/netmap/netmap.go b/netmap/netmap.go index c839df86..c9969b60 100644 --- a/netmap/netmap.go +++ b/netmap/netmap.go @@ -181,6 +181,10 @@ func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, e result := make([][]NodeInfo, len(p.replicas)) + // Note that the cached selectors are not used when the policy contains the UNIQUE flag. + // This is necessary because each selection vector affects potentially the subsequent vectors + // and thus we call getSelection in such case, in order to take into account nodes previously + // marked as used by earlier replicas. for i := range p.replicas { sName := p.replicas[i].GetSelector() if sName == "" { @@ -198,18 +202,39 @@ func (m NetMap) ContainerNodes(p PlacementPolicy, pivot []byte) ([][]NodeInfo, e } for i := range p.selectors { - result[i] = append(result[i], flattenNodes(c.selections[p.selectors[i].GetName()])...) + if p.unique { + nodes, err := c.getSelection(p.selectors[i]) + if err != nil { + return nil, err + } + result[i] = append(result[i], flattenNodes(nodes)...) + } else { + result[i] = append(result[i], flattenNodes(c.selections[p.selectors[i].GetName()])...) + } + } + + if p.unique { + c.addUsedNodes(result[i]...) } continue } - nodes, ok := c.selections[sName] - if !ok { - return nil, fmt.Errorf("selector not found: REPLICA '%s'", sName) + if p.unique { + nodes, err := c.getSelection(*c.processedSelectors[sName]) + if err != nil { + return nil, err + } + result[i] = append(result[i], flattenNodes(nodes)...) + c.addUsedNodes(result[i]...) + } else { + nodes, ok := c.selections[sName] + if !ok { + return nil, fmt.Errorf("selector not found: REPLICA '%s'", sName) + } + result[i] = append(result[i], flattenNodes(nodes)...) } - result[i] = append(result[i], flattenNodes(nodes)...) } return result, nil diff --git a/netmap/parser/Query.g4 b/netmap/parser/Query.g4 index a52746a9..abae1810 100644 --- a/netmap/parser/Query.g4 +++ b/netmap/parser/Query.g4 @@ -4,7 +4,7 @@ options { tokenVocab = QueryLexer; } -policy: repStmt+ cbfStmt? selectStmt* filterStmt* EOF; +policy: UNIQUE? repStmt+ cbfStmt? selectStmt* filterStmt* EOF; repStmt: REP Count = NUMBER1 // number of object replicas diff --git a/netmap/parser/Query.interp b/netmap/parser/Query.interp index 60db0a9f647f693717d038b8e90e24368ed60b30..df98c281f48e2c2fc4c59a85f2448b44c6d9eadd 100644 GIT binary patch literal 4611 zcmbW5TW{M&5QX3OSLn@c;R2-Y%2O3vDTLaRE6Fv`qA+ZS0gT8O$TAxL`+jF;NpaUe zP!yncXU?9PIkTk6P4-V;tH;jveqZfwww=eDhw9}+czoS%!_i{7ISNP9#VO-*brjLd z#r*fn8PIBW!8l)tvt~H?_=#~nJDZ&-?$c^{u4#U@nGt;SlNP7viaedKH}i$De!%^a z-!Cz}S1#IK*qg+cw};!O?fqS%5sBB!i-1N=%az9U{QTlCyR<+n?DSr#Q>Uq6?*oV8@FE+na+v;xb(Dvr_r3zo}x7>-@x943n zZLvD|zg2H><&T@~YsF1@xUF{KYxVZe)9!P)|6D!peY`peA>8aAKZL*f$DQ)H)9o?! z#u&$);Hu?J=|Vh_z`#D?G(HdU~_*2HW^@X`xwk{3&R z?b35-(wdjo#4>ygjr>T<=qQqevKUc^l|;CAF3WvL?P!`{txrru@wj4ipJ-$Yurac| zF`)^2fY)Y6Ar_3CUEbEf_4t~a_SWmsN!f_YHFOotnxi8$kg`F^m)ViW9cy^LM?TUb zG5>ocJFyc|ko`YqfuM{R1jV-W3N-I=f)FUPoN?u(YA)LZ742t_y8How?O5f?1&T931*KW_V)FA)#17~M zn(KvWz9e#kJXRpy016XJ4x5iga@dnhdNCCWEm0^e+d}!;sydrOX>O?5-gjO^{!q=d z)kL5js~5mf-H_5F6$miYjwQkLJIq=c!q8U^zBb)7i6cCzA`D)F;SaOsxLzSh=A z%8=wqG? z4i$!oobV#Xg@|3hAOwrm=OR0~_DC=98>bLb6mh)7g zfSeF%dlCgwg;g#A6K|X4h^cEb9-5)#L_fOJjE_1Iq#^MFqSAl`!9q(mv3I_pVo~w^Rx#3-9RgcotBEux7h08r0 zmTI!KC^dDwafMpZ1eI9*5>RdHm`VC}+j`6mCqQSDx}HkeQKyEio}r3JQ0+zz`r!wC zSv?*6>?|u>Ib%UT7r{?;*gqeQ*RJTOGQCIj;3TN_ND32B+oLySTebnFFQJN};}!E^ ze*~C{gsL)jdh)%D@8{AEV!~AwPHfrESouNMkAeBo&9df4$x??hJGy6kZ2th&NlNut ztLvGom>Sal+iC6aPu7}Cbbdoz+J~ literal 4477 zcmbW4UvC>X5X9g4DfH&HZ~>kED^FEyr4VXMhNRR$i^8y-3t&XH16fAvZ{OeS@+6W< zi=x1VCp$e$eLRa>{f*TdikvV|_>XJ^y}+s$Q_2 zMqy{pUfv$>o;MHonKhiX#P46}KdtODMGI}7p^+*P=qU7Vjy zmgnK@V)Ah{y^+6W-Ixp)H&>J8bRL#*o~*;{d^%r;`Nzxm(`6NYn=Th&wO-EVKZom8 z2;0|9-MIWJ%Wq*@e_ib!cj5l-v&}E{roP`fw7GqKsl(@o4JSYS>+3cyZL>baztnGW z=hxfKYt2n~ysNk2Oa1oe^Y&AC_*6gbe7rsjA>8hs-i6*L=)#)&G`z%gd?bFuK zMq#!V!7gxLbPZ=DL;;+UH43al)1IY5G9{6(I{ghGKLO2iejd!%AeK*H`(@|$d2rfkn){O08i z^xcm$)Sfrlj7};>Lau?k*zZLY4|v<7=oM?{4Vm^ll;HV@AJ+eSL{=Rk&GjEupmB|P zT4E08tyGRfI7iAQfTsU-)KlWm%0G;_6GzIFayko=82v=5%6&LYVK(<86sX(g^d*0?ct^LTS6YRf94Bq48;m0#%grPIW$k?X5;0ulC$MC6A1!mcIrBfkv} zFxttqwMgX5aXi!mQ#C7pFb<&3PA#SB7TbF+(X?1clra@|q>(aJsH;OxK}dS*aGv`e zomH7^91_!9y_L#y6;{?z+$|h-DX6y?6FU&(ftB#AhOpvrEU&mNU7FMTk94hEk9#6K z(}Sb;VTPgAE$&|ztXG`B;$GoJTH>a9J=)RRRjshZff9+dkr5&Fioz-&ZpIT7kE5KyOTmiUFAHNrWO)sYSnHy5B*l8idpk)|w;ZZNcVOl{&iE)%=Vr!^&%+8O#C16%>qV1)Nv5?}-+mn1rpq@XZm>j130eglSV zWVOLm{|GC2h>hW9Jh~p!mRhEWHz;5X3scBOj94EYhhEqnvptRoQ)IFlqs9IKBhIr0 zsOjP!3X^K;QHlDt$uRm5_XsQQ%UCg_jHjN9bExchv<*$7dv+zHYGWvN$u3VKM)Hy}D1N0l(3GH4c#=o(n}2)ZpX&~4l7epe{C8 zkqH43EbHkk8eEkc5uJu`3MW47Q|CzBQ7JWsrR1n|GL%Ta6FI1-w}Z9RwgIZ0Q@LYR z2Uk$ZigpDkKd0&-^dY34Rl#?wj-3U#4i(pph8=}+8pygZH1%aD*{YdQ^(|J}2NauT z(}XJfU!rg&96a0SnB}DP97Q*mRtu#GtlDRt{&?`CFAV*T+ixIy`k~OP&t4D8wZCb5 NX8em)opn2Z{0;aeFINBn diff --git a/netmap/parser/Query.tokens b/netmap/parser/Query.tokens index 8fdec7d8bace57f62664e5a0fc14b64c49b7f0cd..6376ea2554427a870ced03dce5ce8ad0847fdf62 100644 GIT binary patch literal 372 zcmXxfv2Mg55CqVEe`J$X2Kz2|#Y*AKIzqzW09K?l{{O$oAj{PZvOMroZb#n4kW0Q7 zOS$wMsfKln+WSO%3O~Ebjf!q^r;y~6T$KmSuSK3zHR{~N478NIiZQf=*tCeT^c$j| zUGZW@nxosR9@VWXX1b0()D}|z|3>lHT+t-vPUWh&3f~?Sye5<dFUwr-BaJCjzi8fCk=i VJEoEN0|EF60r)op@B#Y=dIL*mP;USL diff --git a/netmap/parser/QueryLexer.g4 b/netmap/parser/QueryLexer.g4 index f32023ca..c9b5ae68 100644 --- a/netmap/parser/QueryLexer.g4 +++ b/netmap/parser/QueryLexer.g4 @@ -5,6 +5,7 @@ AND_OP : 'AND'; OR_OP : 'OR'; SIMPLE_OP : 'EQ' | 'NE' | 'GE' | 'GT' | 'LT' | 'LE'; +UNIQUE : 'UNIQUE'; REP : 'REP'; IN : 'IN'; AS : 'AS'; diff --git a/netmap/parser/QueryLexer.interp b/netmap/parser/QueryLexer.interp index 71b093c1f05cead0ee1535f20cee74dbb4f0bd2f..95db14431c9a18ee3d040fb153ab75a3adaa9e06 100644 GIT binary patch literal 7459 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 VJEoEN0|EF60r)op@B#Y=dIL*mP;USL diff --git a/netmap/parser/generate.go b/netmap/parser/generate.go index f2202d28..66a855bd 100644 --- a/netmap/parser/generate.go +++ b/netmap/parser/generate.go @@ -1,4 +1,4 @@ package parser -// ANTLR can be downloaded from https://www.antlr.org/download/antlr-4.12.0-complete.jar -//go:generate java -Xmx500M -cp "./antlr-4.12.0-complete.jar:$CLASSPATH" org.antlr.v4.Tool -Dlanguage=Go -no-listener -visitor QueryLexer.g4 Query.g4 +// ANTLR can be downloaded from https://www.antlr.org/download/antlr-4.13.0-complete.jar +//go:generate java -Xmx500M -cp "./antlr-4.13.0-complete.jar:$CLASSPATH" org.antlr.v4.Tool -Dlanguage=Go -no-listener -visitor QueryLexer.g4 Query.g4 diff --git a/netmap/parser/query_base_visitor.go b/netmap/parser/query_base_visitor.go index fa1cce8f..4badbceb 100644 --- a/netmap/parser/query_base_visitor.go +++ b/netmap/parser/query_base_visitor.go @@ -1,3 +1,5 @@ +// Code generated from Query.g4 by ANTLR 4.13.0. DO NOT EDIT. + package parser // Query import "github.com/antlr4-go/antlr/v4" diff --git a/netmap/parser/query_lexer.go b/netmap/parser/query_lexer.go index b9224b61..c1ae141a 100644 --- a/netmap/parser/query_lexer.go +++ b/netmap/parser/query_lexer.go @@ -1,11 +1,12 @@ +// Code generated from QueryLexer.g4 by ANTLR 4.13.0. DO NOT EDIT. + package parser import ( "fmt" + "github.com/antlr4-go/antlr/v4" "sync" "unicode" - - "github.com/antlr4-go/antlr/v4" ) // Suppress unused import error @@ -42,114 +43,119 @@ func querylexerLexerInit() { "DEFAULT_MODE", } staticData.LiteralNames = []string{ - "", "'NOT'", "'AND'", "'OR'", "", "'REP'", "'IN'", "'AS'", "'CBF'", - "'SELECT'", "'FROM'", "'FILTER'", "'*'", "'SAME'", "'DISTINCT'", "'('", - "')'", "'@'", "", "", "'0'", + "", "'NOT'", "'AND'", "'OR'", "", "'UNIQUE'", "'REP'", "'IN'", "'AS'", + "'CBF'", "'SELECT'", "'FROM'", "'FILTER'", "'*'", "'SAME'", "'DISTINCT'", + "'('", "')'", "'@'", "", "", "'0'", } staticData.SymbolicNames = []string{ - "", "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "REP", "IN", "AS", "CBF", - "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", "CLAUSE_DISTINCT", - "L_PAREN", "R_PAREN", "AT", "IDENT", "NUMBER1", "ZERO", "STRING", "WS", + "", "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "UNIQUE", "REP", "IN", + "AS", "CBF", "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", + "CLAUSE_DISTINCT", "L_PAREN", "R_PAREN", "AT", "IDENT", "NUMBER1", "ZERO", + "STRING", "WS", } staticData.RuleNames = []string{ - "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "REP", "IN", "AS", "CBF", - "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", "CLAUSE_DISTINCT", + "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "UNIQUE", "REP", "IN", "AS", + "CBF", "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", "CLAUSE_DISTINCT", "L_PAREN", "R_PAREN", "AT", "IDENT", "Digit", "Nondigit", "NUMBER1", "ZERO", "STRING", "ESC", "UNICODE", "HEX", "SAFECODEPOINTSINGLE", "SAFECODEPOINTDOUBLE", "WS", } staticData.PredictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 0, 22, 204, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, + 4, 0, 23, 213, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, - 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 83, 8, 3, 1, 4, 1, 4, 1, 4, 1, - 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, - 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, - 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, - 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, - 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 5, 17, - 143, 8, 17, 10, 17, 12, 17, 146, 9, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, - 20, 1, 20, 5, 20, 154, 8, 20, 10, 20, 12, 20, 157, 9, 20, 1, 21, 1, 21, - 1, 22, 1, 22, 1, 22, 5, 22, 164, 8, 22, 10, 22, 12, 22, 167, 9, 22, 1, - 22, 1, 22, 1, 22, 1, 22, 5, 22, 173, 8, 22, 10, 22, 12, 22, 176, 9, 22, - 1, 22, 3, 22, 179, 8, 22, 1, 23, 1, 23, 1, 23, 3, 23, 184, 8, 23, 1, 24, - 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, - 27, 1, 28, 4, 28, 199, 8, 28, 11, 28, 12, 28, 200, 1, 28, 1, 28, 0, 0, - 29, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, - 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 0, 39, - 0, 41, 19, 43, 20, 45, 21, 47, 0, 49, 0, 51, 0, 53, 0, 55, 0, 57, 22, 1, - 0, 8, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 1, 0, 49, 57, 9, 0, - 34, 34, 39, 39, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, - 116, 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, 0, 31, 39, 39, 92, 92, 3, 0, - 0, 31, 34, 34, 92, 92, 3, 0, 9, 10, 13, 13, 32, 32, 211, 0, 1, 1, 0, 0, - 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, - 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, - 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, - 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, - 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, - 45, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 1, 59, 1, 0, 0, 0, 3, 63, 1, 0, 0, 0, - 5, 67, 1, 0, 0, 0, 7, 82, 1, 0, 0, 0, 9, 84, 1, 0, 0, 0, 11, 88, 1, 0, - 0, 0, 13, 91, 1, 0, 0, 0, 15, 94, 1, 0, 0, 0, 17, 98, 1, 0, 0, 0, 19, 105, - 1, 0, 0, 0, 21, 110, 1, 0, 0, 0, 23, 117, 1, 0, 0, 0, 25, 119, 1, 0, 0, - 0, 27, 124, 1, 0, 0, 0, 29, 133, 1, 0, 0, 0, 31, 135, 1, 0, 0, 0, 33, 137, - 1, 0, 0, 0, 35, 139, 1, 0, 0, 0, 37, 147, 1, 0, 0, 0, 39, 149, 1, 0, 0, - 0, 41, 151, 1, 0, 0, 0, 43, 158, 1, 0, 0, 0, 45, 178, 1, 0, 0, 0, 47, 180, - 1, 0, 0, 0, 49, 185, 1, 0, 0, 0, 51, 191, 1, 0, 0, 0, 53, 193, 1, 0, 0, - 0, 55, 195, 1, 0, 0, 0, 57, 198, 1, 0, 0, 0, 59, 60, 5, 78, 0, 0, 60, 61, - 5, 79, 0, 0, 61, 62, 5, 84, 0, 0, 62, 2, 1, 0, 0, 0, 63, 64, 5, 65, 0, - 0, 64, 65, 5, 78, 0, 0, 65, 66, 5, 68, 0, 0, 66, 4, 1, 0, 0, 0, 67, 68, - 5, 79, 0, 0, 68, 69, 5, 82, 0, 0, 69, 6, 1, 0, 0, 0, 70, 71, 5, 69, 0, - 0, 71, 83, 5, 81, 0, 0, 72, 73, 5, 78, 0, 0, 73, 83, 5, 69, 0, 0, 74, 75, - 5, 71, 0, 0, 75, 83, 5, 69, 0, 0, 76, 77, 5, 71, 0, 0, 77, 83, 5, 84, 0, - 0, 78, 79, 5, 76, 0, 0, 79, 83, 5, 84, 0, 0, 80, 81, 5, 76, 0, 0, 81, 83, - 5, 69, 0, 0, 82, 70, 1, 0, 0, 0, 82, 72, 1, 0, 0, 0, 82, 74, 1, 0, 0, 0, - 82, 76, 1, 0, 0, 0, 82, 78, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 83, 8, 1, 0, - 0, 0, 84, 85, 5, 82, 0, 0, 85, 86, 5, 69, 0, 0, 86, 87, 5, 80, 0, 0, 87, - 10, 1, 0, 0, 0, 88, 89, 5, 73, 0, 0, 89, 90, 5, 78, 0, 0, 90, 12, 1, 0, - 0, 0, 91, 92, 5, 65, 0, 0, 92, 93, 5, 83, 0, 0, 93, 14, 1, 0, 0, 0, 94, - 95, 5, 67, 0, 0, 95, 96, 5, 66, 0, 0, 96, 97, 5, 70, 0, 0, 97, 16, 1, 0, - 0, 0, 98, 99, 5, 83, 0, 0, 99, 100, 5, 69, 0, 0, 100, 101, 5, 76, 0, 0, - 101, 102, 5, 69, 0, 0, 102, 103, 5, 67, 0, 0, 103, 104, 5, 84, 0, 0, 104, - 18, 1, 0, 0, 0, 105, 106, 5, 70, 0, 0, 106, 107, 5, 82, 0, 0, 107, 108, - 5, 79, 0, 0, 108, 109, 5, 77, 0, 0, 109, 20, 1, 0, 0, 0, 110, 111, 5, 70, - 0, 0, 111, 112, 5, 73, 0, 0, 112, 113, 5, 76, 0, 0, 113, 114, 5, 84, 0, - 0, 114, 115, 5, 69, 0, 0, 115, 116, 5, 82, 0, 0, 116, 22, 1, 0, 0, 0, 117, - 118, 5, 42, 0, 0, 118, 24, 1, 0, 0, 0, 119, 120, 5, 83, 0, 0, 120, 121, - 5, 65, 0, 0, 121, 122, 5, 77, 0, 0, 122, 123, 5, 69, 0, 0, 123, 26, 1, - 0, 0, 0, 124, 125, 5, 68, 0, 0, 125, 126, 5, 73, 0, 0, 126, 127, 5, 83, - 0, 0, 127, 128, 5, 84, 0, 0, 128, 129, 5, 73, 0, 0, 129, 130, 5, 78, 0, - 0, 130, 131, 5, 67, 0, 0, 131, 132, 5, 84, 0, 0, 132, 28, 1, 0, 0, 0, 133, - 134, 5, 40, 0, 0, 134, 30, 1, 0, 0, 0, 135, 136, 5, 41, 0, 0, 136, 32, - 1, 0, 0, 0, 137, 138, 5, 64, 0, 0, 138, 34, 1, 0, 0, 0, 139, 144, 3, 39, - 19, 0, 140, 143, 3, 37, 18, 0, 141, 143, 3, 39, 19, 0, 142, 140, 1, 0, - 0, 0, 142, 141, 1, 0, 0, 0, 143, 146, 1, 0, 0, 0, 144, 142, 1, 0, 0, 0, - 144, 145, 1, 0, 0, 0, 145, 36, 1, 0, 0, 0, 146, 144, 1, 0, 0, 0, 147, 148, - 7, 0, 0, 0, 148, 38, 1, 0, 0, 0, 149, 150, 7, 1, 0, 0, 150, 40, 1, 0, 0, - 0, 151, 155, 7, 2, 0, 0, 152, 154, 3, 37, 18, 0, 153, 152, 1, 0, 0, 0, - 154, 157, 1, 0, 0, 0, 155, 153, 1, 0, 0, 0, 155, 156, 1, 0, 0, 0, 156, - 42, 1, 0, 0, 0, 157, 155, 1, 0, 0, 0, 158, 159, 5, 48, 0, 0, 159, 44, 1, - 0, 0, 0, 160, 165, 5, 34, 0, 0, 161, 164, 3, 47, 23, 0, 162, 164, 3, 55, - 27, 0, 163, 161, 1, 0, 0, 0, 163, 162, 1, 0, 0, 0, 164, 167, 1, 0, 0, 0, - 165, 163, 1, 0, 0, 0, 165, 166, 1, 0, 0, 0, 166, 168, 1, 0, 0, 0, 167, - 165, 1, 0, 0, 0, 168, 179, 5, 34, 0, 0, 169, 174, 5, 39, 0, 0, 170, 173, - 3, 47, 23, 0, 171, 173, 3, 53, 26, 0, 172, 170, 1, 0, 0, 0, 172, 171, 1, - 0, 0, 0, 173, 176, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 174, 175, 1, 0, 0, - 0, 175, 177, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 177, 179, 5, 39, 0, 0, 178, - 160, 1, 0, 0, 0, 178, 169, 1, 0, 0, 0, 179, 46, 1, 0, 0, 0, 180, 183, 5, - 92, 0, 0, 181, 184, 7, 3, 0, 0, 182, 184, 3, 49, 24, 0, 183, 181, 1, 0, - 0, 0, 183, 182, 1, 0, 0, 0, 184, 48, 1, 0, 0, 0, 185, 186, 5, 117, 0, 0, - 186, 187, 3, 51, 25, 0, 187, 188, 3, 51, 25, 0, 188, 189, 3, 51, 25, 0, - 189, 190, 3, 51, 25, 0, 190, 50, 1, 0, 0, 0, 191, 192, 7, 4, 0, 0, 192, - 52, 1, 0, 0, 0, 193, 194, 8, 5, 0, 0, 194, 54, 1, 0, 0, 0, 195, 196, 8, - 6, 0, 0, 196, 56, 1, 0, 0, 0, 197, 199, 7, 7, 0, 0, 198, 197, 1, 0, 0, - 0, 199, 200, 1, 0, 0, 0, 200, 198, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, - 202, 1, 0, 0, 0, 202, 203, 6, 28, 0, 0, 203, 58, 1, 0, 0, 0, 12, 0, 82, - 142, 144, 155, 163, 165, 172, 174, 178, 183, 200, 1, 6, 0, 0, + 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 85, 8, 3, 1, 4, + 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, + 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, + 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, + 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, + 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, + 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 5, 18, 152, 8, + 18, 10, 18, 12, 18, 155, 9, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, + 5, 21, 163, 8, 21, 10, 21, 12, 21, 166, 9, 21, 1, 22, 1, 22, 1, 23, 1, + 23, 1, 23, 5, 23, 173, 8, 23, 10, 23, 12, 23, 176, 9, 23, 1, 23, 1, 23, + 1, 23, 1, 23, 5, 23, 182, 8, 23, 10, 23, 12, 23, 185, 9, 23, 1, 23, 3, + 23, 188, 8, 23, 1, 24, 1, 24, 1, 24, 3, 24, 193, 8, 24, 1, 25, 1, 25, 1, + 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, + 4, 29, 208, 8, 29, 11, 29, 12, 29, 209, 1, 29, 1, 29, 0, 0, 30, 1, 1, 3, + 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, + 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 0, 41, 0, 43, + 20, 45, 21, 47, 22, 49, 0, 51, 0, 53, 0, 55, 0, 57, 0, 59, 23, 1, 0, 8, + 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 1, 0, 49, 57, 9, 0, 34, 34, + 39, 39, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, + 3, 0, 48, 57, 65, 70, 97, 102, 3, 0, 0, 31, 39, 39, 92, 92, 3, 0, 0, 31, + 34, 34, 92, 92, 3, 0, 9, 10, 13, 13, 32, 32, 220, 0, 1, 1, 0, 0, 0, 0, + 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, + 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, + 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, + 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, + 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, + 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 1, 61, 1, 0, 0, 0, 3, 65, + 1, 0, 0, 0, 5, 69, 1, 0, 0, 0, 7, 84, 1, 0, 0, 0, 9, 86, 1, 0, 0, 0, 11, + 93, 1, 0, 0, 0, 13, 97, 1, 0, 0, 0, 15, 100, 1, 0, 0, 0, 17, 103, 1, 0, + 0, 0, 19, 107, 1, 0, 0, 0, 21, 114, 1, 0, 0, 0, 23, 119, 1, 0, 0, 0, 25, + 126, 1, 0, 0, 0, 27, 128, 1, 0, 0, 0, 29, 133, 1, 0, 0, 0, 31, 142, 1, + 0, 0, 0, 33, 144, 1, 0, 0, 0, 35, 146, 1, 0, 0, 0, 37, 148, 1, 0, 0, 0, + 39, 156, 1, 0, 0, 0, 41, 158, 1, 0, 0, 0, 43, 160, 1, 0, 0, 0, 45, 167, + 1, 0, 0, 0, 47, 187, 1, 0, 0, 0, 49, 189, 1, 0, 0, 0, 51, 194, 1, 0, 0, + 0, 53, 200, 1, 0, 0, 0, 55, 202, 1, 0, 0, 0, 57, 204, 1, 0, 0, 0, 59, 207, + 1, 0, 0, 0, 61, 62, 5, 78, 0, 0, 62, 63, 5, 79, 0, 0, 63, 64, 5, 84, 0, + 0, 64, 2, 1, 0, 0, 0, 65, 66, 5, 65, 0, 0, 66, 67, 5, 78, 0, 0, 67, 68, + 5, 68, 0, 0, 68, 4, 1, 0, 0, 0, 69, 70, 5, 79, 0, 0, 70, 71, 5, 82, 0, + 0, 71, 6, 1, 0, 0, 0, 72, 73, 5, 69, 0, 0, 73, 85, 5, 81, 0, 0, 74, 75, + 5, 78, 0, 0, 75, 85, 5, 69, 0, 0, 76, 77, 5, 71, 0, 0, 77, 85, 5, 69, 0, + 0, 78, 79, 5, 71, 0, 0, 79, 85, 5, 84, 0, 0, 80, 81, 5, 76, 0, 0, 81, 85, + 5, 84, 0, 0, 82, 83, 5, 76, 0, 0, 83, 85, 5, 69, 0, 0, 84, 72, 1, 0, 0, + 0, 84, 74, 1, 0, 0, 0, 84, 76, 1, 0, 0, 0, 84, 78, 1, 0, 0, 0, 84, 80, + 1, 0, 0, 0, 84, 82, 1, 0, 0, 0, 85, 8, 1, 0, 0, 0, 86, 87, 5, 85, 0, 0, + 87, 88, 5, 78, 0, 0, 88, 89, 5, 73, 0, 0, 89, 90, 5, 81, 0, 0, 90, 91, + 5, 85, 0, 0, 91, 92, 5, 69, 0, 0, 92, 10, 1, 0, 0, 0, 93, 94, 5, 82, 0, + 0, 94, 95, 5, 69, 0, 0, 95, 96, 5, 80, 0, 0, 96, 12, 1, 0, 0, 0, 97, 98, + 5, 73, 0, 0, 98, 99, 5, 78, 0, 0, 99, 14, 1, 0, 0, 0, 100, 101, 5, 65, + 0, 0, 101, 102, 5, 83, 0, 0, 102, 16, 1, 0, 0, 0, 103, 104, 5, 67, 0, 0, + 104, 105, 5, 66, 0, 0, 105, 106, 5, 70, 0, 0, 106, 18, 1, 0, 0, 0, 107, + 108, 5, 83, 0, 0, 108, 109, 5, 69, 0, 0, 109, 110, 5, 76, 0, 0, 110, 111, + 5, 69, 0, 0, 111, 112, 5, 67, 0, 0, 112, 113, 5, 84, 0, 0, 113, 20, 1, + 0, 0, 0, 114, 115, 5, 70, 0, 0, 115, 116, 5, 82, 0, 0, 116, 117, 5, 79, + 0, 0, 117, 118, 5, 77, 0, 0, 118, 22, 1, 0, 0, 0, 119, 120, 5, 70, 0, 0, + 120, 121, 5, 73, 0, 0, 121, 122, 5, 76, 0, 0, 122, 123, 5, 84, 0, 0, 123, + 124, 5, 69, 0, 0, 124, 125, 5, 82, 0, 0, 125, 24, 1, 0, 0, 0, 126, 127, + 5, 42, 0, 0, 127, 26, 1, 0, 0, 0, 128, 129, 5, 83, 0, 0, 129, 130, 5, 65, + 0, 0, 130, 131, 5, 77, 0, 0, 131, 132, 5, 69, 0, 0, 132, 28, 1, 0, 0, 0, + 133, 134, 5, 68, 0, 0, 134, 135, 5, 73, 0, 0, 135, 136, 5, 83, 0, 0, 136, + 137, 5, 84, 0, 0, 137, 138, 5, 73, 0, 0, 138, 139, 5, 78, 0, 0, 139, 140, + 5, 67, 0, 0, 140, 141, 5, 84, 0, 0, 141, 30, 1, 0, 0, 0, 142, 143, 5, 40, + 0, 0, 143, 32, 1, 0, 0, 0, 144, 145, 5, 41, 0, 0, 145, 34, 1, 0, 0, 0, + 146, 147, 5, 64, 0, 0, 147, 36, 1, 0, 0, 0, 148, 153, 3, 41, 20, 0, 149, + 152, 3, 39, 19, 0, 150, 152, 3, 41, 20, 0, 151, 149, 1, 0, 0, 0, 151, 150, + 1, 0, 0, 0, 152, 155, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 153, 154, 1, 0, + 0, 0, 154, 38, 1, 0, 0, 0, 155, 153, 1, 0, 0, 0, 156, 157, 7, 0, 0, 0, + 157, 40, 1, 0, 0, 0, 158, 159, 7, 1, 0, 0, 159, 42, 1, 0, 0, 0, 160, 164, + 7, 2, 0, 0, 161, 163, 3, 39, 19, 0, 162, 161, 1, 0, 0, 0, 163, 166, 1, + 0, 0, 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 44, 1, 0, 0, + 0, 166, 164, 1, 0, 0, 0, 167, 168, 5, 48, 0, 0, 168, 46, 1, 0, 0, 0, 169, + 174, 5, 34, 0, 0, 170, 173, 3, 49, 24, 0, 171, 173, 3, 57, 28, 0, 172, + 170, 1, 0, 0, 0, 172, 171, 1, 0, 0, 0, 173, 176, 1, 0, 0, 0, 174, 172, + 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 177, 1, 0, 0, 0, 176, 174, 1, 0, + 0, 0, 177, 188, 5, 34, 0, 0, 178, 183, 5, 39, 0, 0, 179, 182, 3, 49, 24, + 0, 180, 182, 3, 55, 27, 0, 181, 179, 1, 0, 0, 0, 181, 180, 1, 0, 0, 0, + 182, 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, + 186, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 188, 5, 39, 0, 0, 187, 169, + 1, 0, 0, 0, 187, 178, 1, 0, 0, 0, 188, 48, 1, 0, 0, 0, 189, 192, 5, 92, + 0, 0, 190, 193, 7, 3, 0, 0, 191, 193, 3, 51, 25, 0, 192, 190, 1, 0, 0, + 0, 192, 191, 1, 0, 0, 0, 193, 50, 1, 0, 0, 0, 194, 195, 5, 117, 0, 0, 195, + 196, 3, 53, 26, 0, 196, 197, 3, 53, 26, 0, 197, 198, 3, 53, 26, 0, 198, + 199, 3, 53, 26, 0, 199, 52, 1, 0, 0, 0, 200, 201, 7, 4, 0, 0, 201, 54, + 1, 0, 0, 0, 202, 203, 8, 5, 0, 0, 203, 56, 1, 0, 0, 0, 204, 205, 8, 6, + 0, 0, 205, 58, 1, 0, 0, 0, 206, 208, 7, 7, 0, 0, 207, 206, 1, 0, 0, 0, + 208, 209, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, + 211, 1, 0, 0, 0, 211, 212, 6, 29, 0, 0, 212, 60, 1, 0, 0, 0, 12, 0, 84, + 151, 153, 164, 172, 174, 181, 183, 187, 192, 209, 1, 6, 0, 0, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) @@ -194,22 +200,23 @@ const ( QueryLexerAND_OP = 2 QueryLexerOR_OP = 3 QueryLexerSIMPLE_OP = 4 - QueryLexerREP = 5 - QueryLexerIN = 6 - QueryLexerAS = 7 - QueryLexerCBF = 8 - QueryLexerSELECT = 9 - QueryLexerFROM = 10 - QueryLexerFILTER = 11 - QueryLexerWILDCARD = 12 - QueryLexerCLAUSE_SAME = 13 - QueryLexerCLAUSE_DISTINCT = 14 - QueryLexerL_PAREN = 15 - QueryLexerR_PAREN = 16 - QueryLexerAT = 17 - QueryLexerIDENT = 18 - QueryLexerNUMBER1 = 19 - QueryLexerZERO = 20 - QueryLexerSTRING = 21 - QueryLexerWS = 22 + QueryLexerUNIQUE = 5 + QueryLexerREP = 6 + QueryLexerIN = 7 + QueryLexerAS = 8 + QueryLexerCBF = 9 + QueryLexerSELECT = 10 + QueryLexerFROM = 11 + QueryLexerFILTER = 12 + QueryLexerWILDCARD = 13 + QueryLexerCLAUSE_SAME = 14 + QueryLexerCLAUSE_DISTINCT = 15 + QueryLexerL_PAREN = 16 + QueryLexerR_PAREN = 17 + QueryLexerAT = 18 + QueryLexerIDENT = 19 + QueryLexerNUMBER1 = 20 + QueryLexerZERO = 21 + QueryLexerSTRING = 22 + QueryLexerWS = 23 ) diff --git a/netmap/parser/query_parser.go b/netmap/parser/query_parser.go index 3dda93e4..63577271 100644 --- a/netmap/parser/query_parser.go +++ b/netmap/parser/query_parser.go @@ -1,3 +1,5 @@ +// Code generated from Query.g4 by ANTLR 4.13.0. DO NOT EDIT. + package parser // Query import ( @@ -31,14 +33,15 @@ var QueryParserStaticData struct { func queryParserInit() { staticData := &QueryParserStaticData staticData.LiteralNames = []string{ - "", "'NOT'", "'AND'", "'OR'", "", "'REP'", "'IN'", "'AS'", "'CBF'", - "'SELECT'", "'FROM'", "'FILTER'", "'*'", "'SAME'", "'DISTINCT'", "'('", - "')'", "'@'", "", "", "'0'", + "", "'NOT'", "'AND'", "'OR'", "", "'UNIQUE'", "'REP'", "'IN'", "'AS'", + "'CBF'", "'SELECT'", "'FROM'", "'FILTER'", "'*'", "'SAME'", "'DISTINCT'", + "'('", "')'", "'@'", "", "", "'0'", } staticData.SymbolicNames = []string{ - "", "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "REP", "IN", "AS", "CBF", - "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", "CLAUSE_DISTINCT", - "L_PAREN", "R_PAREN", "AT", "IDENT", "NUMBER1", "ZERO", "STRING", "WS", + "", "NOT_OP", "AND_OP", "OR_OP", "SIMPLE_OP", "UNIQUE", "REP", "IN", + "AS", "CBF", "SELECT", "FROM", "FILTER", "WILDCARD", "CLAUSE_SAME", + "CLAUSE_DISTINCT", "L_PAREN", "R_PAREN", "AT", "IDENT", "NUMBER1", "ZERO", + "STRING", "WS", } staticData.RuleNames = []string{ "policy", "repStmt", "cbfStmt", "selectStmt", "clause", "filterExpr", @@ -47,62 +50,64 @@ func queryParserInit() { } staticData.PredictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 1, 22, 135, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, + 4, 1, 23, 138, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, - 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 1, 0, 4, 0, 30, 8, 0, 11, - 0, 12, 0, 31, 1, 0, 3, 0, 35, 8, 0, 1, 0, 5, 0, 38, 8, 0, 10, 0, 12, 0, - 41, 9, 0, 1, 0, 5, 0, 44, 8, 0, 10, 0, 12, 0, 47, 9, 0, 1, 0, 1, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 3, 1, 55, 8, 1, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, - 1, 3, 3, 3, 64, 8, 3, 1, 3, 3, 3, 67, 8, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, - 3, 73, 8, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, - 1, 5, 1, 5, 1, 5, 3, 5, 88, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, - 5, 96, 8, 5, 10, 5, 12, 5, 99, 9, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, - 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 112, 8, 7, 1, 8, 1, 8, 3, 8, 116, 8, - 8, 1, 9, 1, 9, 1, 9, 3, 9, 121, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, - 1, 12, 3, 12, 129, 8, 12, 1, 13, 1, 13, 3, 13, 133, 8, 13, 1, 13, 0, 1, - 10, 14, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 3, 1, 0, - 13, 14, 1, 0, 19, 20, 2, 0, 5, 7, 9, 11, 138, 0, 29, 1, 0, 0, 0, 2, 50, - 1, 0, 0, 0, 4, 56, 1, 0, 0, 0, 6, 59, 1, 0, 0, 0, 8, 74, 1, 0, 0, 0, 10, - 87, 1, 0, 0, 0, 12, 100, 1, 0, 0, 0, 14, 111, 1, 0, 0, 0, 16, 115, 1, 0, - 0, 0, 18, 120, 1, 0, 0, 0, 20, 122, 1, 0, 0, 0, 22, 124, 1, 0, 0, 0, 24, - 128, 1, 0, 0, 0, 26, 132, 1, 0, 0, 0, 28, 30, 3, 2, 1, 0, 29, 28, 1, 0, - 0, 0, 30, 31, 1, 0, 0, 0, 31, 29, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 34, - 1, 0, 0, 0, 33, 35, 3, 4, 2, 0, 34, 33, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, - 35, 39, 1, 0, 0, 0, 36, 38, 3, 6, 3, 0, 37, 36, 1, 0, 0, 0, 38, 41, 1, - 0, 0, 0, 39, 37, 1, 0, 0, 0, 39, 40, 1, 0, 0, 0, 40, 45, 1, 0, 0, 0, 41, - 39, 1, 0, 0, 0, 42, 44, 3, 12, 6, 0, 43, 42, 1, 0, 0, 0, 44, 47, 1, 0, - 0, 0, 45, 43, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 48, 1, 0, 0, 0, 47, 45, - 1, 0, 0, 0, 48, 49, 5, 0, 0, 1, 49, 1, 1, 0, 0, 0, 50, 51, 5, 5, 0, 0, - 51, 54, 5, 19, 0, 0, 52, 53, 5, 6, 0, 0, 53, 55, 3, 24, 12, 0, 54, 52, - 1, 0, 0, 0, 54, 55, 1, 0, 0, 0, 55, 3, 1, 0, 0, 0, 56, 57, 5, 8, 0, 0, - 57, 58, 5, 19, 0, 0, 58, 5, 1, 0, 0, 0, 59, 60, 5, 9, 0, 0, 60, 66, 5, - 19, 0, 0, 61, 63, 5, 6, 0, 0, 62, 64, 3, 8, 4, 0, 63, 62, 1, 0, 0, 0, 63, - 64, 1, 0, 0, 0, 64, 65, 1, 0, 0, 0, 65, 67, 3, 24, 12, 0, 66, 61, 1, 0, - 0, 0, 66, 67, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 69, 5, 10, 0, 0, 69, - 72, 3, 26, 13, 0, 70, 71, 5, 7, 0, 0, 71, 73, 3, 24, 12, 0, 72, 70, 1, - 0, 0, 0, 72, 73, 1, 0, 0, 0, 73, 7, 1, 0, 0, 0, 74, 75, 7, 0, 0, 0, 75, - 9, 1, 0, 0, 0, 76, 77, 6, 5, -1, 0, 77, 78, 5, 1, 0, 0, 78, 79, 5, 15, - 0, 0, 79, 80, 3, 10, 5, 0, 80, 81, 5, 16, 0, 0, 81, 88, 1, 0, 0, 0, 82, - 83, 5, 15, 0, 0, 83, 84, 3, 10, 5, 0, 84, 85, 5, 16, 0, 0, 85, 88, 1, 0, - 0, 0, 86, 88, 3, 14, 7, 0, 87, 76, 1, 0, 0, 0, 87, 82, 1, 0, 0, 0, 87, - 86, 1, 0, 0, 0, 88, 97, 1, 0, 0, 0, 89, 90, 10, 4, 0, 0, 90, 91, 5, 2, - 0, 0, 91, 96, 3, 10, 5, 5, 92, 93, 10, 3, 0, 0, 93, 94, 5, 3, 0, 0, 94, - 96, 3, 10, 5, 4, 95, 89, 1, 0, 0, 0, 95, 92, 1, 0, 0, 0, 96, 99, 1, 0, - 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 11, 1, 0, 0, 0, 99, 97, - 1, 0, 0, 0, 100, 101, 5, 11, 0, 0, 101, 102, 3, 10, 5, 0, 102, 103, 5, - 7, 0, 0, 103, 104, 3, 24, 12, 0, 104, 13, 1, 0, 0, 0, 105, 106, 5, 17, - 0, 0, 106, 112, 3, 24, 12, 0, 107, 108, 3, 16, 8, 0, 108, 109, 5, 4, 0, - 0, 109, 110, 3, 18, 9, 0, 110, 112, 1, 0, 0, 0, 111, 105, 1, 0, 0, 0, 111, - 107, 1, 0, 0, 0, 112, 15, 1, 0, 0, 0, 113, 116, 3, 24, 12, 0, 114, 116, - 5, 21, 0, 0, 115, 113, 1, 0, 0, 0, 115, 114, 1, 0, 0, 0, 116, 17, 1, 0, - 0, 0, 117, 121, 3, 24, 12, 0, 118, 121, 3, 20, 10, 0, 119, 121, 5, 21, - 0, 0, 120, 117, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 119, 1, 0, 0, 0, - 121, 19, 1, 0, 0, 0, 122, 123, 7, 1, 0, 0, 123, 21, 1, 0, 0, 0, 124, 125, - 7, 2, 0, 0, 125, 23, 1, 0, 0, 0, 126, 129, 3, 22, 11, 0, 127, 129, 5, 18, - 0, 0, 128, 126, 1, 0, 0, 0, 128, 127, 1, 0, 0, 0, 129, 25, 1, 0, 0, 0, - 130, 133, 3, 24, 12, 0, 131, 133, 5, 12, 0, 0, 132, 130, 1, 0, 0, 0, 132, - 131, 1, 0, 0, 0, 133, 27, 1, 0, 0, 0, 16, 31, 34, 39, 45, 54, 63, 66, 72, - 87, 95, 97, 111, 115, 120, 128, 132, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 1, 0, 3, 0, 30, 8, 0, 1, + 0, 4, 0, 33, 8, 0, 11, 0, 12, 0, 34, 1, 0, 3, 0, 38, 8, 0, 1, 0, 5, 0, + 41, 8, 0, 10, 0, 12, 0, 44, 9, 0, 1, 0, 5, 0, 47, 8, 0, 10, 0, 12, 0, 50, + 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 58, 8, 1, 1, 2, 1, 2, 1, + 2, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 67, 8, 3, 1, 3, 3, 3, 70, 8, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 3, 3, 76, 8, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, + 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 91, 8, 5, 1, 5, 1, 5, 1, 5, + 1, 5, 1, 5, 1, 5, 5, 5, 99, 8, 5, 10, 5, 12, 5, 102, 9, 5, 1, 6, 1, 6, + 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 115, 8, 7, + 1, 8, 1, 8, 3, 8, 119, 8, 8, 1, 9, 1, 9, 1, 9, 3, 9, 124, 8, 9, 1, 10, + 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 3, 12, 132, 8, 12, 1, 13, 1, 13, 3, + 13, 136, 8, 13, 1, 13, 0, 1, 10, 14, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, + 20, 22, 24, 26, 0, 3, 1, 0, 14, 15, 1, 0, 20, 21, 2, 0, 6, 8, 10, 12, 142, + 0, 29, 1, 0, 0, 0, 2, 53, 1, 0, 0, 0, 4, 59, 1, 0, 0, 0, 6, 62, 1, 0, 0, + 0, 8, 77, 1, 0, 0, 0, 10, 90, 1, 0, 0, 0, 12, 103, 1, 0, 0, 0, 14, 114, + 1, 0, 0, 0, 16, 118, 1, 0, 0, 0, 18, 123, 1, 0, 0, 0, 20, 125, 1, 0, 0, + 0, 22, 127, 1, 0, 0, 0, 24, 131, 1, 0, 0, 0, 26, 135, 1, 0, 0, 0, 28, 30, + 5, 5, 0, 0, 29, 28, 1, 0, 0, 0, 29, 30, 1, 0, 0, 0, 30, 32, 1, 0, 0, 0, + 31, 33, 3, 2, 1, 0, 32, 31, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 32, 1, + 0, 0, 0, 34, 35, 1, 0, 0, 0, 35, 37, 1, 0, 0, 0, 36, 38, 3, 4, 2, 0, 37, + 36, 1, 0, 0, 0, 37, 38, 1, 0, 0, 0, 38, 42, 1, 0, 0, 0, 39, 41, 3, 6, 3, + 0, 40, 39, 1, 0, 0, 0, 41, 44, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 42, 43, + 1, 0, 0, 0, 43, 48, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 45, 47, 3, 12, 6, 0, + 46, 45, 1, 0, 0, 0, 47, 50, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, + 0, 0, 0, 49, 51, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 51, 52, 5, 0, 0, 1, 52, + 1, 1, 0, 0, 0, 53, 54, 5, 6, 0, 0, 54, 57, 5, 20, 0, 0, 55, 56, 5, 7, 0, + 0, 56, 58, 3, 24, 12, 0, 57, 55, 1, 0, 0, 0, 57, 58, 1, 0, 0, 0, 58, 3, + 1, 0, 0, 0, 59, 60, 5, 9, 0, 0, 60, 61, 5, 20, 0, 0, 61, 5, 1, 0, 0, 0, + 62, 63, 5, 10, 0, 0, 63, 69, 5, 20, 0, 0, 64, 66, 5, 7, 0, 0, 65, 67, 3, + 8, 4, 0, 66, 65, 1, 0, 0, 0, 66, 67, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, + 70, 3, 24, 12, 0, 69, 64, 1, 0, 0, 0, 69, 70, 1, 0, 0, 0, 70, 71, 1, 0, + 0, 0, 71, 72, 5, 11, 0, 0, 72, 75, 3, 26, 13, 0, 73, 74, 5, 8, 0, 0, 74, + 76, 3, 24, 12, 0, 75, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 7, 1, 0, + 0, 0, 77, 78, 7, 0, 0, 0, 78, 9, 1, 0, 0, 0, 79, 80, 6, 5, -1, 0, 80, 81, + 5, 1, 0, 0, 81, 82, 5, 16, 0, 0, 82, 83, 3, 10, 5, 0, 83, 84, 5, 17, 0, + 0, 84, 91, 1, 0, 0, 0, 85, 86, 5, 16, 0, 0, 86, 87, 3, 10, 5, 0, 87, 88, + 5, 17, 0, 0, 88, 91, 1, 0, 0, 0, 89, 91, 3, 14, 7, 0, 90, 79, 1, 0, 0, + 0, 90, 85, 1, 0, 0, 0, 90, 89, 1, 0, 0, 0, 91, 100, 1, 0, 0, 0, 92, 93, + 10, 4, 0, 0, 93, 94, 5, 2, 0, 0, 94, 99, 3, 10, 5, 5, 95, 96, 10, 3, 0, + 0, 96, 97, 5, 3, 0, 0, 97, 99, 3, 10, 5, 4, 98, 92, 1, 0, 0, 0, 98, 95, + 1, 0, 0, 0, 99, 102, 1, 0, 0, 0, 100, 98, 1, 0, 0, 0, 100, 101, 1, 0, 0, + 0, 101, 11, 1, 0, 0, 0, 102, 100, 1, 0, 0, 0, 103, 104, 5, 12, 0, 0, 104, + 105, 3, 10, 5, 0, 105, 106, 5, 8, 0, 0, 106, 107, 3, 24, 12, 0, 107, 13, + 1, 0, 0, 0, 108, 109, 5, 18, 0, 0, 109, 115, 3, 24, 12, 0, 110, 111, 3, + 16, 8, 0, 111, 112, 5, 4, 0, 0, 112, 113, 3, 18, 9, 0, 113, 115, 1, 0, + 0, 0, 114, 108, 1, 0, 0, 0, 114, 110, 1, 0, 0, 0, 115, 15, 1, 0, 0, 0, + 116, 119, 3, 24, 12, 0, 117, 119, 5, 22, 0, 0, 118, 116, 1, 0, 0, 0, 118, + 117, 1, 0, 0, 0, 119, 17, 1, 0, 0, 0, 120, 124, 3, 24, 12, 0, 121, 124, + 3, 20, 10, 0, 122, 124, 5, 22, 0, 0, 123, 120, 1, 0, 0, 0, 123, 121, 1, + 0, 0, 0, 123, 122, 1, 0, 0, 0, 124, 19, 1, 0, 0, 0, 125, 126, 7, 1, 0, + 0, 126, 21, 1, 0, 0, 0, 127, 128, 7, 2, 0, 0, 128, 23, 1, 0, 0, 0, 129, + 132, 3, 22, 11, 0, 130, 132, 5, 19, 0, 0, 131, 129, 1, 0, 0, 0, 131, 130, + 1, 0, 0, 0, 132, 25, 1, 0, 0, 0, 133, 136, 3, 24, 12, 0, 134, 136, 5, 13, + 0, 0, 135, 133, 1, 0, 0, 0, 135, 134, 1, 0, 0, 0, 136, 27, 1, 0, 0, 0, + 17, 29, 34, 37, 42, 48, 57, 66, 69, 75, 90, 98, 100, 114, 118, 123, 131, + 135, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) @@ -145,24 +150,25 @@ const ( QueryAND_OP = 2 QueryOR_OP = 3 QuerySIMPLE_OP = 4 - QueryREP = 5 - QueryIN = 6 - QueryAS = 7 - QueryCBF = 8 - QuerySELECT = 9 - QueryFROM = 10 - QueryFILTER = 11 - QueryWILDCARD = 12 - QueryCLAUSE_SAME = 13 - QueryCLAUSE_DISTINCT = 14 - QueryL_PAREN = 15 - QueryR_PAREN = 16 - QueryAT = 17 - QueryIDENT = 18 - QueryNUMBER1 = 19 - QueryZERO = 20 - QuerySTRING = 21 - QueryWS = 22 + QueryUNIQUE = 5 + QueryREP = 6 + QueryIN = 7 + QueryAS = 8 + QueryCBF = 9 + QuerySELECT = 10 + QueryFROM = 11 + QueryFILTER = 12 + QueryWILDCARD = 13 + QueryCLAUSE_SAME = 14 + QueryCLAUSE_DISTINCT = 15 + QueryL_PAREN = 16 + QueryR_PAREN = 17 + QueryAT = 18 + QueryIDENT = 19 + QueryNUMBER1 = 20 + QueryZERO = 21 + QuerySTRING = 22 + QueryWS = 23 ) // Query rules. @@ -192,6 +198,7 @@ type IPolicyContext interface { // Getter signatures EOF() antlr.TerminalNode + UNIQUE() antlr.TerminalNode AllRepStmt() []IRepStmtContext RepStmt(i int) IRepStmtContext CbfStmt() ICbfStmtContext @@ -240,6 +247,10 @@ func (s *PolicyContext) EOF() antlr.TerminalNode { return s.GetToken(QueryEOF, 0) } +func (s *PolicyContext) UNIQUE() antlr.TerminalNode { + return s.GetToken(QueryUNIQUE, 0) +} + func (s *PolicyContext) AllRepStmt() []IRepStmtContext { children := s.GetChildren() len := 0 @@ -410,20 +421,38 @@ func (p *Query) Policy() (localctx IPolicyContext) { } _la = p.GetTokenStream().LA(1) - for ok := true; ok; ok = _la == QueryREP { + if _la == QueryUNIQUE { { p.SetState(28) + p.Match(QueryUNIQUE) + if p.HasError() { + // Recognition error - abort rule + goto errorExit + } + } + + } + p.SetState(32) + p.GetErrorHandler().Sync(p) + if p.HasError() { + goto errorExit + } + _la = p.GetTokenStream().LA(1) + + for ok := true; ok; ok = _la == QueryREP { + { + p.SetState(31) p.RepStmt() } - p.SetState(31) + p.SetState(34) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit } _la = p.GetTokenStream().LA(1) } - p.SetState(34) + p.SetState(37) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -432,12 +461,12 @@ func (p *Query) Policy() (localctx IPolicyContext) { if _la == QueryCBF { { - p.SetState(33) + p.SetState(36) p.CbfStmt() } } - p.SetState(39) + p.SetState(42) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -446,18 +475,18 @@ func (p *Query) Policy() (localctx IPolicyContext) { for _la == QuerySELECT { { - p.SetState(36) + p.SetState(39) p.SelectStmt() } - p.SetState(41) + p.SetState(44) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit } _la = p.GetTokenStream().LA(1) } - p.SetState(45) + p.SetState(48) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -466,11 +495,11 @@ func (p *Query) Policy() (localctx IPolicyContext) { for _la == QueryFILTER { { - p.SetState(42) + p.SetState(45) p.FilterStmt() } - p.SetState(47) + p.SetState(50) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -478,7 +507,7 @@ func (p *Query) Policy() (localctx IPolicyContext) { _la = p.GetTokenStream().LA(1) } { - p.SetState(48) + p.SetState(51) p.Match(QueryEOF) if p.HasError() { // Recognition error - abort rule @@ -623,7 +652,7 @@ func (p *Query) RepStmt() (localctx IRepStmtContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(50) + p.SetState(53) p.Match(QueryREP) if p.HasError() { // Recognition error - abort rule @@ -631,7 +660,7 @@ func (p *Query) RepStmt() (localctx IRepStmtContext) { } } { - p.SetState(51) + p.SetState(54) var _m = p.Match(QueryNUMBER1) @@ -641,7 +670,7 @@ func (p *Query) RepStmt() (localctx IRepStmtContext) { goto errorExit } } - p.SetState(54) + p.SetState(57) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -650,7 +679,7 @@ func (p *Query) RepStmt() (localctx IRepStmtContext) { if _la == QueryIN { { - p.SetState(52) + p.SetState(55) p.Match(QueryIN) if p.HasError() { // Recognition error - abort rule @@ -658,7 +687,7 @@ func (p *Query) RepStmt() (localctx IRepStmtContext) { } } { - p.SetState(53) + p.SetState(56) var _x = p.Ident() @@ -769,7 +798,7 @@ func (p *Query) CbfStmt() (localctx ICbfStmtContext) { p.EnterRule(localctx, 4, QueryRULE_cbfStmt) p.EnterOuterAlt(localctx, 1) { - p.SetState(56) + p.SetState(59) p.Match(QueryCBF) if p.HasError() { // Recognition error - abort rule @@ -777,7 +806,7 @@ func (p *Query) CbfStmt() (localctx ICbfStmtContext) { } } { - p.SetState(57) + p.SetState(60) var _m = p.Match(QueryNUMBER1) @@ -1017,7 +1046,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(59) + p.SetState(62) p.Match(QuerySELECT) if p.HasError() { // Recognition error - abort rule @@ -1025,7 +1054,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { } } { - p.SetState(60) + p.SetState(63) var _m = p.Match(QueryNUMBER1) @@ -1035,7 +1064,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { goto errorExit } } - p.SetState(66) + p.SetState(69) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -1044,14 +1073,14 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { if _la == QueryIN { { - p.SetState(61) + p.SetState(64) p.Match(QueryIN) if p.HasError() { // Recognition error - abort rule goto errorExit } } - p.SetState(63) + p.SetState(66) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -1060,13 +1089,13 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { if _la == QueryCLAUSE_SAME || _la == QueryCLAUSE_DISTINCT { { - p.SetState(62) + p.SetState(65) p.Clause() } } { - p.SetState(65) + p.SetState(68) var _x = p.Ident() @@ -1075,7 +1104,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { } { - p.SetState(68) + p.SetState(71) p.Match(QueryFROM) if p.HasError() { // Recognition error - abort rule @@ -1083,13 +1112,13 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { } } { - p.SetState(69) + p.SetState(72) var _x = p.IdentWC() localctx.(*SelectStmtContext).Filter = _x } - p.SetState(72) + p.SetState(75) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -1098,7 +1127,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { if _la == QueryAS { { - p.SetState(70) + p.SetState(73) p.Match(QueryAS) if p.HasError() { // Recognition error - abort rule @@ -1106,7 +1135,7 @@ func (p *Query) SelectStmt() (localctx ISelectStmtContext) { } } { - p.SetState(71) + p.SetState(74) var _x = p.Ident() @@ -1208,7 +1237,7 @@ func (p *Query) Clause() (localctx IClauseContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(74) + p.SetState(77) _la = p.GetTokenStream().LA(1) if !(_la == QueryCLAUSE_SAME || _la == QueryCLAUSE_DISTINCT) { @@ -1440,7 +1469,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { var _alt int p.EnterOuterAlt(localctx, 1) - p.SetState(87) + p.SetState(90) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -1449,7 +1478,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { switch p.GetTokenStream().LA(1) { case QueryNOT_OP: { - p.SetState(77) + p.SetState(80) var _m = p.Match(QueryNOT_OP) @@ -1460,7 +1489,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { } } { - p.SetState(78) + p.SetState(81) p.Match(QueryL_PAREN) if p.HasError() { // Recognition error - abort rule @@ -1468,14 +1497,14 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { } } { - p.SetState(79) + p.SetState(82) var _x = p.filterExpr(0) localctx.(*FilterExprContext).F1 = _x } { - p.SetState(80) + p.SetState(83) p.Match(QueryR_PAREN) if p.HasError() { // Recognition error - abort rule @@ -1485,7 +1514,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { case QueryL_PAREN: { - p.SetState(82) + p.SetState(85) p.Match(QueryL_PAREN) if p.HasError() { // Recognition error - abort rule @@ -1493,14 +1522,14 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { } } { - p.SetState(83) + p.SetState(86) var _x = p.filterExpr(0) localctx.(*FilterExprContext).Inner = _x } { - p.SetState(84) + p.SetState(87) p.Match(QueryR_PAREN) if p.HasError() { // Recognition error - abort rule @@ -1510,7 +1539,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryAT, QueryIDENT, QuerySTRING: { - p.SetState(86) + p.SetState(89) p.Expr() } @@ -1519,12 +1548,12 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { goto errorExit } p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) - p.SetState(97) + p.SetState(100) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit } - _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 10, p.GetParserRuleContext()) + _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 11, p.GetParserRuleContext()) if p.HasError() { goto errorExit } @@ -1534,25 +1563,25 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { p.TriggerExitRuleEvent() } _prevctx = localctx - p.SetState(95) + p.SetState(98) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit } - switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 9, p.GetParserRuleContext()) { + switch p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 10, p.GetParserRuleContext()) { case 1: localctx = NewFilterExprContext(p, _parentctx, _parentState) localctx.(*FilterExprContext).F1 = _prevctx p.PushNewRecursionContext(localctx, _startState, QueryRULE_filterExpr) - p.SetState(89) + p.SetState(92) if !(p.Precpred(p.GetParserRuleContext(), 4)) { p.SetError(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 4)", "")) goto errorExit } { - p.SetState(90) + p.SetState(93) var _m = p.Match(QueryAND_OP) @@ -1563,7 +1592,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { } } { - p.SetState(91) + p.SetState(94) var _x = p.filterExpr(5) @@ -1574,14 +1603,14 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { localctx = NewFilterExprContext(p, _parentctx, _parentState) localctx.(*FilterExprContext).F1 = _prevctx p.PushNewRecursionContext(localctx, _startState, QueryRULE_filterExpr) - p.SetState(92) + p.SetState(95) if !(p.Precpred(p.GetParserRuleContext(), 3)) { p.SetError(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 3)", "")) goto errorExit } { - p.SetState(93) + p.SetState(96) var _m = p.Match(QueryOR_OP) @@ -1592,7 +1621,7 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { } } { - p.SetState(94) + p.SetState(97) var _x = p.filterExpr(4) @@ -1604,12 +1633,12 @@ func (p *Query) filterExpr(_p int) (localctx IFilterExprContext) { } } - p.SetState(99) + p.SetState(102) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit } - _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 10, p.GetParserRuleContext()) + _alt = p.GetInterpreter().AdaptivePredict(p.BaseParser, p.GetTokenStream(), 11, p.GetParserRuleContext()) if p.HasError() { goto errorExit } @@ -1762,7 +1791,7 @@ func (p *Query) FilterStmt() (localctx IFilterStmtContext) { p.EnterRule(localctx, 12, QueryRULE_filterStmt) p.EnterOuterAlt(localctx, 1) { - p.SetState(100) + p.SetState(103) p.Match(QueryFILTER) if p.HasError() { // Recognition error - abort rule @@ -1770,14 +1799,14 @@ func (p *Query) FilterStmt() (localctx IFilterStmtContext) { } } { - p.SetState(101) + p.SetState(104) var _x = p.filterExpr(0) localctx.(*FilterStmtContext).Expr = _x } { - p.SetState(102) + p.SetState(105) p.Match(QueryAS) if p.HasError() { // Recognition error - abort rule @@ -1785,7 +1814,7 @@ func (p *Query) FilterStmt() (localctx IFilterStmtContext) { } } { - p.SetState(103) + p.SetState(106) var _x = p.Ident() @@ -1965,7 +1994,7 @@ func (s *ExprContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { func (p *Query) Expr() (localctx IExprContext) { localctx = NewExprContext(p, p.GetParserRuleContext(), p.GetState()) p.EnterRule(localctx, 14, QueryRULE_expr) - p.SetState(111) + p.SetState(114) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -1975,7 +2004,7 @@ func (p *Query) Expr() (localctx IExprContext) { case QueryAT: p.EnterOuterAlt(localctx, 1) { - p.SetState(105) + p.SetState(108) p.Match(QueryAT) if p.HasError() { // Recognition error - abort rule @@ -1983,7 +2012,7 @@ func (p *Query) Expr() (localctx IExprContext) { } } { - p.SetState(106) + p.SetState(109) var _x = p.Ident() @@ -1993,14 +2022,14 @@ func (p *Query) Expr() (localctx IExprContext) { case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT, QuerySTRING: p.EnterOuterAlt(localctx, 2) { - p.SetState(107) + p.SetState(110) var _x = p.FilterKey() localctx.(*ExprContext).Key = _x } { - p.SetState(108) + p.SetState(111) p.Match(QuerySIMPLE_OP) if p.HasError() { // Recognition error - abort rule @@ -2008,7 +2037,7 @@ func (p *Query) Expr() (localctx IExprContext) { } } { - p.SetState(109) + p.SetState(112) var _x = p.FilterValue() @@ -2121,7 +2150,7 @@ func (s *FilterKeyContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { func (p *Query) FilterKey() (localctx IFilterKeyContext) { localctx = NewFilterKeyContext(p, p.GetParserRuleContext(), p.GetState()) p.EnterRule(localctx, 16, QueryRULE_filterKey) - p.SetState(115) + p.SetState(118) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -2131,14 +2160,14 @@ func (p *Query) FilterKey() (localctx IFilterKeyContext) { case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT: p.EnterOuterAlt(localctx, 1) { - p.SetState(113) + p.SetState(116) p.Ident() } case QuerySTRING: p.EnterOuterAlt(localctx, 2) { - p.SetState(114) + p.SetState(117) p.Match(QuerySTRING) if p.HasError() { // Recognition error - abort rule @@ -2269,7 +2298,7 @@ func (s *FilterValueContext) Accept(visitor antlr.ParseTreeVisitor) interface{} func (p *Query) FilterValue() (localctx IFilterValueContext) { localctx = NewFilterValueContext(p, p.GetParserRuleContext(), p.GetState()) p.EnterRule(localctx, 18, QueryRULE_filterValue) - p.SetState(120) + p.SetState(123) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -2279,21 +2308,21 @@ func (p *Query) FilterValue() (localctx IFilterValueContext) { case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT: p.EnterOuterAlt(localctx, 1) { - p.SetState(117) + p.SetState(120) p.Ident() } case QueryNUMBER1, QueryZERO: p.EnterOuterAlt(localctx, 2) { - p.SetState(118) + p.SetState(121) p.Number() } case QuerySTRING: p.EnterOuterAlt(localctx, 3) { - p.SetState(119) + p.SetState(122) p.Match(QuerySTRING) if p.HasError() { // Recognition error - abort rule @@ -2399,7 +2428,7 @@ func (p *Query) Number() (localctx INumberContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(122) + p.SetState(125) _la = p.GetTokenStream().LA(1) if !(_la == QueryNUMBER1 || _la == QueryZERO) { @@ -2523,10 +2552,10 @@ func (p *Query) Keyword() (localctx IKeywordContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(124) + p.SetState(127) _la = p.GetTokenStream().LA(1) - if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&3808) != 0) { + if !((int64(_la) & ^0x3f) == 0 && ((int64(1)<<_la)&7616) != 0) { p.GetErrorHandler().RecoverInline(p) } else { p.GetErrorHandler().ReportMatch(p) @@ -2635,7 +2664,7 @@ func (s *IdentContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { func (p *Query) Ident() (localctx IIdentContext) { localctx = NewIdentContext(p, p.GetParserRuleContext(), p.GetState()) p.EnterRule(localctx, 24, QueryRULE_ident) - p.SetState(128) + p.SetState(131) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -2645,14 +2674,14 @@ func (p *Query) Ident() (localctx IIdentContext) { case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER: p.EnterOuterAlt(localctx, 1) { - p.SetState(126) + p.SetState(129) p.Keyword() } case QueryIDENT: p.EnterOuterAlt(localctx, 2) { - p.SetState(127) + p.SetState(130) p.Match(QueryIDENT) if p.HasError() { // Recognition error - abort rule @@ -2766,7 +2795,7 @@ func (s *IdentWCContext) Accept(visitor antlr.ParseTreeVisitor) interface{} { func (p *Query) IdentWC() (localctx IIdentWCContext) { localctx = NewIdentWCContext(p, p.GetParserRuleContext(), p.GetState()) p.EnterRule(localctx, 26, QueryRULE_identWC) - p.SetState(132) + p.SetState(135) p.GetErrorHandler().Sync(p) if p.HasError() { goto errorExit @@ -2776,14 +2805,14 @@ func (p *Query) IdentWC() (localctx IIdentWCContext) { case QueryREP, QueryIN, QueryAS, QuerySELECT, QueryFROM, QueryFILTER, QueryIDENT: p.EnterOuterAlt(localctx, 1) { - p.SetState(130) + p.SetState(133) p.Ident() } case QueryWILDCARD: p.EnterOuterAlt(localctx, 2) { - p.SetState(131) + p.SetState(134) p.Match(QueryWILDCARD) if p.HasError() { // Recognition error - abort rule diff --git a/netmap/parser/query_visitor.go b/netmap/parser/query_visitor.go index 8123c390..960dc2fb 100644 --- a/netmap/parser/query_visitor.go +++ b/netmap/parser/query_visitor.go @@ -1,3 +1,5 @@ +// Code generated from Query.g4 by ANTLR 4.13.0. DO NOT EDIT. + package parser // Query import "github.com/antlr4-go/antlr/v4" diff --git a/netmap/policy.go b/netmap/policy.go index 3f6986e0..a03d36e1 100644 --- a/netmap/policy.go +++ b/netmap/policy.go @@ -28,6 +28,8 @@ type PlacementPolicy struct { selectors []netmap.Selector replicas []netmap.Replica + + unique bool } func (p *PlacementPolicy) readFromV2(m netmap.PlacementPolicy, checkFieldPresence bool) error { @@ -39,6 +41,7 @@ func (p *PlacementPolicy) readFromV2(m netmap.PlacementPolicy, checkFieldPresenc p.backupFactor = m.GetContainerBackupFactor() p.selectors = m.GetSelectors() p.filters = m.GetFilters() + p.unique = m.GetUnique() return nil } @@ -113,6 +116,7 @@ func (p PlacementPolicy) WriteToV2(m *netmap.PlacementPolicy) { m.SetFilters(p.filters) m.SetSelectors(p.selectors) m.SetReplicas(p.replicas) + m.SetUnique(p.unique) } // ReplicaDescriptor replica descriptor characterizes replicas of objects from @@ -178,6 +182,14 @@ func (p *PlacementPolicy) SetContainerBackupFactor(f uint32) { p.backupFactor = f } +// SetUnique sets the unique flag: it controls whether the selected replica buckets +// are disjoint or not. +// +// Zero PlacementPolicy has false unique flag. +func (p *PlacementPolicy) SetUnique(b bool) { + p.unique = b +} + // Selector describes the bucket selection operator: choose a number of nodes // from the bucket taking the nearest nodes to the related container by hash distance. type Selector struct { @@ -363,6 +375,12 @@ func (p *PlacementPolicy) AddFilters(fs ...Filter) { // // See also DecodeString. func (p PlacementPolicy) WriteStringTo(w io.StringWriter) (err error) { + if p.unique { + if _, err := w.WriteString("UNIQUE\n"); err != nil { + return err + } + } + delim := "" for i := range p.replicas { @@ -572,6 +590,9 @@ func (p *policyVisitor) VisitPolicy(ctx *parser.PolicyContext) any { } pl := new(PlacementPolicy) + + pl.unique = ctx.UNIQUE() != nil + repStmts := ctx.AllRepStmt() pl.replicas = make([]netmap.Replica, 0, len(repStmts)) diff --git a/netmap/policy_test.go b/netmap/policy_test.go index f0a7bc5e..75167dca 100644 --- a/netmap/policy_test.go +++ b/netmap/policy_test.go @@ -27,6 +27,10 @@ FILTER City EQ SPB AND SSD EQ true OR City EQ SPB AND Rating GE 5 AS SPBSSD`, `REP 7 IN SPB SELECT 1 IN City FROM SPBSSD AS SPB FILTER NOT (NOT (City EQ SPB) AND SSD EQ true OR City EQ SPB AND Rating GE 5) AS SPBSSD`, + + `UNIQUE +REP 1 +REP 1`, } var p PlacementPolicy diff --git a/netmap/selector.go b/netmap/selector.go index 51ceb47d..d8c767a2 100644 --- a/netmap/selector.go +++ b/netmap/selector.go @@ -140,6 +140,9 @@ func (c *context) getSelectionBase(s netmap.Selector) []nodeAttrPair { attr := s.GetAttribute() for i := range c.netMap.nodes { + if c.usedNodes[c.netMap.nodes[i].hash] { + continue + } if isMain || c.match(f, c.netMap.nodes[i]) { if attr == "" { // Default attribute is transparent identifier which is different for every node. diff --git a/netmap/selector_test.go b/netmap/selector_test.go index a9748522..a80d9223 100644 --- a/netmap/selector_test.go +++ b/netmap/selector_test.go @@ -1,6 +1,7 @@ package netmap import ( + "encoding/binary" "fmt" "math/rand" "sort" @@ -244,6 +245,43 @@ func TestPlacementPolicy_ProcessSelectors(t *testing.T) { } } +func TestPlacementPolicy_Unique(t *testing.T) { + p := newPlacementPolicy(2, + []ReplicaDescriptor{ + newReplica(1, "S"), + newReplica(1, "S"), + }, + []Selector{ + newSelector("S", "City", 1, "*", (*Selector).SelectSame), + }, + []Filter{}) + p.unique = true + + var nodes []NodeInfo + for i, city := range []string{"Moscow", "Berlin", "Shenzhen"} { + for j := 0; j < 3; j++ { + node := nodeInfoFromAttributes("City", city) + node.SetPublicKey(binary.BigEndian.AppendUint16(nil, uint16(i*4+j))) + nodes = append(nodes, node) + } + } + + var nm NetMap + nm.SetNodes(nodes) + + v, err := nm.ContainerNodes(p, nil) + require.NoError(t, err) + for i, vi := range v { + for _, ni := range vi { + for j := 0; j < i; j++ { + for _, nj := range v[j] { + require.NotEqual(t, ni.hash, nj.hash) + } + } + } + } +} + func TestPlacementPolicy_ProcessSelectorsExceptForNodes(t *testing.T) { p := newPlacementPolicy(1, nil, []Selector{