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
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,32 @@ DB::setSystemVariables(['long_query_time' => 10.0, 'tx_isolation' => 'read-commi

// Assign a variable on a different connection
DB::connection('other_mysql_connection')->setSystemVariable('long_query_time', 10.0);

// Run callback temporarily assigning a variable
DB::usingSystemVariable('long_query_time', 10.0, function () {
/* ... */
});

// Run callback temporarily assigning multiple variables
DB::usingSystemVariables(['long_query_time' => 10.0, 'tx_isolation' => 'read-committed'], function () {
/* ... */
});

// Run callback replacing current value
// NOTE: You MUST declare closure return types.
DB::usingSystemVariables(
[
'long_query_time' => function (float $currentValue): float {
return $currentValue + 5.0;
},
'sql_mode' => function (string $currentValue): string {
return str_replace('ONLY_FULL_GROUP_BY', '', $currentValue);
},
],
function () {
/* ... */
}
);
```

**WARNING:**
Expand Down Expand Up @@ -97,12 +123,14 @@ class MySqlConnection extends BaseMySqlConnection

public function withoutForeignKeyChecks(callable $callback, ...$args)
{
$this->setSystemVariable('foreign_key_checks', false);
try {
return $callback(...$args);
} finally {
$this->setSystemVariable('foreign_key_checks', true);
}
return $this->usingSystemVariable('foreign_key_checks', false, $callback, ...$args);
}

public function allowingPartialGroupBy(callable $callback, ...$args)
{
return $this->usingSystemVariable('sql_mode', function (string $mode): string {
return str_replace('ONLY_FULL_GROUP_BY', '', $mode);
}, $callback, ...$args);
}
}
```
Expand Down
40 changes: 40 additions & 0 deletions src/ExpressionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Mpyw\LaravelMySqlSystemVariableManager;

interface ExpressionInterface
{
public const TYPE_INTEGER = 'integer';
public const TYPE_BOOLEAN = 'boolean';
public const TYPE_FLOAT = 'double';
public const TYPE_STRING = 'string';

public const GRAMMATICAL_TYPE_TO_STRING_TYPE = [
'int' => self::TYPE_INTEGER,
'bool' => self::TYPE_BOOLEAN,
'float' => self::TYPE_FLOAT,
'double' => self::TYPE_FLOAT,
'string' => self::TYPE_STRING,
];

/**
* Return type.
*
* @return string
*/
public function getType(): string;

/**
* Return PDO::PARAM_* type.s
*
* @return int
*/
public function getParamType(): int;

/**
* Return placeholder for prepared statement.
*
* @return string
*/
public function getPlaceholder(): string;
}
55 changes: 55 additions & 0 deletions src/ExpressionTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Mpyw\LaravelMySqlSystemVariableManager;

use PDO;

/**
* Trait ExpressionTrait
*/
trait ExpressionTrait
{
/**
* Return type.
*
* @return string
*/
abstract public function getType(): string;

/**
* Return PDO::PARAM_* type.
*
* @return int
*/
public function getParamType(): int
{
switch ($this->getType()) {
case ExpressionInterface::TYPE_INTEGER:
return PDO::PARAM_INT;
case ExpressionInterface::TYPE_BOOLEAN:
return PDO::PARAM_BOOL;
case ExpressionInterface::TYPE_FLOAT:
case ExpressionInterface::TYPE_STRING:
default:
return PDO::PARAM_STR;
}
}

/**
* Return a placeholder format.
*
* @return string
*/
public function getPlaceholder(): string
{
switch ($this->getType()) {
case ExpressionInterface::TYPE_FLOAT:
return 'cast(? as decimal(65, 30))';
case ExpressionInterface::TYPE_INTEGER:
case ExpressionInterface::TYPE_BOOLEAN:
case ExpressionInterface::TYPE_STRING:
default:
return '?';
}
}
}
32 changes: 32 additions & 0 deletions src/ManagesSystemVariables.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,36 @@ public function setSystemVariables(array $values, bool $memoizeForReconnect = tr

return $this;
}

/**
* Run callback temporarily setting MySQL system variable for both read and write PDOs.
* It is lazily executed for unresolved PDO instance.
*
* @param string $key
* @param mixed $value
* @param callable $callback
* @param mixed ...$args
* @return $this
*/
public function usingSystemVariable(string $key, $value, callable $callback, ...$args)
{
return $this->usingSystemVariables([$key => $value], $callback, ...$args);
}

/**
* Run callback temporarily setting MySQL system variables for both read and write PDOs.
* It is lazily executed for unresolved PDO instance.
*
* @param array $values
* @param callable $callback
* @param mixed ...$args
* @return $this
*/
public function usingSystemVariables(array $values, callable $callback, ...$args)
{
(new SystemVariableTemporaryAssigner($this->readPdo, $this->pdo))
->using($values, $callback, ...$args);

return $this;
}
}
83 changes: 83 additions & 0 deletions src/Replacer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Mpyw\LaravelMySqlSystemVariableManager;

use InvalidArgumentException;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\BooleanReplacerInterface;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\CallbackBooleanReplacer;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\CallbackFloatReplacer;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\CallbackIntegerReplacer;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\CallbackStringReplacer;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\FloatReplacerInterface;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\IntegerReplacerInterface;
use Mpyw\LaravelMySqlSystemVariableManager\Replacers\StringReplacerInterface;

class Replacer
{
/**
* Create new int replacer for MySQL system variable.
*
* @param callable $callback
* @return \Mpyw\LaravelMySqlSystemVariableManager\Replacers\IntegerReplacerInterface
*/
public static function int(callable $callback): IntegerReplacerInterface
{
return new CallbackIntegerReplacer($callback);
}

/**
* Create new bool replacer for MySQL system variable.
*
* @param callable $callback
* @return \Mpyw\LaravelMySqlSystemVariableManager\Replacers\BooleanReplacerInterface
*/
public static function bool(callable $callback): BooleanReplacerInterface
{
return new CallbackBooleanReplacer($callback);
}

/**
* Create new float replacer for MySQL system variable.
*
* @param callable $callback
* @return \Mpyw\LaravelMySqlSystemVariableManager\Replacers\FloatReplacerInterface
*/
public static function float(callable $callback): FloatReplacerInterface
{
return new CallbackFloatReplacer($callback);
}

/**
* Create new string replacer for MySQL system variable.
*
* @param callable $callback
* @return \Mpyw\LaravelMySqlSystemVariableManager\Replacers\StringReplacerInterface
*/
public static function str(callable $callback): StringReplacerInterface
{
return new CallbackStringReplacer($callback);
}

/**
* Create new typed replacer for MySQL system variable.
*
* @param string $type
* @param bool|float|int|string $callback
* @return \Mpyw\LaravelMySqlSystemVariableManager\ExpressionInterface
*/
public static function as(string $type, $callback): ExpressionInterface
{
switch ($type) {
case ExpressionInterface::TYPE_INTEGER:
return static::int($callback);
case ExpressionInterface::TYPE_BOOLEAN:
return static::bool($callback);
case ExpressionInterface::TYPE_FLOAT:
return static::float($callback);
case ExpressionInterface::TYPE_STRING:
return static::str($callback);
default:
throw new InvalidArgumentException('The return type must be one of "integer", "boolean", "double" or "string".');
}
}
}
16 changes: 16 additions & 0 deletions src/Replacers/BooleanReplacerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Mpyw\LaravelMySqlSystemVariableManager\Replacers;

use Mpyw\LaravelMySqlSystemVariableManager\ExpressionInterface;

interface BooleanReplacerInterface extends ExpressionInterface
{
/**
* Replace boolean variable value.
*
* @param bool $value
* @return bool
*/
public function replace(bool $value): bool;
}
47 changes: 47 additions & 0 deletions src/Replacers/CallbackBooleanReplacer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Mpyw\LaravelMySqlSystemVariableManager\Replacers;

use Mpyw\LaravelMySqlSystemVariableManager\ExpressionInterface;
use Mpyw\LaravelMySqlSystemVariableManager\ExpressionTrait;

class CallbackBooleanReplacer implements BooleanReplacerInterface
{
use ExpressionTrait;

/**
* @var callable
*/
protected $callback;

/**
* ClosureBooleanReplacer constructor.
*
* @param callable $callback
*/
public function __construct(callable $callback)
{
$this->callback = $callback;
}

/**
* Replace boolean variable value.
*
* @param bool $value
* @return bool
*/
public function replace(bool $value): bool
{
return ($this->callback)($value);
}

/**
* Return type.
*
* @return string
*/
public function getType(): string
{
return ExpressionInterface::TYPE_BOOLEAN;
}
}
47 changes: 47 additions & 0 deletions src/Replacers/CallbackFloatReplacer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Mpyw\LaravelMySqlSystemVariableManager\Replacers;

use Mpyw\LaravelMySqlSystemVariableManager\ExpressionInterface;
use Mpyw\LaravelMySqlSystemVariableManager\ExpressionTrait;

class CallbackFloatReplacer implements FloatReplacerInterface
{
use ExpressionTrait;

/**
* @var callable
*/
protected $callback;

/**
* ClosureFloatReplacer constructor.
*
* @param callable $callback
*/
public function __construct(callable $callback)
{
$this->callback = $callback;
}

/**
* Replace float variable value.
*
* @param float $value
* @return float
*/
public function replace(float $value): float
{
return ($this->callback)($value);
}

/**
* Return type.
*
* @return string
*/
public function getType(): string
{
return ExpressionInterface::TYPE_FLOAT;
}
}
Loading