From 3ff97f3bf009449e003f8e71caf38f872746296d Mon Sep 17 00:00:00 2001 From: Dave Mc Nicoll Date: Thu, 9 Apr 2020 13:20:07 -0400 Subject: [PATCH] - Added identifier escaping to match differents PDO drivers --- src/Adapter/AdapterInterface.php | 6 ++++++ src/Adapter/MsSQL.php | 11 +++++++++++ src/Adapter/MySQL.php | 11 +++++++++++ src/Common/EntityField.php | 6 ++++-- src/Common/PdoObject.php | 27 +++++++++------------------ src/EntityTrait.php | 2 +- src/Repository.php | 26 ++++++++++++++++++++------ src/Ulmus.php | 12 +++++++++--- 8 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/Adapter/AdapterInterface.php b/src/Adapter/AdapterInterface.php index 8449e2f..e26b222 100644 --- a/src/Adapter/AdapterInterface.php +++ b/src/Adapter/AdapterInterface.php @@ -5,7 +5,13 @@ namespace Ulmus\Adapter; use Ulmus\Common\PdoObject; interface AdapterInterface { + public const IDENTIFIER_FIELD = 1; + public const IDENTIFIER_TABLE = 2; + public const IDENTIFIER_DATABASE = 3; + public const IDENTIFIER_SCHEMA = 4; + public function connect() : PdoObject; public function buildDataSourceName() : string; public function setup(array $configuration) : void; + public function escapeIdentifier(string $segment, int $type) : string; } diff --git a/src/Adapter/MsSQL.php b/src/Adapter/MsSQL.php index 99e2626..baccea3 100644 --- a/src/Adapter/MsSQL.php +++ b/src/Adapter/MsSQL.php @@ -185,4 +185,15 @@ class MsSQL implements AdapterInterface { $this->traceOn = $configuration['trace_on']; } } + + public function escapeIdentifier(string $segment, int $type) : string + { + switch($type) { + case static::IDENTIFIER_SCHEMA: + case static::IDENTIFIER_DATABASE: + case static::IDENTIFIER_TABLE: + case static::IDENTIFIER_FIELD: + return "[" . str_replace(["[", "]"], [ "[[", "]]" ], $segment) . "]"; + } + } } \ No newline at end of file diff --git a/src/Adapter/MySQL.php b/src/Adapter/MySQL.php index 926a482..77bb267 100644 --- a/src/Adapter/MySQL.php +++ b/src/Adapter/MySQL.php @@ -123,4 +123,15 @@ class MySQL implements AdapterInterface { $this->charset = $configuration['charset']; } } + + public function escapeIdentifier(string $segment, int $type) : string + { + switch($type) { + case static::IDENTIFIER_DATABASE: + case static::IDENTIFIER_TABLE: + case static::IDENTIFIER_FIELD: + return "`" . str_replace("`", "``", $segment) . "`"; + } + } + } diff --git a/src/Common/EntityField.php b/src/Common/EntityField.php index a2d5d56..a23398c 100644 --- a/src/Common/EntityField.php +++ b/src/Common/EntityField.php @@ -3,6 +3,7 @@ namespace Ulmus\Common; use Ulmus\Ulmus, + Ulmus\Adapter\AdapterInterface, Ulmus\Annotation\Property\Field; class EntityField @@ -27,8 +28,9 @@ class EntityField { $name = $this->entityResolver->searchFieldAnnotation($this->name, new Field() )->name ?? $this->name; - #return $useAlias ? "{$this->alias}.`{$this->name}`" : "`{$this->name}`"; <-SQL - return $useAlias ? "{$this->alias}.\"{$name}\"" : "\"{$name}\""; + $name = ( $this->entityResolver->databaseAdapter() ?? Ulmus::$defaultAdapter )->adapter()->escapeIdentifier($name, AdapterInterface::IDENTIFIER_FIELD); + + return $useAlias ? "{$this->alias}.$name" : $name; } public static function isScalarType($type) : bool diff --git a/src/Common/PdoObject.php b/src/Common/PdoObject.php index e481aca..58b2608 100644 --- a/src/Common/PdoObject.php +++ b/src/Common/PdoObject.php @@ -15,14 +15,9 @@ class PdoObject extends PDO { return $statement; } - } catch (\PDOException $e) { - switch ( $e->getCode() ) { - case 42000: - throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters)); - - default: - throw $e; - } + } + catch (\PDOException $e) { + throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters)); } } @@ -31,14 +26,9 @@ class PdoObject extends PDO { if (false !== ( $statement = $this->prepare($sql) )) { return $this->execute($statement, $parameters, true); } - } catch (\PDOException $e) { - switch ( $e->getCode() ) { - case 42000: - throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters)); - - default: - throw $e; - } + } + catch (\PDOException $e) { + throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters)); } return null; @@ -62,10 +52,11 @@ class PdoObject extends PDO { else { throw new \PDOException($statement->errorCode() . " - " . json_encode($statement->errorInfo())); } - } catch (\PDOException $e) { + } + catch (\PDOException $e) { $this->rollback(); - throw $e; + throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters)); } return null; diff --git a/src/EntityTrait.php b/src/EntityTrait.php index 2638954..ce4315d 100644 --- a/src/EntityTrait.php +++ b/src/EntityTrait.php @@ -136,7 +136,7 @@ trait EntityTrait { $loaded = $this->isLoaded(); $entityResolver = $this->resolveEntity(); - + foreach($dataset as $key => $value) { $field = $entityResolver->field(strtolower($key), EntityResolver::KEY_COLUMN_NAME, false) ?? null; diff --git a/src/Repository.php b/src/Repository.php index 0f91da9..d3021ca 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -8,7 +8,7 @@ class Repository { const DEFAULT_ALIAS = "this"; - protected ? ConnectionAdapter $adapter; + public ? ConnectionAdapter $adapter; protected QueryBuilder $queryBuilder; @@ -141,7 +141,7 @@ class Repository public function insert(array $fieldlist, string $table, string $alias, ? string $schema) : self { - $this->queryBuilder->insert($fieldlist, $table, $alias, $schema); + $this->queryBuilder->insert($fieldlist, $this->escapeTable($table), $alias, $schema); return $this; } @@ -155,7 +155,7 @@ class Repository public function update(string $table, string $alias, ? string $schema) : self { - $this->queryBuilder->update($table, $alias, $schema); + $this->queryBuilder->update($this->escapeTable($table), $alias, $schema); return $this; } @@ -176,14 +176,14 @@ class Repository public function from(string $table, ? string $alias, ? string $schema) : self { - $this->queryBuilder->from($table, $alias, $this->adapter->adapter()->database, $schema); + $this->queryBuilder->from($this->escapeTable($table), $alias, $this->escapeDatabase($this->adapter->adapter()->database), $schema ? $this->escapeSchema($schema) : null); return $this; } public function join(string $type, $table, $field, $value) : self { - $this->queryBuilder->join($type, $table, $field, $value); + $this->queryBuilder->join($type, $this->escapeTable($table), $field, $value); return $this; } @@ -470,7 +470,6 @@ class Repository public function collectionFromQuery(? string $entityClass = null) : EntityCollection { - $class = $entityClass ?: $this->entityClass; $entityCollection = new EntityCollection(); @@ -556,5 +555,20 @@ class Repository return "REFLECT TABLE"; } + public function escapeTable(string $identifier) : string + { + return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_TABLE); + } + + public function escapeDatabase(string $identifier) : string + { + return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_DATABASE); + } + + public function escapeSchema(string $identifier) : string + { + return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\AdapterInterface::IDENTIFIER_SCHEMA); + } + protected function finalizeQuery() : void {} } diff --git a/src/Ulmus.php b/src/Ulmus.php index bee371c..d93e1a2 100644 --- a/src/Ulmus.php +++ b/src/Ulmus.php @@ -44,12 +44,18 @@ abstract class Ulmus public static function runSelectQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null) { - return static::pdo($adapter)->select($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? [])); + $dataset = static::pdo($adapter)->select($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? [])); + $queryBuilder->reset(); + + return $dataset; } public static function runQuery(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null) { - return static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? [])); + $return = static::pdo($adapter)->runQuery($queryBuilder->render(), array_merge($queryBuilder->values ?? [], $queryBuilder->parameters ?? [])); + $queryBuilder->reset(); + + return $return; } public static function resolveEntity(string $entityClass) : Common\EntityResolver @@ -93,7 +99,7 @@ abstract class Ulmus protected static function fetchQueryBuilder(QueryBuilder $queryBuilder, ? ConnectionAdapter $adapter = null) : array { - $result = ( $adapter ?: static::$defaultAdapter )->pdo->select($queryBuilder->render(), $queryBuilder->parameters ?? [])->fetchAll(); + $result = ( $adapter ?: static::$defaultAdapter )->pdo->select($queryBuilder->render(), $queryBuilder->parameters ?? [])->fetchAll(); $queryBuilder->reset(); return $result;