/** * Displays a MySQL error message in the main panel when $exit is true. * Returns the error message otherwise. * * @param string|bool $server_msg Server's error message. * @param string $sql_query The SQL query that failed. * @param bool $is_modify_link Whether to show a "modify" link or not. * @param string $back_url URL for the "back" link (full path is * not required). * @param bool $exit Whether execution should be stopped or * the error message should be returned. * * @return string * * @global string $table The current table. * @global string $db The current database. * * @access public */ public static function mysqlDie( $server_msg = '', $sql_query = '', $is_modify_link = true, $back_url = '', $exit = true ) { global $table, $db; /** * Error message to be built. * @var string $error_msg */ $error_msg = ''; // Checking for any server errors. if (empty($server_msg)) { $server_msg = $GLOBALS['dbi']->getError(); } // Finding the query that failed, if not specified. if ((empty($sql_query) && (!empty($GLOBALS['sql_query'])))) { $sql_query = $GLOBALS['sql_query']; } $sql_query = trim($sql_query); /** * The lexer used for analysis. * @var Lexer $lexer */ $lexer = new Lexer($sql_query); /** * The parser used for analysis. * @var Parser $parser */ $parser = new Parser($lexer->list); /** * The errors found by the lexer and the parser. * @var array $errors */ $errors = ParserError::get(array($lexer, $parser)); if (empty($sql_query)) { $formatted_sql = ''; } elseif (count($errors)) { $formatted_sql = htmlspecialchars($sql_query); } else { $formatted_sql = self::formatSql($sql_query, true); } $error_msg .= '<div class="error"><h1>' . __('Error') . '</h1>'; // For security reasons, if the MySQL refuses the connection, the query // is hidden so no details are revealed. if ((!empty($sql_query)) && (!(mb_strstr($sql_query, 'connect')))) { // Static analysis errors. if (!empty($errors)) { $error_msg .= '<p><strong>' . __('Static analysis:') . '</strong></p>'; $error_msg .= '<p>' . sprintf( __('%d errors were found during analysis.'), count($errors) ) . '</p>'; $error_msg .= '<p><ol>'; $error_msg .= implode( ParserError::format( $errors, '<li>%2$s (near "%4$s" at position %5$d)</li>' ) ); $error_msg .= '</ol></p>'; } // Display the SQL query and link to MySQL documentation. $error_msg .= '<p><strong>' . __('SQL query:') . '</strong>' . "\n"; $formattedSqlToLower = mb_strtolower($formatted_sql); // TODO: Show documentation for all statement types. if (mb_strstr($formattedSqlToLower, 'select')) { // please show me help to the error on select $error_msg .= self::showMySQLDocu('SELECT'); } if ($is_modify_link) { $_url_params = array( 'sql_query' => $sql_query, 'show_query' => 1, ); if (strlen($table) > 0) { $_url_params['db'] = $db; $_url_params['table'] = $table; $doedit_goto = '<a href="tbl_sql.php' . URL::getCommon($_url_params) . '">'; } elseif (strlen($db) > 0) { $_url_params['db'] = $db; $doedit_goto = '<a href="db_sql.php' . URL::getCommon($_url_params) . '">'; } else { $doedit_goto = '<a href="server_sql.php' . URL::getCommon($_url_params) . '">'; } $error_msg .= $doedit_goto . self::getIcon('b_edit.png', __('Edit')) . '</a>'; } $error_msg .= ' </p>' . "\n" . '<p>' . "\n" . $formatted_sql . "\n" . '</p>' . "\n"; } // Display server's error. if (!empty($server_msg)) { $server_msg = preg_replace( "@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $server_msg ); // Adds a link to MySQL documentation. $error_msg .= '<p>' . "\n" . ' <strong>' . __('MySQL said: ') . '</strong>' . self::showMySQLDocu('Error-messages-server') . "\n" . '</p>' . "\n"; // The error message will be displayed within a CODE segment. // To preserve original formatting, but allow word-wrapping, // a couple of replacements are done. // All non-single blanks and TAB-characters are replaced with their // HTML-counterpart $server_msg = str_replace( array(' ', "\t"), array(' ', ' '), $server_msg ); // Replace line breaks $server_msg = nl2br($server_msg); $error_msg .= '<code>' . $server_msg . '</code><br/>'; } $error_msg .= '</div>'; $_SESSION['Import_message']['message'] = $error_msg; if (!$exit) { return $error_msg; } /** * If this is an AJAX request, there is no "Back" link and * `Response()` is used to send the response. */ $response = Response::getInstance(); if ($response->isAjax()) { $response->setRequestStatus(false); $response->addJSON('message', $error_msg); exit; } if (!empty($back_url)) { if (mb_strstr($back_url, '?')) { $back_url .= '&no_history=true'; } else { $back_url .= '?no_history=true'; } $_SESSION['Import_message']['go_back_url'] = $back_url; $error_msg .= '<fieldset class="tblFooters">' . '[ <a href="' . $back_url . '">' . __('Back') . '</a> ]' . '</fieldset>' . "\n\n"; } exit($error_msg); }
public function runLint() { $params = $this->parseLint(); if ($params === false) { return 1; } if (isset($params['h'])) { $this->usageLint(); return 0; } if (isset($params['q'])) { $lexer = new Lexer($params['q'], false); $parser = new Parser($lexer->list); $errors = Error::get(array($lexer, $parser)); if (count($errors) == 0) { return 0; } $output = Error::format($errors); echo implode("\n", $output); echo "\n"; return 10; } echo "ERROR: Missing parameters!\n"; $this->usageLint(); return 1; }
public function testFormat() { $this->assertEquals(array('#1: error msg (near "token" at position 100)'), Error::format(array(array('error msg', 42, 'token', 100)))); }
/** * Runs the linting process. * * @param string $query The query to be checked. * * @return array */ public static function lint($query) { // Disabling lint for huge queries to save some resources. if (mb_strlen($query) > 10000) { return array(array('message' => __('Linting is disabled for this query because it exceeds the ' . 'maximum length.'), 'fromLine' => 0, 'fromColumn' => 0, 'toLine' => 0, 'toColumn' => 0, 'severity' => 'warning')); } /** * Lexer used for tokenizing the query. * * @var Lexer */ $lexer = new Lexer($query); /** * Parsed used for analysing the query. * * @var Parser */ $parser = new Parser($lexer->list); /** * Array containing all errors. * * @var array */ $errors = Error::get(array($lexer, $parser)); /** * The response containing of all errors. * * @var array */ $response = array(); /** * The starting position for each line. * * CodeMirror requires relative position to line, but the parser stores * only the absolute position of the character in string. * * @var array */ $lines = static::getLines($query); // Building the response. foreach ($errors as $idx => $error) { // Starting position of the string that caused the error. list($fromLine, $fromColumn) = static::findLineNumberAndColumn($lines, $error[3]); // Ending position of the string that caused the error. list($toLine, $toColumn) = static::findLineNumberAndColumn($lines, $error[3] + mb_strlen($error[2])); // Building the response. $response[] = array('message' => sprintf(__('%1$s (near <code>%2$s</code>)'), $error[0], $error[2]), 'fromLine' => $fromLine, 'fromColumn' => $fromColumn, 'toLine' => $toLine, 'toColumn' => $toColumn, 'severity' => 'error'); } // Sending back the answer. return $response; }