Skip to content

Commit

Permalink
big refactoring. (yiisoft#44)
Browse files Browse the repository at this point in the history
big refactoring. (yiisoft#44)
  • Loading branch information
terabytesoftw authored Feb 12, 2022
1 parent f179431 commit 9331584
Show file tree
Hide file tree
Showing 21 changed files with 2,664 additions and 428 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ Documentation is at [docs/guide/README.md](docs/guide/README.md).
[![Latest Stable Version](https://poser.pugx.org/yiisoft/db-oracle/v/stable.png)](https://packagist.org/packages/yiisoft/db-oracle)
[![Total Downloads](https://poser.pugx.org/yiisoft/db-oracle/downloads.png)](https://packagist.org/packages/yiisoft/db-oracle)
[![Build status](https://github.com/yiisoft/db-oracle/workflows/build/badge.svg)](https://github.com/yiisoft/db-oracle/actions?query=workflow%3Abuild)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/db-oracle/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/db-oracle/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/db-oracle/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/db-oracle/?branch=master)
[![codecov](https://codecov.io/gh/yiisoft/db-oracle/branch/master/graph/badge.svg?token=XGJAFXVHSH)](https://codecov.io/gh/yiisoft/db-oracle)
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Fdb-oracle%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/db-oracle/master)
[![static analysis](https://github.com/yiisoft/db-oracle/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/db-oracle/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/db-oracle/coverage.svg)](https://shepherd.dev/github/yiisoft/db-oracle)
Expand Down
20 changes: 9 additions & 11 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@
"minimum-stability": "dev",
"require": {
"ext-pdo": "*",
"php": "^7.4|^8.0",
"php": "^8.0",
"yiisoft/arrays": "^2.0",
"yiisoft/db": "dev-dev",
"yiisoft/strings": "^2.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"roave/infection-static-analysis-plugin": "^1.16",
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^4.18",
"yiisoft/active-record": "dev-master",
"roave/infection-static-analysis-plugin": "^1.6",
"vimeo/psalm": "^4.2",
"yiisoft/aliases": "^1.1|^2.0",
"yiisoft/cache": "^1.0",
"yiisoft/log": "^1.0"
Expand All @@ -49,11 +47,11 @@
}
},
"config": {
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"composer/package-versions-deprecated": true,
"infection/extension-installer": true
}
},
"prefer-stable": true,
"scripts": {
"test": "phpunit --testdox --no-interaction",
"test-watch": "phpunit-watcher watch"
}
"prefer-stable": true
}
15 changes: 5 additions & 10 deletions src/ColumnSchemaBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,11 @@ protected function buildUnsignedString(): string
*/
public function __toString(): string
{
switch ($this->getTypeCategory()) {
case self::CATEGORY_PK:
$format = '{type}{length}{check}{append}';
break;
case self::CATEGORY_NUMERIC:
$format = '{type}{length}{unsigned}{default}{notnull}{check}{append}';
break;
default:
$format = '{type}{length}{default}{notnull}{check}{append}';
}
$format = match ($this->getTypeCategory()) {
self::CATEGORY_PK => '{type}{length}{check}{append}',
self::CATEGORY_NUMERIC => '{type}{length}{unsigned}{default}{notnull}{check}{append}',
default => '{type}{length}{default}{notnull}{check}{append}',
};

return $this->buildCompleteString($format);
}
Expand Down
10 changes: 10 additions & 0 deletions src/Conditions/InConditionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@
use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Query\Conditions\InCondition;
use Yiisoft\Db\Query\Conditions\InConditionBuilder as AbstractInConditionBuilder;
use Yiisoft\Db\Query\QueryBuilderInterface;

final class InConditionBuilder extends AbstractInConditionBuilder
{
public function __construct(private QueryBuilderInterface $queryBuilder)
{
parent::__construct($queryBuilder);
}

/**
* Method builds the raw SQL from the $expression that will not be additionally
* escaped or quoted.
Expand All @@ -23,6 +29,7 @@ public function build(ExpressionInterface $expression, array &$params = []): str
{
/** @var Incondition $expression */
$splitCondition = $this->splitCondition($expression, $params);

if ($splitCondition !== null) {
return $splitCondition;
}
Expand Down Expand Up @@ -51,14 +58,17 @@ protected function splitCondition(InCondition $condition, &$params)

$maxParameters = 1000;
$count = count($values);

if ($count <= $maxParameters) {
return null;
}

$slices = [];

for ($i = 0; $i < $count; $i += $maxParameters) {
$slices[] = $this->queryBuilder->createConditionFromArray([$operator, $column, array_slice($values, $i, $maxParameters)]);
}

array_unshift($slices, ($operator === 'IN') ? 'OR' : 'AND');

return $this->queryBuilder->buildCondition($slices, $params);
Expand Down
8 changes: 7 additions & 1 deletion src/Conditions/LikeConditionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Query\Conditions\LikeConditionBuilder as AbstractLikeConditionBuilder;
use Yiisoft\Db\Query\QueryBuilderInterface;

final class LikeConditionBuilder extends AbstractLikeConditionBuilder
{
Expand All @@ -25,14 +26,19 @@ final class LikeConditionBuilder extends AbstractLikeConditionBuilder
'!' => '!!',
];

public function __construct(private QueryBuilderInterface $queryBuilder)
{
parent::__construct($queryBuilder);
}

public function build(ExpressionInterface $expression, array &$params = []): string
{
if (!isset($this->escapingReplacements['\\'])) {
/*
* Different pdo_oci8 versions may or may not implement PDO::quote(), so
* Yiisoft\Db\Schema::quoteValue() may or may not quote \.
*/
$this->escapingReplacements['\\'] = substr((string) $this->queryBuilder->getDb()->quoteValue('\\'), 1, -1);
$this->escapingReplacements['\\'] = substr((string) $this->queryBuilder->quoter()->quoteValue('\\'), 1, -1);
}

return parent::build($expression, $params);
Expand Down
30 changes: 30 additions & 0 deletions src/DDLQueryBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Oracle;

use Yiisoft\Db\Query\DDLQueryBuilder as AbstractDDLQueryBuilder;
use Yiisoft\Db\Query\QueryBuilderInterface;

final class DDLQueryBuilder extends AbstractDDLQueryBuilder
{
public function __construct(private QueryBuilderInterface $queryBuilder)
{
parent::__construct($queryBuilder);
}

public function dropCommentFromColumn(string $table, string $column): string
{
return 'COMMENT ON COLUMN '
. $this->queryBuilder->quoter()->quoteTableName($table)
. '.'
. $this->queryBuilder->quoter()->quoteColumnName($column)
. " IS ''";
}

public function dropCommentFromTable(string $table): string
{
return 'COMMENT ON TABLE ' . $this->queryBuilder->quoter()->quoteTableName($table) . " IS ''";
}
}
125 changes: 125 additions & 0 deletions src/DMLQueryBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Oracle;

use InvalidArgumentException;
use JsonException;
use Yiisoft\Db\Constraint\Constraint;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Exception\InvalidConfigException;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Query\DMLQueryBuilder as AbstractDMLQueryBuilder;
use Yiisoft\Db\Query\QueryBuilderInterface;

final class DMLQueryBuilder extends AbstractDMLQueryBuilder
{
public function __construct(private QueryBuilderInterface $queryBuilder)
{
parent::__construct($queryBuilder);
}

/**
* @link https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm#SQLRF01606
*
* @param string $table
* @param $insertColumns
* @param $updateColumns
* @param array $params
*
* @throws Exception|InvalidArgumentException|InvalidConfigException|JsonException|NotSupportedException
*
* @return string
*/
public function upsert(string $table, $insertColumns, $updateColumns, array &$params = []): string
{
$constraints = [];

/** @var Constraint[] $constraints */
[$uniqueNames, $insertNames, $updateNames] = $this->queryBuilder->prepareUpsertColumns(
$table,
$insertColumns,
$updateColumns,
$constraints
);

if (empty($uniqueNames)) {
return $this->insert($table, $insertColumns, $params);
}

if ($updateNames === []) {
/** there are no columns to update */
$updateColumns = false;
}

$onCondition = ['or'];
$quotedTableName = $this->queryBuilder->quoter()->quoteTableName($table);

foreach ($constraints as $constraint) {
$constraintCondition = ['and'];
foreach ($constraint->getColumnNames() as $name) {
$quotedName = $this->queryBuilder->quoter()->quoteColumnName($name);
$constraintCondition[] = "$quotedTableName.$quotedName=\"EXCLUDED\".$quotedName";
}

$onCondition[] = $constraintCondition;
}

$on = $this->queryBuilder->buildCondition($onCondition, $params);
[, $placeholders, $values, $params] = $this->queryBuilder->prepareInsertValues($table, $insertColumns, $params);

if (!empty($placeholders)) {
$usingSelectValues = [];
foreach ($insertNames as $index => $name) {
$usingSelectValues[$name] = new Expression($placeholders[$index]);
}

/** @psalm-suppress UndefinedInterfaceMethod */
$usingSubQuery = $this->queryBuilder->query()->select($usingSelectValues)->from('DUAL');
[$usingValues, $params] = $this->queryBuilder->build($usingSubQuery, $params);
}

$insertValues = [];
$mergeSql = 'MERGE INTO '
. $this->queryBuilder->quoter()->quoteTableName($table)
. ' '
. 'USING (' . ($usingValues ?? ltrim($values, ' '))
. ') "EXCLUDED" '
. "ON ($on)";

foreach ($insertNames as $name) {
$quotedName = $this->queryBuilder->quoter()->quoteColumnName($name);

if (strrpos($quotedName, '.') === false) {
$quotedName = '"EXCLUDED".' . $quotedName;
}

$insertValues[] = $quotedName;
}

$insertSql = 'INSERT (' . implode(', ', $insertNames) . ')' . ' VALUES (' . implode(', ', $insertValues) . ')';

if ($updateColumns === false) {
return "$mergeSql WHEN NOT MATCHED THEN $insertSql";
}

if ($updateColumns === true) {
$updateColumns = [];
foreach ($updateNames as $name) {
$quotedName = $this->queryBuilder->quoter()->quoteColumnName($name);

if (strrpos($quotedName, '.') === false) {
$quotedName = '"EXCLUDED".' . $quotedName;
}
$updateColumns[$name] = new Expression($quotedName);
}
}

[$updates, $params] = $this->queryBuilder->prepareUpdateSets($table, $updateColumns, $params);
$updateSql = 'UPDATE SET ' . implode(', ', $updates);

return "$mergeSql WHEN MATCHED THEN $updateSql WHEN NOT MATCHED THEN $insertSql";
}
}
Loading

0 comments on commit 9331584

Please sign in to comment.