libgraviton / php-rql-parser Goto Github PK
View Code? Open in Web Editor NEWA PHP RQL Parsing Library
A PHP RQL Parsing Library
This should be simple. We just need to add some classes based off Exception
document them and throw them at the right places. This will also need some kind of example in the docs and it should be built in a way that it interacts nicely with symfonys expection stuff.
From README:Usage section:
/** @var \Doctrine\ODM\MongoDB\Query\Builder $builder */
$visitor = new \Graviton\Rql\Visitor\MongoOdm($builder);
MongoOdm doesn't have constructor and so it cannot set builder from constructor.
Add return $this;
to setters.
Why is class MongoOdm final??
if we ever run into versioning problems with mongo this makes alot of sense, it also paves the way for integrating new visitors without cluttering our repo and issue tracker
No limit in AST eq(id,1),sort(+a,-b),limit(1,2)
:
Graviton\Rql\AST\QueryOperation {#148
-queries: array:2 [
0 => Graviton\Rql\AST\EqOperation {#147
-property: "id"
-value: 1
}
1 => Graviton\Rql\AST\SortOperation {#149
-fields: array:2 [
0 => array:2 [
0 => "a"
1 => "asc"
]
1 => array:2 [
0 => "b"
1 => "desc"
]
]
}
]
}
No sort in AST eq(id,1),limit(1,2),sort(+a,-b)
:
Graviton\Rql\AST\QueryOperation {#162
-queries: array:2 [
0 => Graviton\Rql\AST\EqOperation {#161
-property: "id"
-value: 1
}
1 => Graviton\Rql\AST\LimitOperation {#163
-limit: "1"
-skip: "2"
}
]
}
No eq in AST sort(+a,-b),eq(id,1)
:
Graviton\Rql\AST\SortOperation {#175
-fields: array:2 [
0 => array:2 [
0 => "a"
1 => "asc"
]
1 => array:2 [
0 => "b"
1 => "desc"
]
]
}
I was trying to implement them by my self but I could not get the regex working. I'm not so good at regex :D
What I was trying to do is parsing a query like this "(eq(foo,3)<(price,10))|eq(bar,5)" and I was expecting to get it parsed according to what you written in the README but actually it is not.
Could you please help me parsing this query so then I can fix my Queriable class to handle it?
Thanks a lot
We need a small visitor implementation for pretty printing of parsed rql. I assume we'll be adding a rql:debug
command in graviton/rql-parser-bundle so devs can debug snippets of rql using this visitor.
After we remove the mongodb visitor in #16 this will also be the reference implementation of a visitor.
it should be possible to configure the set of RQL-Parser-Strategies to be able to influence the parsing process.
It would further open the parser to other strategies without the need to change the implementation.
This is from GRV-1497 and pertains to 2.0.0-alpha1
.
Only eq()
and ne()
seem to be supported as <query>
in and()
and or()
operators. The following example is how this was reproduced.
and(eq(name,foo),lt(count,3))
2.0.0-alpha2
v2.0.0-alpha7
MongoDbVisitor
RQL in(id,[1,2,3])
cannot be parsed:
Graviton\Rql\Exceptions\SyntaxErrorException {#92
#message: "no string found"
#code: 0
#file: "vendor/graviton/php-rql-parser/src/Parser/ParserUtil.p"…2
#line: 155
}
But in(id,[a,b,c])
is parsed correctly:
Graviton\Rql\AST\InOperation {#106
-property: "id"
-array: array:3 [
0 => "a"
1 => "b"
2 => "c"
]
}
And eq(id,1)
:
Graviton\Rql\AST\EqOperation {#64
-property: "id"
-value: 1
}
Lots of it! We need to be able to pass a PSR\Log\LoggerInterface
to the parser and visitor structures so they can do heaps of logging.
Fixing this should add a lot of log calls throughout the codebase and make debugging this when it is embedded in your code base possible.
The logger part should be injectable using constructor injection making it optional by passing an included dummy logger.
An idea is to add monolog/monolog
to "dev"
in composer.json so we can have a nice embedded example of how it all really works in test/
.
This is from GRV-1497 and pertains to 2.0.0-alpha1
.
Sorting seems to not work in combination with lt()
. The following example is how this was reproduced.
lt(id,3),sort(-group)
2.0.0-alpha7
MongoDbVisitor
I cannot figure out why it cannot parse a query string like this "eq(field,fieldValue)>(fieldName,55)" that is the query used in your documentation
Lexer ignores rules written in RQL documentation:
The RQL grammar is based around standard URI delimiters. The standard rules for encoding strings with URL encoding (%xx) are observed.
For example RQL eq(id,a%20b)
is parsed as:
Graviton\Rql\AST\EqOperation {
-property: "id"
-value: "a%20b"
}
Expected result:
Graviton\Rql\AST\EqOperation {
-property: "id"
-value: "a b"
}
This issues tracks new features we should add to the AST.
select(<property>,<property>,...)
- Trims each object down to the set of properties defined in the argumentsfirst()
- Returns the first record of the query's result setone()
- Returns the first and only record of the query's result set, or produces an error if the query's result set has more or less than one record in itcount()
- Returns the count of the number of records in the query's result setI copied those that I think look handy :) Feel free to just add more if you have edit right or ping us with you needs if you need anything not on the list.
I get the following error:
Invalid character \" \" at position 14
when executing the following query:
(eq(field,some value with spaces))
I have got around this by amending the REGEX_VALUE const in the Lexer class to:
const REGEX_VALUE = '/(\s|\w|\-|\+|\*|\?|\:|\.|\%[0-9a-f]{2})+/Ai';
According to the RQL specification, sort()
requires a list of properties prepended with a +
or -
, not a property followed by a direction. The current parser does a great job of allowing this functionality, no complaints there, but the sort()
description in QueryInterface.php
is misleading. Something akin to the following might be better:
/**
* @param string $fields,... List of fields, each prefixed with <+|->
*
* @return mixed
*/
public function sort(/* ... */);
...and here is one possible implementation:
/**
* {@inheritdoc}
*/
public function sort(/* ... */)
{
$fields = func_get_args();
$out = array();
// Note that + must be URL encoded as %2B
foreach( $fields as $field ) {
switch( $field[0] ) {
case '+' : array_push($out, substr($field, 1) . ' ASC' ); break;
case '-' : array_push($out, substr($field, 1) . ' DESC' ); break;
default: throw new \Exception("Must specify valid sort order for field {$field}"); break;
}
}
$out = implode( ', ', $out );
// And just for debugging...
print_r( $out );
exit;
}
Personally, I like implementing sorting as sort($field, $direction = false)
, where $direction
indicates whether the sorting should be reversed (i.e. DESC
). This works great with the pipe/ajax functionality of the SmartTable module for AngularJS. (However, much like the suggested implementation described in QueryInterface.php
, my implementation does not follow RQL spec.)
Here it is, if anyone out there is looking for more examples:
public function sort($field, $direction = false)
{
// protected function wrapTable() turns objects.title into `objects`.title
// It is meant for resolving ambiguity in joins by verifying against a list of allowed tables
// e.g. foobar.title would not be allowed, b/c table `foobar` is not assoc. with the current entity
$field = $this->wrapTable( $field );
$direction = filter_var($direction, FILTER_VALIDATE_BOOLEAN);
$direction = $direction ? 'DESC' : 'ASC';
array_push( $this->order, "{$field} {$direction}" );
// ...and then I retrieve the order with $queriable->get_order();
// Of course, currently, I'm limited to sorting by one field at a time
}
I'm using PHP ActiveRecord in my project. I've written a QueryInterface implementation for it, which generates an $options['conditions']
array. I'd be happy to add it to the project as an example. I've never done a pull request before, but let me know if you are interested, and I'll figure out how to do it. Cheers!
We need the parser to implement at least some of the sugar syntax variants. In some areas this will need quite some refactoring of the existing parsers but other areas should be easy.
&
instead of and()
(maybe ,
should do this as per spec as well)|
instead of or()
name=val
instead of eq(name,val)
count=lt=10
instead of lt(count,10)
name=val&count=1
instead of eq(name,val),eq(count,1)
()
based arrays (ie. foo=in=(3,bar,true,2000-01-01T00:00:00Z)
foo=string:3
)(foo,bar)=3
instead of eq(foo.bar,3)
foo/bar=3
instead of eq(foo.bar,3)
This listing is neither complete neither do I expect us to implement all of it. We'll close this as soon as we reach some kind of consensus that what's implemented is easy enough.
RQL limit(a,b)
is parsed without errors:
Graviton\Rql\AST\LimitOperation {#227
-limit: null
-skip: null
}
This module needs acceptance, unit testing as well as some basic qa. For starters I believe we will need to implement the following.
Graviton\Rql\QueryInterface
. This should cover all the code except Graviton\Rql\Queriable\MongoOdm
.Graviton\Rql\Queriable\MongoOdm
mocked (or even faked) data.For example parsing eq(id,gt)
throws SyntaxtErrorException "no valid argument found"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.