diff options
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Sql.php')
| -rw-r--r-- | srcs/phpmyadmin/libraries/classes/Sql.php | 2328 |
1 files changed, 0 insertions, 2328 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Sql.php b/srcs/phpmyadmin/libraries/classes/Sql.php deleted file mode 100644 index fb4b07f..0000000 --- a/srcs/phpmyadmin/libraries/classes/Sql.php +++ /dev/null @@ -1,2328 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * Set of functions for the SQL executor - * - * @package PhpMyAdmin - */ -declare(strict_types=1); - -namespace PhpMyAdmin; - -use PhpMyAdmin\Bookmark; -use PhpMyAdmin\Core; -use PhpMyAdmin\DatabaseInterface; -use PhpMyAdmin\Display\Results as DisplayResults; -use PhpMyAdmin\Index; -use PhpMyAdmin\Message; -use PhpMyAdmin\Operations; -use PhpMyAdmin\ParseAnalyze; -use PhpMyAdmin\Relation; -use PhpMyAdmin\RelationCleanup; -use PhpMyAdmin\Response; -use PhpMyAdmin\SqlParser\Statements\AlterStatement; -use PhpMyAdmin\SqlParser\Statements\DropStatement; -use PhpMyAdmin\SqlParser\Statements\SelectStatement; -use PhpMyAdmin\SqlParser\Utils\Query; -use PhpMyAdmin\Table; -use PhpMyAdmin\Transformations; -use PhpMyAdmin\Url; -use PhpMyAdmin\Util; - -/** - * Set of functions for the SQL executor - * - * @package PhpMyAdmin - */ -class Sql -{ - /** - * @var Relation - */ - private $relation; - - /** - * @var RelationCleanup - */ - private $relationCleanup; - - /** - * @var Transformations - */ - private $transformations; - - /** - * @var Operations - */ - private $operations; - - /** - * @var Template - */ - private $template; - - /** - * Constructor - */ - public function __construct() - { - $this->relation = new Relation($GLOBALS['dbi']); - $this->relationCleanup = new RelationCleanup($GLOBALS['dbi'], $this->relation); - $this->operations = new Operations($GLOBALS['dbi'], $this->relation); - $this->transformations = new Transformations(); - $this->template = new Template(); - } - - /** - * Parses and analyzes the given SQL query. - * - * @param string $sql_query SQL query - * @param string $db DB name - * - * @return mixed - */ - public function parseAndAnalyze($sql_query, $db = null) - { - if ($db === null && isset($GLOBALS['db']) && strlen($GLOBALS['db'])) { - $db = $GLOBALS['db']; - } - list($analyzed_sql_results,,) = ParseAnalyze::sqlQuery($sql_query, $db); - return $analyzed_sql_results; - } - - /** - * Handle remembered sorting order, only for single table query - * - * @param string $db database name - * @param string $table table name - * @param array $analyzed_sql_results the analyzed query results - * @param string $full_sql_query SQL query - * - * @return void - */ - private function handleSortOrder( - $db, - $table, - array &$analyzed_sql_results, - &$full_sql_query - ) { - $pmatable = new Table($table, $db); - - if (empty($analyzed_sql_results['order'])) { - // Retrieving the name of the column we should sort after. - $sortCol = $pmatable->getUiProp(Table::PROP_SORTED_COLUMN); - if (empty($sortCol)) { - return; - } - - // Remove the name of the table from the retrieved field name. - $sortCol = str_replace( - Util::backquote($table) . '.', - '', - $sortCol - ); - - // Create the new query. - $full_sql_query = Query::replaceClause( - $analyzed_sql_results['statement'], - $analyzed_sql_results['parser']->list, - 'ORDER BY ' . $sortCol - ); - - // TODO: Avoid reparsing the query. - $analyzed_sql_results = Query::getAll($full_sql_query); - } else { - // Store the remembered table into session. - $pmatable->setUiProp( - Table::PROP_SORTED_COLUMN, - Query::getClause( - $analyzed_sql_results['statement'], - $analyzed_sql_results['parser']->list, - 'ORDER BY' - ) - ); - } - } - - /** - * Append limit clause to SQL query - * - * @param array $analyzed_sql_results the analyzed query results - * - * @return string limit clause appended SQL query - */ - private function getSqlWithLimitClause(array &$analyzed_sql_results) - { - return Query::replaceClause( - $analyzed_sql_results['statement'], - $analyzed_sql_results['parser']->list, - 'LIMIT ' . $_SESSION['tmpval']['pos'] . ', ' - . $_SESSION['tmpval']['max_rows'] - ); - } - - /** - * Verify whether the result set has columns from just one table - * - * @param array $fields_meta meta fields - * - * @return boolean whether the result set has columns from just one table - */ - private function resultSetHasJustOneTable(array $fields_meta) - { - $just_one_table = true; - $prev_table = ''; - foreach ($fields_meta as $one_field_meta) { - if ($one_field_meta->table != '' - && $prev_table != '' - && $one_field_meta->table != $prev_table - ) { - $just_one_table = false; - } - if ($one_field_meta->table != '') { - $prev_table = $one_field_meta->table; - } - } - return $just_one_table && $prev_table != ''; - } - - /** - * Verify whether the result set contains all the columns - * of at least one unique key - * - * @param string $db database name - * @param string $table table name - * @param array $fields_meta meta fields - * - * @return boolean whether the result set contains a unique key - */ - private function resultSetContainsUniqueKey($db, $table, array $fields_meta) - { - $columns = $GLOBALS['dbi']->getColumns($db, $table); - $resultSetColumnNames = []; - foreach ($fields_meta as $oneMeta) { - $resultSetColumnNames[] = $oneMeta->name; - } - foreach (Index::getFromTable($table, $db) as $index) { - if ($index->isUnique()) { - $indexColumns = $index->getColumns(); - $numberFound = 0; - foreach ($indexColumns as $indexColumnName => $dummy) { - if (in_array($indexColumnName, $resultSetColumnNames)) { - $numberFound++; - } elseif (! in_array($indexColumnName, $columns)) { - $numberFound++; - } elseif (strpos($columns[$indexColumnName]['Extra'], 'INVISIBLE') !== false) { - $numberFound++; - } - } - if ($numberFound == count($indexColumns)) { - return true; - } - } - } - return false; - } - - /** - * Get the HTML for relational column dropdown - * During grid edit, if we have a relational field, returns the html for the - * dropdown - * - * @param string $db current database - * @param string $table current table - * @param string $column current column - * @param string $curr_value current selected value - * - * @return string html for the dropdown - */ - private function getHtmlForRelationalColumnDropdown($db, $table, $column, $curr_value) - { - $foreigners = $this->relation->getForeigners($db, $table, $column); - - $foreignData = $this->relation->getForeignData( - $foreigners, - $column, - false, - '', - '' - ); - - if ($foreignData['disp_row'] == null) { - //Handle the case when number of values - //is more than $cfg['ForeignKeyMaxLimit'] - $_url_params = [ - 'db' => $db, - 'table' => $table, - 'field' => $column, - ]; - - $dropdown = $this->template->render('sql/relational_column_dropdown', [ - 'current_value' => $_POST['curr_value'], - 'params' => $_url_params, - ]); - } else { - $dropdown = $this->relation->foreignDropdown( - $foreignData['disp_row'], - $foreignData['foreign_field'], - $foreignData['foreign_display'], - $curr_value, - $GLOBALS['cfg']['ForeignKeyMaxLimit'] - ); - $dropdown = '<select>' . $dropdown . '</select>'; - } - - return $dropdown; - } - - /** - * Get the HTML for the profiling table and accompanying chart if profiling is set. - * Otherwise returns null - * - * @param string|null $urlQuery url query - * @param string $database current database - * @param array $profilingResults array containing the profiling info - * - * @return string html for the profiling table and chart - */ - private function getHtmlForProfilingChart($urlQuery, $database, $profilingResults): string - { - if (! empty($profilingResults)) { - $urlQuery = isset($urlQuery) ? $urlQuery : Url::getCommon(['db' => $database]); - - list( - $detailedTable, - $chartJson, - $profilingStats - ) = $this->analyzeAndGetTableHtmlForProfilingResults($profilingResults); - - return $this->template->render('sql/profiling_chart', [ - 'url_query' => $urlQuery, - 'detailed_table' => $detailedTable, - 'states' => $profilingStats['states'], - 'total_time' => $profilingStats['total_time'], - 'chart_json' => $chartJson, - ]); - } - return ''; - } - - /** - * Function to get HTML for detailed profiling results table, profiling stats, and - * $chart_json for displaying the chart. - * - * @param array $profiling_results profiling results - * - * @return mixed - */ - private function analyzeAndGetTableHtmlForProfilingResults( - $profiling_results - ) { - $profiling_stats = [ - 'total_time' => 0, - 'states' => [], - ]; - $chart_json = []; - $i = 1; - $table = ''; - foreach ($profiling_results as $one_result) { - if (! isset($profiling_stats['states'][ucwords($one_result['Status'])])) { - $profiling_stats['states'][ucwords($one_result['Status'])] = [ - 'total_time' => $one_result['Duration'], - 'calls' => 1, - ]; - } - $profiling_stats['total_time'] += $one_result['Duration']; - - $table .= $this->template->render('sql/detailed_table', [ - 'index' => $i++, - 'status' => $one_result['Status'], - 'duration' => $one_result['Duration'], - ]); - - if (isset($chart_json[ucwords($one_result['Status'])])) { - $chart_json[ucwords($one_result['Status'])] - += $one_result['Duration']; - } else { - $chart_json[ucwords($one_result['Status'])] - = $one_result['Duration']; - } - } - return [ - $table, - $chart_json, - $profiling_stats, - ]; - } - - /** - * Get the HTML for the enum column dropdown - * During grid edit, if we have a enum field, returns the html for the - * dropdown - * - * @param string $db current database - * @param string $table current table - * @param string $column current column - * @param string $curr_value currently selected value - * - * @return string html for the dropdown - */ - private function getHtmlForEnumColumnDropdown($db, $table, $column, $curr_value) - { - $values = $this->getValuesForColumn($db, $table, $column); - return $this->template->render('sql/enum_column_dropdown', [ - 'values' => $values, - 'selected_values' => [$curr_value], - ]); - } - - /** - * Get value of a column for a specific row (marked by $where_clause) - * - * @param string $db current database - * @param string $table current table - * @param string $column current column - * @param string $where_clause where clause to select a particular row - * - * @return string with value - */ - private function getFullValuesForSetColumn($db, $table, $column, $where_clause) - { - $result = $GLOBALS['dbi']->fetchSingleRow( - "SELECT `$column` FROM `$db`.`$table` WHERE $where_clause" - ); - - return $result[$column]; - } - - /** - * Get the HTML for the set column dropdown - * During grid edit, if we have a set field, returns the html for the - * dropdown - * - * @param string $db current database - * @param string $table current table - * @param string $column current column - * @param string $curr_value currently selected value - * - * @return string html for the set column - */ - private function getHtmlForSetColumn($db, $table, $column, $curr_value): string - { - $values = $this->getValuesForColumn($db, $table, $column); - - $full_values = isset($_POST['get_full_values']) ? $_POST['get_full_values'] : false; - $where_clause = isset($_POST['where_clause']) ? $_POST['where_clause'] : null; - - // If the $curr_value was truncated, we should - // fetch the correct full values from the table - if ($full_values && ! empty($where_clause)) { - $curr_value = $this->getFullValuesForSetColumn( - $db, - $table, - $column, - $where_clause - ); - } - - //converts characters of $curr_value to HTML entities - $converted_curr_value = htmlentities( - $curr_value, - ENT_COMPAT, - "UTF-8" - ); - - $selected_values = explode(',', $converted_curr_value); - $select_size = (count($values) > 10) ? 10 : count($values); - - return $this->template->render('sql/set_column', [ - 'size' => $select_size, - 'values' => $values, - 'selected_values' => $selected_values, - ]); - } - - /** - * Get all the values for a enum column or set column in a table - * - * @param string $db current database - * @param string $table current table - * @param string $column current column - * - * @return array array containing the value list for the column - */ - private function getValuesForColumn($db, $table, $column) - { - $field_info_query = $GLOBALS['dbi']->getColumnsSql($db, $table, $column); - - $field_info_result = $GLOBALS['dbi']->fetchResult( - $field_info_query, - null, - null, - DatabaseInterface::CONNECT_USER, - DatabaseInterface::QUERY_STORE - ); - - return Util::parseEnumSetValues($field_info_result[0]['Type']); - } - - /** - * Function to get html for bookmark support if bookmarks are enabled. Else will - * return null - * - * @param array $displayParts the parts to display - * @param array $cfgBookmark configuration setting for bookmarking - * @param string $sql_query sql query - * @param string $db current database - * @param string $table current table - * @param string|null $complete_query complete query - * @param string $bkm_user bookmarking user - * - * @return string - */ - public function getHtmlForBookmark( - array $displayParts, - array $cfgBookmark, - $sql_query, - $db, - $table, - ?string $complete_query, - $bkm_user - ): string { - if ($displayParts['bkm_form'] == '1' - && (! empty($cfgBookmark) && empty($_GET['id_bookmark'])) - && ! empty($sql_query) - ) { - return $this->template->render('sql/bookmark', [ - 'db' => $db, - 'goto' => 'sql.php' . Url::getCommon([ - 'db' => $db, - 'table' => $table, - 'sql_query' => $sql_query, - 'id_bookmark' => 1, - ]), - 'user' => $bkm_user, - 'sql_query' => isset($complete_query) ? $complete_query : $sql_query, - ]); - } - return ''; - } - - /** - * Function to check whether to remember the sorting order or not - * - * @param array $analyzed_sql_results the analyzed query and other variables set - * after analyzing the query - * - * @return boolean - */ - private function isRememberSortingOrder(array $analyzed_sql_results) - { - return $GLOBALS['cfg']['RememberSorting'] - && ! ($analyzed_sql_results['is_count'] - || $analyzed_sql_results['is_export'] - || $analyzed_sql_results['is_func'] - || $analyzed_sql_results['is_analyse']) - && $analyzed_sql_results['select_from'] - && isset($analyzed_sql_results['select_expr']) - && isset($analyzed_sql_results['select_tables']) - && (empty($analyzed_sql_results['select_expr']) - || ((count($analyzed_sql_results['select_expr']) === 1) - && ($analyzed_sql_results['select_expr'][0] == '*'))) - && count($analyzed_sql_results['select_tables']) === 1; - } - - /** - * Function to check whether the LIMIT clause should be appended or not - * - * @param array $analyzed_sql_results the analyzed query and other variables set - * after analyzing the query - * - * @return boolean - */ - private function isAppendLimitClause(array $analyzed_sql_results) - { - // Assigning LIMIT clause to an syntactically-wrong query - // is not needed. Also we would want to show the true query - // and the true error message to the query executor - - return (isset($analyzed_sql_results['parser']) - && count($analyzed_sql_results['parser']->errors) === 0) - && ($_SESSION['tmpval']['max_rows'] != 'all') - && ! ($analyzed_sql_results['is_export'] - || $analyzed_sql_results['is_analyse']) - && ($analyzed_sql_results['select_from'] - || $analyzed_sql_results['is_subquery']) - && empty($analyzed_sql_results['limit']); - } - - /** - * Function to check whether this query is for just browsing - * - * @param array $analyzed_sql_results the analyzed query and other variables set - * after analyzing the query - * @param boolean|null $find_real_end whether the real end should be found - * - * @return boolean - */ - public function isJustBrowsing(array $analyzed_sql_results, ?bool $find_real_end): bool - { - return ! $analyzed_sql_results['is_group'] - && ! $analyzed_sql_results['is_func'] - && empty($analyzed_sql_results['union']) - && empty($analyzed_sql_results['distinct']) - && $analyzed_sql_results['select_from'] - && (count($analyzed_sql_results['select_tables']) === 1) - && (empty($analyzed_sql_results['statement']->where) - || (count($analyzed_sql_results['statement']->where) === 1 - && $analyzed_sql_results['statement']->where[0]->expr === '1')) - && empty($analyzed_sql_results['group']) - && ! isset($find_real_end) - && ! $analyzed_sql_results['is_subquery'] - && ! $analyzed_sql_results['join'] - && empty($analyzed_sql_results['having']); - } - - /** - * Function to check whether the related transformation information should be deleted - * - * @param array $analyzed_sql_results the analyzed query and other variables set - * after analyzing the query - * - * @return boolean - */ - private function isDeleteTransformationInfo(array $analyzed_sql_results) - { - return ! empty($analyzed_sql_results['querytype']) - && (($analyzed_sql_results['querytype'] == 'ALTER') - || ($analyzed_sql_results['querytype'] == 'DROP')); - } - - /** - * Function to check whether the user has rights to drop the database - * - * @param array $analyzed_sql_results the analyzed query and other variables set - * after analyzing the query - * @param boolean $allowUserDropDatabase whether the user is allowed to drop db - * @param boolean $is_superuser whether this user is a superuser - * - * @return boolean - */ - public function hasNoRightsToDropDatabase( - array $analyzed_sql_results, - $allowUserDropDatabase, - $is_superuser - ) { - return ! $allowUserDropDatabase - && isset($analyzed_sql_results['drop_database']) - && $analyzed_sql_results['drop_database'] - && ! $is_superuser; - } - - /** - * Function to set a column property - * - * @param Table $pmatable Table instance - * @param string $request_index col_order|col_visib - * - * @return boolean - */ - private function setColumnProperty($pmatable, $request_index) - { - $property_value = array_map('intval', explode(',', $_POST[$request_index])); - switch ($request_index) { - case 'col_order': - $property_to_set = Table::PROP_COLUMN_ORDER; - break; - case 'col_visib': - $property_to_set = Table::PROP_COLUMN_VISIB; - break; - default: - $property_to_set = ''; - } - $retval = $pmatable->setUiProp( - $property_to_set, - $property_value, - isset($_POST['table_create_time']) ? $_POST['table_create_time'] : null - ); - if (gettype($retval) != 'boolean') { - $response = Response::getInstance(); - $response->setRequestStatus(false); - $response->addJSON('message', $retval->getString()); - exit; - } - - return $retval; - } - - /** - * Function to check the request for setting the column order or visibility - * - * @param string $table the current table - * @param string $db the current database - * - * @return void - */ - public function setColumnOrderOrVisibility($table, $db) - { - $pmatable = new Table($table, $db); - $retval = false; - - // set column order - if (isset($_POST['col_order'])) { - $retval = $this->setColumnProperty($pmatable, 'col_order'); - } - - // set column visibility - if ($retval === true && isset($_POST['col_visib'])) { - $retval = $this->setColumnProperty($pmatable, 'col_visib'); - } - - $response = Response::getInstance(); - $response->setRequestStatus($retval === true); - exit; - } - - /** - * Function to add a bookmark - * - * @param string $goto goto page URL - * - * @return void - */ - public function addBookmark($goto) - { - $bookmark = Bookmark::createBookmark( - $GLOBALS['dbi'], - $GLOBALS['cfg']['Server']['user'], - $_POST['bkm_fields'], - (isset($_POST['bkm_all_users']) - && $_POST['bkm_all_users'] == 'true' ? true : false - ) - ); - $result = $bookmark->save(); - $response = Response::getInstance(); - if ($response->isAjax()) { - if ($result) { - $msg = Message::success(__('Bookmark %s has been created.')); - $msg->addParam($_POST['bkm_fields']['bkm_label']); - $response->addJSON('message', $msg); - } else { - $msg = Message::error(__('Bookmark not created!')); - $response->setRequestStatus(false); - $response->addJSON('message', $msg); - } - exit; - } else { - // go back to sql.php to redisplay query; do not use & in this case: - /** - * @todo In which scenario does this happen? - */ - Core::sendHeaderLocation( - './' . $goto - . '&label=' . $_POST['bkm_fields']['bkm_label'] - ); - } - } - - /** - * Function to find the real end of rows - * - * @param string $db the current database - * @param string $table the current table - * - * @return mixed the number of rows if "retain" param is true, otherwise true - */ - public function findRealEndOfRows($db, $table) - { - $unlim_num_rows = $GLOBALS['dbi']->getTable($db, $table)->countRecords(true); - $_SESSION['tmpval']['pos'] = $this->getStartPosToDisplayRow($unlim_num_rows); - - return $unlim_num_rows; - } - - /** - * Function to get values for the relational columns - * - * @param string $db the current database - * @param string $table the current table - * - * @return void - */ - public function getRelationalValues($db, $table) - { - $column = $_POST['column']; - if ($_SESSION['tmpval']['relational_display'] == 'D' - && isset($_POST['relation_key_or_display_column']) - && $_POST['relation_key_or_display_column'] - ) { - $curr_value = $_POST['relation_key_or_display_column']; - } else { - $curr_value = $_POST['curr_value']; - } - $dropdown = $this->getHtmlForRelationalColumnDropdown( - $db, - $table, - $column, - $curr_value - ); - $response = Response::getInstance(); - $response->addJSON('dropdown', $dropdown); - exit; - } - - /** - * Function to get values for Enum or Set Columns - * - * @param string $db the current database - * @param string $table the current table - * @param string $columnType whether enum or set - * - * @return void - */ - public function getEnumOrSetValues($db, $table, $columnType) - { - $column = $_POST['column']; - $curr_value = $_POST['curr_value']; - $response = Response::getInstance(); - if ($columnType == "enum") { - $dropdown = $this->getHtmlForEnumColumnDropdown( - $db, - $table, - $column, - $curr_value - ); - $response->addJSON('dropdown', $dropdown); - } else { - $select = $this->getHtmlForSetColumn( - $db, - $table, - $column, - $curr_value - ); - $response->addJSON('select', $select); - } - exit; - } - - /** - * Function to get the default sql query for browsing page - * - * @param string $db the current database - * @param string $table the current table - * - * @return string the default $sql_query for browse page - */ - public function getDefaultSqlQueryForBrowse($db, $table) - { - $bookmark = Bookmark::get( - $GLOBALS['dbi'], - $GLOBALS['cfg']['Server']['user'], - $db, - $table, - 'label', - false, - true - ); - - if (! empty($bookmark) && ! empty($bookmark->getQuery())) { - $GLOBALS['using_bookmark_message'] = Message::notice( - __('Using bookmark "%s" as default browse query.') - ); - $GLOBALS['using_bookmark_message']->addParam($table); - $GLOBALS['using_bookmark_message']->addHtml( - Util::showDocu('faq', 'faq6-22') - ); - $sql_query = $bookmark->getQuery(); - } else { - $defaultOrderByClause = ''; - - if (isset($GLOBALS['cfg']['TablePrimaryKeyOrder']) - && ($GLOBALS['cfg']['TablePrimaryKeyOrder'] !== 'NONE') - ) { - $primaryKey = null; - $primary = Index::getPrimary($table, $db); - - if ($primary !== false) { - $primarycols = $primary->getColumns(); - - foreach ($primarycols as $col) { - $primaryKey = $col->getName(); - break; - } - - if ($primaryKey != null) { - $defaultOrderByClause = ' ORDER BY ' - . Util::backquote($table) . '.' - . Util::backquote($primaryKey) . ' ' - . $GLOBALS['cfg']['TablePrimaryKeyOrder']; - } - } - } - - $sql_query = 'SELECT * FROM ' . Util::backquote($table) - . $defaultOrderByClause; - } - - return $sql_query; - } - - /** - * Responds an error when an error happens when executing the query - * - * @param boolean $is_gotofile whether goto file or not - * @param string $error error after executing the query - * @param string $full_sql_query full sql query - * - * @return void - */ - private function handleQueryExecuteError($is_gotofile, $error, $full_sql_query) - { - if ($is_gotofile) { - $message = Message::rawError($error); - $response = Response::getInstance(); - $response->setRequestStatus(false); - $response->addJSON('message', $message); - } else { - Util::mysqlDie($error, $full_sql_query, '', ''); - } - exit; - } - - /** - * Function to store the query as a bookmark - * - * @param string $db the current database - * @param string $bkm_user the bookmarking user - * @param string $sql_query_for_bookmark the query to be stored in bookmark - * @param string $bkm_label bookmark label - * @param boolean|null $bkm_replace whether to replace existing bookmarks - * - * @return void - */ - public function storeTheQueryAsBookmark( - $db, - $bkm_user, - $sql_query_for_bookmark, - $bkm_label, - ?bool $bkm_replace - ) { - $bfields = [ - 'bkm_database' => $db, - 'bkm_user' => $bkm_user, - 'bkm_sql_query' => $sql_query_for_bookmark, - 'bkm_label' => $bkm_label, - ]; - - // Should we replace bookmark? - if (isset($bkm_replace)) { - $bookmarks = Bookmark::getList( - $GLOBALS['dbi'], - $GLOBALS['cfg']['Server']['user'], - $db - ); - foreach ($bookmarks as $bookmark) { - if ($bookmark->getLabel() == $bkm_label) { - $bookmark->delete(); - } - } - } - - $bookmark = Bookmark::createBookmark( - $GLOBALS['dbi'], - $GLOBALS['cfg']['Server']['user'], - $bfields, - isset($_POST['bkm_all_users']) - ); - $bookmark->save(); - } - - /** - * Executes the SQL query and measures its execution time - * - * @param string $full_sql_query the full sql query - * - * @return array ($result, $querytime) - */ - private function executeQueryAndMeasureTime($full_sql_query) - { - // close session in case the query takes too long - session_write_close(); - - // Measure query time. - $querytime_before = array_sum(explode(' ', microtime())); - - $result = @$GLOBALS['dbi']->tryQuery( - $full_sql_query, - DatabaseInterface::CONNECT_USER, - DatabaseInterface::QUERY_STORE - ); - $querytime_after = array_sum(explode(' ', microtime())); - - // reopen session - session_start(); - - return [ - $result, - $querytime_after - $querytime_before, - ]; - } - - /** - * Function to get the affected or changed number of rows after executing a query - * - * @param boolean $is_affected whether the query affected a table - * @param mixed $result results of executing the query - * - * @return int number of rows affected or changed - */ - private function getNumberOfRowsAffectedOrChanged($is_affected, $result) - { - if (! $is_affected) { - $num_rows = $result ? @$GLOBALS['dbi']->numRows($result) : 0; - } else { - $num_rows = @$GLOBALS['dbi']->affectedRows(); - } - - return $num_rows; - } - - /** - * Checks if the current database has changed - * This could happen if the user sends a query like "USE `database`;" - * - * @param string $db the database in the query - * - * @return bool whether to reload the navigation(1) or not(0) - */ - private function hasCurrentDbChanged($db): bool - { - if (strlen($db) > 0) { - $current_db = $GLOBALS['dbi']->fetchValue('SELECT DATABASE()'); - // $current_db is false, except when a USE statement was sent - return ($current_db != false) && ($db !== $current_db); - } - - return false; - } - - /** - * If a table, database or column gets dropped, clean comments. - * - * @param string $db current database - * @param string $table current table - * @param string|null $column current column - * @param bool $purge whether purge set or not - * - * @return void - */ - private function cleanupRelations($db, $table, ?string $column, $purge) - { - if (! empty($purge) && strlen($db) > 0) { - if (strlen($table) > 0) { - if (isset($column) && strlen($column) > 0) { - $this->relationCleanup->column($db, $table, $column); - } else { - $this->relationCleanup->table($db, $table); - } - } else { - $this->relationCleanup->database($db); - } - } - } - - /** - * 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 unlimited number of rows - */ - private function countQueryResults( - $num_rows, - $justBrowsing, - $db, - $table, - array $analyzed_sql_results - ) { - - /* Shortcut for not analyzed/empty query */ - if (empty($analyzed_sql_results)) { - return 0; - } - - if (! $this->isAppendLimitClause($analyzed_sql_results)) { - // if we did not append a limit, set this to get a correct - // "Showing rows..." message |
