Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/DeleteQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ByJG\MicroOrm;

use ByJG\AnyDataset\Db\DbDriverInterface;
use ByJG\AnyDataset\Db\DbFunctionsInterface;
use ByJG\MicroOrm\Exception\InvalidArgumentException;
use ByJG\MicroOrm\Interface\QueryBuilderInterface;
Expand All @@ -13,7 +14,7 @@ public static function getInstance(): DeleteQuery
return new DeleteQuery();
}

public function build(DbFunctionsInterface $dbHelper = null): SqlObject
public function build(DbFunctionsInterface|DbDriverInterface|null $dbDriverOrHelper = null): SqlObject
{
$whereStr = $this->getWhere();
if (is_null($whereStr)) {
Expand Down
19 changes: 12 additions & 7 deletions src/InsertBulkQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ByJG\MicroOrm;

use ByJG\AnyDataset\Db\DbDriverInterface;
use ByJG\AnyDataset\Db\DbFunctionsInterface;
use ByJG\MicroOrm\Exception\OrmInvalidFieldsException;
use ByJG\MicroOrm\Interface\QueryBuilderInterface;
Expand Down Expand Up @@ -60,19 +61,23 @@ public function values(array $values, bool $allowNonMatchFields = true): static
}

/**
* @param DbFunctionsInterface|null $dbHelper
* @param DbDriverInterface|DbFunctionsInterface|null $dbDriverOrHelper
* @return SqlObject
* @throws OrmInvalidFieldsException
*/
public function build(DbFunctionsInterface $dbHelper = null): SqlObject
public function build(DbFunctionsInterface|DbDriverInterface|null $dbDriverOrHelper = null): SqlObject
{
if (empty($this->fields)) {
throw new OrmInvalidFieldsException('You must specify the fields for insert');
}

if ($dbDriverOrHelper instanceof DbDriverInterface) {
$dbDriverOrHelper = $dbDriverOrHelper->getDbHelper();
}

$tableStr = $this->table;
if (!is_null($dbHelper)) {
$tableStr = $dbHelper->delimiterTable($tableStr);
if (!is_null($dbDriverOrHelper)) {
$tableStr = $dbDriverOrHelper->delimiterTable($tableStr);
}

// Extract column names
Expand All @@ -96,16 +101,16 @@ public function build(DbFunctionsInterface $dbHelper = null): SqlObject
} else {
$value = str_replace("'", "''", $this->fields[$col][$i]);
if (!is_numeric($value)) {
$value = $dbHelper?->delimiterField($value) ?? "'{$value}'";
$value = $dbDriverOrHelper?->delimiterField($value) ?? "'{$value}'";
Comment on lines 103 to +104
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect NULL Value Handling category Functionality

Tell me more
What is the issue?

The code assumes non-numeric values need field delimiters or quotes, which may not handle null values correctly.

Why this matters

NULL values could be incorrectly wrapped in quotes, causing them to be treated as strings rather than NULL in the database.

Suggested change ∙ Feature Preview

Add a specific check for NULL values before the numeric check:

if ($value === null) {
    $value = 'NULL';
} elseif (!is_numeric($value)) {
    $value = $dbDriverOrHelper?->delimiterField($value) ?? "'{$value}'";
}
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

}
$params[$paramKey] = new Literal($value); // Map parameter key to value
}
}
$placeholders[] = '(' . implode(', ', $rowPlaceholders) . ')'; // Add row placeholders to query
}

if (!is_null($dbHelper)) {
$columns = $dbHelper->delimiterField($columns);
if (!is_null($dbDriverOrHelper)) {
$columns = $dbDriverOrHelper->delimiterField($columns);
}

// Construct the final SQL query
Expand Down
17 changes: 11 additions & 6 deletions src/InsertQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ByJG\MicroOrm;

use ByJG\AnyDataset\Db\DbDriverInterface;
use ByJG\AnyDataset\Db\DbFunctionsInterface;
use ByJG\MicroOrm\Exception\InvalidArgumentException;
use ByJG\MicroOrm\Exception\OrmInvalidFieldsException;
Expand Down Expand Up @@ -65,24 +66,28 @@ public function defineFields(array $fields): static
}

/**
* @param DbFunctionsInterface|null $dbHelper
* @param DbDriverInterface|DbFunctionsInterface|null $dbDriverOrHelper
* @return SqlObject
* @throws OrmInvalidFieldsException
*/
public function build(DbFunctionsInterface $dbHelper = null): SqlObject
public function build(DbFunctionsInterface|DbDriverInterface|null $dbDriverOrHelper = null): SqlObject
{
if (empty($this->values)) {
throw new OrmInvalidFieldsException('You must specify the fields for insert');
}

if ($dbDriverOrHelper instanceof DbDriverInterface) {
$dbDriverOrHelper = $dbDriverOrHelper->getDbHelper();
}

$fieldsStr = array_keys($this->values); // get the fields from the first element only
if (!is_null($dbHelper)) {
$fieldsStr = $dbHelper->delimiterField($fieldsStr);
if (!is_null($dbDriverOrHelper)) {
$fieldsStr = $dbDriverOrHelper->delimiterField($fieldsStr);
}

$tableStr = $this->table;
if (!is_null($dbHelper)) {
$tableStr = $dbHelper->delimiterTable($tableStr);
if (!is_null($dbDriverOrHelper)) {
$tableStr = $dbDriverOrHelper->delimiterTable($tableStr);
}

$sql = 'INSERT INTO '
Expand Down
17 changes: 11 additions & 6 deletions src/InsertSelectQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace ByJG\MicroOrm;

use ByJG\AnyDataset\Db\DbDriverInterface;
use ByJG\AnyDataset\Db\DbFunctionsInterface;
use ByJG\MicroOrm\Exception\OrmInvalidFieldsException;
use ByJG\MicroOrm\Interface\QueryBuilderInterface;
Expand Down Expand Up @@ -49,30 +50,34 @@ public function fromSqlObject(SqlObject $sqlObject): static
}

/**
* @param DbFunctionsInterface|null $dbHelper
* @param DbDriverInterface|DbFunctionsInterface|null $dbDriverOrHelper
* @return SqlObject
* @throws OrmInvalidFieldsException
*/
public function build(DbFunctionsInterface $dbHelper = null): SqlObject
public function build(DbFunctionsInterface|DbDriverInterface|null $dbDriverOrHelper = null): SqlObject
{
if (empty($this->fields)) {
throw new OrmInvalidFieldsException('You must specify the fields for insert');
}

if ($dbDriverOrHelper instanceof DbDriverInterface) {
$dbDriverOrHelper = $dbDriverOrHelper->getDbHelper();
}

if (empty($this->query) && empty($this->sqlObject)) {
throw new OrmInvalidFieldsException('You must specify the query for insert');
} elseif (!empty($this->query) && !empty($this->sqlObject)) {
throw new OrmInvalidFieldsException('You must specify only one query for insert');
}

$fieldsStr = $this->fields;
if (!is_null($dbHelper)) {
$fieldsStr = $dbHelper->delimiterField($fieldsStr);
if (!is_null($dbDriverOrHelper)) {
$fieldsStr = $dbDriverOrHelper->delimiterField($fieldsStr);
}

$tableStr = $this->table;
if (!is_null($dbHelper)) {
$tableStr = $dbHelper->delimiterTable($tableStr);
if (!is_null($dbDriverOrHelper)) {
$tableStr = $dbDriverOrHelper->delimiterTable($tableStr);
}

$sql = 'INSERT INTO '
Expand Down
2 changes: 1 addition & 1 deletion src/Interface/UpdateBuilderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

interface UpdateBuilderInterface
{
public function build(?DbFunctionsInterface $dbHelper = null): SqlObject;
public function build(DbFunctionsInterface|DbDriverInterface|null $dbDriverOrHelper = null): SqlObject;

public function buildAndExecute(DbDriverInterface $dbDriver, $params = [], ?DbFunctionsInterface $dbHelper = null);

Expand Down
38 changes: 32 additions & 6 deletions src/UpdateQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace ByJG\MicroOrm;

use ByJG\AnyDataset\Db\DbDriverInterface;
use ByJG\AnyDataset\Db\DbFunctionsInterface;
use ByJG\AnyDataset\Db\SqlStatement;
use ByJG\MicroOrm\Exception\InvalidArgumentException;
use ByJG\MicroOrm\Interface\QueryBuilderInterface;
use ByJG\MicroOrm\Literal\Literal;
Expand Down Expand Up @@ -65,34 +67,58 @@ public function setLiteral(string $field, mixed $value): UpdateQuery
return $this;
}

protected function getJoinTables(DbFunctionsInterface $dbHelper = null): array
protected function getJoinTables(DbFunctionsInterface|DbDriverInterface $dbDriverOrHelper = null): array
{
$dbDriver = null;
if ($dbDriverOrHelper instanceof DbDriverInterface) {
$dbDriver = $dbDriverOrHelper;
$dbHelper = $dbDriverOrHelper->getDbHelper();
} else {
$dbHelper = $dbDriverOrHelper;
}

if (is_null($dbHelper)) {
if (!empty($this->joinTables)) {
throw new InvalidArgumentException('You must specify a DbFunctionsInterface to use join tables');
}
return ['sql' => '', 'position' => 'before_set'];
}
foreach ($this->joinTables as $key => $joinTable) {
if ($this->joinTables[$key]['table'] instanceof QueryBasic) {
if (is_null($dbDriver)) {
Throw new InvalidArgumentException('You must specify a DbDriverInterface to use Query join tables');
}
Comment on lines +88 to +90
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect 'Throw' keyword capitalization category Error Handling

Tell me more
What is the issue?

Inconsistent capitalization in the 'Throw' keyword - it should be lowercase 'throw' as per PHP standards.

Why this matters

While the error is caught correctly, using inconsistent capitalization violates PHP coding standards and makes the code less maintainable.

Suggested change ∙ Feature Preview

Replace the capitalized 'Throw' with lowercase 'throw':

if (is_null($dbDriver)) {
    throw new InvalidArgumentException('You must specify a DbDriverInterface to use Query join tables');
}
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

$this->joinTables[$key]['table'] = new SqlStatement($this->joinTables[$key]['table']->build($dbDriver)->getSql());
}
}

return $dbHelper->getJoinTablesUpdate($this->joinTables);
}

public function join(string $table, string $joinCondition): UpdateQuery
public function join(QueryBasic|string $table, string $joinCondition, ?string $alias = null): UpdateQuery
{
$this->joinTables[] = ["table" => $table, "condition" => $joinCondition];
$this->joinTables[] = ["table" => $table, "condition" => $joinCondition, "alias" => $alias];
return $this;
}

/**
* @param DbFunctionsInterface|null $dbHelper
* @param DbDriverInterface|DbFunctionsInterface|null $dbDriverOrHelper
* @return SqlObject
* @throws InvalidArgumentException
*/
public function build(DbFunctionsInterface $dbHelper = null): SqlObject
public function build(DbFunctionsInterface|DbDriverInterface|null $dbDriverOrHelper = null): SqlObject
{
if (empty($this->set)) {
throw new InvalidArgumentException('You must specify the fields for update');
}

$dbDriver = null;
if ($dbDriverOrHelper instanceof DbDriverInterface) {
$dbHelper = $dbDriverOrHelper->getDbHelper();
$dbDriver = $dbDriverOrHelper;
} else {
$dbHelper = $dbDriverOrHelper;
}

$fieldsStr = [];
$params = [];
Expand Down Expand Up @@ -120,7 +146,7 @@ public function build(DbFunctionsInterface $dbHelper = null): SqlObject
$tableName = $dbHelper->delimiterTable($tableName);
}

$joinTables = $this->getJoinTables($dbHelper);
$joinTables = $this->getJoinTables($dbDriverOrHelper);
$joinBeforeSet = $joinTables['position'] === 'before_set' ? $joinTables['sql'] : '';
$joinAfterSet = $joinTables['position'] === 'after_set' ? $joinTables['sql'] : '';

Expand Down
57 changes: 57 additions & 0 deletions tests/UpdateQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

namespace Tests;

use ByJG\AnyDataset\Db\Factory;
use ByJG\AnyDataset\Db\Helpers\DbMysqlFunctions;
use ByJG\AnyDataset\Db\Helpers\DbPgsqlFunctions;
use ByJG\AnyDataset\Db\Helpers\DbSqliteFunctions;
use ByJG\AnyDataset\Db\PdoMysql;
use ByJG\AnyDataset\Db\PdoObj;
use ByJG\MicroOrm\Exception\InvalidArgumentException;
use ByJG\MicroOrm\Query;
use ByJG\MicroOrm\SqlObject;
use ByJG\MicroOrm\SqlObjectEnum;
use ByJG\MicroOrm\UpdateQuery;
use ByJG\Util\Uri;
use PHPUnit\Framework\TestCase;

class UpdateQueryTest extends TestCase
Expand Down Expand Up @@ -144,6 +149,58 @@ public function testUpdateJoinMySQl()
);
}

public function testUpdateJoinMySQlAlias()
{
$this->object->table('test');
$this->object->join('table2', 't2.id = test.id', 't2');
$this->object->set('fld1', 'A');
$this->object->set('fld2', 'B');
$this->object->set('fld3', 'C');
$this->object->where('fld1 = :id', ['id' => 10]);

$sqlObject = $this->object->build(new DbMysqlFunctions());
$this->assertEquals(
new SqlObject(
'UPDATE `test` INNER JOIN `table2` AS t2 ON t2.id = test.id SET `fld1` = :fld1 , `fld2` = :fld2 , `fld3` = :fld3 WHERE fld1 = :id',
['id' => 10, 'fld1' => 'A', 'fld2' => 'B', 'fld3' => 'C'],
SqlObjectEnum::UPDATE
),
$sqlObject
);
}

public function testUpdateJoinMySQlSubqueryAlias()
{
$query = Query::getInstance()
->table('table2')
->where('id = 10');
$this->object->table('test');
$this->object->join($query, 't2.id = test.id', 't2');
$this->object->set('fld1', 'A');
$this->object->set('fld2', 'B');
$this->object->set('fld3', 'C');
$this->object->where('fld1 = :id', ['id' => 10]);


$dbDriver = new class extends PdoMysql
{
public function __construct()
{
$this->pdoObj = new PdoObj(new Uri('mysql://root:root@localhost/test'));
}
};

$sqlObject = $this->object->build($dbDriver);
$this->assertEquals(
new SqlObject(
'UPDATE `test` INNER JOIN (SELECT * FROM table2 WHERE id = 10) AS t2 ON t2.id = test.id SET `fld1` = :fld1 , `fld2` = :fld2 , `fld3` = :fld3 WHERE fld1 = :id',
['id' => 10, 'fld1' => 'A', 'fld2' => 'B', 'fld3' => 'C'],
SqlObjectEnum::UPDATE
),
$sqlObject
);
}

public function testUpdateJoinPostgres()
{
$this->object->table('test');
Expand Down