The branch, master has been updated
via 4f487780a07d2a89e97bb3249fd4389c7362681a (commit)
via 68e1ff379806ab49b17855a66a9086b8f5714d69 (commit)
via 8ce53e5bc81a8b798db7b4701d7afdad88c1406f (commit)
via c63d3dde811b9e0deaf7eb8599871e3d47b76126 (commit)
from fefd6a7def3433b7b9c52b0016044726015d43eb (commit)
- Log -----------------------------------------------------------------
commit 4f487780a07d2a89e97bb3249fd4389c7362681a
Author: Michal Čihař <mcihar(a)novell.com>
Date: Mon Aug 30 17:17:07 2010 +0200
bug #3042665 [parser] Add workaround for MySQL way of handling backtick.
commit 68e1ff379806ab49b17855a66a9086b8f5714d69
Author: Michal Čihař <mcihar(a)novell.com>
Date: Mon Aug 30 17:16:44 2010 +0200
Do not fail if parsing query has failed.
commit 8ce53e5bc81a8b798db7b4701d7afdad88c1406f
Author: Michal Čihař <mcihar(a)novell.com>
Date: Mon Aug 30 17:03:55 2010 +0200
Not used anywhere.
commit c63d3dde811b9e0deaf7eb8599871e3d47b76126
Author: Michal Čihař <mcihar(a)novell.com>
Date: Mon Aug 30 16:59:53 2010 +0200
Add more testcases.
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 1 +
libraries/import/sql.php | 14 +++++-
libraries/sqlparser.lib.php | 39 +++++++++++++--
test/PMA_SQL_parser_test.php | 104 +++++++++++++++++++++++++++++++++++++----
4 files changed, 140 insertions(+), 18 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 3613acb..bdbba03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -112,6 +112,7 @@ $Id$
+ [interface] Added charts to status tab, profiling page and query results
+ [interface] AJAXification on various pages
- [core] Remove last remaining parts of profiling code which was removed in 2006.
+- bug #3042665 [parser] Add workaround for MySQL way of handling backtick.
3.3.7.0 (not yet released)
- patch #3050492 [PDF scratchboard] Cannot drag table box to the edge after
diff --git a/libraries/import/sql.php b/libraries/import/sql.php
index fe62ca5..0e61080 100644
--- a/libraries/import/sql.php
+++ b/libraries/import/sql.php
@@ -168,8 +168,20 @@ while (!($GLOBALS['finished'] && $i >= $len)
&& !$error && !$timeout_passed) {
while (!$endq) {
// Find next quote
$pos = strpos($buffer, $quote, $i + 1);
+ /*
+ * Behave same as MySQL and accept end of query as end of backtick.
+ * I know this is sick, but MySQL behaves like this:
+ *
+ * SELECT * FROM `table
+ *
+ * is treated like
+ *
+ * SELECT * FROM `table`
+ */
+ if ($pos === FALSE && $quote == '`' &&
$found_delimiter) {
+ $pos = $first_sql_delimiter - 1;
// No quote? Too short string
- if ($pos === FALSE) {
+ } elseif ($pos === FALSE) {
// We hit end of string => unclosed quote, but we handle it as end
of query
if ($GLOBALS['finished']) {
$endq = TRUE;
diff --git a/libraries/sqlparser.lib.php b/libraries/sqlparser.lib.php
index b8b2bba..7c8e8fa 100644
--- a/libraries/sqlparser.lib.php
+++ b/libraries/sqlparser.lib.php
@@ -211,7 +211,6 @@ if (! defined('PMA_MINIMUM_COMMON')) {
*/
function PMA_SQP_parse($sql)
{
- global $cfg;
global $PMA_SQPdata_column_attrib, $PMA_SQPdata_reserved_word,
$PMA_SQPdata_column_type, $PMA_SQPdata_function_name,
$PMA_SQPdata_column_attrib_cnt, $PMA_SQPdata_reserved_word_cnt,
$PMA_SQPdata_column_type_cnt, $PMA_SQPdata_function_name_cnt;
global $mysql_charsets, $mysql_collations_flat, $mysql_charsets_count,
$mysql_collations_count;
@@ -342,10 +341,38 @@ if (! defined('PMA_MINIMUM_COMMON')) {
$pos = $GLOBALS['PMA_strpos'](' ' . $sql,
$quotetype, $oldpos + 1) - 1;
// ($pos === FALSE)
if ($pos < 0) {
- $debugstr = __('Unclosed quote') . ' @ ' .
$startquotepos. "\n"
- . 'STR: ' . htmlspecialchars($quotetype);
- PMA_SQP_throwError($debugstr, $sql);
- return $sql_array;
+ if ($c == '`') {
+ /*
+ * Behave same as MySQL and accept end of query as end of
backtick.
+ * I know this is sick, but MySQL behaves like this:
+ *
+ * SELECT * FROM `table
+ *
+ * is treated like
+ *
+ * SELECT * FROM `table`
+ */
+ $pos_quote_separator = $GLOBALS['PMA_strpos']('
' . $sql, $GLOBALS['sql_delimiter'], $oldpos + 1) - 1;
+ if ($pos_quote_separator < 0) {
+ $len += 1;
+ $sql .= '`';
+ $sql_array['raw'] .= '`';
+ $pos = $len;
+ } else {
+ $len += 1;
+ $sql = $GLOBALS['PMA_substr']($sql, 0,
$pos_quote_separator) . '`' . $GLOBALS['PMA_substr']($sql,
$pos_quote_separator);
+ $sql_array['raw'] = $sql;
+ $pos = $pos_quote_separator;
+ }
+ if (class_exists('PMA_Message')) {
+ PMA_Message::warning(__('Automatically appended
backtick to the end of query!'))->display();
+ }
+ } else {
+ $debugstr = __('Unclosed quote') . ' @ ' .
$startquotepos. "\n"
+ . 'STR: ' . htmlspecialchars($quotetype);
+ PMA_SQP_throwError($debugstr, $sql);
+ return $sql_array;
+ }
}
// If the quote is the first character, it can't be
@@ -806,7 +833,7 @@ if (! defined('PMA_MINIMUM_COMMON')) {
*/
function PMA_SQP_analyze($arr)
{
- if ($arr == array()) {
+ if ($arr == array() || !isset($arr['len'])) {
return array();
}
$result = array();
diff --git a/test/PMA_SQL_parser_test.php b/test/PMA_SQL_parser_test.php
index 2774ba1..aa3299c 100644
--- a/test/PMA_SQL_parser_test.php
+++ b/test/PMA_SQL_parser_test.php
@@ -149,12 +149,13 @@ class PMA_SQL_parser_test extends PHPUnit_Framework_TestCase
public function testParse_4()
{
$this->assertParser('SELECT * from `aaa;', array (
- 'raw' => 'SELECT * from `aaa;',
+ 'raw' => 'SELECT * from `aaa`;',
0 =>
array (
- 'type' => 'alpha',
+ 'type' => 'alpha_reservedWord',
'data' => 'SELECT',
'pos' => 6,
+ 'forbidden' => true,
),
1 =>
array (
@@ -164,18 +165,99 @@ class PMA_SQL_parser_test extends PHPUnit_Framework_TestCase
),
2 =>
array (
- 'type' => 'alpha',
+ 'type' => 'alpha_reservedWord',
'data' => 'from',
'pos' => 13,
+ 'forbidden' => true,
),
- ),
-'<p>There seems to be an error in your SQL query. The MySQL server error output
below, if there is any, may also help you in diagnosing the problem</p>
-<pre>
-ERROR: Unclosed quote @ 14
-STR: `
-SQL: SELECT * from `aaa;
-</pre>
-');
+ 3 =>
+ array (
+ 'type' => 'quote_backtick',
+ 'data' => '`aaa`',
+ 'pos' => 0,
+ ),
+ 4 =>
+ array (
+ 'type' => 'punct_queryend',
+ 'data' => ';',
+ 'pos' => 0,
+ ),
+ 'len' => 5,
+ ));
+ }
+
+ public function testParse_5()
+ {
+ $this->assertParser('SELECT * FROM `a_table` tbla INNER JOIN b_table` tblb
ON tblb.id = tbla.id WHERE tblb.field1 != tbla.field1`;', array (
+ 'raw' => 'SELECT * FROM `a_table` tbla INNER JOIN b_table` tblb
ON tblb.id = tbla.id WHERE tblb.field1 != tbla.field1`;',
+ 0 =>
+ array (
+ 'type' => 'alpha_reservedWord',
+ 'data' => 'SELECT',
+ 'pos' => 6,
+ 'forbidden' => true,
+ ),
+ 1 =>
+ array (
+ 'type' => 'punct',
+ 'data' => '*',
+ 'pos' => 0,
+ ),
+ 2 =>
+ array (
+ 'type' => 'alpha_reservedWord',
+ 'data' => 'FROM',
+ 'pos' => 13,
+ 'forbidden' => true,
+ ),
+ 3 =>
+ array (
+ 'type' => 'quote_backtick',
+ 'data' => '`a_table`',
+ 'pos' => 0,
+ ),
+ 4 =>
+ array (
+ 'type' => 'alpha_identifier',
+ 'data' => 'tbla',
+ 'pos' => 28,
+ 'forbidden' => false,
+ ),
+ 5 =>
+ array (
+ 'type' => 'alpha_reservedWord',
+ 'data' => 'INNER',
+ 'pos' => 34,
+ 'forbidden' => true,
+ ),
+ 6 =>
+ array (
+ 'type' => 'alpha_reservedWord',
+ 'data' => 'JOIN',
+ 'pos' => 39,
+ 'forbidden' => true,
+ ),
+ 7 =>
+ array (
+ 'type' => 'alpha_identifier',
+ 'data' => 'b_table',
+ 'pos' => 47,
+ 'forbidden' => false,
+ ),
+ 8 =>
+ array (
+ 'type' => 'quote_backtick',
+ 'data' => '` tblb ON tblb.id = tbla.id WHERE tblb.field1 !=
tbla.field1`',
+ 'pos' => 0,
+ ),
+ 9 =>
+ array (
+ 'type' => 'punct_queryend',
+ 'data' => ';',
+ 'pos' => 0,
+ ),
+ 'len' => 10,
+ ));
}
}
?>
hooks/post-receive
--
phpMyAdmin