mirror of
https://github.com/owncloud/ocis
synced 2026-04-25 17:25:21 +02:00
Add NumericRestrictionNode to the KQL PEG grammar so that range operators work with numeric values, not just DateTimes. This enables queries like `size>=1048576`, `photo.iso>=100`, `photo.fNumber>=2.8`, and `photo.focalLength<50`. Changes: - ast: add NumericNode with Key, Operator, Value (float64) - kql/dictionary.peg: add NumericRestrictionNode and Number rules - kql/factory.go: add buildNumericNode() - kql/cast.go: add toFloat64() - bleve/compiler.go: compile NumericNode to NumericRangeQuery Fixes: #12093 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
252 lines
5.1 KiB
Plaintext
252 lines
5.1 KiB
Plaintext
{
|
|
package kql
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// ast
|
|
////////////////////////////////////////////////////////
|
|
|
|
AST <-
|
|
n:Nodes {
|
|
return buildAST(n, c.text, c.pos)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// nodes
|
|
////////////////////////////////////////////////////////
|
|
|
|
Nodes <-
|
|
(_ Node)+
|
|
|
|
Node <-
|
|
GroupNode /
|
|
PropertyRestrictionNodes /
|
|
OperatorBooleanNodes /
|
|
FreeTextKeywordNodes
|
|
|
|
////////////////////////////////////////////////////////
|
|
// nesting
|
|
////////////////////////////////////////////////////////
|
|
|
|
GroupNode <-
|
|
k:(Char+)? (OperatorColonNode / OperatorEqualNode)? "(" v:Nodes ")" {
|
|
return buildGroupNode(k, v, c.text, c.pos)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// property restrictions
|
|
////////////////////////////////////////////////////////
|
|
|
|
PropertyRestrictionNodes <-
|
|
YesNoPropertyRestrictionNode /
|
|
DateTimeRestrictionNode /
|
|
NumericRestrictionNode /
|
|
TextPropertyRestrictionNode
|
|
|
|
YesNoPropertyRestrictionNode <-
|
|
k:Char+ (OperatorColonNode / OperatorEqualNode) v:("true" / "false"){
|
|
return buildBooleanNode(k, v, c.text, c.pos)
|
|
}
|
|
|
|
DateTimeRestrictionNode <-
|
|
k:Char+ o:(
|
|
OperatorGreaterOrEqualNode /
|
|
OperatorLessOrEqualNode /
|
|
OperatorGreaterNode /
|
|
OperatorLessNode /
|
|
OperatorEqualNode /
|
|
OperatorColonNode
|
|
) '"'? v:(
|
|
DateTime /
|
|
FullDate /
|
|
FullTime
|
|
) '"'? {
|
|
return buildDateTimeNode(k, o, v, c.text, c.pos)
|
|
} /
|
|
k:Char+ (
|
|
OperatorEqualNode /
|
|
OperatorColonNode
|
|
) '"'? v:NaturalLanguageDateTime '"'? {
|
|
return buildNaturalLanguageDateTimeNodes(k, v, c.text, c.pos)
|
|
}
|
|
|
|
NumericRestrictionNode <-
|
|
k:Char+ o:(
|
|
OperatorGreaterOrEqualNode /
|
|
OperatorLessOrEqualNode /
|
|
OperatorGreaterNode /
|
|
OperatorLessNode
|
|
) v:Number {
|
|
return buildNumericNode(k, o, v, c.text, c.pos)
|
|
}
|
|
|
|
TextPropertyRestrictionNode <-
|
|
k:Char+ (OperatorColonNode / OperatorEqualNode) v:(String / [^ ()]+){
|
|
return buildStringNode(k, v, c.text, c.pos)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// free text-keywords
|
|
////////////////////////////////////////////////////////
|
|
|
|
FreeTextKeywordNodes <-
|
|
PhraseNode /
|
|
WordNode
|
|
|
|
PhraseNode <-
|
|
OperatorColonNode? _ v:String _ OperatorColonNode? {
|
|
return buildStringNode("", v, c.text, c.pos)
|
|
}
|
|
|
|
WordNode <-
|
|
OperatorColonNode? _ v:[^ :()]+ _ OperatorColonNode? {
|
|
return buildStringNode("", v, c.text, c.pos)
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// operators
|
|
////////////////////////////////////////////////////////
|
|
|
|
OperatorBooleanNodes <-
|
|
OperatorBooleanAndNode /
|
|
OperatorBooleanNotNode /
|
|
OperatorBooleanOrNode
|
|
|
|
OperatorBooleanAndNode <-
|
|
("AND" / "+") {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorBooleanNotNode <-
|
|
("NOT" / "-") {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorBooleanOrNode <-
|
|
("OR") {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorColonNode <-
|
|
":" {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorEqualNode <-
|
|
"=" {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorLessNode <-
|
|
"<" {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorLessOrEqualNode <-
|
|
"<=" {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorGreaterNode <-
|
|
">" {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
OperatorGreaterOrEqualNode <-
|
|
">=" {
|
|
return buildOperatorNode(c.text, c.pos)
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////
|
|
// time
|
|
////////////////////////////////////////////////////////
|
|
|
|
TimeYear <-
|
|
Digit Digit Digit Digit {
|
|
return c.text, nil
|
|
}
|
|
|
|
TimeMonth <-
|
|
Digit Digit {
|
|
return c.text, nil
|
|
}
|
|
|
|
TimeDay <-
|
|
Digit Digit {
|
|
return c.text, nil
|
|
}
|
|
|
|
TimeHour <-
|
|
Digit Digit {
|
|
return c.text, nil
|
|
}
|
|
|
|
TimeMinute <-
|
|
Digit Digit {
|
|
return c.text, nil
|
|
}
|
|
|
|
TimeSecond <-
|
|
Digit Digit {
|
|
return c.text, nil
|
|
}
|
|
|
|
FullDate <-
|
|
TimeYear "-" TimeMonth "-" TimeDay {
|
|
return c.text, nil
|
|
}
|
|
|
|
FullTime <-
|
|
TimeHour ":" TimeMinute ":" TimeSecond ("." Digit+)? ("Z" / ("+" / "-") TimeHour ":" TimeMinute) {
|
|
return c.text, nil
|
|
}
|
|
|
|
DateTime <-
|
|
FullDate "T" FullTime {
|
|
return c.text, nil
|
|
}
|
|
|
|
NaturalLanguageDateTime <-
|
|
"today" /
|
|
"yesterday" /
|
|
"this week" /
|
|
"last week" /
|
|
"last 7 days" /
|
|
"this month" /
|
|
"last month" /
|
|
"last 30 days" /
|
|
"this year" /
|
|
"last year" {
|
|
return c.text, nil
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
// misc
|
|
////////////////////////////////////////////////////////
|
|
|
|
Char <-
|
|
[A-Za-z.] {
|
|
return c.text, nil
|
|
}
|
|
|
|
String <-
|
|
'"' v:[^"]* '"' {
|
|
return v, nil
|
|
}
|
|
|
|
Number <-
|
|
[0-9]+ ("." [0-9]+)? {
|
|
return c.text, nil
|
|
}
|
|
|
|
Digit <-
|
|
[0-9] {
|
|
return c.text, nil
|
|
}
|
|
|
|
_ <-
|
|
[ \t]* {
|
|
return nil, nil
|
|
}
|