예제 #1
0
 /**
  * @param string $rql
  * @param string $exceptionMessage
  * @return void
  *
  * @dataProvider dataSyntaxError()
  */
 public function testSyntaxError($rql, $exceptionMessage)
 {
     $this->setExpectedException(SyntaxErrorException::class, $exceptionMessage);
     $lexer = new Lexer();
     $parser = new Parser();
     $parser->parse($lexer->tokenize($rql));
 }
예제 #2
0
 /**
  * @param string $rql
  * @param string $exceptionMessage
  * @return void
  *
  * @covers Parser::parse()
  * @dataProvider dataSyntaxError()
  */
 public function testSyntaxError($rql, $exceptionMessage)
 {
     $this->setExpectedException('Xiag\\Rql\\Parser\\Exception\\SyntaxErrorException', $exceptionMessage);
     $lexer = new Lexer();
     $parser = Parser::createDefault();
     $parser->parse($lexer->tokenize($rql));
 }
예제 #3
0
 /**
  * 
  * @param ServerRequestInterface $request
  * @param ResponseInterface $response
  * @param callable|null $next
  * @return ResponseInterface
  */
 public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
 {
     $id = $request->getAttribute('id');
     if (is_null($id)) {
         $rqlQueryString = $request->getUri()->getQuery();
         $tokens = $this->lexer->tokenize($rqlQueryString);
         /* @var $rqlQueryObject \Xiag\Rql\Parser\Query */
         $rqlQueryObject = $this->parser->parse($tokens);
         $request = $request->withAttribute('Rql-Query-Object', $rqlQueryObject);
         //$response->write(var_dump($rqlQueryObject));
         $attributes['order'] = $rqlQueryObject->getSort();
         $attributes['limit'] = $rqlQueryObject->getLimit();
         $attributes['select'] = $rqlQueryObject->getSelect();
         $request = $this->setAttributes($request, $attributes);
     }
     if ($next) {
         return $next($request, $response);
     }
     /**        
     if($key = 'select-param') {
     //'select-param': 'prop1,prop2'
     $fildsArray = explode(',', urldecode($value)); 
     */
     return $response;
 }
 protected function processValue($value)
 {
     if ($value === 'true()') {
         $this->pushToken(Token::T_TRUE, $value);
         $this->moveCursor($value);
     } elseif ($value === 'false()') {
         $this->pushToken(Token::T_FALSE, $value);
         $this->moveCursor($value);
     } elseif ($value === 'null()') {
         $this->pushToken(Token::T_NULL, $value);
         $this->moveCursor($value);
     } elseif ($value === 'empty()') {
         $this->pushToken(Token::T_EMPTY, $value);
         $this->moveCursor($value);
     } elseif ($value === 'true' || $value === 'false' || $value === 'null') {
         $this->pushToken(Token::T_STRING, $value);
         $this->moveCursor($value);
     } else {
         parent::processValue($value);
     }
 }
예제 #5
0
        return $this;
    }
}
class QueryBuilder extends BaseQueryBuilder
{
    public function __construct()
    {
        parent::__construct();
        $this->query = new Query();
    }
    public function addNode(AbstractNode $node)
    {
        if ($node instanceof GroupbyNode) {
            return $this->query->setGroupby($node);
        }
        return parent::addNode($node);
    }
}
class Parser extends BaseParser
{
    protected function createQueryBuilder()
    {
        return new QueryBuilder();
    }
}
$nodeParser = (new NodeParserChain())->addNodeParser(new SelectTokenParser(['count', 'sum', 'avg', 'min', 'max']))->addNodeParser(new GroupbyTokenParser())->addNodeParser(new EqNodeParser(new FieldParser(), new ScalarParser()));
// parse
$lexer = new Lexer();
$parser = new Parser($nodeParser);
$tokenStream = $lexer->tokenize(implode('&', ['select(type,avg(age),min(age),max(age))', 'eq(type,customer)', 'groupby(type)']));
var_dump($parser->parse($tokenStream));
 /**
  * execute a query againts the test db
  *
  * @param string   $query   query to execute
  * @param MongoOdm $visitor visitor we are testing
  *
  * @return array
  */
 private function runTestQuery($query, $visitor)
 {
     $lexer = new Lexer();
     $parser = RqlParser::createDefault();
     $rqlQuery = $parser->parse($lexer->tokenize($query));
     $builder = $visitor->visit($rqlQuery);
     $results = [];
     foreach ($builder->getQuery()->execute() as $doc) {
         $results[] = $doc;
     }
     return $results;
 }
    {
        return $tokenStream->test(Token::T_OPERATOR, 'elemMatch');
    }
    public function parse(TokenStream $tokenStream)
    {
        $tokenStream->expect(Token::T_OPERATOR, 'elemMatch');
        $tokenStream->expect(Token::T_OPEN_PARENTHESIS);
        $field = $tokenStream->expect(Token::T_STRING)->getValue();
        $tokenStream->expect(Token::T_COMMA);
        $query = $this->queryParser->parse($tokenStream);
        if (!$query instanceof AbstractQueryNode) {
            throw new SyntaxErrorException(sprintf('"elemMatch" operator expects parameter "query" to be instance of "%s", "%s" given', AbstractQueryNode::class, get_class($query)));
        }
        $tokenStream->expect(Token::T_CLOSE_PARENTHESIS);
        return new ElemMatchNode($field, $query);
    }
}
// create node parser
$scalarParser = (new ValueParser\ScalarParser())->registerTypeCaster('string', new TypeCaster\StringTypeCaster())->registerTypeCaster('integer', new TypeCaster\IntegerTypeCaster())->registerTypeCaster('float', new TypeCaster\FloatTypeCaster())->registerTypeCaster('boolean', new TypeCaster\BooleanTypeCaster());
$arrayParser = new ValueParser\ArrayParser($scalarParser);
$globParser = new ValueParser\GlobParser();
$fieldParser = new ValueParser\FieldParser();
$integerParser = new ValueParser\IntegerParser();
$queryNodeParser = new NodeParser\QueryNodeParser();
$queryNodeParser->addNodeParser(new NodeParser\Query\GroupNodeParser($queryNodeParser))->addNodeParser(new NodeParser\Query\LogicalOperator\AndNodeParser($queryNodeParser))->addNodeParser(new NodeParser\Query\LogicalOperator\OrNodeParser($queryNodeParser))->addNodeParser(new NodeParser\Query\LogicalOperator\NotNodeParser($queryNodeParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\InNodeParser($fieldParser, $arrayParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\OutNodeParser($fieldParser, $arrayParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\EqNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\NeNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\LtNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\GtNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\LeNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\GeNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Rql\LikeNodeParser($fieldParser, $globParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\InNodeParser($fieldParser, $arrayParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\OutNodeParser($fieldParser, $arrayParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\EqNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\NeNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\LtNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\GtNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\LeNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\GeNodeParser($fieldParser, $scalarParser))->addNodeParser(new NodeParser\Query\ComparisonOperator\Fiql\LikeNodeParser($fieldParser, $globParser))->addNodeParser(new BetweenTokenParser($scalarParser))->addNodeParser(new ElemMatchNodeParser($queryNodeParser));
$nodeParser = (new NodeParserChain())->addNodeParser($queryNodeParser)->addNodeParser(new NodeParser\SelectNodeParser($fieldParser))->addNodeParser(new NodeParser\SortNodeParser($fieldParser))->addNodeParser(new NodeParser\LimitNodeParser($integerParser));
// parse
$lexer = new Lexer();
$parser = new Parser($nodeParser);
$tokenStream = $lexer->tokenize('between(x,1,2)&elemMatch(array,(between(x,3,4)&a=b&(c!=d|e!=f)&not(le(g,h))))');
var_dump($parser->parse($tokenStream));
예제 #8
0
namespace Xiag\Rql\ParserExample07;

use Xiag\Rql\Parser\Lexer;
use Xiag\Rql\Parser\Parser;
use Xiag\Rql\Parser\Token;
use Xiag\Rql\Parser\TypeCasterInterface;
use Xiag\Rql\Parser\Exception\SyntaxErrorException;
use Xiag\Rql\Parser\NodeParser\Query\ComparisonOperator\Rql\EqNodeParser;
use Xiag\Rql\Parser\ValueParser;
require __DIR__ . '/../vendor/autoload.php';
class TimestampCaster implements TypeCasterInterface
{
    /**
     * @inheritdoc
     */
    public function typeCast(Token $token)
    {
        if (!$token->test(Token::T_INTEGER)) {
            throw new SyntaxErrorException('Timestamp type caster expects an integer token');
        }
        return new \DateTime('@' . $token->getValue());
    }
}
$scalarParser = (new ValueParser\ScalarParser())->registerTypeCaster('timestamp', new TimestampCaster());
$fieldNameParser = new ValueParser\FieldParser();
$nodeParser = new EqNodeParser($fieldNameParser, $scalarParser);
// parse
$lexer = new Lexer();
$parser = new Parser($nodeParser);
$tokenStream = $lexer->tokenize('eq(a,timestamp:1444000000)');
var_dump($parser->parse($tokenStream));
예제 #9
0
<?php

namespace Xiag\Rql\ParserExample01;

use Xiag\Rql\Parser\Lexer;
use Xiag\Rql\Parser\Parser;
use Xiag\Rql\Parser\ExpressionParser;
use Xiag\Rql\Parser\TokenParserGroup;
use Xiag\Rql\Parser\TokenParser\Query\GroupTokenParser;
use Xiag\Rql\Parser\TokenParser\Query\Fiql;
require __DIR__ . '/../vendor/autoload.php';
$queryTokenParser = new TokenParserGroup();
$queryTokenParser->addTokenParser(new GroupTokenParser($queryTokenParser))->addTokenParser(new Fiql\ArrayOperator\InTokenParser())->addTokenParser(new Fiql\ArrayOperator\OutTokenParser())->addTokenParser(new Fiql\ScalarOperator\EqTokenParser())->addTokenParser(new Fiql\ScalarOperator\NeTokenParser())->addTokenParser(new Fiql\ScalarOperator\LtTokenParser())->addTokenParser(new Fiql\ScalarOperator\GtTokenParser())->addTokenParser(new Fiql\ScalarOperator\LeTokenParser())->addTokenParser(new Fiql\ScalarOperator\GeTokenParser());
$parser = new Parser(new ExpressionParser());
$parser->addTokenParser($queryTokenParser);
$lexer = new Lexer();
// ok
$tokenStream = $lexer->tokenize('((a==true|b!=str)&c>=10&d=in=(1,value,null))');
var_dump($parser->parse($tokenStream));
// error
$tokenStream = $lexer->tokenize('or(eq(a,true),ne(b,str))&gte(c,10)&in(d,(1,value,null))');
var_dump($parser->parse($tokenStream));
예제 #10
0
    private function visitLogicalNode(Node\Query\AbstractLogicalOperatorNode $node, SqlBuilder $sqlBuilder)
    {
        if ($node->getNodeName() === 'not') {
            $operator = ' AND ';
            $sqlBuilder->addRawWhere('NOT');
        } elseif ($node->getNodeName() === 'and') {
            $operator = ' AND ';
        } elseif ($node->getNodeName() === 'or') {
            $operator = ' OR ';
        } else {
            throw new \LogicException(sprintf('Unknown logical node "%s"', $node->getNodeName()));
        }
        $sqlBuilder->addRawWhere('(');
        foreach ($node->getQueries() as $index => $query) {
            $this->visitQueryNode($query, $sqlBuilder);
            if ($index !== count($node->getQueries()) - 1) {
                $sqlBuilder->addRawWhere($operator);
            }
        }
        $sqlBuilder->addRawWhere(')');
    }
}
// parse
$lexer = new Lexer();
$parser = new Parser();
$query = $parser->parse($lexer->tokenize(implode('&', ['select(a,b,c)', 'ne(a,b)', '(not(c=d)|e=f)&out(c,(1,2))', 'in(d,(true(),false(),null(),empty()))', 'ge(e,2016-06-30T12:09:44Z)', 'like(f,*sea?rch?)', 'sort(-a,+b)', 'limit(1,0)'])));
// traversing
$sqlBuilder = new SqlBuilder();
$nodeVisitor = new SqlNodeVisitor();
$nodeVisitor->visit($query, $sqlBuilder);
var_dump($sqlBuilder->createQuery());
예제 #11
0
use Xiag\Rql\Parser\Exception\SyntaxErrorException;
use Xiag\Rql\Parser\Lexer;
use Xiag\Rql\Parser\Node;
use Xiag\Rql\Parser\Parser;
use Xiag\Rql\Parser\Token;
use Xiag\Rql\Parser\SubLexerChain;
use Xiag\Rql\Parser\SubLexer;
use Xiag\Rql\Parser\SubLexerInterface;
require __DIR__ . '/../vendor/autoload.php';
class DateSubLexer implements SubLexerInterface
{
    /**
     * @inheritdoc
     */
    public function getTokenAt($code, $cursor)
    {
        if (!preg_match('/(?<y>\\d{4})-(?<m>\\d{2})-(?<d>\\d{2})/A', $code, $matches, null, $cursor)) {
            return null;
        }
        if (!checkdate($matches['m'], $matches['d'], $matches['y'])) {
            throw new SyntaxErrorException(sprintf('Invalid date value "%s"', $matches[0]));
        }
        return new Token(Token::T_DATE, $matches[0] . 'T00:00:00+00:00', $cursor, $cursor + strlen($matches[0]));
    }
}
$subLexer = (new SubLexerChain())->addSubLexer(new SubLexer\ConstantSubLexer())->addSubLexer(new SubLexer\PunctuationSubLexer())->addSubLexer(new SubLexer\FiqlOperatorSubLexer())->addSubLexer(new SubLexer\RqlOperatorSubLexer())->addSubLexer(new SubLexer\TypeSubLexer())->addSubLexer(new SubLexer\GlobSubLexer())->addSubLexer(new SubLexer\StringSubLexer())->addSubLexer(new SubLexer\DatetimeSubLexer())->addSubLexer(new DateSubLexer())->addSubLexer(new SubLexer\NumberSubLexer())->addSubLexer(new SubLexer\SortSubLexer());
// parse
$lexer = new Lexer($subLexer);
$parser = new Parser();
$tokenStream = $lexer->tokenize('in(a,(2016-06-30,2016-06-30T09:12:33Z))');
var_dump($parser->parse($tokenStream));
예제 #12
0
 /**
  * @param string $value
  * @return Glob
  */
 private function getGlob($value)
 {
     $lexer = new Lexer();
     $parser = new Parser();
     $rql = 'like(field,' . $value . ')';
     $stream = $lexer->tokenize($rql);
     $query = $parser->parse($stream);
     /** @var LikeNode $like */
     $like = $query->getQuery();
     $this->assertInstanceOf(LikeNode::class, $like);
     /** @var Glob $glob */
     $glob = $like->getValue();
     $this->assertInstanceOf(Glob::class, $glob);
     return $glob;
 }
use Xiag\Rql\Parser\Parser;
use Xiag\Rql\Parser\Node;
use Xiag\Rql\Parser\Token;
use Xiag\Rql\Parser\NodeParser\Query\ComparisonOperator\Rql\InNodeParser;
use Xiag\Rql\Parser\TokenStream;
use Xiag\Rql\Parser\ValueParser;
require __DIR__ . '/../vendor/autoload.php';
class ArrayParser extends ValueParser\ArrayParser
{
    /**
     * @inheritdoc
     */
    public function parse(TokenStream $tokenStream)
    {
        if ($tokenStream->nextIf(Token::T_TYPE, 'array')) {
            $tokenStream->expect(Token::T_COLON);
            return [$this->itemParser->parse($tokenStream)];
        } else {
            return parent::parse($tokenStream);
        }
    }
}
$scalarParser = new ValueParser\ScalarParser();
$fieldNameParser = new ValueParser\FieldParser();
$arrayParser = new ArrayParser($scalarParser);
$nodeParser = new InNodeParser($fieldNameParser, $arrayParser);
// parse
$lexer = new Lexer();
$parser = new Parser($nodeParser);
$tokenStream = $lexer->tokenize(implode('&', ['in(a,(1,string,true()))', 'in(b,array:1)']));
var_dump($parser->parse($tokenStream));
예제 #14
0
 /**
  * Workaround for https://github.com/xiag-ag/rql-parser/issues/8
  *
  * @param string $code
  *
  * @return \Xiag\Rql\Parser\TokenStream
  * @author Andreas Glaser
  */
 public function tokenize($code)
 {
     $code = str_replace('.', '%2E', $code);
     return parent::tokenize($code);
 }
예제 #15
0
        if ($tokenStream->nextIf(Token::T_FALSE)) {
            return false;
        } elseif ($tokenStream->nextIf(Token::T_TRUE)) {
            return true;
        } elseif ($tokenStream->nextIf(Token::T_NULL)) {
            return null;
        } elseif ($tokenStream->nextIf(Token::T_DATE)) {
            return new \DateTime($token->getValue());
        } elseif ($tokenStream->nextIf(Token::T_STRING)) {
            return $token->getValue();
        } elseif ($tokenStream->nextIf(Token::T_INTEGER)) {
            return (int) $token->getValue();
        } elseif ($tokenStream->nextIf(Token::T_FLOAT)) {
            return (double) $token->getValue();
        }
        throw new SyntaxErrorException(sprintf('Invalid scalar token "%s" (%s)', $token->getValue(), $token->getName()));
    }
}
$subLexer = (new SubLexerChain())->addSubLexer(new SubLexer\PunctuationSubLexer())->addSubLexer(new SubLexer\FiqlOperatorSubLexer())->addSubLexer(new SubLexer\RqlOperatorSubLexer())->addSubLexer(new ConstantSubLexer())->addSubLexer(new StringSubLexer())->addSubLexer(new IdentifierSubLexer())->addSubLexer(new SubLexer\DatetimeSubLexer())->addSubLexer(new SubLexer\NumberSubLexer())->addSubLexer(new SubLexer\SortSubLexer());
$identifierParser = new IdentifierParser();
$scalarParser = new ScalarParser();
$arrayParser = new ValueParser\ArrayParser($scalarParser);
$integerParser = new ValueParser\IntegerParser();
$queryNodeParser = new NodeParser\QueryNodeParser();
$queryNodeParser->addNodeParser(new NodeParser\Query\GroupNodeParser($queryNodeParser))->addNodeParser(new LogicalOperator\AndNodeParser($queryNodeParser))->addNodeParser(new LogicalOperator\OrNodeParser($queryNodeParser))->addNodeParser(new LogicalOperator\NotNodeParser($queryNodeParser))->addNodeParser(new ComparisonOperator\Rql\InNodeParser($identifierParser, $arrayParser))->addNodeParser(new ComparisonOperator\Rql\OutNodeParser($identifierParser, $arrayParser))->addNodeParser(new ComparisonOperator\Rql\EqNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Rql\NeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Rql\LtNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Rql\GtNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Rql\LeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Rql\GeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Rql\LikeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\InNodeParser($identifierParser, $arrayParser))->addNodeParser(new ComparisonOperator\Fiql\OutNodeParser($identifierParser, $arrayParser))->addNodeParser(new ComparisonOperator\Fiql\EqNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\NeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\LtNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\GtNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\LeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\GeNodeParser($identifierParser, $scalarParser))->addNodeParser(new ComparisonOperator\Fiql\LikeNodeParser($identifierParser, $scalarParser));
$nodeParser = (new NodeParserChain())->addNodeParser($queryNodeParser)->addNodeParser(new NodeParser\SelectNodeParser($identifierParser))->addNodeParser(new NodeParser\SortNodeParser($identifierParser))->addNodeParser(new NodeParser\LimitNodeParser($integerParser));
// parse
$lexer = new Lexer($subLexer);
$parser = new Parser($nodeParser);
$tokenStream = $lexer->tokenize(implode('&', ['select(a.b,c.d)', 'ne(a.b,"quoted string !@#$%^&*()_+[]{} ;:\'\\"\\| ,<.>/? ~ + escaped \\" double quote")', '(not(c.d="d")|e=false)', 'out(f,(1,"2",null,2016-06-29T23:30:33Z,true))', 'sort(-a.b,+c.d)', 'limit(1,2)']));
var_dump($parser->parse($tokenStream));