From 95ead5ae752d0b4c7ec693a2673ac24735609a04 Mon Sep 17 00:00:00 2001 From: Unlink Date: Thu, 2 Jun 2016 12:46:23 +0200 Subject: [PATCH] ResultSet: improved error message on duplicated names in select statement --- src/Database/Helpers.php | 28 +++++++++++++++++++++++++++ src/Database/ResultSet.php | 3 ++- tests/Database/ResultSet.fetch().phpt | 19 +++++++++++++++++- tests/Database/Table/Table.join.phpt | 4 ++-- 4 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/Database/Helpers.php b/src/Database/Helpers.php index c7e76f32d..7be001b5e 100644 --- a/src/Database/Helpers.php +++ b/src/Database/Helpers.php @@ -267,4 +267,32 @@ public static function toPairs(array $rows, $key = NULL, $value = NULL) return $return; } + + /** + * Finds duplicate columns in select statement + * @param \PDOStatement + * @return string + */ + public static function findDuplicates(\PDOStatement $statement) + { + $cols = []; + for ($i=0; $i<$statement->columnCount(); $i++) { + $meta = $statement->getColumnMeta($i); + $tableName = isset($meta['table']) ? $meta['table'] : ''; + if (isset($cols[$meta['name']])) { + $cols[$meta['name']][] = $tableName; + } + else { + $cols[$meta['name']] = [$tableName]; + } + } + $duplicates = ''; + foreach ($cols as $name => $tables) { + if (count($tables) > 1) { + $duplicates .= ($duplicates === '' ? '' : '; ')."'$name'".(($tmp = implode(', ', array_unique($tables))) != '' ? " from $tmp" : ''); + } + } + return $duplicates; + } + } diff --git a/src/Database/ResultSet.php b/src/Database/ResultSet.php index deeeffadb..84a7c11ae 100644 --- a/src/Database/ResultSet.php +++ b/src/Database/ResultSet.php @@ -266,7 +266,8 @@ public function fetch() } if ($this->result === NULL && count($data) !== $this->pdoStatement->columnCount()) { - trigger_error('Found duplicate columns in database result set.', E_USER_NOTICE); + $duplicates = Helpers::findDuplicates($this->pdoStatement); + trigger_error("Found duplicate columns in database result set: $duplicates.", E_USER_NOTICE); } $this->resultKey++; diff --git a/tests/Database/ResultSet.fetch().phpt b/tests/Database/ResultSet.fetch().phpt index 1dbac5a36..584490999 100644 --- a/tests/Database/ResultSet.fetch().phpt +++ b/tests/Database/ResultSet.fetch().phpt @@ -17,7 +17,7 @@ test(function () use ($context) { Assert::error(function () use ($res) { $res->fetch(); - }, E_USER_NOTICE, 'Found duplicate columns in database result set.'); + }, E_USER_NOTICE); $res->fetch(); }); @@ -35,3 +35,20 @@ test(function () use ($context, $driverName) { // tests closeCursor() foreach ($res as $row) {} } }); + +test(function () use ($context, $driverName) { + + $result = $context->query('SELECT book.id, author.id, author.name, translator.name FROM book JOIN author ON (author.id = book.author_id) JOIN author translator ON (translator.id = book.translator_id)'); + if ($driverName == 'mysql') { + $errorMsg = "'id' from book, author; 'name' from author, translator"; + } + else if ($driverName == 'sqlite') { + $errorMsg = "'id' from book, author; 'name' from author"; + } + else { + $errorMsg = "'id'; 'name'"; + } + Assert::error(function() use($result) { + iterator_to_array($result); + }, E_USER_NOTICE, "Found duplicate columns in database result set: $errorMsg."); +}); diff --git a/tests/Database/Table/Table.join.phpt b/tests/Database/Table/Table.join.phpt index cd100ee5c..cf06abd5d 100644 --- a/tests/Database/Table/Table.join.phpt +++ b/tests/Database/Table/Table.join.phpt @@ -82,7 +82,7 @@ test(function () use ($context) { }); -test(function () use ($connection, $structure) { +test(function () use ($connection, $structure, $driverName) { $context = new Nette\Database\Context( $connection, $structure, @@ -92,5 +92,5 @@ test(function () use ($connection, $structure) { $books = $context->table('book')->select('book.*, author.name, translator.name'); Assert::error(function() use($books) { iterator_to_array($books); - }, E_USER_NOTICE, 'Found duplicate columns in database result set.'); + }, E_USER_NOTICE); });