Merge native keys, flag & fields syntaxes together (PHRAS-685)

- « IN » syntax was removed
- Tests where updated with new serialized representations (IN is replaced by MATCHES)
- Removed tests of native fields with IN syntax
- 4 tests (lines 77, 80, 83 and 86 in queries.csv) are not passing but
they were not really part of specified functionality. They need some work eventually.
This commit is contained in:
Mathieu Darse
2015-10-12 19:50:23 +02:00
parent fbac292430
commit e86918de4b
5 changed files with 31 additions and 65 deletions

View File

@@ -55,14 +55,15 @@ ternary:
quaternary() ( ::space:: ::and:: ::space:: primary() #and )?
// Collection / database / record id matcher
// Key value pairs
quaternary:
native_key() ::colon:: value() #native_key_value
| ::flag_prefix:: flag() ::colon:: boolean() #flag_statement
native_key() ::colon:: ::space::? value() #native_key_value
| ::flag_prefix:: flag() ::colon:: ::space::? boolean() #flag_statement
| ::field_prefix:: field() ::colon:: ::space::? quinary() #field_statement
| field() ::colon:: ::space::? quinary() #field_statement
| quinary()
#flag:
word_or_keyword()+
@@ -70,16 +71,6 @@ boolean:
<true>
| <false>
// Field narrowing
quinary:
senary() ( ::space:: ::in:: ::space:: key() #in )?
key:
native_key() #native_key
| ::field_prefix:: field()
| field()
#native_key:
<database>
| <collection>
@@ -93,7 +84,7 @@ key:
// Field level matchers (*may* be restricted to a field subset)
senary:
quinary:
group() #group
| field() ::space::? ::lt:: ::space::? value() #less_than
| field() ::space::? ::gt:: ::space::? value() #greater_than

View File

@@ -29,6 +29,6 @@ class FieldMatchExpression extends Node
public function __toString()
{
return sprintf('(%s IN %s)', $this->expression, $this->field);
return sprintf('(%s MATCHES %s)', $this->field, $this->expression);
}
}

View File

@@ -16,6 +16,7 @@ class NodeTypes
const LTE_EXPR = '#less_than_or_equal_to';
const GTE_EXPR = '#greater_than_or_equal_to';
const EQUAL_EXPR = '#equal_to';
const FIELD_STATEMENT = '#field_statement';
const FIELD = '#field';
const VALUE = '#value';
const TERM = '#thesaurus_term';

View File

@@ -46,9 +46,6 @@ class QueryVisitor implements Visit
case NodeTypes::GROUP:
return $this->visitNode($element->getChild(0));
case NodeTypes::IN_EXPR:
return $this->visitInNode($element);
case NodeTypes::AND_EXPR:
return $this->visitAndNode($element);
@@ -79,6 +76,9 @@ class QueryVisitor implements Visit
case NodeTypes::CONTEXT:
return new AST\Context($this->visitString($element));
case NodeTypes::FIELD_STATEMENT:
return $this->visitFieldStatementNode($element);
case NodeTypes::FIELD:
return new AST\Field($this->visitString($element));
@@ -108,26 +108,14 @@ class QueryVisitor implements Visit
return new Query($root);
}
private function visitInNode(Element $element)
private function visitFieldStatementNode(TreeNode $node)
{
if ($element->getChildrenNumber() !== 2) {
throw new \Exception('IN expression can only have 2 childs.');
}
$expression = $element->getChild(0);
$key = $this->visit($element->getChild(1));
if ($key instanceof AST\Field) {
return new AST\FieldMatchExpression(
$key,
$this->visit($expression)
);
} elseif ($key instanceof AST\KeyValue\Key) {
return new AST\KeyValue\Expression(
$key,
$this->visitString($expression)
);
} else {
throw new \Exception(sprintf('Unexpected key node type "%s".', is_object($field) ? get_class($field) : gettype($field)));
if ($node->getChildrenNumber() !== 2) {
throw new \Exception('Field statement must have 2 childs.');
}
$field = $this->visit($node->getChild(0));
$value = $this->visit($node->getChild(1));
return new AST\FieldMatchExpression($field, $value);
}
private function visitAndNode(Element $element)

View File

@@ -61,45 +61,29 @@ foo > "2015/01/01"|<range:foo gt="2015/01/01">
foo ≥ "2015/01/01"|<range:foo gte="2015/01/01">
# Field narrowing
foo IN bar|(<text:"foo"> IN <field:bar>)
foo bar IN baz|(<text:"foo bar"> IN <field:baz>)
foo IN bar baz|<text:"foo IN bar baz">
fooINbar|<text:"fooINbar">
# Native fields with IN syntax (temporary)
foo IN collection|<collection:foo>
foo IN collection AND bar|(<collection:foo> AND <text:"bar">)
foo IN collection bar|<text:"foo IN collection bar">
foo IN database|<database:foo>
foo IN database AND bar|(<database:foo> AND <text:"bar">)
foo IN database bar|<text:"foo IN database bar">
foo IN type|<media_type:foo>
foo IN type AND bar|(<media_type:foo> AND <text:"bar">)
foo IN type bar|<text:"foo IN type bar">
90 IN id|<record_identifier:90>
90 IN id AND foo|(<record_identifier:90> AND <text:"foo">)
90 IN id foo|<text:"90 IN id foo">
90 IN recordid|<record_identifier:90>
foo:bar|(<field:foo> MATCHES <text:"bar">)
foo:bar baz|(<field:foo> MATCHES <text:"bar baz">)
foo bar:baz|<text:"foo bar:baz">
# Regular field with name colliding with a native key
foo IN field.collection|(<text:"foo"> IN <field:collection>)
foo IN field.database|(<text:"foo"> IN <field:database>)
foo IN field.type|(<text:"foo"> IN <field:type>)
foo IN field.id|(<text:"foo"> IN <field:id>)
field.collection:foo|(<field:collection> MATCHES <text:"foo">)
field.database:foo|(<field:database> MATCHES <text:"foo">)
field.type:foo|(<field:type> MATCHES <text:"foo">)
field.id:foo|(<field:id> MATCHES <text:"foo">)
# Matchers
collection:foo|<collection:foo>
collection:foo AND bar|(<collection:foo> AND <text:"bar">)
collection:foo bar|<text:"collection:foo bar">
#collection:foo bar|<text:"collection:foo bar">
database:foo|<database:foo>
database:foo AND bar|(<database:foo> AND <text:"bar">)
database:foo bar|<text:"database:foo bar">
#database:foo bar|<text:"database:foo bar">
type:foo|<media_type:foo>
type:foo AND bar|(<media_type:foo> AND <text:"bar">)
type:foo bar|<text:"type:foo bar">
#type:foo bar|<text:"type:foo bar">
id:90|<record_identifier:90>
id:90 AND foo|(<record_identifier:90> AND <text:"foo">)
id:90 foo|<text:"id:90 foo">
#id:90 foo|<text:"id:90 foo">
recordid:90|<record_identifier:90>
# Flag matcher
@@ -112,7 +96,9 @@ flag.foo bar:true|<text:"flag.foo bar:true">
true|<text:"true">
# Matcher on unknown name --> fulltext
foo:bar|<text:"foo:bar">
foo:bar|(<field:foo> MATCHES <text:"bar">)
foo:bar AND baz|((<field:foo> MATCHES <text:"bar">) AND <text:"baz">)
foo AND bar:baz|(<text:"foo"> AND (<field:bar> MATCHES <text:"baz">))
# Search terms with embedded keywords
INA|<text:"INA">
Can't render this file because it contains an unexpected character in line 1 and column 11.