diff --git a/system/Database/Query.php b/system/Database/Query.php
index 01d27d8bdfff..a4bb1b2b9de5 100644
--- a/system/Database/Query.php
+++ b/system/Database/Query.php
@@ -367,46 +367,53 @@ public function debugToolbarDisplay(): string
{
// Key words we want bolded
static $highlight = [
- 'SELECT',
- 'DISTINCT',
- 'FROM',
- 'WHERE',
'AND',
- 'LEFT JOIN',
- 'RIGHT JOIN',
- 'JOIN',
- 'ORDER BY',
+ 'AS',
'ASC',
+ 'AVG',
+ 'BY',
+ 'COUNT',
'DESC',
- 'GROUP BY',
- 'LIMIT',
- 'INSERT',
- 'INTO',
- 'VALUES',
- 'UPDATE',
- 'OR',
+ 'DISTINCT',
+ 'FROM',
+ 'GROUP',
'HAVING',
- 'OFFSET',
- 'NOT IN',
'IN',
+ 'INNER',
+ 'INSERT',
+ 'INTO',
+ 'IS',
+ 'JOIN',
+ 'LEFT',
'LIKE',
- 'NOT LIKE',
- 'COUNT',
+ 'LIMIT',
'MAX',
'MIN',
+ 'NOT',
+ 'NULL',
+ 'OFFSET',
'ON',
- 'AS',
- 'AVG',
+ 'OR',
+ 'ORDER',
+ 'RIGHT',
+ 'SELECT',
'SUM',
+ 'UPDATE',
+ 'VALUES',
+ 'WHERE',
];
if (empty($this->finalQueryString)) {
$this->compileBinds(); // @codeCoverageIgnore
}
- $sql = $this->finalQueryString;
+ $sql = esc($this->finalQueryString);
- $search = '/\b(?:' . implode('|', $highlight) . ')\b/';
+ /**
+ * @see https://stackoverflow.com/a/20767160
+ * @see https://regex101.com/r/hUlrGN/4
+ */
+ $search = '/\b(?:' . implode('|', $highlight) . ')\b(?![^(')]*'(?:(?:[^(')]*'){2})*[^(')]*$)/';
return preg_replace_callback($search, static function ($matches) {
return '' . str_replace(' ', ' ', $matches[0]) . '';
diff --git a/tests/system/Database/BaseQueryTest.php b/tests/system/Database/BaseQueryTest.php
index deec43c4f5bb..fe942ffeb187 100644
--- a/tests/system/Database/BaseQueryTest.php
+++ b/tests/system/Database/BaseQueryTest.php
@@ -363,4 +363,37 @@ public function testSetQueryBinds()
$this->assertSame($expected, $query->getQuery());
}
+
+ public function queryKeywords()
+ {
+ return [
+ 'highlightKeyWords' => [
+ 'SELECT `a`.*, `b`.`id` AS `b_id` FROM `a` LEFT JOIN `b` ON `b`.`a_id` = `a`.`id` WHERE `b`.`id` IN ('1') AND `a`.`deleted_at` IS NOT NULL LIMIT 1',
+ 'SELECT `a`.*, `b`.`id` AS `b_id` FROM `a` LEFT JOIN `b` ON `b`.`a_id` = `a`.`id` WHERE `b`.`id` IN (\'1\') AND `a`.`deleted_at` IS NOT NULL LIMIT 1',
+ ],
+ 'ignoreKeyWordsInValues' => [
+ 'SELECT * FROM `a` WHERE `a`.`col` = 'SELECT escaped keyword in value' LIMIT 1',
+ 'SELECT * FROM `a` WHERE `a`.`col` = \'SELECT escaped keyword in value\' LIMIT 1',
+ ],
+ 'escapeHtmlValues' => [
+ 'SELECT '<s>' FROM dual',
+ 'SELECT \'\' FROM dual',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider queryKeywords
+ *
+ * @param mixed $expected
+ * @param mixed $sql
+ */
+ public function testHighlightQueryKeywords($expected, $sql)
+ {
+ $query = new Query($this->db);
+ $query->setQuery($sql);
+ $query->getQuery();
+
+ $this->assertSame($expected, $query->debugToolbarDisplay());
+ }
}