chrisbryan17's picture
Upload folder using huggingface_hub
d2897cd verified
<?php
/** @noinspection SqlResolve SqlAggregates */
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Segment\Query;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Mautic\LeadBundle\Segment\Query\Expression\ExpressionBuilder;
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
use Mautic\LeadBundle\Segment\Query\QueryException;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCase;
class QueryBuilderTest extends TestCase
{
private QueryBuilder $queryBuilder;
private Connection $connection;
protected function setUp(): void
{
$this->connection = $this->createConnectionFake();
$this->queryBuilder = new QueryBuilder($this->connection);
}
public function testExpr(): void
{
$expr = $this->queryBuilder->expr();
Assert::assertInstanceOf(ExpressionBuilder::class, $expr);
Assert::assertSame($expr, $this->queryBuilder->expr());
}
public function testSetParameter(): void
{
$queryBuilder = $this->queryBuilder->setParameter(':one', 'first');
Assert::assertSame($queryBuilder, $this->queryBuilder);
$this->queryBuilder->setParameter('two', true);
$this->queryBuilder->setParameter(':three', false);
$this->queryBuilder->setParameter(4, 'fourth');
Assert::assertSame([
'one' => 'first',
'two' => 1,
'three' => 0,
4 => 'fourth',
], $this->queryBuilder->getParameters());
}
public function testSetQueryPart(): void
{
$this->queryBuilder->select('t.name', 't.enabled')
->distinct()
->from('table1', 't')
->leftJoin('t', 'table2', 'j', 't.id = j.tid')
->where('t.enabled = 1');
$queryBuilder = $this->queryBuilder->setQueryPart('select', 't.name');
Assert::assertSame($queryBuilder, $this->queryBuilder);
$this->queryBuilder->setQueryPart('where', 't.enabled = 0');
$this->queryBuilder->setQueryPart('groupBy', 'j.code');
$this->queryBuilder->setQueryPart('distinct', null);
$this->assertSQL('SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.tid WHERE t.enabled = 0 GROUP BY j.code');
}
public function testGetSQLSelectSimple(): void
{
$this->queryBuilder->select('1')
->from('table1');
$this->assertSQL('SELECT 1 FROM table1', 2);
}
public function testGetSQLSelectComplex(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->leftJoin('t', 'table2', 'j', 't.id = j.fid')
->where('t.enabled = 1')
->groupBy('t.type')
->having('t.salary > 5000')
->orderBy('t.id', 'DESC')
->setFirstResult(30)
->setMaxResults(10);
$this->assertSQL('SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.fid WHERE t.enabled = 1 GROUP BY t.type HAVING t.salary > 5000 ORDER BY t.id DESC LIMIT 10 OFFSET 30', 2);
}
public function testGetSQLSelectHint(): void
{
$this->queryBuilder->select('1')
->add('from', [
'table' => 'table1',
'alias' => 't',
'hint' => 'USE INDEX (`PRIMARY`)',
], true)
->where('t.enabled = 0');
$this->assertSQL('SELECT 1 FROM table1 t USE INDEX (`PRIMARY`) WHERE t.enabled = 0', 2);
}
public function testGetSQLInsert(): void
{
$this->queryBuilder->insert('table1')
->values(['name' => 'Jack', 'enabled' => 1]);
$this->assertSQL('INSERT INTO table1 (name, enabled) VALUES(Jack, 1)', 2);
}
public function testGetSQLUpdate(): void
{
$this->queryBuilder->update('table1')
->set('enabled', '1')
->where('enabled = 0');
$this->assertSQL('UPDATE table1 SET enabled = 1 WHERE enabled = 0', 2);
}
public function testGetSQLDelete(): void
{
$this->queryBuilder->delete('table1')
->where('enabled = 1');
$this->assertSQL('DELETE FROM table1 WHERE enabled = 1', 2);
}
public function testGetJoinCondition(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 'l')
->leftJoin('l', 'table2', 'j', 'l.id = j.fid');
Assert::assertSame('l.id = j.fid', $this->queryBuilder->getJoinCondition('j'));
Assert::assertFalse($this->queryBuilder->getJoinCondition('k'));
}
public function testAddJoinCondition(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->leftJoin('t', 'table2', 'j', 't.id = j.fid');
$this->queryBuilder->addJoinCondition('j', $this->queryBuilder->expr()->eq('j.removed', 1));
$this->assertSQL('SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.fid and (j.removed = 1)');
}
public function testAddJoinConditionNonExistentJoin(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->leftJoin('t', 'table2', 'j', 't.id = j.fid');
$this->expectException(QueryException::class);
$this->expectExceptionMessage('Inserting condition to nonexistent join x');
$this->queryBuilder->addJoinCondition('x', $this->queryBuilder->expr()->eq('j.removed', 1));
}
public function testReplaceJoinCondition(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 'l')
->leftJoin('l', 'table2', 'j', 'l.id = j.fid');
$this->queryBuilder->replaceJoinCondition('j', $this->queryBuilder->expr()->eq('j.removed', 1));
$this->assertSQL('SELECT t.name FROM table1 l LEFT JOIN table2 j ON j.removed = 1');
}
public function testSetParametersPairsNonArray(): void
{
$queryBuilder = $this->queryBuilder->setParametersPairs('one', 'first');
Assert::assertSame($queryBuilder, $this->queryBuilder);
$this->queryBuilder->setParametersPairs('two', 'second');
$this->queryBuilder->setParametersPairs(':three', 'third');
Assert::assertSame([
'one' => 'first',
'two' => 'second',
'three' => 'third',
], $this->queryBuilder->getParameters());
}
public function testSetParametersPairsWithArray(): void
{
$queryBuilder = $this->queryBuilder->setParametersPairs(['one', 'three', ':five'], ['first', 'third', 'fifth']);
Assert::assertSame($queryBuilder, $this->queryBuilder);
Assert::assertSame([
'one' => 'first',
'three' => 'third',
'five' => 'fifth',
], $this->queryBuilder->getParameters());
}
public function testGetTableAlias(): void
{
$this->queryBuilder->select('1')
->from('tableFrom', 'f')
->leftJoin('f', 'leftJoinTable', 'l', 'f.id = l.fid')
->rightJoin('l', 'rightJoinTable', 'r', 'l.id = r.lid')
->innerJoin('f', 'innerJoinTable', 'i', 'f.id = i.fid')
->where('t.enabled = 1')
->groupBy('t.type')
->having('t.salary > 5000')
->orderBy('t.id', 'DESC')
->setFirstResult(30)
->setMaxResults(10);
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent'));
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent', 'inner'));
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent', 'left'));
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent', 'right'));
Assert::assertSame('f', $this->queryBuilder->getTableAlias('tableFrom'));
Assert::assertFalse($this->queryBuilder->getTableAlias('tableFrom', 'inner'));
Assert::assertFalse($this->queryBuilder->getTableAlias('tableFrom', 'left'));
Assert::assertFalse($this->queryBuilder->getTableAlias('tableFrom', 'right'));
Assert::assertSame('l', $this->queryBuilder->getTableAlias('leftJoinTable'));
Assert::assertFalse($this->queryBuilder->getTableAlias('leftJoinTable', 'inner'));
Assert::assertSame('l', $this->queryBuilder->getTableAlias('leftJoinTable', 'left'));
Assert::assertFalse($this->queryBuilder->getTableAlias('leftJoinTable', 'right'));
Assert::assertSame('r', $this->queryBuilder->getTableAlias('rightJoinTable'));
Assert::assertFalse($this->queryBuilder->getTableAlias('rightJoinTable', 'inner'));
Assert::assertFalse($this->queryBuilder->getTableAlias('rightJoinTable', 'left'));
Assert::assertSame('r', $this->queryBuilder->getTableAlias('rightJoinTable', 'right'));
Assert::assertSame('i', $this->queryBuilder->getTableAlias('innerJoinTable'));
Assert::assertSame('i', $this->queryBuilder->getTableAlias('innerJoinTable', 'inner'));
Assert::assertFalse($this->queryBuilder->getTableAlias('innerJoinTable', 'left'));
Assert::assertFalse($this->queryBuilder->getTableAlias('innerJoinTable', 'right'));
}
public function testGetTableJoins(): void
{
$this->queryBuilder->select('1')
->from('tableFrom', 'f')
->leftJoin('f', 'leftJoinTable', 'l', 'f.id = l.fid')
->rightJoin('l', 'rightJoinTable', 'r', 'l.id = r.lid')
->innerJoin('f', 'innerJoinTable', 'i', 'f.id = i.fid')
->innerJoin('f', 'innerJoinTable', 'i2', 'f.id = i2.fid')
->where('t.enabled = 1')
->groupBy('t.type')
->having('t.salary > 5000')
->orderBy('t.id', 'DESC')
->setFirstResult(30)
->setMaxResults(10);
Assert::assertSame([], $this->queryBuilder->getTableJoins('nonExistent'));
Assert::assertSame([], $this->queryBuilder->getTableJoins('tableFrom'));
Assert::assertSame([
[
'joinType' => 'left',
'joinTable' => 'leftJoinTable',
'joinAlias' => 'l',
'joinCondition' => 'f.id = l.fid',
],
], $this->queryBuilder->getTableJoins('leftJoinTable'));
Assert::assertSame([
[
'joinType' => 'right',
'joinTable' => 'rightJoinTable',
'joinAlias' => 'r',
'joinCondition' => 'l.id = r.lid',
],
], $this->queryBuilder->getTableJoins('rightJoinTable'));
Assert::assertSame([
[
'joinType' => 'inner',
'joinTable' => 'innerJoinTable',
'joinAlias' => 'i',
'joinCondition' => 'f.id = i.fid',
],
[
'joinType' => 'inner',
'joinTable' => 'innerJoinTable',
'joinAlias' => 'i2',
'joinCondition' => 'f.id = i2.fid',
],
], $this->queryBuilder->getTableJoins('innerJoinTable'));
}
public function testGuessPrimaryLeadContactIdColumnWithOrphanedLeads(): void
{
$this->queryBuilder->select('1')
->from('lead_lists_leads', 'orp');
Assert::assertSame('orp.lead_id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
}
public function testGuessPrimaryLeadContactIdColumnWithoutJoins(): void
{
$this->queryBuilder->select('1')
->from('leads', 'l');
Assert::assertSame('l.id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
}
public function testGuessPrimaryLeadContactIdColumnWithNonRightJoin(): void
{
$this->queryBuilder->select('1')
->from('leads', 'l')
->leftJoin('l', 'leftJoinTable', 'lj', 'l.id = lj.lid')
->innerJoin('l', 'innerJoinTable', 'ij', 'l.id = ij.lid');
Assert::assertSame('l.id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
}
public function testGuessPrimaryLeadContactIdColumnWithNonMatchingRightJoin(): void
{
$this->queryBuilder->select('1')
->from('leads', 'l')
->rightJoin('l', 'rightJoinTable', 'r', 'l.name = r.name');
Assert::assertSame('l.id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
}
public function testGuessPrimaryLeadContactIdColumnWithMatchingRightJoin(): void
{
$this->queryBuilder->select('1')
->from('leads', 'l')
->rightJoin('l', 'rightJoinTable', 'r', 'l.id = r.lid');
Assert::assertSame('r.lid', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
}
public function testIsJoinTable(): void
{
$this->queryBuilder->select('1')
->from('leads', 'l')
->leftJoin('l', 'leftJoinTable', 'lj', 'l.id = lj.lid')
->rightJoin('l', 'rightJoinTable', 'rj', 'l.id = rj.lid')
->innerJoin('l', 'innerJoinTable', 'ij', 'l.id = ij.lid');
Assert::assertFalse($this->queryBuilder->isJoinTable('nonExistent'));
Assert::assertFalse($this->queryBuilder->isJoinTable('leads'));
Assert::assertTrue($this->queryBuilder->isJoinTable('leftJoinTable'));
Assert::assertTrue($this->queryBuilder->isJoinTable('rightJoinTable'));
Assert::assertTrue($this->queryBuilder->isJoinTable('innerJoinTable'));
}
public function testGetDebugOutput(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->leftJoin('t', 'table2', 'j', 't.id = j.fid')
->where('t.enabled = :enabled')
->andWhere('t.state IN (:states)')
->groupBy('t.type')
->having('t.salary > :salary AND t.flag = :flag')
->orderBy('t.id', 'DESC')
->setParameter('enabled', true)
->setParameter(':salary', 5000)
->setParameter('states', ['new', 'active'], ArrayParameterType::STRING)
->setParameter('flag', 'internal')
->setFirstResult(30)
->setMaxResults(10);
Assert::assertSame("SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.fid WHERE (t.enabled = 1) AND (t.state IN ('new', 'active')) GROUP BY t.type HAVING t.salary > 5000 AND t.flag = 'internal' ORDER BY t.id DESC LIMIT 10 OFFSET 30", $this->queryBuilder->getDebugOutput());
}
public function testHasLogicStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
Assert::assertFalse($this->queryBuilder->hasLogicStack());
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
Assert::assertTrue($this->queryBuilder->hasLogicStack());
}
public function testGetLogicStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
Assert::assertSame([], $this->queryBuilder->getLogicStack());
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->lt('a.salary', 3000), 'AND');
Assert::assertSame([
'a.name = John',
'a.salary < 3000',
], $this->queryBuilder->getLogicStack());
}
public function testPopLogicStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->lt('a.salary', 3000), 'AND');
Assert::assertSame([
'a.name = John',
'a.salary < 3000',
], $this->queryBuilder->popLogicStack());
Assert::assertSame([], $this->queryBuilder->getLogicStack());
}
public function testAddLogicOrWithEmptyWhere(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
Assert::assertSame([], $this->queryBuilder->getLogicStack());
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
$this->queryBuilder->applyStackLogic();
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
}
public function testAddLogicOrWithExistingWhereWithEmptyStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
Assert::assertSame(['a.name = John'], $this->queryBuilder->getLogicStack());
$this->assertSQL('SELECT t.name FROM table1 t WHERE t.enabled = 1');
$this->queryBuilder->applyStackLogic();
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR (a.name = John)');
}
public function testAddLogicOrWithExistingWhereWithExistingStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.flag', 'active'), 'OR');
Assert::assertSame(['a.flag = active'], $this->queryBuilder->getLogicStack());
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR (a.name = John)');
$this->queryBuilder->applyStackLogic();
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR (a.name = John) OR (a.flag = active)');
}
public function testAddLogicAndWithEmptyWhere(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'AND');
Assert::assertSame([], $this->queryBuilder->getLogicStack());
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
$this->queryBuilder->applyStackLogic();
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
}
public function testAddLogicAndWithExistingWhereWithEmptyStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'AND');
Assert::assertSame([], $this->queryBuilder->getLogicStack());
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) AND (a.name = John)');
$this->queryBuilder->applyStackLogic();
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) AND (a.name = John)');
}
public function testAddLogicAndWithExistingWhereWithExistingStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.flag', 'active'), 'AND');
Assert::assertSame([
'a.name = John',
'a.flag = active',
], $this->queryBuilder->getLogicStack());
$this->assertSQL('SELECT t.name FROM table1 t WHERE t.enabled = 1');
$this->queryBuilder->applyStackLogic();
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR ((a.name = John) AND (a.flag = active))');
}
public function testApplyStackLogicWithEmptyStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$queryBuilder = $this->queryBuilder->applyStackLogic();
Assert::assertSame($queryBuilder, $this->queryBuilder);
$this->assertSQL('SELECT t.name FROM table1 t WHERE t.enabled = 1');
}
public function testApplyStackLogicWithExistingStack(): void
{
$this->queryBuilder->select('t.name')
->from('table1', 't')
->where('t.enabled = 1');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'AND');
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.flag', 'active'), 'AND');
$queryBuilder = $this->queryBuilder->applyStackLogic();
Assert::assertSame($queryBuilder, $this->queryBuilder);
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) AND (a.name = John) AND (a.flag = active)');
}
private function assertSQL(string $sql, int $repeat = 1): void
{
for ($i = 0; $i < $repeat; ++$i) {
Assert::assertSame($sql, $this->queryBuilder->getSQL());
}
}
private function createConnectionFake(): Connection
{
return new class() extends Connection {
/** @noinspection PhpMissingParentConstructorInspection */
public function __construct()
{
}
public function getDatabasePlatform()
{
return new MySQLPlatform();
}
};
}
}