Skip to content

Commit 5c87d56

Browse files
Unlinkdg
authored andcommitted
ResultSet: improved error message on duplicated names in select statement
1 parent 077916c commit 5c87d56

File tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

src/Database/Helpers.php

+23
Original file line numberDiff line numberDiff line change
@@ -266,4 +266,27 @@ public static function toPairs(array $rows, $key = NULL, $value = NULL)
266266
return $return;
267267
}
268268

269+
270+
/**
271+
* Finds duplicate columns in select statement
272+
* @param \PDOStatement
273+
* @return string
274+
*/
275+
public static function findDuplicates(\PDOStatement $statement)
276+
{
277+
$cols = [];
278+
for ($i = 0; $i < $statement->columnCount(); $i++) {
279+
$meta = $statement->getColumnMeta($i);
280+
$cols[$meta['name']][] = isset($meta['table']) ? $meta['table'] : '';
281+
}
282+
$duplicates = [];
283+
foreach ($cols as $name => $tables) {
284+
if (count($tables) > 1) {
285+
$tables = array_filter(array_unique($tables));
286+
$duplicates[] = "'$name'" . ($tables ? ' (from ' . implode(', ', $tables) . ')' : '');
287+
}
288+
}
289+
return implode(', ', $duplicates);
290+
}
291+
269292
}

src/Database/ResultSet.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ public function fetch()
253253
if (!$data) {
254254
$this->pdoStatement->closeCursor();
255255
return FALSE;
256+
257+
} elseif ($this->result === NULL && count($data) !== $this->pdoStatement->columnCount()) {
258+
$duplicates = Helpers::findDuplicates($this->pdoStatement);
259+
trigger_error("Found duplicate columns in database result set: $duplicates.", E_USER_NOTICE);
256260
}
257261

258262
$row = new Row;
@@ -262,10 +266,6 @@ public function fetch()
262266
}
263267
}
264268

265-
if ($this->result === NULL && count($data) !== $this->pdoStatement->columnCount()) {
266-
trigger_error('Found duplicate columns in database result set.', E_USER_NOTICE);
267-
}
268-
269269
$this->resultKey++;
270270
return $this->result = $row;
271271
}

tests/Database/ResultSet.fetch().phpt

+42-3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,27 @@ require __DIR__ . '/connect.inc.php'; // create $connection
1212
Nette\Database\Helpers::loadFromFile($connection, __DIR__ . "/files/{$driverName}-nette_test1.sql");
1313

1414

15-
test(function () use ($context) {
15+
test(function () use ($context, $driverName) {
1616
$res = $context->query('SELECT name, name FROM author');
17-
17+
switch ($driverName) {
18+
case 'mysql':
19+
$message = "Found duplicate columns in database result set: 'name' (from author).";
20+
break;
21+
case 'pgsql':
22+
$message = "Found duplicate columns in database result set: 'name'%a%";
23+
break;
24+
case 'sqlite':
25+
$message = "Found duplicate columns in database result set: 'name' (from author).";
26+
break;
27+
case 'sqlsrv':
28+
$message = "Found duplicate columns in database result set: 'name'.";
29+
break;
30+
default:
31+
Assert::fail("Unsupported driver $driverName");
32+
}
1833
Assert::error(function () use ($res) {
1934
$res->fetch();
20-
}, E_USER_NOTICE, 'Found duplicate columns in database result set.');
35+
}, E_USER_NOTICE, $message);
2136

2237
$res->fetch();
2338
});
@@ -35,3 +50,27 @@ test(function () use ($context, $driverName) { // tests closeCursor()
3550
foreach ($res as $row) {}
3651
}
3752
});
53+
54+
55+
test(function () use ($context, $driverName) {
56+
$res = $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)');
57+
switch ($driverName) {
58+
case 'mysql':
59+
$message = "Found duplicate columns in database result set: 'id' (from book, author), 'name' (from author, translator).";
60+
break;
61+
case 'pgsql':
62+
$message = "Found duplicate columns in database result set: 'id'%a% 'name'%a%";
63+
break;
64+
case 'sqlite':
65+
$message = "Found duplicate columns in database result set: 'id' (from book, author), 'name' (from author).";
66+
break;
67+
case 'sqlsrv':
68+
$message = "Found duplicate columns in database result set: 'id', 'name'.";
69+
break;
70+
default:
71+
Assert::fail("Unsupported driver $driverName");
72+
}
73+
Assert::error(function() use ($res) {
74+
$res->fetch();
75+
}, E_USER_NOTICE, $message);
76+
});

tests/Database/Table/Table.join.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ test(function () use ($context) {
8282
});
8383

8484

85-
test(function () use ($connection, $structure) {
85+
test(function () use ($connection, $structure, $driverName) {
8686
$context = new Nette\Database\Context(
8787
$connection,
8888
$structure,

0 commit comments

Comments
 (0)