Optimized code for database and pgsql.

This commit is contained in:
李铭昕 2022-08-09 23:14:58 +08:00
parent 07086599eb
commit 900d56c015
26 changed files with 238 additions and 381 deletions

2
src/database-pgsql/.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
/tests export-ignore
/.github export-ignore

View File

@ -1,2 +0,0 @@
/tests export-ignore
/.github export-ignore

View File

@ -19,6 +19,7 @@
},
"require": {
"php": ">=8.0",
"ext-swoole": ">=5.0",
"hyperf/database": "~3.0.0"
},
"autoload": {
@ -36,7 +37,7 @@
},
"extra": {
"branch-alias": {
"dev-main": "2.2-dev"
"dev-main": "3.0-dev"
},
"hyperf": {
"config": "Hyperf\\Database\\PgSQL\\ConfigProvider"

View File

@ -12,23 +12,10 @@ declare(strict_types=1);
namespace Hyperf\Database\PgSQL\Connectors;
use Hyperf\Database\Connectors\ConnectorInterface;
use PDO;
use Swoole\Coroutine\PostgreSQL;
class PostgresSqlSwooleExtConnector implements ConnectorInterface
{
/**
* The default PDO connection options.
*
* @var array
*/
protected $options = [
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
];
/**
* @return PostgreSQL
*/
@ -75,68 +62,41 @@ class PostgresSqlSwooleExtConnector implements ConnectorInterface
return $connection;
}
/**
* Get the default PDO connection options.
*
* @return array
*/
public function getDefaultOptions()
{
return $this->options;
}
/**
* Set the default PDO connection options.
*/
public function setDefaultOptions(array $options)
{
$this->options = $options;
}
/**
* Set the connection character set and collation.
*
* @param $connection
* @param array $config
*/
protected function configureEncoding($connection, $config)
protected function configureEncoding(PostgreSQL $connection, $config)
{
if (! isset($config['charset'])) {
return;
}
$id = uniqid();
$connection->prepare($id, "set names '{$config['charset']}'");
$connection->execute($id, []);
$connection->prepare("set names '{$config['charset']}'")->execute();
}
/**
* Set the timezone on the connection.
*
* @param $connection
*/
protected function configureTimezone($connection, array $config)
protected function configureTimezone(PostgreSQL $connection, array $config)
{
if (isset($config['timezone'])) {
$timezone = $config['timezone'];
$id = uniqid();
$connection->prepare($id, "set time zone '{$timezone}'");
$connection->execute($id, []);
$connection->prepare("set time zone '{$timezone}'")->execute();
}
}
/**
* Set the schema on the connection.
*
* @param $connection
* @param array $config
*/
protected function configureSchema($connection, $config)
protected function configureSchema(PostgreSQL $connection, $config)
{
if (isset($config['schema'])) {
$schema = $this->formatSchema($config['schema']);
$id = uniqid();
$connection->prepare($id, "set search_path to {$schema}");
$connection->execute($id, []);
$connection->prepare("set search_path to {$schema}")->execute();
}
}
@ -165,9 +125,7 @@ class PostgresSqlSwooleExtConnector implements ConnectorInterface
{
if (isset($config['application_name'])) {
$applicationName = $config['application_name'];
$id = uniqid();
$connection->prepare($id, "set application_name to '{$applicationName}'");
$connection->execute($id, []);
$connection->prepare("set application_name to '{$applicationName}'")->execute();
}
}
@ -181,8 +139,6 @@ class PostgresSqlSwooleExtConnector implements ConnectorInterface
if (! isset($config['synchronous_commit'])) {
return;
}
$id = uniqid();
$connection->prepare($id, "set synchronous_commit to '{$config['synchronous_commit']}'");
$connection->execute($id, []);
$connection->prepare("set synchronous_commit to '{$config['synchronous_commit']}'")->execute();
}
}

View File

@ -20,19 +20,11 @@ use Psr\Container\ContainerInterface;
class RegisterConnectionListener implements ListenerInterface
{
/**
* The IoC container instance.
*
* @var ContainerInterface
*/
protected $container;
/**
* Create a new connection factory instance.
*/
public function __construct(ContainerInterface $container)
public function __construct(protected ContainerInterface $container)
{
$this->container = $container;
}
public function listen(): array
@ -45,12 +37,12 @@ class RegisterConnectionListener implements ListenerInterface
/**
* register pgsql and pgsql-swoole need Connector and Connection.
*/
public function process(object $event)
public function process(object $event): void
{
Connection::resolverFor('pgsql', function ($connection, $database, $prefix, $config) {
Connection::resolverFor('pgsql', static function ($connection, $database, $prefix, $config) {
return new PostgreSqlConnection($connection, $database, $prefix, $config);
});
Connection::resolverFor('pgsql-swoole', function ($connection, $database, $prefix, $config) {
Connection::resolverFor('pgsql-swoole', static function ($connection, $database, $prefix, $config) {
return new PostgreSqlSwooleExtConnection($connection, $database, $prefix, $config);
});
}

View File

@ -49,7 +49,7 @@ class PostgreSqlConnection extends Connection
* Get the default query grammar instance.
* @return \Hyperf\Database\Query\Grammars\PostgresGrammar
*/
protected function getDefaultQueryGrammar()
protected function getDefaultQueryGrammar(): QueryGrammar
{
return $this->withTablePrefix(new QueryGrammar());
}
@ -57,7 +57,7 @@ class PostgreSqlConnection extends Connection
/**
* Get the default schema grammar instance.
*/
protected function getDefaultSchemaGrammar()
protected function getDefaultSchemaGrammar(): SchemaGrammar
{
return $this->withTablePrefix(new SchemaGrammar());
}
@ -67,7 +67,7 @@ class PostgreSqlConnection extends Connection
*
* @return \Hyperf\Database\Query\Processors\PostgresProcessor
*/
protected function getDefaultPostProcessor()
protected function getDefaultPostProcessor(): PostgresProcessor
{
return new PostgresProcessor();
}

View File

@ -19,11 +19,18 @@ use Hyperf\Database\PgSQL\Query\Grammars\PostgresSqlSwooleExtGrammar as QueryGra
use Hyperf\Database\PgSQL\Query\Processors\PostgresProcessor;
use Hyperf\Database\PgSQL\Schema\Grammars\PostgresSqlSwooleExtGrammar as SchemaGrammar;
use Hyperf\Database\PgSQL\Schema\PostgresBuilder;
use Swoole\Coroutine\PostgreSQL;
use Swoole\Coroutine\PostgreSQLStatement;
class PostgreSqlSwooleExtConnection extends Connection
{
use PostgreSqlSwooleExtManagesTransactions;
/**
* @var PostgreSQL
*/
protected mixed $pdo;
/**
* Get a schema builder instance for the connection.
*/
@ -48,11 +55,11 @@ class PostgreSqlSwooleExtConnection extends Connection
$this->getPdo();
$id = $this->prepare($query);
$statement = $this->prepare($query);
$this->recordsHaveBeenModified();
return (bool) $this->pdo->execute($id, $this->prepareBindings($bindings));
return $statement->execute($this->prepareBindings($bindings));
});
}
@ -68,10 +75,10 @@ class PostgreSqlSwooleExtConnection extends Connection
$this->getPdo();
$id = $this->prepare($query);
$statement = $this->prepare($query);
$this->recordsHaveBeenModified();
$result = $this->pdo->execute($id, $this->prepareBindings($bindings));
$result = $statement->execute($this->prepareBindings($bindings));
$this->recordsHaveBeenModified(
($count = $this->pdo->affectedRows($result)) > 0
@ -93,9 +100,9 @@ class PostgreSqlSwooleExtConnection extends Connection
$this->getPdoForSelect($useReadPdo);
$id = $this->prepare($query);
$statement = $this->prepare($query);
$result = $this->pdo->execute($id, $this->prepareBindings($bindings));
$result = $statement->execute($this->prepareBindings($bindings));
if ($result === false) {
throw new QueryException($query, [], new \Exception($this->pdo->error));
@ -110,21 +117,21 @@ class PostgreSqlSwooleExtConnection extends Connection
*/
public function cursor(string $query, array $bindings = [], bool $useReadPdo = true): \Generator
{
$this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
$statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
if ($this->pretending()) {
return [];
}
$this->getPdoForSelect($useReadPdo);
$id = $this->prepare($query);
$statement = $this->prepare($query);
$this->pdo->execute($id, $this->prepareBindings($bindings));
$statement->execute($this->prepareBindings($bindings));
return $this->pdo;
return $statement;
});
while ($record = $this->fetch($query, $bindings)) {
while ($record = $statement->fetchRow(0)) {
yield $record;
}
}
@ -140,12 +147,12 @@ class PostgreSqlSwooleExtConnection extends Connection
{
$statement = $this->prepare($query);
$result = $this->pdo->execute($statement, $bindings);
if ($result === false) {
$result = $statement->execute($bindings);
if (! $result) {
throw new QueryException($query, [], new \Exception($this->pdo->error));
}
return $this->pdo->fetchAll($result) ?: [];
return $statement->fetchAll(SW_PGSQL_ASSOC);
}
public function str_replace_once($needle, $replace, $haystack)
@ -165,7 +172,7 @@ class PostgreSqlSwooleExtConnection extends Connection
* Get the default query grammar instance.
* @return \Hyperf\Database\Grammar
*/
protected function getDefaultQueryGrammar()
protected function getDefaultQueryGrammar(): QueryGrammar
{
return $this->withTablePrefix(new QueryGrammar());
}
@ -173,17 +180,15 @@ class PostgreSqlSwooleExtConnection extends Connection
/**
* Get the default schema grammar instance.
*/
protected function getDefaultSchemaGrammar()
protected function getDefaultSchemaGrammar(): SchemaGrammar
{
return $this->withTablePrefix(new SchemaGrammar());
}
/**
* Get the default post processor instance.
*
* @return \Hyperf\Database\Query\Processors\PostgresProcessor
*/
protected function getDefaultPostProcessor()
protected function getDefaultPostProcessor(): PostgresProcessor
{
return new PostgresProcessor();
}
@ -196,19 +201,18 @@ class PostgreSqlSwooleExtConnection extends Connection
return new PostgresDriver();
}
protected function prepare(string $query): string
protected function prepare(string $query): PostgreSQLStatement
{
$num = 1;
while (strpos($query, '?')) {
$query = $this->str_replace_once('?', '$' . $num++, $query);
}
$id = uniqid();
$res = $this->pdo->prepare($id, $query);
if ($res === false) {
$statement = $this->pdo->prepare($query);
if (! $statement) {
throw new QueryException($query, [], new \Exception($this->pdo->error));
}
return $id;
return $statement;
}
}

View File

@ -23,7 +23,7 @@ class PostgresGrammar extends Grammar
*
* @var string[]
*/
protected $operators = [
protected array $operators = [
'=', '<', '>', '<=', '>=', '<>', '!=',
'like', 'not like', 'between', 'ilike', 'not ilike',
'~', '&', '|', '#', '<<', '>>', '<<=', '>>=',
@ -46,9 +46,8 @@ class PostgresGrammar extends Grammar
*
* @param array $values
* @param string $sequence
* @return string
*/
public function compileInsertGetId(Builder $query, $values, $sequence)
public function compileInsertGetId(Builder $query, $values, $sequence): string
{
return $this->compileInsert($query, $values) . ' returning ' . $this->wrap($sequence ?: 'id');
}
@ -57,9 +56,8 @@ class PostgresGrammar extends Grammar
* Compile an update statement into SQL.
*
* @param mixed $values
* @return string
*/
public function compileUpdate(Builder $query, $values)
public function compileUpdate(Builder $query, $values): string
{
$table = $this->wrapTable($query->from);
@ -117,10 +115,8 @@ class PostgresGrammar extends Grammar
/**
* Prepare the bindings for an update statement.
*
* @return array
*/
public function prepareBindingsForUpdate(array $bindings, array $values)
public function prepareBindingsForUpdate(array $bindings, array $values): array
{
$values = collect($values)->map(function ($value, $column) {
return is_array($value) || ($this->isJsonSelector($column) && ! $this->isExpression($value))
@ -137,10 +133,8 @@ class PostgresGrammar extends Grammar
/**
* Compile a delete statement into SQL.
*
* @return string
*/
public function compileDelete(Builder $query)
public function compileDelete(Builder $query): string
{
if (isset($query->joins) || isset($query->limit)) {
return $this->compileDeleteWithJoinsOrLimit($query);
@ -151,10 +145,8 @@ class PostgresGrammar extends Grammar
/**
* Compile a truncate table statement into SQL.
*
* @return array
*/
public function compileTruncate(Builder $query)
public function compileTruncate(Builder $query): array
{
return ['truncate ' . $this->wrapTable($query->from) . ' restart identity cascade' => []];
}
@ -186,9 +178,8 @@ class PostgresGrammar extends Grammar
* {@inheritdoc}
*
* @param array $where
* @return string
*/
protected function whereBasic(Builder $query, $where)
protected function whereBasic(Builder $query, $where): string
{
if (Str::contains(strtolower($where['operator']), 'like')) {
return sprintf(
@ -206,9 +197,8 @@ class PostgresGrammar extends Grammar
* Compile a "where date" clause.
*
* @param array $where
* @return string
*/
protected function whereDate(Builder $query, $where)
protected function whereDate(Builder $query, $where): string
{
$value = $this->parameter($where['value']);
@ -219,9 +209,8 @@ class PostgresGrammar extends Grammar
* Compile a "where time" clause.
*
* @param array $where
* @return string
*/
protected function whereTime(Builder $query, $where)
protected function whereTime(Builder $query, $where): string
{
$value = $this->parameter($where['value']);
@ -233,9 +222,8 @@ class PostgresGrammar extends Grammar
*
* @param string $type
* @param array $where
* @return string
*/
protected function dateBasedWhere($type, Builder $query, $where)
protected function dateBasedWhere($type, Builder $query, $where): string
{
$value = $this->parameter($where['value']);
@ -246,15 +234,14 @@ class PostgresGrammar extends Grammar
* Compile the "select *" portion of the query.
*
* @param array $columns
* @return null|string
*/
protected function compileColumns(Builder $query, $columns)
protected function compileColumns(Builder $query, $columns): ?string
{
// If the query is actually performing an aggregating select, we will let that
// compiler handle the building of the select clauses, as it will need some
// more syntax that is best handled by that function to keep things neat.
if (! is_null($query->aggregate)) {
return;
return null;
}
if (is_array($query->distinct)) {
@ -273,9 +260,8 @@ class PostgresGrammar extends Grammar
*
* @param string $column
* @param string $value
* @return string
*/
protected function compileJsonContains($column, $value)
protected function compileJsonContains($column, $value): string
{
$column = str_replace('->>', '->', $this->wrap($column));
@ -288,9 +274,8 @@ class PostgresGrammar extends Grammar
* @param string $column
* @param string $operator
* @param string $value
* @return string
*/
protected function compileJsonLength($column, $operator, $value)
protected function compileJsonLength($column, $operator, $value): string
{
$column = str_replace('->>', '->', $this->wrap($column));
@ -301,9 +286,8 @@ class PostgresGrammar extends Grammar
* Compile the lock into SQL.
*
* @param bool|string $value
* @return string
*/
protected function compileLock(Builder $query, $value)
protected function compileLock(Builder $query, $value): string
{
if (! is_string($value)) {
return $value ? 'for update' : 'for share';
@ -434,9 +418,8 @@ class PostgresGrammar extends Grammar
* Wrap the given JSON selector.
*
* @param string $value
* @return string
*/
protected function wrapJsonSelector($value)
protected function wrapJsonSelector($value): string
{
$path = explode('->', $value);
@ -491,8 +474,8 @@ class PostgresGrammar extends Grammar
{
return array_map(function ($attribute) {
return filter_var($attribute, FILTER_VALIDATE_INT) !== false
? $attribute
: "'{$attribute}'";
? $attribute
: "'{$attribute}'";
}, $path);
}
}

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
*/
namespace Hyperf\Database\PgSQL\Schema;
use Hyperf\Database\Schema\Blueprint;
use Hyperf\Database\Schema\ColumnDefinition;
use Hyperf\Utils\Str;
@ -18,15 +19,12 @@ class ForeignIdColumnDefinition extends ColumnDefinition
{
/**
* The schema builder blueprint instance.
*
* @var \Hyperf\Database\Schema\Blueprint
*/
protected $blueprint;
protected Blueprint $blueprint;
/**
* Create a new foreign ID column definition.
*
* @param \Hyperf\Database\Schema\Blueprint $blueprint
* @param array $attributes
*/
public function __construct(Blueprint $blueprint, $attributes = [])

View File

@ -20,10 +20,8 @@ class PostgresGrammar extends Grammar
{
/**
* If this Grammars supports schema changes wrapped in a transaction.
*
* @var bool
*/
protected $transactions = true;
protected bool $transactions = true;
/**
* The possible column modifiers.
@ -44,16 +42,15 @@ class PostgresGrammar extends Grammar
*
* @var string[]
*/
protected $fluentCommands = ['Comment'];
protected array $fluentCommands = ['Comment'];
/**
* Compile a create database command.
*
* @param string $name
* @param \Hyperf\Database\Connection $connection
* @return string
*/
public function compileCreateDatabase($name, $connection)
public function compileCreateDatabase($name, $connection): string
{
return sprintf(
'create database %s encoding %s',
@ -66,9 +63,8 @@ class PostgresGrammar extends Grammar
* Compile a drop database if exists command.
*
* @param string $name
* @return string
*/
public function compileDropDatabaseIfExists($name)
public function compileDropDatabaseIfExists($name): string
{
return sprintf(
'drop database if exists %s',
@ -78,20 +74,16 @@ class PostgresGrammar extends Grammar
/**
* Compile the query to determine if a table exists.
*
* @return string
*/
public function compileTableExists()
public function compileTableExists(): string
{
return "select * from information_schema.tables where table_schema = ? and table_name = ? and table_type = 'BASE TABLE'";
}
/**
* Compile the query to determine the list of columns.
*
* @return string
*/
public function compileColumnListing()
public function compileColumnListing(): string
{
return 'select column_name as column_name, data_type as data_type from information_schema.columns where table_catalog = ? and table_schema = ? and table_name = ?';
}
@ -106,39 +98,37 @@ class PostgresGrammar extends Grammar
/**
* Compile a create table command.
*
* @return array
*/
public function compileCreate(Blueprint $blueprint, Fluent $command)
public function compileCreate(Blueprint $blueprint, Fluent $command): array
{
return array_values(array_filter(array_merge([sprintf(
'%s table %s (%s)',
$blueprint->temporary ? 'create temporary' : 'create',
$this->wrapTable($blueprint),
implode(', ', $this->getColumns($blueprint))
)], $this->compileAutoIncrementStartingValues($blueprint))));
return array_values(array_filter(array_merge([
sprintf(
'%s table %s (%s)',
$blueprint->temporary ? 'create temporary' : 'create',
$this->wrapTable($blueprint),
implode(', ', $this->getColumns($blueprint))
),
], $this->compileAutoIncrementStartingValues($blueprint))));
}
/**
* Compile a column addition command.
*
* @return string
*/
public function compileAdd(Blueprint $blueprint, Fluent $command)
public function compileAdd(Blueprint $blueprint, Fluent $command): array
{
return array_values(array_filter(array_merge([sprintf(
'alter table %s %s',
$this->wrapTable($blueprint),
implode(', ', $this->prefixArray('add column', $this->getColumns($blueprint)))
)], $this->compileAutoIncrementStartingValues($blueprint))));
return array_values(array_filter(array_merge([
sprintf(
'alter table %s %s',
$this->wrapTable($blueprint),
implode(', ', $this->prefixArray('add column', $this->getColumns($blueprint)))
),
], $this->compileAutoIncrementStartingValues($blueprint))));
}
/**
* Compile the auto-incrementing column starting values.
*
* @return array
*/
public function compileAutoIncrementStartingValues(Blueprint $blueprint)
public function compileAutoIncrementStartingValues(Blueprint $blueprint): array
{
return collect($blueprint->autoIncrementingStartingValues())->map(function ($value, $column) use ($blueprint) {
return 'alter sequence ' . $blueprint->getTable() . '_' . $column . '_seq restart with ' . $value;
@ -147,10 +137,8 @@ class PostgresGrammar extends Grammar
/**
* Compile a primary key command.
*
* @return string
*/
public function compilePrimary(Blueprint $blueprint, Fluent $command)
public function compilePrimary(Blueprint $blueprint, Fluent $command): string
{
$columns = $this->columnize($command->columns);
@ -225,10 +213,8 @@ class PostgresGrammar extends Grammar
/**
* Compile a foreign key command.
*
* @return string
*/
public function compileForeign(Blueprint $blueprint, Fluent $command)
public function compileForeign(Blueprint $blueprint, Fluent $command): string
{
$sql = parent::compileForeign($blueprint, $command);

View File

@ -15,20 +15,16 @@ class PostgresSqlSwooleExtGrammar extends PostgresGrammar
{
/**
* Compile the query to determine if a table exists.
*
* @return string
*/
public function compileTableExists()
public function compileTableExists(): string
{
return "select * from information_schema.tables where table_schema = $1 and table_name = $2 and table_type = 'BASE TABLE'";
}
/**
* Compile the query to determine the list of columns.
*
* @return string
*/
public function compileColumnListing()
public function compileColumnListing(): string
{
return 'select column_name as column_name, data_type as data_type from information_schema.columns where table_catalog = $1 and table_schema = $2 and table_name = $3';
}

View File

@ -20,9 +20,8 @@ class PostgresBuilder extends Builder
* Create a database in the schema.
*
* @param string $name
* @return bool
*/
public function createDatabase($name)
public function createDatabase($name): bool
{
return $this->connection->statement(
$this->grammar->compileCreateDatabase($name, $this->connection)
@ -33,9 +32,8 @@ class PostgresBuilder extends Builder
* Drop a database from the schema if the database exists.
*
* @param string $name
* @return bool
*/
public function dropDatabaseIfExists($name)
public function dropDatabaseIfExists($name): bool
{
return $this->connection->statement(
$this->grammar->compileDropDatabaseIfExists($name)
@ -46,9 +44,8 @@ class PostgresBuilder extends Builder
* Determine if the given table exists.
*
* @param string $table
* @return bool
*/
public function hasTable($table)
public function hasTable($table): bool
{
[$schema, $table] = $this->parseSchemaAndTable($table);
@ -63,7 +60,7 @@ class PostgresBuilder extends Builder
/**
* Drop all tables from the database.
*/
public function dropAllTables()
public function dropAllTables(): void
{
$tables = [];
@ -91,7 +88,7 @@ class PostgresBuilder extends Builder
/**
* Drop all views from the database.
*/
public function dropAllViews()
public function dropAllViews(): void
{
$views = [];
@ -134,10 +131,8 @@ class PostgresBuilder extends Builder
/**
* Get all of the table names for the database.
*
* @return array
*/
public function getAllTables()
public function getAllTables(): array
{
return $this->connection->select(
$this->grammar->compileGetAllTables((array) $this->connection->getConfig('schema'))
@ -146,10 +141,8 @@ class PostgresBuilder extends Builder
/**
* Get all of the view names for the database.
*
* @return array
*/
public function getAllViews()
public function getAllViews(): array
{
return $this->connection->select(
$this->grammar->compileGetAllViews((array) $this->connection->getConfig('schema'))
@ -172,9 +165,8 @@ class PostgresBuilder extends Builder
* Get the column listing for a given table.
*
* @param string $table
* @return array
*/
public function getColumnListing($table)
public function getColumnListing($table): array
{
[$schema, $table] = $this->parseSchemaAndTable($table);

View File

@ -16,6 +16,7 @@ use DateTimeInterface;
use Doctrine\DBAL\Connection as DoctrineConnection;
use Exception;
use Hyperf\Database\Events\QueryExecuted;
use Hyperf\Database\Exception\InvalidArgumentException;
use Hyperf\Database\Exception\QueryException;
use Hyperf\Database\Query\Builder;
use Hyperf\Database\Query\Builder as QueryBuilder;
@ -23,6 +24,7 @@ use Hyperf\Database\Query\Expression;
use Hyperf\Database\Query\Grammars\Grammar as QueryGrammar;
use Hyperf\Database\Query\Processors\Processor;
use Hyperf\Database\Schema\Builder as SchemaBuilder;
use Hyperf\Database\Schema\Grammars\Grammar as SchemaGrammar;
use Hyperf\Utils\Arr;
use LogicException;
use PDO;
@ -40,77 +42,61 @@ class Connection implements ConnectionInterface
*
* @var Closure|PDO
*/
protected $pdo;
protected mixed $pdo;
/**
* The active PDO connection used for reads.
*
* @var Closure|PDO
*/
protected $readPdo;
protected mixed $readPdo;
/**
* The name of the connected database.
*
* @var string
*/
protected $database;
protected string $database;
/**
* The table prefix for the connection.
*
* @var string
*/
protected $tablePrefix = '';
protected string $tablePrefix = '';
/**
* The database connection configuration options.
*
* @var array
*/
protected $config = [];
protected array $config = [];
/**
* The reconnector instance for the connection.
*
* @var callable
*/
protected $reconnector;
protected mixed $reconnector;
/**
* The query grammar implementation.
*
* @var \Hyperf\Database\Query\Grammars\Grammar
*/
protected $queryGrammar;
protected QueryGrammar $queryGrammar;
/**
* The schema grammar implementation.
*
* @var \Hyperf\Database\Schema\Grammars\Grammar
*/
protected $schemaGrammar;
protected ?SchemaGrammar $schemaGrammar = null;
/**
* The query post processor implementation.
*
* @var \Hyperf\Database\Query\Processors\Processor
*/
protected $postProcessor;
protected Processor $postProcessor;
/**
* The event dispatcher instance.
*
* @var EventDispatcherInterface
*/
protected $events;
protected ?EventDispatcherInterface $events = null;
/**
* The default fetch mode of the connection.
*
* @var int
*/
protected $fetchMode = PDO::FETCH_OBJ;
protected int $fetchMode = PDO::FETCH_OBJ;
/**
* The number of active transactions.
@ -142,10 +128,11 @@ class Connection implements ConnectionInterface
*
* @var \Doctrine\DBAL\Connection
*/
protected $doctrineConnection;
protected mixed $doctrineConnection;
/**
* The connection resolvers.
* @var Closure[]
*/
protected static array $resolvers = [];
@ -160,10 +147,8 @@ class Connection implements ConnectionInterface
* Create a new database connection instance.
*
* @param Closure|PDO $pdo
* @param string $database
* @param string $tablePrefix
*/
public function __construct($pdo, $database = '', $tablePrefix = '', array $config = [])
public function __construct($pdo, string $database = '', string $tablePrefix = '', array $config = [])
{
$this->pdo = $pdo;
@ -210,9 +195,8 @@ class Connection implements ConnectionInterface
/**
* Get a schema builder instance for the connection.
* @return SchemaBuilder
*/
public function getSchemaBuilder()
public function getSchemaBuilder(): SchemaBuilder
{
if (is_null($this->schemaGrammar)) {
$this->useDefaultSchemaGrammar();
@ -673,10 +657,8 @@ class Connection implements ConnectionInterface
/**
* Set the reconnect instance on the connection.
*
* @return $this
*/
public function setReconnector(callable $reconnector)
public function setReconnector(callable $reconnector): static
{
$this->reconnector = $reconnector;
@ -738,11 +720,13 @@ class Connection implements ConnectionInterface
/**
* Get the schema grammar used by the connection.
*
* @return \Hyperf\Database\Schema\Grammars\Grammar
*/
public function getSchemaGrammar()
public function getSchemaGrammar(): SchemaGrammar
{
if (is_null($this->schemaGrammar)) {
$this->useDefaultSchemaGrammar();
}
return $this->schemaGrammar;
}
@ -761,20 +745,16 @@ class Connection implements ConnectionInterface
/**
* Get the query post processor used by the connection.
*
* @return \Hyperf\Database\Query\Processors\Processor
*/
public function getPostProcessor()
public function getPostProcessor(): Processor
{
return $this->postProcessor;
}
/**
* Set the query post processor used by the connection.
*
* @return $this
*/
public function setPostProcessor(Processor $processor)
public function setPostProcessor(Processor $processor): static
{
$this->postProcessor = $processor;
@ -890,21 +870,16 @@ class Connection implements ConnectionInterface
/**
* Get the table prefix for the connection.
*
* @return string
*/
public function getTablePrefix()
public function getTablePrefix(): string
{
return $this->tablePrefix;
}
/**
* Set the table prefix in use by the connection.
*
* @param string $prefix
* @return $this
*/
public function setTablePrefix($prefix)
public function setTablePrefix(string $prefix): static
{
$this->tablePrefix = $prefix;
@ -915,11 +890,8 @@ class Connection implements ConnectionInterface
/**
* Set the table prefix and return the grammar.
*
* @param \Hyperf\Database\Grammar $grammar
* @return \Hyperf\Database\Grammar
*/
public function withTablePrefix(Grammar $grammar)
public function withTablePrefix(Grammar $grammar): Grammar
{
$grammar->setTablePrefix($this->tablePrefix);
@ -928,49 +900,40 @@ class Connection implements ConnectionInterface
/**
* Register a connection resolver.
*
* @param string $driver
*/
public static function resolverFor($driver, Closure $callback)
public static function resolverFor(string $driver, Closure $callback)
{
static::$resolvers[$driver] = $callback;
}
/**
* Get the connection resolver for the given driver.
*
* @param string $driver
*/
public static function getResolver($driver)
public static function getResolver(string $driver): ?Closure
{
return static::$resolvers[$driver] ?? null;
}
/**
* Get the default query grammar instance.
*
* @return \Hyperf\Database\Query\Grammars\Grammar
*/
protected function getDefaultQueryGrammar()
protected function getDefaultQueryGrammar(): QueryGrammar
{
return new QueryGrammar();
}
/**
* Get the default schema grammar instance.
*
* @return \Hyperf\Database\Schema\Grammars\Grammar
*/
protected function getDefaultSchemaGrammar()
protected function getDefaultSchemaGrammar(): SchemaGrammar
{
throw new InvalidArgumentException("Don't has the default grammar.");
}
/**
* Get the default post processor instance.
*
* @return \Hyperf\Database\Query\Processors\Processor
*/
protected function getDefaultPostProcessor()
protected function getDefaultPostProcessor(): Processor
{
return new Processor();
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\Database\Exception;
class InvalidArgumentException extends \InvalidArgumentException
{
}

View File

@ -20,17 +20,13 @@ abstract class Grammar
/**
* The grammar table prefix.
*
* @var string
*/
protected $tablePrefix = '';
protected string $tablePrefix = '';
/**
* Wrap an array of values.
*
* @return array
*/
public function wrapArray(array $values)
public function wrapArray(array $values): array
{
return array_map([$this, 'wrap'], $values);
}
@ -38,7 +34,7 @@ abstract class Grammar
/**
* Wrap a table in keyword identifiers.
*
* @param \Hyperf\Database\Query\Expression|string $table
* @param Expression|string $table
* @return string
*/
public function wrapTable($table)
@ -53,11 +49,10 @@ abstract class Grammar
/**
* Wrap a value in keyword identifiers.
*
* @param \Hyperf\Database\Query\Expression|string $value
* @param bool $prefixAlias
* @return string
*/
public function wrap($value, $prefixAlias = false)
public function wrap(Expression|string $value, $prefixAlias = false)
{
if ($this->isExpression($value)) {
return $this->getValue($value);
@ -83,10 +78,8 @@ abstract class Grammar
/**
* Create query parameter place-holders for an array.
*
* @return string
*/
public function parameterize(array $values)
public function parameterize(array $values): string
{
return implode(', ', array_map([$this, 'parameter'], $values));
}
@ -94,10 +87,9 @@ abstract class Grammar
/**
* Get the appropriate query parameter place-holder for a value.
*
* @param mixed $value
* @return string
*/
public function parameter($value)
public function parameter(mixed $value)
{
return $this->isExpression($value) ? $this->getValue($value) : '?';
}
@ -106,9 +98,8 @@ abstract class Grammar
* Quote the given string literal.
*
* @param array|string $value
* @return string
*/
public function quoteString($value)
public function quoteString($value): string
{
if (is_array($value)) {
return implode(', ', array_map([$this, __FUNCTION__], $value));
@ -119,11 +110,8 @@ abstract class Grammar
/**
* Determine if the given value is a raw expression.
*
* @param mixed $value
* @return bool
*/
public function isExpression($value)
public function isExpression(mixed $value): bool
{
return $value instanceof Expression;
}
@ -131,10 +119,9 @@ abstract class Grammar
/**
* Get the value of a raw expression.
*
* @param \Hyperf\Database\Query\Expression $expression
* @return string
*/
public function getValue($expression)
public function getValue(Expression $expression)
{
return $expression->getValue();
}
@ -149,10 +136,8 @@ abstract class Grammar
/**
* Get the grammar's table prefix.
*
* @return string
*/
public function getTablePrefix()
public function getTablePrefix(): string
{
return $this->tablePrefix;
}
@ -160,10 +145,9 @@ abstract class Grammar
/**
* Set the grammar's table prefix.
*
* @param string $prefix
* @return $this
*/
public function setTablePrefix($prefix)
public function setTablePrefix(string $prefix): static
{
$this->tablePrefix = $prefix;
@ -199,9 +183,8 @@ abstract class Grammar
* Wrap the given value segments.
*
* @param array $segments
* @return string
*/
protected function wrapSegments($segments)
protected function wrapSegments($segments): string
{
return collect($segments)->map(function ($segment, $key) use ($segments) {
return $key == 0 && count($segments) > 1

View File

@ -497,13 +497,7 @@ class Migrator
*/
protected function getSchemaGrammar($connection): Grammar
{
if (is_null($grammar = $connection->getSchemaGrammar())) {
$connection->useDefaultSchemaGrammar();
$grammar = $connection->getSchemaGrammar();
}
return $grammar;
return $connection->getSchemaGrammar();
}
/**

View File

@ -46,30 +46,24 @@ class MySqlConnection extends Connection
/**
* Get the default query grammar instance.
*
* @return \Hyperf\Database\Query\Grammars\MySqlGrammar
*/
protected function getDefaultQueryGrammar()
protected function getDefaultQueryGrammar(): QueryGrammar
{
return $this->withTablePrefix(new QueryGrammar());
}
/**
* Get the default schema grammar instance.
*
* @return \Hyperf\Database\Schema\Grammars\MySqlGrammar
*/
protected function getDefaultSchemaGrammar()
protected function getDefaultSchemaGrammar(): SchemaGrammar
{
return $this->withTablePrefix(new SchemaGrammar());
}
/**
* Get the default post processor instance.
*
* @return \Hyperf\Database\Query\Processors\MySqlProcessor
*/
protected function getDefaultPostProcessor()
protected function getDefaultPostProcessor(): MySqlProcessor
{
return new MySqlProcessor();
}

View File

@ -13,20 +13,12 @@ namespace Hyperf\Database\Query;
class Expression
{
/**
* The value of the expression.
*
* @var mixed
*/
protected $value;
/**
* Create a new raw query expression.
* @param mixed $value
* @param mixed $value the value of the expression
*/
public function __construct($value)
public function __construct(protected mixed $value)
{
$this->value = $value;
}
/**

View File

@ -13,6 +13,7 @@ namespace Hyperf\Database\Query\Grammars;
use Hyperf\Database\Grammar as BaseGrammar;
use Hyperf\Database\Query\Builder;
use Hyperf\Database\Query\Expression;
use Hyperf\Database\Query\JoinClause;
use Hyperf\Utils\Arr;
use Hyperf\Utils\Str;
@ -261,11 +262,10 @@ class Grammar extends BaseGrammar
/**
* Wrap a value in keyword identifiers.
*
* @param \Hyperf\Database\Query\Expression|string $value
* @param bool $prefixAlias
* @return string
*/
public function wrap($value, $prefixAlias = false)
public function wrap(Expression|string $value, $prefixAlias = false)
{
if ($this->isExpression($value)) {
return $this->getValue($value);

View File

@ -17,9 +17,8 @@ class JsonExpression extends Expression
{
/**
* Create a new raw query expression.
* @param mixed $value
*/
public function __construct($value)
public function __construct(mixed $value)
{
parent::__construct(
$this->getJsonBindingParameter($value)
@ -29,11 +28,10 @@ class JsonExpression extends Expression
/**
* Translate the given value into the appropriate JSON binding parameter.
*
* @param mixed $value
* @throws \InvalidArgumentException
* @return string
*/
protected function getJsonBindingParameter($value)
protected function getJsonBindingParameter(mixed $value)
{
if ($value instanceof Expression) {
return $value->getValue();

View File

@ -14,6 +14,7 @@ namespace Hyperf\Database\Schema;
use Closure;
use Hyperf\Database\Connection;
use Hyperf\Database\ConnectionInterface;
use Hyperf\Database\Schema\Grammars\Grammar as SchemaGrammar;
use LogicException;
class Builder
@ -28,28 +29,24 @@ class Builder
/**
* The database connection instance.
*
* @var \Hyperf\Database\Connection
* @var Connection
*/
protected $connection;
protected ConnectionInterface $connection;
/**
* The schema grammar instance.
*
* @var \Hyperf\Database\Schema\Grammars\MySqlGrammar
*/
protected $grammar;
protected SchemaGrammar $grammar;
/**
* The Blueprint resolver callback.
*
* @var \Closure
*/
protected $resolver;
protected ?Closure $resolver = null;
/**
* Create a new database Schema manager.
*
* @param \Hyperf\Database\Connection $connection
* @param Connection $connection
*/
public function __construct(ConnectionInterface $connection)
{
@ -71,9 +68,8 @@ class Builder
* Determine if the given table exists.
*
* @param string $table
* @return bool
*/
public function hasTable($table)
public function hasTable($table): bool
{
$table = $this->connection->getTablePrefix() . $table;
@ -88,9 +84,8 @@ class Builder
*
* @param string $table
* @param string $column
* @return bool
*/
public function hasColumn($table, $column)
public function hasColumn($table, $column): bool
{
return in_array(
strtolower($column),
@ -102,9 +97,8 @@ class Builder
* Determine if the given table has given columns.
*
* @param string $table
* @return bool
*/
public function hasColumns($table, array $columns)
public function hasColumns($table, array $columns): bool
{
$tableColumns = array_map('strtolower', $this->getColumnListing($table));
@ -135,9 +129,8 @@ class Builder
* Get the column listing for a given table.
*
* @param string $table
* @return array
*/
public function getColumnListing($table)
public function getColumnListing($table): array
{
$results = $this->connection->selectFromWriteConnection($this->grammar->compileColumnListing(
$this->connection->getTablePrefix() . $table

View File

@ -23,24 +23,18 @@ abstract class Grammar extends BaseGrammar
{
/**
* If this Grammar supports schema changes wrapped in a transaction.
*
* @var bool
*/
protected $transactions = false;
protected bool $transactions = false;
/**
* The commands to be executed outside of create or alter command.
*
* @var array
*/
protected $fluentCommands = [];
protected array $fluentCommands = [];
/**
* Compile a rename column command.
*
* @return array
*/
public function compileRenameColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
public function compileRenameColumn(Blueprint $blueprint, Fluent $command, Connection $connection): array
{
return RenameColumn::compile($this, $blueprint, $command, $connection);
}
@ -49,19 +43,16 @@ abstract class Grammar extends BaseGrammar
* Compile a change column command into a series of SQL statements.
*
* @throws \RuntimeException
* @return array
*/
public function compileChange(Blueprint $blueprint, Fluent $command, Connection $connection)
public function compileChange(Blueprint $blueprint, Fluent $command, Connection $connection): array
{
return ChangeColumn::compile($this, $blueprint, $command, $connection);
}
/**
* Compile a foreign key command.
*
* @return string
*/
public function compileForeign(Blueprint $blueprint, Fluent $command)
public function compileForeign(Blueprint $blueprint, Fluent $command): string
{
// We need to prepare several of the elements of the foreign key definition
// before we can create the SQL, such as wrapping the tables and convert
@ -100,9 +91,8 @@ abstract class Grammar extends BaseGrammar
* Add a prefix to an array of values.
*
* @param string $prefix
* @return array
*/
public function prefixArray($prefix, array $values)
public function prefixArray($prefix, array $values): array
{
return array_map(function ($value) use ($prefix) {
return $prefix . ' ' . $value;
@ -129,7 +119,7 @@ abstract class Grammar extends BaseGrammar
* @param bool $prefixAlias
* @return string
*/
public function wrap($value, $prefixAlias = false)
public function wrap(Fluent|Expression|string $value, $prefixAlias = false)
{
return parent::wrap(
$value instanceof Fluent ? $value->name : $value,
@ -153,20 +143,16 @@ abstract class Grammar extends BaseGrammar
/**
* Get the fluent commands for the grammar.
*
* @return array
*/
public function getFluentCommands()
public function getFluentCommands(): array
{
return $this->fluentCommands;
}
/**
* Check if this Grammar supports schema changes wrapped in a transaction.
*
* @return bool
*/
public function supportsSchemaTransactions()
public function supportsSchemaTransactions(): bool
{
return $this->transactions;
}

View File

@ -24,9 +24,8 @@ class RenameColumn
* Compile a rename column command.
*
* @param \Hyperf\Database\Schema\Grammars\Grammar $grammar
* @return array
*/
public static function compile(Grammar $grammar, Blueprint $blueprint, Fluent $command, Connection $connection)
public static function compile(Grammar $grammar, Blueprint $blueprint, Fluent $command, Connection $connection): array
{
$column = $connection->getDoctrineColumn(
$grammar->getTablePrefix() . $blueprint->getTable(),

View File

@ -19,9 +19,8 @@ class MySqlBuilder extends Builder
* Determine if the given table exists.
*
* @param string $table
* @return bool
*/
public function hasTable($table)
public function hasTable($table): bool
{
$table = $this->connection->getTablePrefix() . $table;
@ -35,9 +34,8 @@ class MySqlBuilder extends Builder
* Get the column listing for a given table.
*
* @param string $table
* @return array
*/
public function getColumnListing($table)
public function getColumnListing($table): array
{
$table = $this->connection->getTablePrefix() . $table;

View File

@ -193,13 +193,7 @@ class Seed
*/
protected function getSchemaGrammar($connection): Grammar
{
if (is_null($grammar = $connection->getSchemaGrammar())) {
$connection->useDefaultSchemaGrammar();
$grammar = $connection->getSchemaGrammar();
}
return $grammar;
return $connection->getSchemaGrammar();
}
/**

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Database;
use Hyperf\Database\MySqlConnection;
use Hyperf\Database\Query\Grammars\MySqlGrammar as MySqlQueryGrammar;
use Hyperf\Database\Schema\Grammars\MySqlGrammar;
use Hyperf\Utils\Fluent;
use PHPUnit\Framework\TestCase;
/**
* @internal
* @coversNothing
*/
class GrammarTest extends TestCase
{
public function testWrap()
{
$grammar = new MySqlGrammar();
$this->assertSame('`user`', $grammar->wrap('user'));
$this->assertSame('`book`', $grammar->wrap(new Fluent(['name' => 'book'])));
}
public function testGetDefaultQueryGrammar()
{
$conn = new MySqlConnection(fn () => 1);
$grammar = $conn->getQueryGrammar();
$this->assertInstanceOf(MySqlQueryGrammar::class, $grammar);
}
}