Skip to content

Commit

Permalink
Merge branch 'master' into allow_scalars
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik authored Apr 13, 2024
2 parents 99987b0 + a181ab6 commit b1c85ca
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 21 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# MySQL driver for Yii Database Change Log

## 1.2.1 under development
## 2.0.0 under development

- no changes in this release.
- Enh #320: Minor refactoring of `DDLQueryBuilder::getColumnDefinition()` method (@Tigrov)
- Bug #320: Change visibility of `DDLQueryBuilder::getColumnDefinition()` method to `private` (@Tigrov)
- Enh #321: Implement `SqlParser` and `ExpressionBuilder` driver classes (@Tigrov)

## 1.2.0 March 21, 2024

Expand Down
16 changes: 16 additions & 0 deletions src/Builder/ExpressionBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Mysql\Builder;

use Yiisoft\Db\Expression\AbstractExpressionBuilder;
use Yiisoft\Db\Mysql\SqlParser;

final class ExpressionBuilder extends AbstractExpressionBuilder
{
protected function createSqlParser(string $sql): SqlParser
{
return new SqlParser($sql);
}
}
21 changes: 9 additions & 12 deletions src/DDLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yiisoft\Db\QueryBuilder\AbstractDDLQueryBuilder;

use function preg_match;
use function preg_quote;
use function preg_replace;
use function trim;

Expand Down Expand Up @@ -167,27 +168,23 @@ public function renameColumn(string $table, string $oldName, string $newName): s
* @param string $table The table name.
* @param string $column The column name.
*
* @throws Throwable In case when table doesn't contain a column.
*
* @return string The column definition.
* @return string The column definition or empty string in case when schema does not contain the table
* or the table doesn't contain the column.
*/
public function getColumnDefinition(string $table, string $column): string
private function getColumnDefinition(string $table, string $column): string
{
$result = '';
$sql = $this->schema->getTableSchema($table)?->getCreateSql();

if (empty($sql)) {
return '';
}

if (preg_match_all('/^\s*([`"])(.*?)\\1\s+(.*?),?$/m', $sql, $matches) > 0) {
foreach ($matches[2] as $i => $c) {
if ($c === $column) {
$result = $matches[3][$i];
}
}
$quotedColumn = preg_quote($column, '/');

if (preg_match("/^\s*([`\"])$quotedColumn\\1\s+(.*?),?$/m", $sql, $matches) !== 1) {
return '';
}

return $result;
return $matches[2];
}
}
4 changes: 3 additions & 1 deletion src/DQLQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

namespace Yiisoft\Db\Mysql;

use Yiisoft\Db\Expression\ExpressionBuilder;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Expression\JsonExpression;
use Yiisoft\Db\Mysql\Builder\ExpressionBuilder;
use Yiisoft\Db\Mysql\Builder\JsonExpressionBuilder;
use Yiisoft\Db\QueryBuilder\AbstractDQLQueryBuilder;

Expand Down Expand Up @@ -83,6 +84,7 @@ protected function defaultExpressionBuilders(): array
parent::defaultExpressionBuilders(),
[
JsonExpression::class => JsonExpressionBuilder::class,
Expression::class => ExpressionBuilder::class,
]
);
}
Expand Down
42 changes: 42 additions & 0 deletions src/SqlParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Mysql;

use Yiisoft\Db\Syntax\AbstractSqlParser;

final class SqlParser extends AbstractSqlParser
{
public function getNextPlaceholder(int|null &$position = null): string|null
{
$result = null;
$length = $this->length - 1;

while ($this->position < $length) {
$pos = $this->position++;

match ($this->sql[$pos]) {
':' => ($word = $this->parseWord()) === ''
? $this->skipChars(':')
: $result = ':' . $word,
'"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]),
'-' => $this->sql[$this->position] === '-'
? ++$this->position && $this->skipToAfterChar("\n")

Check warning on line 25 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "Increment": --- Original +++ New @@ @@ match ($this->sql[$pos]) { ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), - '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, + '-' => $this->sql[$this->position] === '-' ? --$this->position && $this->skipToAfterChar("\n") : null, '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, default => null, };

Check warning on line 25 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndNegation": --- Original +++ New @@ @@ match ($this->sql[$pos]) { ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), - '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, + '-' => $this->sql[$this->position] === '-' ? !(++$this->position && $this->skipToAfterChar("\n")) : null, '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, default => null, };

Check warning on line 25 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndSingleSubExprNegation": --- Original +++ New @@ @@ match ($this->sql[$pos]) { ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), - '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, + '-' => $this->sql[$this->position] === '-' ? ++$this->position && !$this->skipToAfterChar("\n") : null, '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, default => null, };

Check warning on line 25 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "Increment": --- Original +++ New @@ @@ match ($this->sql[$pos]) { ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), - '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, + '-' => $this->sql[$this->position] === '-' ? --$this->position && $this->skipToAfterChar("\n") : null, '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, default => null, };

Check warning on line 25 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndNegation": --- Original +++ New @@ @@ match ($this->sql[$pos]) { ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), - '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, + '-' => $this->sql[$this->position] === '-' ? !(++$this->position && $this->skipToAfterChar("\n")) : null, '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, default => null, };

Check warning on line 25 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndSingleSubExprNegation": --- Original +++ New @@ @@ match ($this->sql[$pos]) { ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), - '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, + '-' => $this->sql[$this->position] === '-' ? ++$this->position && !$this->skipToAfterChar("\n") : null, '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, default => null, };
: null,
'/' => $this->sql[$this->position] === '*'
? ++$this->position && $this->skipToAfterString('*/')

Check warning on line 28 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "Increment": --- Original +++ New @@ @@ ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, - '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, + '/' => $this->sql[$this->position] === '*' ? --$this->position && $this->skipToAfterString('*/') : null, default => null, }; if ($result !== null) {

Check warning on line 28 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndNegation": --- Original +++ New @@ @@ ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, - '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, + '/' => $this->sql[$this->position] === '*' ? !(++$this->position && $this->skipToAfterString('*/')) : null, default => null, }; if ($result !== null) {

Check warning on line 28 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndSingleSubExprNegation": --- Original +++ New @@ @@ ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, - '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, + '/' => $this->sql[$this->position] === '*' ? ++$this->position && !$this->skipToAfterString('*/') : null, default => null, }; if ($result !== null) {

Check warning on line 28 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "Increment": --- Original +++ New @@ @@ ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, - '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, + '/' => $this->sql[$this->position] === '*' ? --$this->position && $this->skipToAfterString('*/') : null, default => null, }; if ($result !== null) {

Check warning on line 28 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndNegation": --- Original +++ New @@ @@ ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, - '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, + '/' => $this->sql[$this->position] === '*' ? !(++$this->position && $this->skipToAfterString('*/')) : null, default => null, }; if ($result !== null) {

Check warning on line 28 in src/SqlParser.php

View workflow job for this annotation

GitHub Actions / PHP 8.1-ubuntu-latest

Escaped Mutant for Mutator "LogicalAndSingleSubExprNegation": --- Original +++ New @@ @@ ':' => ($word = $this->parseWord()) === '' ? $this->skipChars(':') : ($result = ':' . $word), '"', "'", '`' => $this->skipQuotedWithEscape($this->sql[$pos]), '-' => $this->sql[$this->position] === '-' ? ++$this->position && $this->skipToAfterChar("\n") : null, - '/' => $this->sql[$this->position] === '*' ? ++$this->position && $this->skipToAfterString('*/') : null, + '/' => $this->sql[$this->position] === '*' ? ++$this->position && !$this->skipToAfterString('*/') : null, default => null, }; if ($result !== null) {
: null,
default => null,
};

if ($result !== null) {
$position = $pos;

return $result;
}
}

return null;
}
}
5 changes: 3 additions & 2 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,10 @@ public function testUpdate(
array $columns,
array|string $conditions,
array $params,
string $expected
array $expectedValues,
int $expectedCount,
): void {
parent::testUpdate($table, $columns, $conditions, $params, $expected);
parent::testUpdate($table, $columns, $conditions, $params, $expectedValues, $expectedCount);
}

/**
Expand Down
35 changes: 35 additions & 0 deletions tests/Provider/SqlParserProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Mysql\Tests\Provider;

class SqlParserProvider extends \Yiisoft\Db\Tests\Provider\SqlParserProvider
{
public static function getNextPlaceholder(): array
{
return [
...parent::getNextPlaceholder(),
[
'`:field` = :name AND age = :age',
':name',
11,
],
[
'`:fie\\`ld` = :name AND age = :age',
':name',
13,
],
[
'":fie\\"ld" = :name AND age = :age',
':name',
13,
],
[
"name = ':na\\'me' AND age = :age",
':age',
27,
],
];
}
}
22 changes: 18 additions & 4 deletions tests/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,6 @@ public function testInsertInteger()
public function testRenameColumn(): void
{
$db = $this->getConnection();

$qb = $db->getQueryBuilder();

$this->assertSame(
Expand All @@ -525,6 +524,20 @@ public function testRenameColumn(): void
SQL,
$qb->renameColumn('alpha', 'string_identifier', 'string_identifier_test'),
);

$this->assertSame(
<<<SQL
ALTER TABLE `alpha` CHANGE `non_exist_column` `new_column`
SQL,
$qb->renameColumn('alpha', 'non_exist_column', 'new_column'),
);

$this->assertSame(
<<<SQL
ALTER TABLE `non_exist_table` CHANGE `non_exist_column` `new_column`
SQL,
$qb->renameColumn('non_exist_table', 'non_exist_column', 'new_column'),
);
}

/**
Expand Down Expand Up @@ -602,10 +615,11 @@ public function testUpdate(
string $table,
array $columns,
array|string $condition,
string $expectedSQL,
array $expectedParams
array $params,
string $expectedSql,
array $expectedParams,
): void {
parent::testUpdate($table, $columns, $condition, $expectedSQL, $expectedParams);
parent::testUpdate($table, $columns, $condition, $params, $expectedSql, $expectedParams);
}

/**
Expand Down
25 changes: 25 additions & 0 deletions tests/SqlParserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Mysql\Tests;

use Yiisoft\Db\Mysql\SqlParser;
use Yiisoft\Db\Tests\AbstractSqlParserTest;

/**
* @group mysql
*/
final class SqlParserTest extends AbstractSqlParserTest
{
protected function createSqlParser(string $sql): SqlParser
{
return new SqlParser($sql);
}

/** @dataProvider \Yiisoft\Db\Mysql\Tests\Provider\SqlParserProvider::getNextPlaceholder */
public function testGetNextPlaceholder(string $sql, string|null $expectedPlaceholder, int|null $expectedPosition): void
{
parent::testGetNextPlaceholder($sql, $expectedPlaceholder, $expectedPosition);
}
}

0 comments on commit b1c85ca

Please sign in to comment.