【问题标题】:Nested DQL User Defined Functions嵌套 DQL 用户定义函数
【发布时间】:2013-01-24 15:39:28
【问题描述】:

如果我一次返回自定义函数,它会起作用,但我想将它分成两个不同的用户定义函数。

按照这里的例子:

这是我的嵌套函数查询示例

SELECT *
FROM database
WHERE 
    FUNC_1(FUNC_2('field_name'),'constraint_default') = 
        FUNC_1(FUNC_2('value_entered'),'constraint_entered')

示例函数

<?php
namespace Foo\Bundle\FooBundle\DQL\NumericFunction;

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

class BarFunction extends FunctionNode
{
    public $stringExpression = null;
    public $trimValueExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->stringExpression = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_COMMA);

        $this->trimValueExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_1(' .
            $this->stringExpression->dispatch($sqlWalker) . ',' .
            $this->trimValueExpression->dispatch($sqlWalker) .
            ')';
    }
}

现在 FUNC_2 非常接近 FUNC_1 但永远不会被调用,因为我认为 FUNC_1 返回已解析的语法,它删除了 FUNC_2 所需的语法。

<?php
namespace Foo\Bundle\FooBundle\DQL\NumericFunction;

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

class FooFunction extends FunctionNode
{
    public $stringExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->stringExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_2(' .
            $this->stringExpression->dispatch($sqlWalker) .
        ')';
    }
}

现在我创建了一个有效的组合函数:

<?php
namespace Foo\Bundle\FooBundle\DQL\NumericFunction;

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

class CombinedFunction extends FunctionNode
{
    public $stringExpression = null;
    public $trimValueExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->stringExpression = $parser->ArithmeticPrimary();

        $parser->match(Lexer::T_COMMA);

        $this->trimValueExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_1(FUNC_2(' .
            $this->stringExpression->dispatch($sqlWalker) . '),' .
            $this->trimValueExpression->dispatch($sqlWalker) .
            ')';
    }
}

但我想知道是否可以使用嵌套的两个单独函数而不是创建这个组合函数?

想法?

更新:

添加 yml 配置

doctrine:
    dbal:
        ...

    orm:        
        entity_managers:
            foo_manager:
                dql:
                    numeric_functions:
                        FUNC_1: Foo\Bundle\FooBundle\DQL\NumericFunction\BarFunction
                        FUNC_2: Foo\Bundle\FooBundle\DQL\NumericFunction\FooFunction
                        COMB_FUNC: Foo\Bundle\FooBundle\DQL\NumericFunction\CombinedFunction

更新 #2

所以 FUNC_1 会匹配这个

FUNC_1(value_of_func_2,'constraint_default')  

FUNC_2 会匹配这个

FUNC_2('field_name')

【问题讨论】:

  • 解析器不处理这个问题吗? AFAIK,ArithmeticPrimary 可以是函数表达式。您在 DQL 中将其称为 DQL_F1(DQL_F2(...), ...) 吗?
  • @meze 是的,当我尝试单个函数时,我将其称为 FUNC_1(FUNC_2,因为这就是我在 yml 配置中为其命名的方式,添加了配置
  • 嗯,它对我有用:AND FUNC_1(FUNC_2('field_name','TEST'),'constraint_default') = FUNC_1(FUNC_2('field_name','TEST'),'constraint_default') 已生成。你能分享一下FooFunction吗?
  • FooFunction 只会匹配 FUNC_2 'FUNC_2('field_name','TEST')' 几乎一样,但我不需要检查 '),因为这是由 FUNC_1 检查的跨度>
  • 其实你需要检查)。 FUNC_1 只能看到 FUNC_1(expr1, expr2),也就是说它只能看到一个逗号。

标签: php symfony doctrine user-defined-functions dql


【解决方案1】:

我将 FUNC_2 定义为:

class FooFunction extends FunctionNode
{
    public $stringExpression = null;

    public function parse(\Doctrine\ORM\Query\Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->stringExpression = $parser->ArithmeticPrimary();

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

    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
    {
        return 'FUNC_2(' .
            $this->stringExpression->dispatch($sqlWalker) . ')';
    }
}

它为我生成了正确的 sql:FUNC_1(FUNC_2(123),123) = FUNC_1(FUNC_2(123),123)

【讨论】:

  • LOL 这是我的确切功能,但当它为我解析时,我得到 FUNC_1(123) = FUNC_1(123)。 FUNC_1 错了吗?
  • 我已将 FUNC_2 添加到我的问题中
  • 可能是 2.0.x 中的错误?我将 2.3.3-DEV 与您的课程代码一起使用
  • hmm 使用 2.3.0,也许这是一个错误。感谢您的努力 +1
  • @PhillPafford 也适用于 2.3.0 ;s 如果它有错误,它至少会产生 FUNC_1(,123)。
猜你喜欢
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-03
  • 1970-01-01
相关资源
最近更新 更多