FriendsOfDoctrine / dbal-clickhouse

Doctrine DBAL driver for ClickHouse database
GNU General Public License v3.0
98 stars 82 forks source link

Operation 'FOD\DBALClickHouse\ClickHousePlatform::appendLockHint' is not supported by platform. #5

Open stepanselyuk opened 7 years ago

stepanselyuk commented 7 years ago

Hello, I tried to create a query using QueryBuilder, but got error:

Operation 'FOD\DBALClickHouse\ClickHousePlatform::appendLockHint' is not supported by platform.

The code which produces this error:

$qb = $this->createQueryBuilder('c')
->select('count(c)')
->andWhere('c.link = :link_id')
->setParameter('link_id', $linkId);

return $qb->getQuery()->getSingleScalarResult();

It produces DQL: SELECT count(c) FROM Trim\Clickhouse\Model\ClickStat c WHERE c.link = :link_id

Can you suggest where there is an error?

Btw, example with the connection use is working:

$conn = $this->getEntityManager()->getConnection();

return $conn->fetchColumn(
            'SELECT count() FROM clicks WHERE link_id = :link_id',
            ['link_id' => $linkId],
            0,
            ['link_id' => 'integer']
);
stepanselyuk commented 7 years ago

appendLockHint used in a query parsing code, and by default (\Doctrine\DBAL\Platforms\AbstractPlatform::appendLockHint):

    public function appendLockHint($fromClause, $lockMode)
    {
        return $fromClause;
    }

Is there a reason why \FOD\DBALClickHouse\ClickHousePlatform::appendLockHint throws exception?

mochalygin commented 7 years ago

Hi, Stepan!

ClickHouse engine does not support locks -- that's why ClickHousePlatform::appendLockHint() throws Exception.

In given query lock is unnecessary. QueryBuilder of ORM layer adds it (we suggest to use DBAL QueryBuilder).

We tried to remove this Exception to allow work with library from ORM layer as well, but we got 2 other errors:

  1. ClickHouse does not support table aliases (QB added them)
  2. ClickHouse does not accept any params in count() except *

We will think how to solve this problem. You can use library without ORM, only with DBAL.

stepanselyuk commented 7 years ago

For count() function possible to use user-defined DQL function like this:

<?php

namespace Trim\Clickhouse\DQL;

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

/**
 * ROWS_COUNT(str)
 * "ROWS_COUNT" "(" ")".
 */
class RowsCountFunction extends FunctionNode
{
    public function getSql(SqlWalker $sqlWalker)
    {
        return 'COUNT(*)';
    }

    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);          // ROWS_COUNT
        $parser->match(Lexer::T_OPEN_PARENTHESIS);
        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

But yeah, yet I didn't found a way how to remove aliases from ORM query builder. I tried just to specify alias as empty string, but got other ORM error, like expected end of string, but got other.