Exemplo n.º 1
0
/**
 * Calls the parser on a query
 *
 * @param string $sql_query the query to parse
 * @param string $db        the current database
 *
 * @return array
 *
 * @access  public
 */
function PMA_parseAnalyze($sql_query, $db)
{
    // @todo: move to returned results (also in all the calling chain)
    $GLOBALS['unparsed_sql'] = $sql_query;
    // Get details about the SQL query.
    $analyzed_sql_results = SqlParser\Utils\Query::getAll($sql_query);
    extract($analyzed_sql_results);
    $table = '';
    // If the targeted table (and database) are different than the ones that is
    // currently browsed, edit `$db` and `$table` to match them so other elements
    // (page headers, links, navigation panel) can be updated properly.
    if (!empty($analyzed_sql_results['select_tables'])) {
        // Previous table and database name is stored to check if it changed.
        $prev_db = $db;
        if (count($analyzed_sql_results['select_tables']) > 1) {
            /**
             * @todo if there are more than one table name in the Select:
             * - do not extract the first table name
             * - do not show a table name in the page header
             * - do not display the sub-pages links)
             */
            $table = '';
        } else {
            $table = $analyzed_sql_results['select_tables'][0][0];
            if (!empty($analyzed_sql_results['select_tables'][0][1])) {
                $db = $analyzed_sql_results['select_tables'][0][1];
            }
        }
        // There is no point checking if a reload is required if we already decided
        // to reload. Also, no reload is required for AJAX requests.
        $response = Response::getInstance();
        if (empty($reload) && !$response->isAjax()) {
            // NOTE: Database names are case-insensitive.
            $reload = strcasecmp($db, $prev_db) != 0;
        }
        // Updating the array.
        $analyzed_sql_results['reload'] = $reload;
    }
    return array($analyzed_sql_results, $db, $table);
}
Exemplo n.º 2
0
 /**
  * Get url sql query without conditions to shorten URLs
  *
  * @param array $analyzed_sql_results analyzed sql results
  *
  * @return  string  $url_sql        analyzed sql query
  *
  * @access  private
  *
  * @see     _getTableBody()
  */
 private function _getUrlSqlQuery($analyzed_sql_results)
 {
     if ($analyzed_sql_results['querytype'] != 'SELECT' || mb_strlen($this->__get('sql_query')) < 200) {
         return $this->__get('sql_query');
     }
     $query = 'SELECT ' . SqlParser\Utils\Query::getClause($analyzed_sql_results['statement'], $analyzed_sql_results['parser']->list, 'SELECT');
     $from_clause = SqlParser\Utils\Query::getClause($analyzed_sql_results['statement'], $analyzed_sql_results['parser']->list, 'FROM');
     if (!empty($from_clause)) {
         $query .= ' FROM ' . $from_clause;
     }
     return $query;
 }
Exemplo n.º 3
0
/**
 * Function to count the total number of rows for the same 'SELECT' query without
 * the 'LIMIT' clause that may have been programatically added
 *
 * @param int    $num_rows             number of rows affected/changed by the query
 * @param bool   $justBrowsing         whether just browsing or not
 * @param string $db                   the current database
 * @param string $table                the current table
 * @param array  $analyzed_sql_results the analyzed query and other variables set
 *                                     after analyzing the query
 *
 * @return int $unlim_num_rows unlimited number of rows
 */
function PMA_countQueryResults($num_rows, $justBrowsing, $db, $table, $analyzed_sql_results)
{
    if (!PMA_isAppendLimitClause($analyzed_sql_results)) {
        // if we did not append a limit, set this to get a correct
        // "Showing rows..." message
        // $_SESSION['tmpval']['max_rows'] = 'all';
        $unlim_num_rows = $num_rows;
    } elseif ($analyzed_sql_results['querytype'] == 'SELECT' || $analyzed_sql_results['is_subquery']) {
        //    c o u n t    q u e r y
        // If we are "just browsing", there is only one table,
        // and no WHERE clause (or just 'WHERE 1 '),
        // we do a quick count (which uses MaxExactCount) because
        // SQL_CALC_FOUND_ROWS is not quick on large InnoDB tables
        // However, do not count again if we did it previously
        // due to $find_real_end == true
        if ($justBrowsing) {
            // Get row count (is approximate for InnoDB)
            $unlim_num_rows = $GLOBALS['dbi']->getTable($db, $table)->countRecords();
            /**
             * @todo Can we know at this point that this is InnoDB,
             *       (in this case there would be no need for getting
             *       an exact count)?
             */
            if ($unlim_num_rows < $GLOBALS['cfg']['MaxExactCount']) {
                // Get the exact count if approximate count
                // is less than MaxExactCount
                /**
                 * @todo In countRecords(), MaxExactCount is also verified,
                 *       so can we avoid checking it twice?
                 */
                $unlim_num_rows = $GLOBALS['dbi']->getTable($db, $table)->countRecords(true);
            }
        } else {
            // The SQL_CALC_FOUND_ROWS option of the SELECT statement is used.
            // For UNION statements, only a SQL_CALC_FOUND_ROWS is required
            // after the first SELECT.
            $count_query = SqlParser\Utils\Query::replaceClause($analyzed_sql_results['statement'], $analyzed_sql_results['parser']->list, 'SELECT SQL_CALC_FOUND_ROWS', null, true);
            // Another LIMIT clause is added to avoid long delays.
            // A complete result will be returned anyway, but the LIMIT would
            // stop the query as soon as the result that is required has been
            // computed.
            if (empty($analyzed_sql_results['union'])) {
                $count_query .= ' LIMIT 1';
            }
            // Running the count query.
            $GLOBALS['dbi']->tryQuery($count_query);
            $unlim_num_rows = $GLOBALS['dbi']->fetchValue('SELECT FOUND_ROWS()');
        }
        // end else "just browsing"
    } else {
        // not $is_select
        $unlim_num_rows = 0;
    }
    return $unlim_num_rows;
}
        foreach ($parser->statements[0]->from as $from) {
            if (!empty($from->table) && !empty($from->alias)) {
                $aliases[$from->alias] = $from->table;
                // We remove the alias of the table because they are going to
                // be replaced anyway.
                $from->alias = null;
                $from->expr = null;
                // Force rebuild.
            }
        }
        // Rebuilding the SELECT and FROM clauses.
        $replaces = array(array('FROM', 'FROM ' . SqlParser\Components\ExpressionArray::build($parser->statements[0]->from)));
        // Checking if the WHERE clause has to be replaced.
        if (!empty($where_clause) && is_array($where_clause)) {
            $replaces[] = array('WHERE', 'WHERE (' . implode(') OR (', $where_clause) . ')');
        }
        // Preparing to remove the LIMIT clause.
        $replaces[] = array('LIMIT', '');
        // Replacing the clauses.
        $sql_query = SqlParser\Utils\Query::replaceClauses($parser->statements[0], $parser->list, $replaces);
        // Removing the aliases by finding the alias followed by a dot.
        $tokens = SqlParser\Lexer::getTokens($sql_query);
        foreach ($aliases as $alias => $table) {
            $tokens = SqlParser\Utils\Tokens::replaceTokens($tokens, array(array('value_str' => $alias), array('type' => SqlParser\Token::TYPE_OPERATOR, 'value_str' => '.')), array());
        }
        $sql_query = SqlParser\TokensList::build($tokens);
    }
    echo PMA_Util::getMessage(PMA_Message::success());
}
$export_type = 'table';
require_once 'libraries/display_export.inc.php';
Exemplo n.º 5
0
/**
 * Checks if ROLLBACK is possible for a SQL query or not.
 *
 * @param string $sql_query SQL query
 *
 * @return bool
 */
function PMA_checkIfRollbackPossible($sql_query)
{
    $parser = new SqlParser\Parser($sql_query);
    if (empty($parser->statements[0])) {
        return false;
    }
    $statement = $parser->statements[0];
    // Check if query is supported.
    if (!($statement instanceof SqlParser\Statements\InsertStatement || $statement instanceof SqlParser\Statements\UpdateStatement || $statement instanceof SqlParser\Statements\DeleteStatement || $statement instanceof SqlParser\Statements\ReplaceStatement)) {
        return false;
    }
    // Get table_references from the query.
    $tables = SqlParser\Utils\Query::getTables($statement);
    // Check if each table is 'InnoDB'.
    foreach ($tables as $table) {
        if (!PMA_isTableTransactional($table)) {
            return false;
        }
    }
    return true;
}
<?php

/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
 * Parse and analyse a SQL query
 *
 * @package PhpMyAdmin
 */
if (!defined('PHPMYADMIN')) {
    exit;
}
$GLOBALS['unparsed_sql'] = $sql_query;
// Get details about the SQL query.
$analyzed_sql_results = SqlParser\Utils\Query::getAll($sql_query);
// TODO: Refactor this.
extract($analyzed_sql_results);
// If the targeted table (and database) are different than the ones that is
// currently browsed, edit `$db` and `$table` to match them so other elements
// (page headers, links, navigation panel) can be updated properly.
if (!empty($analyzed_sql_results['select_tables'])) {
    // Previous table and database name is stored to check if it changed.
    $prev_db = $db;
    if (count($analyzed_sql_results['select_tables']) > 1) {
        /**
         * @todo if there are more than one table name in the Select:
         * - do not extract the first table name
         * - do not show a table name in the page header
         * - do not display the sub-pages links)
         */
        $table = '';
    } else {