<commit_before><?php

use PHPUnit\Framework\TestCase;
use jugger\db\Query;

class WhereTest extends TestCase
{
    /**
     * @dataProvider equivalentProvider
     */
    public function testEquivalent(... $values)
    {
        $sqls = [];
        foreach ($values as $value) {
            $sqls[] = (new Query())->from('t')
                ->where($value)
                ->build();
        }

        for ($i = 0; isset($sqls[$i+1]); $i++) {
            $this->assertEquals(
                $sqls[$i],
                $sqls[$i+1]
            );
        }
    }

    public function equivalentProvider()
    {
        $number = 123;
        $array = [1,2,3];
        $string = "SELECT * FROM t";
        $query = (new Query())->from('t');

        return [
            [
                ['id' => $number],
                ['=id' => $number]
            ],
            [
                ['id' => $array],
                ['=id' => $array],
                ['@id' => $array],
            ],
            [
                ['id' => $query],
                ['=id' => $query],
                ['@id' => $query],
            ],
            [
                ['@id' => $string],
                ['@id' => $query],
            ],
            [
                ['!id' => $query],
                ['!=id' => $query],
                ['<>id' => $query],
                ['!@id' => $query],
            ],
        ];
    }

    /**
     * @dataProvider dataProvider
     */
    public function testOperators($value, $sql)
    {
        $q = (new Query())->from('t')->where($value);

        $this->assertEquals(
            $q->build(),
            "SELECT * FROM t WHERE {$sql}"
        );
    }

    public function dataProvider()
    {
        return [
            [
                't.id = t2.id',
                't.id = t2.id'
            ],
            [
                [
                    ['id' => '123'],
                    ['id' => null],
                    ['id' => true],
                ],
                "(('id' = '123') AND ('id' IS  NULL) AND ('id' IS  TRUE))"
            ],
            [
                [
                    '=col1' => 123,
                    '=col2' => null,
                    '=col3' => true,
                    '=col4' => [1,2,3],
                    '=col5' => (new Query())->from('t2'),
                ],
                "('col1' = '123' AND 'col2' IS  NULL AND 'col3' IS  TRUE AND 'col4' IN (1,2,3) AND 'col5' IN (SELECT * FROM t2))"
            ],
            [
                [
                    '!col1' => 123,
                    '!=col2' => null,
                    '<>col3' => [1,2,3],
                ],
                "('col1' <> '123' AND 'col2' IS NOT NULL AND 'col3' NOT IN (1,2,3))"
            ],
            [
                [
                    'col1' => [1,2,3],
                    '=col2' => [4,5,6],
                    '@col3' => (new Query())->from('t2'),
                ],
                "('col1' IN (1,2,3) AND 'col2' IN (4,5,6) AND 'col3' IN (SELECT * FROM t2))"
            ],
            [
                [
                    '><col1' => [1,50],
                    '>!<col2' => [50,100],
                ],
                "( BETWEEN  1 AND 50  AND  NOT BETWEEN  50 AND 100 )"
            ],
            [
                [
                    '%col1' => "str",
                    '%col2' => "%str",
                    '%col3' => "str%",
                    '%col4' => "%str%",
                    '%col5' => (new Query())->from('t'),
                ],
                "('col1' LIKE 'str' AND 'col2' LIKE '%str' AND 'col3' LIKE 'str%' AND 'col4' LIKE '%str%' AND 'col5' LIKE (SELECT * FROM t))"
            ],
            [
                [
                    '!%col1' => "str",
                    '!%col2' => "%str",
                    '!%col3' => "str%",
                    '!%col4' => "%str%",
                ],
                "('col1' NOT LIKE 'str' AND 'col2' NOT LIKE '%str' AND 'col3' NOT LIKE 'str%' AND 'col4' NOT LIKE '%str%')"
            ],
            [
                [
                    '>col1' => 1,
                    '>=col2' => 2,
                    '<col3' => 3,
                    '<=col4' => 4,
                ],
                "('col1'>'1' AND 'col2'>='2' AND 'col3'<'3' AND 'col4'<='4')"
            ],
        ];
    }

    public function testLogic()
    {
        $q1 = (new Query())->from('t');
        $q1->where([<commit_msg>add comments<commit_after><?php

use PHPUnit\Framework\TestCase;
use jugger\db\Query;

class WhereTest extends TestCase
{
    /**
     * Проверяет равнозначность различных вариантов записи
     * @dataProvider equivalentProvider
     */
    public function testEquivalent(... $values)
    {
        $sqls = [];
        foreach ($values as $value) {
            $sqls[] = (new Query())->from('t')
                ->where($value)
                ->build();
        }

        for ($i = 0; isset($sqls[$i+1]); $i++) {
            $this->assertEquals(
                $sqls[$i],
                $sqls[$i+1]
            );
        }
    }

    public function equivalentProvider()
    {
        $number = 123;
        $array = [1,2,3];
        $string = "SELECT * FROM t";
        $query = (new Query())->from('t');

        return [
            [
                ['id' => $number],
                ['=id' => $number]
            ],
            [
                ['id' => $array],
                ['=id' => $array],
                ['@id' => $array],
            ],
            [
                ['id' => $query],
                ['=id' => $query],
                ['@id' => $query],
            ],
            [
                ['@id' => $string],
                ['@id' => $query],
            ],
            [
                ['!id' => $query],
                ['!=id' => $query],
                ['<>id' => $query],
                ['!@id' => $query],
            ],
        ];
    }

    /**
     * Проверяет все доспустимые операторы
     * @dataProvider dataProvider
     */
    public function testOperators($value, $sql)
    {
        $q = (new Query())->from('t')->where($value);

        $this->assertEquals(
            $q->build(),
            "SELECT * FROM t WHERE {$sql}"
        );
    }

    public function dataProvider()
    {
        return [
            [
                't.id = t2.id',
                't.id = t2.id'
            ],
            [
                [
                    ['id' => '123'],
                    ['id' => null],
                    ['id' => true],
                ],
                "(('id' = '123') AND ('id' IS  NULL) AND ('id' IS  TRUE))"
            ],
            [
                [
                    '=col1' => 123,
                    '=col2' => null,
                    '=col3' => true,
                    '=col4' => [1,2,3],
                    '=col5' => (new Query())->from('t2'),
                ],
                "('col1' = '123' AND 'col2' IS  NULL AND 'col3' IS  TRUE AND 'col4' IN (1,2,3) AND 'col5' IN (SELECT * FROM t2))"
            ],
            [
                [
                    '!col1' => 123,
                    '!=col2' => null,
                    '<>col3' => [1,2,3],
                ],
                "('col1' <> '123' AND 'col2' IS NOT NULL AND 'col3' NOT IN (1,2,3))"
            ],
            [
                [
                    'col1' => [1,2,3],
                    '=col2' => [4,5,6],
                    '@col3' => (new Query())->from('t2'),
                ],
                "('col1' IN (1,2,3) AND 'col2' IN (4,5,6) AND 'col3' IN (SELECT * FROM t2))"
            ],
            [
                [
                    '><col1' => [1,50],
                    '>!<col2' => [50,100],
                ],
                "( BETWEEN  1 AND 50  AND  NOT BETWEEN  50 AND 100 )"
            ],
            [
                [
                    '%col1' => "str",
                    '%col2' => "%str",
                    '%col3' => "str%",
                    '%col4' => "%str%",
                    '%col5' => (new Query())->from('t'),
                ],
                "('col1' LIKE 'str' AND 'col2' LIKE '%str' AND 'col3' LIKE 'str%' AND 'col4' LIKE '%str%' AND 'col5' LIKE (SELECT * FROM t))"
            ],
            [
                [
                    '!%col1' => "str",
                    '!%col2' => "%str",
                    '!%col3' => "str%",
                    '!%col4' => "%str%",
                ],
                "('col1' NOT LIKE 'str' AND 'col2' NOT LIKE '%str' AND 'col3' NOT LIKE 'str%' AND 'col4' NOT LIKE '%str%')"
            ],
            [
                [
                    '>col1' => 1,
                    '>=col2' => 2,
                    '<col3' => 3,
                    '<=col4' => 4,
                ],
                "('col1'>'1' AND 'col2'>='2' AND 'col3'<'3' AND 'col4'<='4')"
            ],
        ];
    }

    /**
     * Проверяет логические конструкции и их вложенность
     */
    public function testLogic()
    {
        $q1 = (new Query())->from('t');
        $q1->where([
{'fraction_non_alphanumeric': 0.1863025765249945, 'fraction_numerical': 0.029288702928870293, 'mean_word_length': 0.8986204013377926, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 135, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5286720', 'n_tokens_mistral': 2952, 'n_tokens_neox': 2721, 'n_words': 575}