- Merged stash after pull
This commit is contained in:
parent
114fa5be09
commit
efa957fe58
|
@ -14,4 +14,5 @@ interface AdapterInterface {
|
|||
public function buildDataSourceName() : string;
|
||||
public function setup(array $configuration) : void;
|
||||
public function escapeIdentifier(string $segment, int $type) : string;
|
||||
public function defaultEngine() : ? string;
|
||||
}
|
||||
|
|
|
@ -196,4 +196,9 @@ class MsSQL implements AdapterInterface {
|
|||
return "[" . str_replace(["[", "]"], [ "[[", "]]" ], $segment) . "]";
|
||||
}
|
||||
}
|
||||
|
||||
public function defaultEngine(): ? string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -134,4 +134,8 @@ class MySQL implements AdapterInterface {
|
|||
}
|
||||
}
|
||||
|
||||
public function defaultEngine(): ? string
|
||||
{
|
||||
return "InnoDB";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,22 @@ class Table implements \Ulmus\Annotation\Annotation {
|
|||
|
||||
public string $name;
|
||||
|
||||
public string $database;
|
||||
|
||||
public string $schema;
|
||||
|
||||
public string $adapter;
|
||||
|
||||
public string $engine;
|
||||
|
||||
public function __construct($name = null)
|
||||
public function __construct($name = null, $engine = null)
|
||||
{
|
||||
if ( $name !== null ) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
if ( $engine !== null ) {
|
||||
$this->engine = $engine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ class Field implements \Ulmus\Annotation\Annotation {
|
|||
|
||||
public int $length;
|
||||
|
||||
public int $precision;
|
||||
|
||||
public array $attributes = [];
|
||||
|
||||
public bool $nullable = false;
|
||||
|
|
|
@ -14,6 +14,7 @@ class ForeignKey extends Id {
|
|||
|
||||
unset($this->nullable);
|
||||
$this->attributes['primary_key'] = false;
|
||||
$this->attributes['auto_increment'] = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Ulmus\Common;
|
||||
|
||||
use Ulmus\Annotation\Annotation;
|
||||
use Ulmus\Migration\FieldDefinition;
|
||||
use Ulmus\Ulmus,
|
||||
Ulmus\Adapter\AdapterInterface,
|
||||
Ulmus\Annotation\Property\Field;
|
||||
|
@ -28,8 +30,8 @@ class EntityField
|
|||
{
|
||||
$name = $this->entityResolver->searchFieldAnnotation($this->name, new Field() )->name ?? $this->name;
|
||||
|
||||
$name = ( $this->entityResolver->databaseAdapter() ?? Ulmus::$defaultAdapter )->adapter()->escapeIdentifier($name, AdapterInterface::IDENTIFIER_FIELD);
|
||||
|
||||
$name = $this->entityResolver->databaseAdapter()->adapter()->escapeIdentifier($name, AdapterInterface::IDENTIFIER_FIELD);
|
||||
|
||||
return $useAlias ? "{$this->alias}.$name" : $name;
|
||||
}
|
||||
|
||||
|
@ -47,6 +49,19 @@ class EntityField
|
|||
return false;
|
||||
}
|
||||
|
||||
public static function generateCreateColumn($field) : string
|
||||
{
|
||||
$definition = new FieldDefinition($field);
|
||||
|
||||
# column_name data_type(length) [NOT NULL] [DEFAULT value] [AUTO_INCREMENT] column_constraint;
|
||||
|
||||
return implode(" ", [
|
||||
$definition->getSqlName(),
|
||||
$definition->getSqlType(),
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public static function isObjectType($type) : bool
|
||||
{
|
||||
# @ Should be fixed with isBuiltIn() instead, it won't be correct based only on name
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace Ulmus\Common;
|
||||
|
||||
use Ulmus\Annotation\Annotation,
|
||||
use Ulmus\Ulmus,
|
||||
Ulmus\Annotation\Annotation,
|
||||
Ulmus\Annotation\Classes\Table,
|
||||
Ulmus\Annotation\Property\Field,
|
||||
Ulmus\Annotation\Property\Relation;
|
||||
|
@ -123,20 +124,36 @@ class EntityResolver {
|
|||
return $list;
|
||||
}
|
||||
|
||||
public function tableName() : string
|
||||
public function tableName($required = false) : string
|
||||
{
|
||||
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
|
||||
$table = $this->tableAnnotation($required);
|
||||
|
||||
if ( ( $table->name ?? "" ) === "") {
|
||||
if ($required) {
|
||||
throw new \ArgumentCountError("Your entity {$this->entityClass} seems to be missing a `name` argument for your @Table() annotation");
|
||||
}
|
||||
}
|
||||
|
||||
if ( $table->name === "" ) {
|
||||
throw new \ArgumentCountError("Your entity {$this->entityClass} seems to be missing a `name` argument for your @Table() annotation");
|
||||
}
|
||||
|
||||
return $table->name;
|
||||
return $table->name ?? "";
|
||||
}
|
||||
|
||||
public function databaseAdapter() : ? \Ulmus\ConnectionAdapter
|
||||
public function tableAnnotation($required = false) : Table
|
||||
{
|
||||
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
if ($required) {
|
||||
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
|
||||
}
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
public function databaseName() : string
|
||||
{
|
||||
return $this->tableAnnotation(false)->database ?? $this->databaseAdapter()->adapter()->database;
|
||||
}
|
||||
|
||||
public function databaseAdapter() : \Ulmus\ConnectionAdapter
|
||||
{
|
||||
if ( null !== $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
if ( $table->adapter ?? null ) {
|
||||
|
@ -148,18 +165,17 @@ class EntityResolver {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return Ulmus::$defaultAdapter;
|
||||
}
|
||||
|
||||
|
||||
public function schemaName() : ? string
|
||||
public function schemaName(bool $required = false) : ? string
|
||||
{
|
||||
if ( null === $table = $this->getAnnotationFromClassname( Table::class ) ) {
|
||||
throw new \LogicException("Your entity {$this->entityClass} seems to be missing a @Table() annotation");
|
||||
}
|
||||
|
||||
if ( $table->name === "" ) {
|
||||
if ( $required && ( ( $table->schema ?? "" ) === "" ) ) {
|
||||
throw new \ArgumentCountError("Your entity {$this->entityClass} seems to be missing a `schema` argument for your @Table() annotation");
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ class PdoObject extends PDO {
|
|||
|
||||
public function select(string $sql, array $parameters = []): PDOStatement
|
||||
{
|
||||
//dump($sql, $parameters);
|
||||
try {
|
||||
if (false !== ( $statement = $this->prepare($sql) )) {
|
||||
$statement = $this->execute($statement, $parameters, false);
|
||||
|
|
|
@ -39,6 +39,11 @@ class ConnectionAdapter
|
|||
$this->adapter->setup($connection);
|
||||
}
|
||||
|
||||
public function getConfiguration() : array
|
||||
{
|
||||
return $this->configuration['connections'][$this->name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect the adapter
|
||||
* @return self
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Container;
|
||||
|
||||
class AdapterProxy
|
||||
{
|
||||
public array $connections = [];
|
||||
|
||||
public function __construct(...$arguments)
|
||||
{
|
||||
$this->connections = $arguments;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Entity\InformationSchema;
|
||||
|
||||
use Ulmus\Entity\Field\Datetime;
|
||||
|
||||
/**
|
||||
* @Table('name' => "columns", 'database' => "information_schema")
|
||||
*/
|
||||
class Column
|
||||
{
|
||||
use \Ulmus\EntityTrait;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_CATALOG", 'length' => 512)
|
||||
*/
|
||||
public string $tableCatalog;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_SCHEMA", 'length' => 64)
|
||||
*/
|
||||
public string $tableSchema;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_NAME", 'length' => 64)
|
||||
*/
|
||||
public string $tableName;
|
||||
|
||||
/**
|
||||
* @Field('name' => "COLUMN_NAME", 'length' => 64, 'attributes' => [ 'primary_key' => true ])
|
||||
*/
|
||||
public string $name;
|
||||
|
||||
/**
|
||||
* @Field('name' => "ORDINAL_POSITION", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public int $ordinalPosition;
|
||||
|
||||
/**
|
||||
* @Field('name' => "COLUMN_DEFAULT", 'type' => "longtext")
|
||||
*/
|
||||
public ? string $default;
|
||||
|
||||
/**
|
||||
* @Field('name' => "IS_NULLABLE", 'length' => 3)
|
||||
*/
|
||||
public string $nullable;
|
||||
|
||||
/**
|
||||
* @Field('name' => "DATA_TYPE", 'length' => 64)
|
||||
*/
|
||||
public string $dataType;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CHARACTER_MAXIMUM_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? int $characterMaximumLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CHARACTER_OCTET_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? int $characterOctetLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "NUMERIC_PRECISION", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? int $numericPrecision;
|
||||
|
||||
/**
|
||||
* @Field('name' => "NUMERIC_SCALE", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? int $numericScale;
|
||||
|
||||
/**
|
||||
* @Field('name' => "DATETIME_PRECISION", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? int $datetimePrecision;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CHARACTER_SET_NAME", 'length' => 32)
|
||||
*/
|
||||
public ? string $characterSetName;
|
||||
|
||||
/**
|
||||
* @Field('name' => "COLLATION_NAME", 'length' => 32)
|
||||
*/
|
||||
public ? string $collationName;
|
||||
|
||||
/**
|
||||
* @Field('name' => "COLLATION_TYPE", 'type' => "longtext")
|
||||
*/
|
||||
public string $type;
|
||||
|
||||
/**
|
||||
* @Field('name' => "COLUMN_KEY", 'length' => 3)
|
||||
*/
|
||||
public string $key;
|
||||
|
||||
/**
|
||||
* @Field('name' => "EXTRA", 'length' => 30)
|
||||
*/
|
||||
public string $extra;
|
||||
|
||||
/**
|
||||
* @Field('name' => "PRIVILEGES", 'length' => 80)
|
||||
*/
|
||||
public string $privileges;
|
||||
|
||||
/**
|
||||
* @Field('name' => "COLUMN_COMMENT", 'length' => 1024)
|
||||
*/
|
||||
public string $comment;
|
||||
|
||||
/**
|
||||
* @Field('name' => "IS_GENERATED", 'length' => 6)
|
||||
*/
|
||||
public string $generated;
|
||||
|
||||
/**
|
||||
* @Field('name' => "GENERATION_EXPRESSION", 'type' => "longtext")
|
||||
*/
|
||||
public ? string $generationExpression;
|
||||
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Entity\InformationSchema;
|
||||
|
||||
use Ulmus\EntityCollection,
|
||||
Ulmus\Entity\Field\Datetime;
|
||||
|
||||
/**
|
||||
* @Table('name' => "tables", 'database' => "information_schema")
|
||||
*/
|
||||
class Table
|
||||
{
|
||||
use \Ulmus\EntityTrait;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_CATALOG", 'length' => 512)
|
||||
*/
|
||||
public string $catalog;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_SCHEMA", 'length' => 64)
|
||||
*/
|
||||
public string $schema;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_NAME", 'length' => 64, 'attributes' => [ 'primary_key' => true ])
|
||||
*/
|
||||
public string $name;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_TYPE", 'length' => 64)
|
||||
*/
|
||||
public string $type;
|
||||
|
||||
/**
|
||||
* @Field('name' => "ENGINE", 'length' => 64)
|
||||
*/
|
||||
public ? string $engine ;
|
||||
|
||||
/**
|
||||
* @Field('name' => "VERSION", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $version;
|
||||
|
||||
/**
|
||||
* @Field('name' => "ROW_FORMAT", 'length' => 10)
|
||||
*/
|
||||
public ? string $rowFormat;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_ROWS", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $rows;
|
||||
|
||||
/**
|
||||
* @Field('name' => "AVG_ROW_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $averageRowLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "DATA_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $dataLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "MAX_DATA_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $maxDataLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "INDEX_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $indexLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "DATA_FREE", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $dataFree;
|
||||
|
||||
/**
|
||||
* @Field('name' => "AUTO_INCREMENT", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $autoIncrement;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CREATE_TIME")
|
||||
*/
|
||||
public ? Datetime $createTime;
|
||||
|
||||
/**
|
||||
* @Field('name' => "UPDATE_TIME")
|
||||
*/
|
||||
public ? Datetime $updateTime;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CHECK_TIME")
|
||||
*/
|
||||
public ? Datetime $checkTime;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_COLLATION", 'length' => 32)
|
||||
*/
|
||||
public ? string $tableCollation;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CHECKSUM", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? string $checksum;
|
||||
|
||||
/**
|
||||
* @Field('name' => "CREATE_OPTIONS", 'length' => 2048)
|
||||
*/
|
||||
public ? string $createOptions;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TABLE_COMMENT", 'length' => 2048)
|
||||
*/
|
||||
public string $tableComment;
|
||||
|
||||
/**
|
||||
* @Field('name' => "MAX_INDEX_LENGTH", 'type' => "bigint", 'length' => 21, 'attributes' => [ 'unsigned' => true ])
|
||||
*/
|
||||
public ? int $maxIndexLength;
|
||||
|
||||
/**
|
||||
* @Field('name' => "TEMPORARY", 'length' => 1)
|
||||
*/
|
||||
public ? string $temporary;
|
||||
|
||||
/**
|
||||
* @Relation('oneToMany', 'key' => 'name', 'foreignKey' => Column::field('tableName'), 'entity' => Column::class)
|
||||
* @Where('TABLE_SCHEMA', Column::field('tableSchema'))
|
||||
*/
|
||||
public EntityCollection $columns;
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Migration;
|
||||
|
||||
use Ulmus\Annotation\Property\Field;
|
||||
|
||||
class FieldDefinition {
|
||||
|
||||
public bool $nullable;
|
||||
|
||||
public bool $builtIn;
|
||||
|
||||
public string $type;
|
||||
|
||||
public array $tags;
|
||||
|
||||
public /* ? string */ $default;
|
||||
|
||||
public ? int $precision;
|
||||
|
||||
public ? int $length;
|
||||
|
||||
public ? string $update;
|
||||
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->name = $data['name'];
|
||||
$this->builtIn = $data['builtin'];
|
||||
$this->tags = $data['tags'];
|
||||
|
||||
$field = $this->getFieldTag();
|
||||
$this->type = $field->type ?? $data['type'];
|
||||
$this->length = $field->length ?? null;
|
||||
$this->precision = $field->precision ?? null;
|
||||
$this->nullable = $field->nullable ?? $data['nullable'];
|
||||
$this->update = $field->attributes['update'] ?? null;
|
||||
}
|
||||
|
||||
public function getSqlName() : string
|
||||
{
|
||||
return $this->getColumnName();
|
||||
}
|
||||
|
||||
public function getSqlType() : string
|
||||
{
|
||||
$type = $this->type;
|
||||
$length = $this->length;
|
||||
$default = $this->getDefault();
|
||||
|
||||
switch($type) {
|
||||
case "bool":
|
||||
$type = "TINYINT";
|
||||
$length = 1;
|
||||
break;
|
||||
|
||||
case "array":
|
||||
case "string":
|
||||
if ($length && $length <= 255) {
|
||||
$type = "VARCHAR";
|
||||
break;
|
||||
}
|
||||
elseif (! $length || ( $length <= 65535 ) ) {
|
||||
$type = "TEXT";
|
||||
}
|
||||
elseif ( $length <= 16777215 ) {
|
||||
$type = "MEDIUMTEXT";
|
||||
}
|
||||
elseif ($length <= 4294967295) {
|
||||
$type = "LONGTEXT";
|
||||
}
|
||||
else {
|
||||
throw new \Exception("A column with size bigger than 4GB cannot be created.");
|
||||
}
|
||||
|
||||
# Length is unnecessary on TEXT fields
|
||||
unset($length);
|
||||
|
||||
break;
|
||||
|
||||
case "float":
|
||||
$type = "DOUBLE";
|
||||
break;
|
||||
|
||||
default:
|
||||
$type = strtoupper($type);
|
||||
break;
|
||||
}
|
||||
|
||||
return implode(' ', array_filter([
|
||||
$type . ( $length ? "($length" . ( $precision ? ",$precision" : "" ) . ")" : "" ),
|
||||
$this->isUnsigned() ? "UNSIGNED" : null,
|
||||
$this->nullable ? "NULL" : "NOT NULL",
|
||||
$default ? "DEFAULT $default" : null,
|
||||
$this->isAutoIncrement() ? "AUTO_INCREMENT" : null,
|
||||
$this->isPrimaryKey() ? "PRIMARY KEY" : null,
|
||||
]));
|
||||
}
|
||||
|
||||
protected function getFieldTag() : ? Field
|
||||
{
|
||||
$field = array_filter($this->tags, function($item) {
|
||||
return $item['object'] instanceof Field;
|
||||
});
|
||||
|
||||
return array_pop($field)['object'];
|
||||
}
|
||||
|
||||
protected function getColumnName() : ? string
|
||||
{
|
||||
return $this->getFieldTag()->name ?? $this->name;
|
||||
}
|
||||
|
||||
protected function getDefault() : ? string
|
||||
{
|
||||
return $this->getFieldTag()->attributes['default'] ?? null;
|
||||
}
|
||||
|
||||
protected function isPrimaryKey() : bool
|
||||
{
|
||||
return $this->getFieldTag()->attributes['primary_key'] ?? false;
|
||||
}
|
||||
|
||||
protected function isAutoIncrement() : bool
|
||||
{
|
||||
return $this->getFieldTag()->attributes['auto_increment'] ?? false;
|
||||
}
|
||||
|
||||
protected function isUnique() : bool
|
||||
{
|
||||
return $this->getFieldTag()->attributes['unique'] ?? false;
|
||||
}
|
||||
|
||||
protected function isUnsigned() : bool
|
||||
{
|
||||
return $this->getFieldTag()->attributes['unsigned'] ?? false;
|
||||
}
|
||||
}
|
|
@ -1,404 +0,0 @@
|
|||
<?php namespace Alive\Storage\Sql;
|
||||
|
||||
use Alive\{
|
||||
constructor,
|
||||
Arrayobj
|
||||
};
|
||||
|
||||
class QueryBuilder {
|
||||
protected $fields;
|
||||
protected $where;
|
||||
protected $order_by;
|
||||
protected $group_by;
|
||||
protected $limit;
|
||||
|
||||
public static $syntax = [
|
||||
'against' => 'AGAINST',
|
||||
'and' => 'AND',
|
||||
'as' => 'AS',
|
||||
'charset' => 'CHARACTER SET',
|
||||
'collate' => 'COLLATE',
|
||||
'create' => 'CREATE',
|
||||
'database' => 'DATABASE',
|
||||
'delete' => 'DELETE FROM',
|
||||
'distinct' => 'DISTINCT',
|
||||
'drop' => 'DROP',
|
||||
'engine' => 'ENGINE',
|
||||
'!exist' => 'IF NOT EXISTS',
|
||||
'exist' => 'IF EXISTS',
|
||||
'explain' => 'EXPLAIN',
|
||||
'from' => 'FROM',
|
||||
'grant' => 'GRANT',
|
||||
'grant_option' => 'GRANT OPTION',
|
||||
'group_by' => 'GROUP BY',
|
||||
'having' => 'HAVING',
|
||||
'in' => 'IN',
|
||||
'insert' => 'INSERT INTO',
|
||||
'join' => 'JOIN',
|
||||
'join-left' => 'LEFT',
|
||||
'join-right' => 'RIGHT',
|
||||
'join-inner' => 'INNER',
|
||||
'join-full' => 'FULL',
|
||||
'join-self' => 'SELF',
|
||||
#'join-outer' => 'OUTER',
|
||||
'join-cross' => 'CROSS',
|
||||
'like' => 'LIKE',
|
||||
'limit' => 'LIMIT',
|
||||
'match' => 'MATCH',
|
||||
'not_in' => 'NOT IN',
|
||||
'on' => 'ON',
|
||||
'on_table' => 'ON TABLE',
|
||||
'or' => 'OR',
|
||||
'order_by' => 'ORDER BY',
|
||||
'offset' => 'OFFSET',
|
||||
'revoke' => 'REVOKE',
|
||||
'select' => 'SELECT',
|
||||
'set' => 'SET',
|
||||
'table' => 'TABLE',
|
||||
'table_charset' => 'DEFAULT CHARSET',
|
||||
'to' => 'TO',
|
||||
'update' => 'UPDATE',
|
||||
'values' => 'VALUES',
|
||||
'where' => 'WHERE'
|
||||
];
|
||||
|
||||
static $escape_char = '`';
|
||||
|
||||
protected $compiled = [];
|
||||
|
||||
public static function select($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
|
||||
return static::prepare_array([
|
||||
$param->if_has('explain' , static::$syntax['explain']),
|
||||
static::$syntax['select'],
|
||||
$param->if_has('distinct' , static::$syntax['distinct']),
|
||||
static::group_fields($param['fields'] ?: '*'),
|
||||
static::$syntax['from'],
|
||||
static::full_tablename($param),
|
||||
static::prepare_join($param['join']),
|
||||
static::prepare_where($param['where'], false, $param->ternary('escaped', true)),
|
||||
$param->if_has('group_by' , static::prepare_group($param['group_by'], $param['alias'] ?? null)),
|
||||
$param->if_has('having' , static::$syntax['having']." {$param['having']}"),
|
||||
/* @todo UNION | INTERSECT | EXCEPT GOES HERE !*/
|
||||
$param->if_has('order_by' , static::prepare_order($param['order_by'], $param['alias'] ?? null)),
|
||||
static::prepare_limit($param)
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will translate parameters into a "create database" or "create table", depending
|
||||
* on given param.
|
||||
*
|
||||
* @param array $param 'subject': table or database
|
||||
*
|
||||
* @return Type Description
|
||||
*/
|
||||
public static function create($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
return strtolower( $param['subject'] ) === 'table' ? static::create_table($param) : static::create_database($param);
|
||||
}
|
||||
|
||||
public static function create_table($param) {
|
||||
$param = is_array($param) ? Arrayobj::make($param) : $param;
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['create'],
|
||||
static::$syntax['table'],
|
||||
$param->if_has('!exist', static::$syntax['!exist']),
|
||||
static::full_tablename($param),
|
||||
static::group_create_fields($param->mandatory('fields'), true),
|
||||
$param->if_has('collation' , static::$syntax['collate']." {$param['collation']}" )
|
||||
]);
|
||||
}
|
||||
|
||||
public static function create_database($param) {
|
||||
$param = is_array($param) ? Arrayobj::make($param) : $param;
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['create'],
|
||||
static::$syntax['database'],
|
||||
$param->if_has('!exist', static::$syntax['!exist']),
|
||||
static::escape( $param->mandatory('database') )
|
||||
]);
|
||||
}
|
||||
|
||||
public static function insert($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
|
||||
$field_label = static::group_fields( $param->mandatory('fields'), true, true );
|
||||
$field_values = static::group_values( $param->mandatory('values'), $param['escaped'] ?: false );
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['insert'],
|
||||
static::full_tablename($param),
|
||||
$field_label,
|
||||
static::$syntax['values'],
|
||||
$field_values
|
||||
]);
|
||||
}
|
||||
|
||||
public static function grant($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
|
||||
$field_label = static::group_fields( $param->mandatory('privileges') );
|
||||
$users = static::group_fields( $param->mandatory('users') );
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['grant'],
|
||||
$field_label,
|
||||
static::$syntax['on_table'],
|
||||
static::full_tablename($param),
|
||||
static::$syntax['to'],
|
||||
$users,
|
||||
$param->if_has('grant_option', static::$syntax['grant_option'])
|
||||
]);
|
||||
}
|
||||
|
||||
public static function delete($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['delete'],
|
||||
static::full_tablename($param),
|
||||
static::prepare_where($param['where'], false, $param->ternary('escaped', true)),
|
||||
static::prepare_order($param),
|
||||
static::prepare_limit($param)
|
||||
]);
|
||||
}
|
||||
|
||||
public static function update($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
|
||||
$fields = static::group_values_and_fields($param->mandatory('fields'), $param->mandatory('values'));
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['update'],
|
||||
static::full_tablename($param),
|
||||
static::$syntax['set'],
|
||||
$fields,
|
||||
static::prepare_where($param['where'])
|
||||
]);
|
||||
}
|
||||
|
||||
public static function drop($param) {
|
||||
$param = Arrayobj::make($param);
|
||||
|
||||
return static::prepare_array([
|
||||
static::$syntax['drop'],
|
||||
$param->exist('table_name') ? static::$syntax['table']." ".static::full_tablename($param) : static::$syntax['database']." ".static::escape($param->mandatory('database'))
|
||||
]);
|
||||
}
|
||||
|
||||
public static function full_tablename($param) {
|
||||
is_array($param) && ($param = Arrayobj::make($param));
|
||||
return $param->if_has('database', static::escape($param['database']).".") . static::escape($param->mandatory('table_name')) . $param->if_has('alias', " ".static::$syntax['as']." " . $param['alias']);
|
||||
}
|
||||
|
||||
public static function group_fields($fields, $enclose = false, $escape = false) {
|
||||
if (is_array($fields)) {
|
||||
return ($enclose ? "(" : "") .implode(', ', $escape ? array_map(function($item){ return static::escape($item); }, $fields) : $fields).($enclose ? ")" : "");
|
||||
}
|
||||
else {
|
||||
return $escape ? static::escape($fields) : $fields;
|
||||
}
|
||||
}
|
||||
|
||||
public static function group_create_fields($fields, $enclose = false) {
|
||||
if (is_array($fields)) {
|
||||
$retval = [];
|
||||
|
||||
foreach($fields as $key => $value) {
|
||||
$retval[] = static::escape($key)." ".$value;
|
||||
}
|
||||
|
||||
return ($enclose ? "(" : "") .implode(', ', $retval).($enclose ? ")" : "");
|
||||
}
|
||||
else {
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
public static function group_values($values, $escaped = false) {
|
||||
$tmp = array_pop($values);
|
||||
array_push($values, $tmp);
|
||||
|
||||
# Are we dealing with an array of values ?
|
||||
if ( is_array($tmp) ) {
|
||||
$retval = [];
|
||||
|
||||
foreach($values as $item) {
|
||||
$retval[] = implode(', ', $escaped ? $item : static::escape_values($item) );
|
||||
}
|
||||
|
||||
return "(".implode('), (', $retval).")";
|
||||
}
|
||||
else {
|
||||
return "(".implode(', ', $escaped ? $values : static::escape_values($values)).")";
|
||||
}
|
||||
}
|
||||
|
||||
public static function escape_values($values) {
|
||||
$type_function = function(& $item) {
|
||||
|
||||
switch( $t = gettype($item) ) {
|
||||
case "boolean":
|
||||
$item = $item ? 1 : 0;
|
||||
break;
|
||||
|
||||
case "double":
|
||||
case "integer":
|
||||
break;
|
||||
|
||||
case "NULL":
|
||||
$item = "NULL";
|
||||
break;
|
||||
|
||||
case "string":
|
||||
$item = "\"$item\"";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return $item;
|
||||
};
|
||||
|
||||
return is_array($values) ? array_map($type_function, $values) : $type_function($values);
|
||||
}
|
||||
|
||||
public static function group_values_and_fields($fields, $values) {
|
||||
$retval = [];
|
||||
|
||||
foreach($fields as $key => $item) {
|
||||
$retval[] = "{$item} = {$values[$key]}";
|
||||
}
|
||||
|
||||
return implode(', ', $retval);
|
||||
}
|
||||
|
||||
public static function prepare_array($sql) {
|
||||
return implode(" ", array_filter($sql)).";";
|
||||
}
|
||||
|
||||
public static function prepare_where($where, $recursion = false, $escaped = false) {
|
||||
$retval = [];
|
||||
|
||||
if (is_array($where)) {
|
||||
$count = count($where);
|
||||
for($i = 0; $i < $count; $i++) {
|
||||
$item = $where[$i];
|
||||
|
||||
if ( ! Arrayobj::array_is_associative($item) ) {
|
||||
$retval[] = "(".static::prepare_where($item, true, $escaped).")";
|
||||
}
|
||||
else {
|
||||
$comparison = (isset($item['comparison']) ? $item['comparison'] : "=");
|
||||
|
||||
# are we having an IN comparison here ...
|
||||
if ( $is_array = (is_array($item['value']) && count($item['value']) > 1) ) {
|
||||
switch ($item['comparison']) {
|
||||
case '=':
|
||||
$comparison = '=';
|
||||
break;
|
||||
|
||||
case '!=':
|
||||
$comparison = 'not_in';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$value = static::group_fields($item['value'], true);
|
||||
|
||||
|
||||
switch($comparison) {
|
||||
case 'match':
|
||||
$retval[] = static::$syntax[$comparison].' ('.static::fieldname($item['field'], $item['alias'] ?? null).") ".static::$syntax['against'].
|
||||
" (".(!$escaped || $is_array ? $value : static::escape_values($value))." IN BOOLEAN MODE)".
|
||||
($i + 1 < $count ? " ".static::$syntax[ isset($item['operator']) ? $item['operator'] : "and" ] : "");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$retval[] = static::fieldname($item['field'], $item['alias'] ?? null)." " . ( isset(static::$syntax[$comparison]) ? static::$syntax[$comparison] : $comparison) .
|
||||
" ".(!$escaped || $is_array ? $value : static::escape_values($value)).
|
||||
($i + 1 < $count ? " ".static::$syntax[ isset($item['operator']) ? $item['operator'] : "and" ] : "");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $retval ? ($recursion ? "" : static::$syntax['where'] . " ") . implode(" ", $retval ) : "";
|
||||
}
|
||||
|
||||
public static function prepare_join($joins) {
|
||||
$retval = [];
|
||||
|
||||
if ( is_array($joins) ) {
|
||||
$count = count($joins);
|
||||
|
||||
for($i = 0; $i < $count; $i++) {
|
||||
$join = [];
|
||||
|
||||
$table = Arrayobj::make([
|
||||
'table_name' => $joins[$i]['table'],
|
||||
'alias' => $joins[$i]['alias_right']
|
||||
]);
|
||||
|
||||
$join[] = static::$syntax[ "join-".$joins[$i]['type'] ] ?? $joins[$i]['type'];
|
||||
$join[] = static::$syntax[ 'join' ];
|
||||
$join[] = static::full_tablename($table);
|
||||
$join[] = static::$syntax[ 'on' ];
|
||||
|
||||
foreach($joins[$i]['fields'] as $left_field => $right_field) {
|
||||
#$join[] = $joins[$i]['alias_left'].".".static::escape($left_field);
|
||||
$join[] = static::fieldname($left_field, $joins[$i]['alias_left']);
|
||||
$join[] = $joins[$i]['comparison'];
|
||||
$join[] = static::fieldname($right_field, $joins[$i]['alias_right']);
|
||||
}
|
||||
|
||||
$retval[] = implode(' ', $join);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return implode(' ', $retval);
|
||||
}
|
||||
|
||||
public static function prepare_order($order, $alias = null)
|
||||
{
|
||||
$retval = [];
|
||||
|
||||
if (is_array($order)) {
|
||||
foreach($order as $item) {
|
||||
$retval[] = static::fieldname($item['field'], $alias).( !empty($item['order']) ? " ".$item['order'] : "" );
|
||||
}
|
||||
}
|
||||
|
||||
return $retval ? static::$syntax['order_by']." ".implode(', ', $retval) : "";
|
||||
}
|
||||
|
||||
public static function prepare_group($group)
|
||||
{
|
||||
return $group ? static::$syntax['group_by']." ".( is_array($group) ? implode(', ', $group) : $group ) : "";
|
||||
}
|
||||
|
||||
public static function prepare_limit($param)
|
||||
{
|
||||
return implode(' ', array_filter([
|
||||
$param->if_has('limit' , static::$syntax['limit'] ." {$param['limit']}"),
|
||||
$param->if_has('offset', static::$syntax['offset']." {$param['offset']}")
|
||||
]));
|
||||
}
|
||||
|
||||
public static function fieldname($field, $alias = null)
|
||||
{
|
||||
return strpos($field, '.') ? $field : (!empty($alias) ? $alias."." : "").static::escape($field);
|
||||
}
|
||||
|
||||
public static function escape($field)
|
||||
{
|
||||
return static::$escape_char . str_replace(static::$escape_char, '', $field) . static::$escape_char;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Query;
|
||||
|
||||
use Ulmus\Annotation,
|
||||
Ulmus\Common\EntityField;
|
||||
|
||||
|
||||
class Create extends Fragment {
|
||||
|
||||
const SQL_TOKEN = "CREATE TABLE";
|
||||
|
||||
public string $table;
|
||||
|
||||
public string $engine;
|
||||
|
||||
public int $order = -80;
|
||||
|
||||
public bool $skipExisting = true;
|
||||
|
||||
public array $fieldList;
|
||||
|
||||
public function render() : string
|
||||
{
|
||||
return $this->renderSegments([
|
||||
static::SQL_TOKEN, $this->renderTables($this->table),
|
||||
$this->renderFields(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function renderFields() : string
|
||||
{
|
||||
return "(" . PHP_EOL . implode(",".PHP_EOL, array_map(function($field) {
|
||||
return " ".EntityField::generateCreateColumn($field);
|
||||
}, $this->fieldList)) . PHP_EOL . ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Ulmus\Query;
|
||||
|
||||
class Engine extends Fragment {
|
||||
|
||||
const SQL_TOKEN = "ENGINE";
|
||||
|
||||
public int $order = 80;
|
||||
|
||||
public string $engine;
|
||||
|
||||
public function render() : string
|
||||
{
|
||||
return $this->renderSegments([
|
||||
static::SQL_TOKEN, $this->engine,
|
||||
], "=");
|
||||
}
|
||||
}
|
|
@ -305,6 +305,42 @@ class QueryBuilder
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function create(array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
|
||||
{
|
||||
if ( null === $this->getFragment(Query\Create::class) ) {
|
||||
if ( $schema ) {
|
||||
$table = "\"$schema\".$table";
|
||||
}
|
||||
|
||||
if ( $database ) {
|
||||
$table = "\"$database\".$table";
|
||||
}
|
||||
|
||||
$create = new Query\Create();
|
||||
$this->push($create);
|
||||
|
||||
$create->fieldList = $fieldlist;
|
||||
$create->table = $table;
|
||||
}
|
||||
else {
|
||||
throw new \Exception("A create SQL fragment was already found within the query builder");
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function engine(string $value) : self
|
||||
{
|
||||
if ( null === $engine = $this->getFragment(Query\Engine::class) ) {
|
||||
$engine = new Query\Engine();
|
||||
$this->push($engine);
|
||||
}
|
||||
|
||||
$engine->engine = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function push(Query\Fragment $queryFragment) : self
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ class Repository
|
|||
$this->entityClass = $entity;
|
||||
$this->alias = $alias;
|
||||
$this->entityResolver = Ulmus::resolveEntity($entity);
|
||||
$this->adapter = $adapter ?? $this->entityResolver->databaseAdapter() ?? Ulmus::$defaultAdapter;
|
||||
$this->adapter = $adapter ?? $this->entityResolver->databaseAdapter();
|
||||
$this->queryBuilder = new QueryBuilder();
|
||||
}
|
||||
|
||||
|
@ -134,8 +134,9 @@ class Repository
|
|||
if ( ! $entity->isLoaded() ) {
|
||||
$statement = $this->insertSqlQuery($dataset)->runQuery();
|
||||
|
||||
if ( ( 0 !== $statement->lastInsertId ) &&
|
||||
( null !== $primaryKeyDefinition )) {
|
||||
if ( ( 0 !== $statement->lastInsertId ) &&
|
||||
( null !== $primaryKeyDefinition )) {
|
||||
|
||||
$pkField = key($primaryKeyDefinition);
|
||||
$entity->$pkField = $statement->lastInsertId;
|
||||
}
|
||||
|
@ -172,7 +173,7 @@ class Repository
|
|||
{
|
||||
$schema = $schema ?: $this->entityResolver->schemaName();
|
||||
|
||||
$this->queryBuilder->truncate($this->escapeTable($table ?: $this->entityResolver->tableName()), $alias ?: $this->alias, $this->escapeDatabase($this->adapter->adapter()->database), $schema ? $this->escapeSchema($schema) : null);
|
||||
$this->queryBuilder->truncate($this->escapeTable($table ?: $this->entityResolver->tableName()), $alias ?: $this->alias, $this->escapedDatabase(), $schema ? $this->escapeSchema($schema) : null);
|
||||
|
||||
$this->finalizeQuery();
|
||||
|
||||
|
@ -181,6 +182,11 @@ class Repository
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function createTable()
|
||||
{
|
||||
return $this->createSqlQuery()->runQuery();
|
||||
}
|
||||
|
||||
public function generateDatasetDiff(object $entity) : array
|
||||
{
|
||||
return array_diff_assoc( array_change_key_case($entity->toArray()), array_change_key_case($entity->entityGetDataset(false, true)) );
|
||||
|
@ -208,7 +214,7 @@ class Repository
|
|||
|
||||
public function insert(array $fieldlist, string $table, string $alias, ? string $schema) : self
|
||||
{
|
||||
$this->queryBuilder->insert($fieldlist, $this->escapeTable($table), $alias, $schema);
|
||||
$this->queryBuilder->insert($fieldlist, $this->escapeTable($table), $alias, $this->escapedDatabase(), $schema);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -222,7 +228,7 @@ class Repository
|
|||
|
||||
public function update(string $table, string $alias, ? string $schema) : self
|
||||
{
|
||||
$this->queryBuilder->update($this->escapeTable($table), $alias, $schema);
|
||||
$this->queryBuilder->update($this->escapeTable($table), $alias, $this->escapedDatabase(), $schema);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -243,8 +249,7 @@ class Repository
|
|||
|
||||
public function from(string $table, ? string $alias, ? string $schema) : self
|
||||
{
|
||||
$this->queryBuilder->from($this->escapeTable($table), $alias, $this->escapeDatabase($this->adapter->adapter()->database), $schema ? $this->escapeSchema($schema) : null);
|
||||
|
||||
$this->queryBuilder->from($this->escapeTable($table), $alias, $this->escapedDatabase(), $schema ? $this->escapeSchema($schema) : null);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -322,7 +327,6 @@ class Repository
|
|||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function limit(int $value) : self
|
||||
{
|
||||
$this->queryBuilder->limit($value);
|
||||
|
@ -337,7 +341,6 @@ class Repository
|
|||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/* @TODO */
|
||||
public function commit() : self
|
||||
{
|
||||
|
@ -363,16 +366,14 @@ class Repository
|
|||
|
||||
public function withJoin(/*string|array*/ $fields) : self
|
||||
{
|
||||
$resolvedEntity = Ulmus::resolveEntity($this->entityClass);
|
||||
|
||||
if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) {
|
||||
$this->select("{$this->alias}.*");
|
||||
}
|
||||
|
||||
foreach((array) $fields as $item) {
|
||||
if ( null !== $join = $resolvedEntity->searchFieldAnnotation($item, new Annotation\Property\Join) ) {
|
||||
if ( null !== $join = $this->entityResolver->searchFieldAnnotation($item, new Annotation\Property\Join) ) {
|
||||
$alias = $join->alias ?? $item;
|
||||
$entity = $join->entity ?? $resolvedEntity->properties[$item]['type'];
|
||||
$entity = $join->entity ?? $this->entityResolver->properties[$item]['type'];
|
||||
|
||||
foreach($entity::resolveEntity()->fieldList(Common\EntityResolver::KEY_COLUMN_NAME) as $key => $field) {
|
||||
$this->select("$alias.$key as {$alias}\${$field['name']}");
|
||||
|
@ -491,6 +492,21 @@ class Repository
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function createSqlQuery() : self
|
||||
{
|
||||
if ( null === $this->queryBuilder->getFragment(Query\Create::class) ) {
|
||||
$this->queryBuilder->create($this->entityResolver->fieldList(), $this->escapeTable($this->entityResolver->tableName()), $this->entityResolver->schemaName());
|
||||
}
|
||||
|
||||
if ( null === $this->queryBuilder->getFragment(Query\Engine::class) ) {
|
||||
if ( $engine = $this->entityResolver->tableAnnotation()->engine ?? $this->entityResolver->databaseAdapter()->adapter()->defaultEngine() ) {
|
||||
$this->queryBuilder->engine($engine);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fromRow($row) : self
|
||||
{
|
||||
|
||||
|
@ -501,6 +517,15 @@ class Repository
|
|||
|
||||
}
|
||||
|
||||
public function getSqlQuery(bool $flush = true) : string
|
||||
{
|
||||
$result = $this->queryBuilder->render();
|
||||
|
||||
$flush and $this->queryBuilder->reset();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function instanciateEntityCollection() : EntityCollection
|
||||
{
|
||||
return $this->entityClass::entityCollection();
|
||||
|
@ -521,6 +546,13 @@ class Repository
|
|||
return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_DATABASE);
|
||||
}
|
||||
|
||||
public function escapedDatabase() : ? string
|
||||
{
|
||||
$name = $this->entityResolver->tableAnnotation()->database ?? $this->adapter->adapter()->database ?? null;
|
||||
|
||||
return $name ? static::escapeDatabase($name) : null;
|
||||
}
|
||||
|
||||
public function escapeSchema(string $identifier) : string
|
||||
{
|
||||
return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_SCHEMA);
|
||||
|
|
Loading…
Reference in New Issue