db icon indicating copy to clipboard operation
db copied to clipboard

`Query::leftJoin` - a simpler way to quote join column?

Open arogachev opened this issue 2 years ago • 3 comments

use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Query\Query;

/**
 * @var ConnectionInterface $database 
 * @var string $tableName
 * @var string $childrenTableName
 */
$quoter = $database->getQuoter();
$quotedJoinColumn = $quoter->quoteTableName($tableName)  . '.' . $quoter->quoteColumnName('name');
$rawItems = (new Query($database))
    ->select($tableName . '.*')
    ->from($tableName)
    ->leftJoin($childrenTableName, [$childrenTableName . '.child' => new Expression($quotedJoinColumn)])
    ->all();

arogachev avatar Sep 22 '23 10:09 arogachev

You can use so code for quote:

$quotedJoinColumn =  $quoter->quoteColumnName($tableName . '.name');

quoteColumnName() supports column names with table.

And simpler way will be so:

use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Query\Query;

/**
 * @var ConnectionInterface $database 
 * @var string $tableName
 * @var string $childrenTableName
 */
$quoter = $database->getQuoter();
$quotedJoinColumn =  $quoter->quoteColumnName($tableName . '.name');
$rawItems = (new Query($database))
    ->select($tableName . '.*')
    ->from($tableName)
    ->leftJoin(
		$childrenTableName, 
		[$childrenTableName . '.child' => new Expression($quotedJoinColumn) ]
	)
    ->all();

vjik avatar Sep 22 '23 12:09 vjik

This could be done by one of the following ways:

  1. By default for ...Join() methods process condition of associative array as "column name" => "column name", e.g. ['parent.id' => 'child.parent_id'] quote key and value of the associative array as column names. Use Expression or parameters if need to pass value (not "column name"), e.g. ['parent.id' => 'child.parent_id', 'child.has_parent' => new Expression('1'), 'child.has_parent' => ':param']

  2. Add one more condition type, e.g. column: ['column', 'parent.id' => 'child.parent_id'] and quote key and value as column names. This condition can be used in other places (not only in ...Join()), e.g. ->where(['column', 'parent.id' => 'child.parent_id'])

  3. Add specific class of ExpressionInstance e.g. ColumnName: ['parent.id' => new ColumnName('child.parent_id')] and quote it as column name. It also can be used in other palces (where(), having(), etc)

Also there is way ->leftJoin('child', ['parent.id' => new Expression('{{child}}.[[parent_id]]')])

Tigrov avatar Sep 23 '23 05:09 Tigrov

In current implementation to $on bind params and used result string. And this OK for me, $on is not so often be a column name.

3th way from @Tigrov looks fine solution for this case.

vjik avatar Nov 05 '23 18:11 vjik