psylo66
psylo66

Reputation: 628

Create custom DQL like IF MySQL Function but it doesn't work - [Symfony 2]

I intend to add IfFunction to DQL but it doesn't work :

//My DQL Class
<?php

namespace Application\HappyBundle\DQL;

use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\Lexer;

/**
 * IFFunction ::= "IF" "( "ArithmeticPrimary" , "ArithmeticPrimary" ,  "ArithmeticPrimary" )"
 */
class IFFunction extends FunctionNode
{
    // (1)
    public $firstNumericExpression = null;
    public $secondNumericExpression = null;
    public $thirdNumericExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {

        $parser->match(Lexer::T_IDENTIFIER); // (2)
        $parser->match(Lexer::T_OPEN_PARENTHESIS); // (3)
        $this->firstNumericExpression = $parser->ArithmeticPrimary(); // (4)
        $parser->match(Lexer::T_COMMA); // (5)
        $this->secondNumericExpression = $parser->ArithmeticPrimary(); // (6)
        $parser->match(Lexer::T_COMMA); // (5)
        //$parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3)
        $this->thirdNumericExpression = $parser->ArithmeticPrimary(); // (6)
        $parser->match(Lexer::T_CLOSE_PARENTHESIS); // (3)

    }

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'IF(' .
            $this->firstNumericExpression->dispatch($sqlWalker) . ', ' .
            $this->secondNumericExpression->dispatch($sqlWalker) . ', ' .
            $this->thirdNumericExpression->dispatch($sqlWalker) .
        ')';
    }
}

//Déclaration in config.yml

        dql:
            datetime_functions:
                timediff: Application\HappyBundle\DQL\TimeDiff  
                addtime: Application\HappyBundle\DQL\AddTime    
            numeric_functions:
                IF: Application\HappyBundle\DQL\IFFunction            

The add of the DQL function work, but when i intend to do for exemple :

SELECT IF(1<2,'oui','non');

There is an error on char '<' If i put the If function like this

SELECT IF('1<2','oui','non');

It's work but is not evaluate the first condition :(

If someone have got an idea ... Thx for your help.

Upvotes: 2

Views: 2639

Answers (1)

psylo66
psylo66

Reputation: 628

I have found the solution, the problem was with the parser which must contain ConditionalExpression like this to evaluate :

class IfFunction extends FunctionNode
{
    private $expr = array();

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $this->expr[] = $parser->ConditionalExpression();

        for ($i = 0; $i < 2; $i++)
        {
            $parser->match(Lexer::T_COMMA);
            $this->expr[] = $parser->ArithmeticExpression();
        }

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return sprintf('IF(%s, %s, %s)',
            $sqlWalker->walkConditionalExpression($this->expr[0]),
            $sqlWalker->walkArithmeticPrimary($this->expr[1]),
            $sqlWalker->walkArithmeticPrimary($this->expr[2]));
    }
}

Upvotes: 6

Related Questions