diff --git a/libraries/classes/Controllers/Database/QueryByExampleController.php b/libraries/classes/Controllers/Database/QueryByExampleController.php
index f21400923d..a0833bf4f5 100644
--- a/libraries/classes/Controllers/Database/QueryByExampleController.php
+++ b/libraries/classes/Controllers/Database/QueryByExampleController.php
@@ -126,7 +126,7 @@ class QueryByExampleController extends AbstractController
);
$this->response->addHTML($sql->executeQueryAndSendQueryResponse(
- null, // analyzed_sql_results
+ null,
false, // is_gotofile
$_POST['db'], // db
null, // table
diff --git a/libraries/classes/Controllers/Import/ImportController.php b/libraries/classes/Controllers/Import/ImportController.php
index 760fc87d92..1fe5588347 100644
--- a/libraries/classes/Controllers/Import/ImportController.php
+++ b/libraries/classes/Controllers/Import/ImportController.php
@@ -715,14 +715,13 @@ final class ImportController extends AbstractController
// can choke on it so avoid parsing)
$sqlLength = mb_strlen($GLOBALS['sql_query']);
if ($sqlLength <= $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
- [
- $analyzed_sql_results,
- $GLOBALS['db'],
- $table_from_sql,
- ] = ParseAnalyze::sqlQuery($GLOBALS['sql_query'], $GLOBALS['db']);
+ [$statementInfo, $GLOBALS['db'], $table_from_sql] = ParseAnalyze::sqlQuery(
+ $GLOBALS['sql_query'],
+ $GLOBALS['db']
+ );
- $GLOBALS['reload'] = $analyzed_sql_results['reload'];
- $GLOBALS['offset'] = $analyzed_sql_results['offset'];
+ $GLOBALS['reload'] = $statementInfo->reload;
+ $GLOBALS['offset'] = $statementInfo->offset;
if ($GLOBALS['table'] != $table_from_sql && ! empty($table_from_sql)) {
$GLOBALS['table'] = $table_from_sql;
@@ -747,19 +746,18 @@ final class ImportController extends AbstractController
foreach ($queriesToBeExecuted as $GLOBALS['sql_query']) {
// parse sql query
- [
- $analyzed_sql_results,
- $GLOBALS['db'],
- $table_from_sql,
- ] = ParseAnalyze::sqlQuery($GLOBALS['sql_query'], $GLOBALS['db']);
+ [$statementInfo, $GLOBALS['db'], $table_from_sql] = ParseAnalyze::sqlQuery(
+ $GLOBALS['sql_query'],
+ $GLOBALS['db']
+ );
- $GLOBALS['offset'] = $analyzed_sql_results['offset'];
- $GLOBALS['reload'] = $analyzed_sql_results['reload'];
+ $GLOBALS['offset'] = $statementInfo->offset;
+ $GLOBALS['reload'] = $statementInfo->reload;
// Check if User is allowed to issue a 'DROP DATABASE' Statement
if (
$this->sql->hasNoRightsToDropDatabase(
- $analyzed_sql_results,
+ $statementInfo,
$GLOBALS['cfg']['AllowUserDropDatabase'],
$this->dbi->isSuperUser()
)
@@ -779,7 +777,7 @@ final class ImportController extends AbstractController
}
$html_output .= $this->sql->executeQueryAndGetQueryResponse(
- $analyzed_sql_results, // analyzed_sql_results
+ $statementInfo,
false, // is_gotofile
$GLOBALS['db'], // db
$GLOBALS['table'], // table
diff --git a/libraries/classes/Controllers/Sql/SqlController.php b/libraries/classes/Controllers/Sql/SqlController.php
index f04f98e854..3bd61e06b0 100644
--- a/libraries/classes/Controllers/Sql/SqlController.php
+++ b/libraries/classes/Controllers/Sql/SqlController.php
@@ -145,11 +145,10 @@ class SqlController extends AbstractController
/**
* Parse and analyze the query
*/
- [
- $analyzed_sql_results,
- $GLOBALS['db'],
- $GLOBALS['table_from_sql'],
- ] = ParseAnalyze::sqlQuery($GLOBALS['sql_query'], $GLOBALS['db']);
+ [$statementInfo, $GLOBALS['db'], $GLOBALS['table_from_sql']] = ParseAnalyze::sqlQuery(
+ $GLOBALS['sql_query'],
+ $GLOBALS['db']
+ );
if ($GLOBALS['table'] != $GLOBALS['table_from_sql'] && ! empty($GLOBALS['table_from_sql'])) {
$GLOBALS['table'] = $GLOBALS['table_from_sql'];
@@ -164,7 +163,7 @@ class SqlController extends AbstractController
*/
if (
$this->sql->hasNoRightsToDropDatabase(
- $analyzed_sql_results,
+ $statementInfo,
$GLOBALS['cfg']['AllowUserDropDatabase'],
$this->dbi->isSuperUser()
)
@@ -206,7 +205,7 @@ class SqlController extends AbstractController
}
$this->response->addHTML($this->sql->executeQueryAndSendQueryResponse(
- $analyzed_sql_results,
+ $statementInfo,
$GLOBALS['is_gotofile'],
$GLOBALS['db'],
$GLOBALS['table'],
diff --git a/libraries/classes/Controllers/Table/SearchController.php b/libraries/classes/Controllers/Table/SearchController.php
index db316574a4..079f679015 100644
--- a/libraries/classes/Controllers/Table/SearchController.php
+++ b/libraries/classes/Controllers/Table/SearchController.php
@@ -259,7 +259,7 @@ class SearchController extends AbstractController
);
$this->response->addHTML($sql->executeQueryAndSendQueryResponse(
- null, // analyzed_sql_results
+ null,
false, // is_gotofile
$GLOBALS['db'], // db
$GLOBALS['table'], // table
diff --git a/libraries/classes/Controllers/Table/Structure/BrowseController.php b/libraries/classes/Controllers/Table/Structure/BrowseController.php
index 4648965350..7666d84b54 100644
--- a/libraries/classes/Controllers/Table/Structure/BrowseController.php
+++ b/libraries/classes/Controllers/Table/Structure/BrowseController.php
@@ -60,13 +60,13 @@ final class BrowseController extends AbstractController
);
// Parse and analyze the query
- [$analyzed_sql_results, $GLOBALS['db']] = ParseAnalyze::sqlQuery($sql_query, $GLOBALS['db']);
+ [$statementInfo, $GLOBALS['db']] = ParseAnalyze::sqlQuery($sql_query, $GLOBALS['db']);
$this->response->addHTML(
$this->sql->executeQueryAndGetQueryResponse(
- $analyzed_sql_results ?? '',
+ $statementInfo,
false, // is_gotofile
- (string) $GLOBALS['db'], // db
+ $GLOBALS['db'], // db
$GLOBALS['table'], // table
null, // find_real_end
null, // sql_query_for_bookmark
diff --git a/libraries/classes/Database/MultiTableQuery.php b/libraries/classes/Database/MultiTableQuery.php
index 60ccd937ed..5bf67a81de 100644
--- a/libraries/classes/Database/MultiTableQuery.php
+++ b/libraries/classes/Database/MultiTableQuery.php
@@ -122,7 +122,7 @@ class MultiTableQuery
);
return $sql->executeQueryAndSendQueryResponse(
- null, // analyzed_sql_results
+ null,
false, // is_gotofile
$db, // db
null, // table
diff --git a/libraries/classes/Display/Results.php b/libraries/classes/Display/Results.php
index f768df180c..3c446494f1 100644
--- a/libraries/classes/Display/Results.php
+++ b/libraries/classes/Display/Results.php
@@ -24,6 +24,7 @@ use PhpMyAdmin\Sql;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Statements\SelectStatement;
use PhpMyAdmin\SqlParser\Utils\Query;
+use PhpMyAdmin\StatementInfo;
use PhpMyAdmin\Table;
use PhpMyAdmin\Template;
use PhpMyAdmin\Theme;
@@ -643,19 +644,17 @@ class Results
* "SELECT * FROM ..."
*
* @see getTableHeaders(), getColumnParams()
- *
- * @param array $analyzedSqlResults analyzed sql results
*/
- private function isSelect(array $analyzedSqlResults): bool
+ private function isSelect(StatementInfo $statementInfo): bool
{
return ! ($this->properties['is_count']
|| $this->properties['is_export']
|| $this->properties['is_func']
|| $this->properties['is_analyse'])
- && ! empty($analyzedSqlResults['select_from'])
- && ! empty($analyzedSqlResults['statement']->from)
- && (count($analyzedSqlResults['statement']->from) === 1)
- && ! empty($analyzedSqlResults['statement']->from[0]->table);
+ && ! empty($statementInfo->selectFrom)
+ && ! empty($statementInfo->statement->from)
+ && (count($statementInfo->statement->from) === 1)
+ && ! empty($statementInfo->statement->from[0]->table);
}
/**
@@ -778,7 +777,6 @@ class Results
*
* @see getTableHeaders()
*
- * @param array $analyzedSqlResults analyzed sql results
* @param array $sortExpression sort expression
* @param array $sortExpressionNoDirection sort expression
* without direction
@@ -791,7 +789,7 @@ class Results
*/
private function getTableHeadersForColumns(
bool $hasSortLink,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
array $sortExpression,
array $sortExpressionNoDirection,
array $sortDirection,
@@ -812,9 +810,9 @@ class Results
// Prepare Display column comments if enabled
// ($GLOBALS['cfg']['ShowBrowseComments']).
- $commentsMap = $this->getTableCommentsArray($analyzedSqlResults);
+ $commentsMap = $this->getTableCommentsArray($statementInfo);
- [$colOrder, $colVisib] = $this->getColumnParams($analyzedSqlResults);
+ [$colOrder, $colVisib] = $this->getColumnParams($statementInfo);
// optimize: avoid calling a method on each iteration
$numberOfColumns = $this->properties['fields_cnt'];
@@ -893,7 +891,6 @@ class Results
*
* @see getTable()
*
- * @param array $analyzedSqlResults analyzed sql results
* @param string $unsortedSqlQuery the unsorted sql query
* @param array $sortExpression sort expression
* @param array $sortExpressionNoDirection sort expression without direction
@@ -911,7 +908,7 @@ class Results
*/
private function getTableHeaders(
DisplayParts $displayParts,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$unsortedSqlQuery,
array $sortExpression = [],
array $sortExpressionNoDirection = [],
@@ -924,7 +921,7 @@ class Results
$displayParams = $this->properties['display_params'];
// Output data needed for column reordering and show/hide column
- $columnOrder = $this->getDataForResettingColumnOrder($analyzedSqlResults);
+ $columnOrder = $this->getDataForResettingColumnOrder($statementInfo);
$displayParams['emptypre'] = 0;
$displayParams['emptyafter'] = 0;
@@ -954,12 +951,12 @@ class Results
// See if we have to highlight any header fields of a WHERE query.
// Uses SQL-Parser results.
- $this->setHighlightedColumnGlobalField($analyzedSqlResults);
+ $this->setHighlightedColumnGlobalField($statementInfo);
// Get the headers for all of the columns
$tableHeadersForColumns = $this->getTableHeadersForColumns(
$displayParts->hasSortLink,
- $analyzedSqlResults,
+ $statementInfo,
$sortExpression,
$sortExpressionNoDirection,
$sortDirection,
@@ -1138,18 +1135,16 @@ class Results
*
* @see getTableHeaders()
*
- * @param array $analyzedSqlResults analyzed sql results
- *
* @return array table comments
*/
- private function getTableCommentsArray(array $analyzedSqlResults)
+ private function getTableCommentsArray(StatementInfo $statementInfo)
{
- if (! $GLOBALS['cfg']['ShowBrowseComments'] || empty($analyzedSqlResults['statement']->from)) {
+ if (! $GLOBALS['cfg']['ShowBrowseComments'] || empty($statementInfo->statement->from)) {
return [];
}
$ret = [];
- foreach ($analyzedSqlResults['statement']->from as $field) {
+ foreach ($statementInfo->statement->from as $field) {
if (empty($field->table)) {
continue;
}
@@ -1167,15 +1162,13 @@ class Results
* Set global array for store highlighted header fields
*
* @see getTableHeaders()
- *
- * @param array $analyzedSqlResults analyzed sql results
*/
- private function setHighlightedColumnGlobalField(array $analyzedSqlResults): void
+ private function setHighlightedColumnGlobalField(StatementInfo $statementInfo): void
{
$highlightColumns = [];
- if (! empty($analyzedSqlResults['statement']->where)) {
- foreach ($analyzedSqlResults['statement']->where as $expr) {
+ if (! empty($statementInfo->statement->where)) {
+ foreach ($statementInfo->statement->where as $expr) {
foreach ($expr->identifiers as $identifier) {
$highlightColumns[$identifier] = 'true';
}
@@ -1190,17 +1183,15 @@ class Results
*
* @see getTableHeaders()
*
- * @param array $analyzedSqlResults analyzed sql results
- *
* @return array
*/
- private function getDataForResettingColumnOrder(array $analyzedSqlResults): array
+ private function getDataForResettingColumnOrder(StatementInfo $statementInfo): array
{
- if (! $this->isSelect($analyzedSqlResults)) {
+ if (! $this->isSelect($statementInfo)) {
return [];
}
- [$columnOrder, $columnVisibility] = $this->getColumnParams($analyzedSqlResults);
+ [$columnOrder, $columnVisibility] = $this->getColumnParams($statementInfo);
$tableCreateTime = '';
$table = new Table($this->properties['table'], $this->properties['db']);
@@ -1936,11 +1927,10 @@ class Results
*
* @see getTable()
*
- * @param ResultInterface $dtResult the link id associated to the query
- * which results have to be displayed
- * @param array $map the list of relations
- * @param array $analyzedSqlResults analyzed sql results
- * @param bool $isLimitedDisplay with limited operations or not
+ * @param ResultInterface $dtResult the link id associated to the query
+ * which results have to be displayed
+ * @param array $map the list of relations
+ * @param bool $isLimitedDisplay with limited operations or not
*
* @return string html content
*
@@ -1950,7 +1940,7 @@ class Results
ResultInterface $dtResult,
DisplayParts $displayParts,
array $map,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$isLimitedDisplay = false
) {
// Mostly because of browser transformations, to make the row-data accessible in a plugin.
@@ -1961,7 +1951,7 @@ class Results
// query without conditions to shorten URLs when needed, 200 is just
// guess, it should depend on remaining URL length
- $urlSqlQuery = $this->getUrlSqlQuery($analyzedSqlResults);
+ $urlSqlQuery = $this->getUrlSqlQuery($statementInfo);
$displayParams = $this->properties['display_params'];
@@ -1982,7 +1972,7 @@ class Results
}
// prepare to get the column order, if available
- [$colOrder, $colVisib] = $this->getColumnParams($analyzedSqlResults);
+ [$colOrder, $colVisib] = $this->getColumnParams($statementInfo);
// Correction University of Virginia 19991216 in the while below
// Previous code assumed that all tables have keys, specifically that
@@ -2044,10 +2034,10 @@ class Results
$expressions = [];
if (
- isset($analyzedSqlResults['statement'])
- && $analyzedSqlResults['statement'] instanceof SelectStatement
+ isset($statementInfo->statement)
+ && $statementInfo->statement instanceof SelectStatement
) {
- $expressions = $analyzedSqlResults['statement']->expr;
+ $expressions = $statementInfo->statement->expr;
}
// Results from a "SELECT" statement -> builds the
@@ -2154,7 +2144,7 @@ class Results
$gridEditConfig,
$colVisib,
$urlSqlQuery,
- $analyzedSqlResults
+ $statementInfo
);
// 3. Displays the modify/delete links on the right if required
@@ -2265,17 +2255,16 @@ class Results
*
* @see getTableBody()
*
- * @param array $row current row data
- * @param int $rowNumber the index of current row
- * @param array|false $colOrder the column order false when
- * a property not found false
- * when a property not found
- * @param array $map the list of relations
- * @param bool|array|string $colVisib column is visible(false);
- * column isn't visible(string
- * array)
- * @param string $urlSqlQuery the analyzed sql query
- * @param array $analyzedSqlResults analyzed sql results
+ * @param array $row current row data
+ * @param int $rowNumber the index of current row
+ * @param array|false $colOrder the column order false when
+ * a property not found false
+ * when a property not found
+ * @param array $map the list of relations
+ * @param bool|array|string $colVisib column is visible(false);
+ * column isn't visible(string
+ * array)
+ * @param string $urlSqlQuery the analyzed sql query
* @psalm-param 'double-click'|'click'|'disabled' $gridEditConfig
*
* @return string html content
@@ -2288,7 +2277,7 @@ class Results
string $gridEditConfig,
$colVisib,
$urlSqlQuery,
- array $analyzedSqlResults
+ StatementInfo $statementInfo
) {
$rowValuesHtml = '';
@@ -2430,10 +2419,10 @@ class Results
$expressions = [];
if (
- isset($analyzedSqlResults['statement'])
- && $analyzedSqlResults['statement'] instanceof SelectStatement
+ isset($statementInfo->statement)
+ && $statementInfo->statement instanceof SelectStatement
) {
- $expressions = $analyzedSqlResults['statement']->expr;
+ $expressions = $statementInfo->statement->expr;
}
/**
@@ -2490,7 +2479,7 @@ class Results
$conditionField,
$meta,
$map,
- $analyzedSqlResults,
+ $statementInfo,
$transformationPlugin,
$transformOptions
);
@@ -2510,7 +2499,7 @@ class Results
$conditionField,
$transformationPlugin,
$transformOptions,
- $analyzedSqlResults
+ $statementInfo
);
} else {
// n o t n u m e r i c
@@ -2524,7 +2513,7 @@ class Results
$conditionField,
$transformationPlugin,
$transformOptions,
- $analyzedSqlResults
+ $statementInfo
);
}
@@ -2620,23 +2609,26 @@ class Results
*
* @see getTableBody()
*
- * @param array $analyzedSqlResults analyzed sql results
- *
* @return string analyzed sql query
*/
- private function getUrlSqlQuery(array $analyzedSqlResults)
+ private function getUrlSqlQuery(StatementInfo $statementInfo)
{
- if (($analyzedSqlResults['querytype'] !== 'SELECT') || (mb_strlen($this->properties['sql_query']) < 200)) {
+ if (
+ $statementInfo->queryType !== 'SELECT'
+ || mb_strlen($this->properties['sql_query']) < 200
+ || $statementInfo->statement === null
+ || $statementInfo->parser === null
+ ) {
return $this->properties['sql_query'];
}
$query = 'SELECT ' . Query::getClause(
- $analyzedSqlResults['statement'],
- $analyzedSqlResults['parser']->list,
+ $statementInfo->statement,
+ $statementInfo->parser->list,
'SELECT'
);
- $fromClause = Query::getClause($analyzedSqlResults['statement'], $analyzedSqlResults['parser']->list, 'FROM');
+ $fromClause = Query::getClause($statementInfo->statement, $statementInfo->parser->list, 'FROM');
if ($fromClause !== '') {
$query .= ' FROM ' . $fromClause;
@@ -2650,13 +2642,11 @@ class Results
*
* @see getTableBody()
*
- * @param array $analyzedSqlResults analyzed sql results
- *
* @return mixed[] 2 element array - $col_order, $col_visib
*/
- private function getColumnParams(array $analyzedSqlResults): array
+ private function getColumnParams(StatementInfo $statementInfo): array
{
- if ($this->isSelect($analyzedSqlResults)) {
+ if ($this->isSelect($statementInfo)) {
$pmatable = new Table($this->properties['table'], $this->properties['db']);
$colOrder = $pmatable->getUiProp(Table::PROP_COLUMN_ORDER);
$fieldsCount = $this->properties['fields_cnt'];
@@ -2930,13 +2920,12 @@ class Results
*
* @see getTableBody()
*
- * @param string|null $column the column's value
- * @param string $class the html class for column
- * @param bool $conditionField the column should highlighted or not
- * @param FieldMetadata $meta the meta-information about this field
- * @param array $map the list of relations
- * @param array $analyzedSqlResults the analyzed query
- * @param array $transformOptions the transformation parameters
+ * @param string|null $column the column's value
+ * @param string $class the html class for column
+ * @param bool $conditionField the column should highlighted or not
+ * @param FieldMetadata $meta the meta-information about this field
+ * @param array $map the list of relations
+ * @param array $transformOptions the transformation parameters
*
* @return string the prepared cell, html content
*/
@@ -2946,7 +2935,7 @@ class Results
bool $conditionField,
FieldMetadata $meta,
array $map,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
?TransformationsPlugin $transformationPlugin,
array $transformOptions
) {
@@ -2963,7 +2952,7 @@ class Results
return $this->getRowData(
$class,
$conditionField,
- $analyzedSqlResults,
+ $statementInfo,
$meta,
$map,
$column,
@@ -2980,14 +2969,13 @@ class Results
*
* @see getTableBody()
*
- * @param string|null $column the relevant column in data row
- * @param string $class the html class for column
- * @param FieldMetadata $meta the meta-information about this field
- * @param array $map the list of relations
- * @param array $urlParams the parameters for generate url
- * @param bool $conditionField the column should highlighted or not
- * @param array $transformOptions the transformation parameters
- * @param array $analyzedSqlResults the analyzed query
+ * @param string|null $column the relevant column in data row
+ * @param string $class the html class for column
+ * @param FieldMetadata $meta the meta-information about this field
+ * @param array $map the list of relations
+ * @param array $urlParams the parameters for generate url
+ * @param bool $conditionField the column should highlighted or not
+ * @param array $transformOptions the transformation parameters
*
* @return string the prepared data cell, html content
*/
@@ -3000,7 +2988,7 @@ class Results
bool $conditionField,
?TransformationsPlugin $transformationPlugin,
$transformOptions,
- array $analyzedSqlResults
+ StatementInfo $statementInfo
) {
if ($column === null) {
return $this->buildNullDisplay($class, $conditionField, $meta);
@@ -3039,7 +3027,7 @@ class Results
return $this->getRowData(
$class,
$conditionField,
- $analyzedSqlResults,
+ $statementInfo,
$meta,
$map,
$wktval,
@@ -3067,7 +3055,7 @@ class Results
return $this->getRowData(
$class,
$conditionField,
- $analyzedSqlResults,
+ $statementInfo,
$meta,
$map,
$wkbval,
@@ -3097,14 +3085,13 @@ class Results
*
* @see getTableBody()
*
- * @param string|null $column the relevant column in data row
- * @param string $class the html class for column
- * @param FieldMetadata $meta the meta-information about the field
- * @param array $map the list of relations
- * @param array $urlParams the parameters for generate url
- * @param bool $conditionField the column should highlighted or not
- * @param array $transformOptions the transformation parameters
- * @param array $analyzedSqlResults the analyzed query
+ * @param string|null $column the relevant column in data row
+ * @param string $class the html class for column
+ * @param FieldMetadata $meta the meta-information about the field
+ * @param array $map the list of relations
+ * @param array $urlParams the parameters for generate url
+ * @param bool $conditionField the column should highlighted or not
+ * @param array $transformOptions the transformation parameters
*
* @return string the prepared data cell, html content
*/
@@ -3117,7 +3104,7 @@ class Results
bool $conditionField,
?TransformationsPlugin $transformationPlugin,
$transformOptions,
- array $analyzedSqlResults
+ StatementInfo $statementInfo
) {
$originalLength = 0;
@@ -3224,7 +3211,7 @@ class Results
return $this->getRowData(
$class,
$conditionField,
- $analyzedSqlResults,
+ $statementInfo,
$meta,
$map,
$column,
@@ -3376,23 +3363,22 @@ class Results
/**
* Prepare a table of results returned by a SQL query.
*
- * @param ResultInterface $dtResult the link id associated to the query
- * which results have to be displayed
- * @param array $analyzedSqlResults analyzed sql results
- * @param bool $isLimitedDisplay With limited operations or not
+ * @param ResultInterface $dtResult the link id associated to the query
+ * which results have to be displayed
+ * @param bool $isLimitedDisplay With limited operations or not
*
* @return string Generated HTML content for resulted table
*/
public function getTable(
ResultInterface $dtResult,
DisplayParts $displayParts,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$isLimitedDisplay = false
) {
// The statement this table is built for.
- if (isset($analyzedSqlResults['statement'])) {
+ if (isset($statementInfo->statement)) {
/** @var SelectStatement $statement */
- $statement = $analyzedSqlResults['statement'];
+ $statement = $statementInfo->statement;
} else {
$statement = null;
}
@@ -3410,7 +3396,7 @@ class Results
$isInnodb = (isset($showTable['Type'])
&& $showTable['Type'] === self::TABLE_TYPE_INNO_DB);
- if ($isInnodb && Sql::isJustBrowsing($analyzedSqlResults, true)) {
+ if ($isInnodb && Sql::isJustBrowsing($statementInfo, true)) {
$preCount = '~';
$afterCount = Generator::showHint(
Sanitize::sanitizeMessage(
@@ -3471,7 +3457,7 @@ class Results
if ($displayParts->hasNavigationBar) {
$message = $this->setMessageInformation(
$sortedColumnMessage,
- $analyzedSqlResults,
+ $statementInfo,
$total,
$posNext,
$preCount,
@@ -3488,7 +3474,7 @@ class Results
}
// 2.3 Prepare the navigation bars
- if ($this->properties['table'] === '' && $analyzedSqlResults['querytype'] === 'SELECT') {
+ if ($this->properties['table'] === '' && $statementInfo->queryType === 'SELECT') {
// table does not always contain a real table name,
// for example in MySQL 5.0.x, the query SHOW STATUS
// returns STATUS as a table name
@@ -3498,16 +3484,20 @@ class Results
$unsortedSqlQuery = '';
$sortByKeyData = [];
// can the result be sorted?
- if ($displayParts->hasSortLink && isset($analyzedSqlResults['statement'])) {
+ if (
+ $displayParts->hasSortLink
+ && $statementInfo->statement !== null
+ && $statementInfo->parser !== null
+ ) {
$unsortedSqlQuery = Query::replaceClause(
- $analyzedSqlResults['statement'],
- $analyzedSqlResults['parser']->list,
+ $statementInfo->statement,
+ $statementInfo->parser->list,
'ORDER BY',
''
);
// Data is sorted by indexes only if there is only one table.
- if ($this->isSelect($analyzedSqlResults)) {
+ if ($this->isSelect($statementInfo)) {
$sortByKeyData = $this->getSortByKeyDropDown(
$sortExpression,
$unsortedSqlQuery
@@ -3547,7 +3537,7 @@ class Results
// 3. ----- Prepare the results table -----
$headers = $this->getTableHeaders(
$displayParts,
- $analyzedSqlResults,
+ $statementInfo,
$unsortedSqlQuery,
$sortExpression,
$sortExpressionNoDirection,
@@ -3555,17 +3545,17 @@ class Results
$isLimitedDisplay
);
- $body = $this->getTableBody($dtResult, $displayParts, $map, $analyzedSqlResults, $isLimitedDisplay);
+ $body = $this->getTableBody($dtResult, $displayParts, $map, $statementInfo, $isLimitedDisplay);
$this->properties['display_params'] = null;
// 4. ----- Prepares the link for multi-fields edit and delete
- $bulkLinks = $this->getBulkLinks($dtResult, $analyzedSqlResults, $displayParts->deleteLink);
+ $bulkLinks = $this->getBulkLinks($dtResult, $statementInfo, $displayParts->deleteLink);
// 5. ----- Prepare "Query results operations"
$operations = [];
if (($printView === null || $printView != '1') && ! $isLimitedDisplay) {
- $operations = $this->getResultsOperations($displayParts->hasPrintLink, $analyzedSqlResults);
+ $operations = $this->getResultsOperations($displayParts->hasPrintLink, $statementInfo);
}
$relationParameters = $this->relation->getRelationParameters();
@@ -3727,7 +3717,6 @@ class Results
* @see getTable()
*
* @param string $sortedColumnMessage the message for sorted column
- * @param array $analyzedSqlResults the analyzed query
* @param int $total the total number of rows returned by
* the SQL query without any
* programmatically appended LIMIT clause
@@ -3739,7 +3728,7 @@ class Results
*/
private function setMessageInformation(
string $sortedColumnMessage,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$total,
$posNext,
string $preCount,
@@ -3747,9 +3736,9 @@ class Results
) {
$unlimNumRows = $this->properties['unlim_num_rows']; // To use in isset()
- if (! empty($analyzedSqlResults['statement']->limit)) {
- $firstShownRec = $analyzedSqlResults['statement']->limit->offset;
- $rowCount = $analyzedSqlResults['statement']->limit->rowCount;
+ if (! empty($statementInfo->statement->limit)) {
+ $firstShownRec = $statementInfo->statement->limit->offset;
+ $rowCount = $statementInfo->statement->limit->rowCount;
if ($rowCount < $total) {
$lastShownRec = $firstShownRec + $rowCount - 1;
@@ -3883,16 +3872,15 @@ class Results
*
* @see getTable()
*
- * @param ResultInterface $dtResult the link id associated to the query which
- * results have to be displayed
- * @param array $analyzedSqlResults analyzed sql results
+ * @param ResultInterface $dtResult the link id associated to the query which
+ * results have to be displayed
* @psalm-param DisplayParts::NO_DELETE|DisplayParts::DELETE_ROW|DisplayParts::KILL_PROCESS $deleteLink
*
* @psalm-return array{has_export_button:bool, clause_is_unique:mixed}|array
*/
private function getBulkLinks(
ResultInterface $dtResult,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
int $deleteLink
): array {
if ($deleteLink !== DisplayParts::DELETE_ROW) {
@@ -3905,8 +3893,8 @@ class Results
$expressions = [];
- if (isset($analyzedSqlResults['statement']) && $analyzedSqlResults['statement'] instanceof SelectStatement) {
- $expressions = $analyzedSqlResults['statement']->expr;
+ if (isset($statementInfo->statement) && $statementInfo->statement instanceof SelectStatement) {
+ $expressions = $statementInfo->statement->expr;
}
/**
@@ -3926,7 +3914,7 @@ class Results
$dtResult->seek(0);
return [
- 'has_export_button' => $analyzedSqlResults['querytype'] === 'SELECT',
+ 'has_export_button' => $statementInfo->queryType === 'SELECT',
'clause_is_unique' => $clauseIsUnique,
];
}
@@ -3936,8 +3924,6 @@ class Results
*
* @see getTable()
*
- * @param array $analyzedSqlResults analyzed sql results
- *
* @psalm-return array{
* has_export_link: bool,
* has_geometry: bool,
@@ -3956,7 +3942,7 @@ class Results
*/
private function getResultsOperations(
bool $hasPrintLink,
- array $analyzedSqlResults
+ StatementInfo $statementInfo
): array {
$urlParams = [
'db' => $this->properties['db'],
@@ -3974,16 +3960,16 @@ class Results
// (most probably PROCEDURE ANALYSE()) it makes no sense to
// display the Export link).
if (
- ($analyzedSqlResults['querytype'] === self::QUERY_TYPE_SELECT)
- && empty($analyzedSqlResults['procedure'])
+ ($statementInfo->queryType === self::QUERY_TYPE_SELECT)
+ && empty($statementInfo->isProcedure)
) {
- if (count($analyzedSqlResults['select_tables']) === 1) {
+ if (count($statementInfo->selectTables) === 1) {
$urlParams['single_table'] = 'true';
}
// In case this query doesn't involve any tables,
// implies only raw query is to be exported
- if (! $analyzedSqlResults['select_tables']) {
+ if (! $statementInfo->selectTables) {
$urlParams['raw_query'] = 'true';
}
@@ -4011,10 +3997,10 @@ class Results
}
return [
- 'has_procedure' => ! empty($analyzedSqlResults['procedure']),
+ 'has_procedure' => ! empty($statementInfo->isProcedure),
'has_geometry' => $geometryFound,
'has_print_link' => $hasPrintLink,
- 'has_export_link' => $analyzedSqlResults['querytype'] === self::QUERY_TYPE_SELECT,
+ 'has_export_link' => $statementInfo->queryType === self::QUERY_TYPE_SELECT,
'url_params' => $urlParams,
];
}
@@ -4153,25 +4139,24 @@ class Results
* @see getDataCellForNumericColumns(), getDataCellForGeometryColumns(),
* getDataCellForNonNumericColumns(),
*
- * @param string $class css classes for the td element
- * @param bool $conditionField whether the column is a part of the where clause
- * @param array $analyzedSqlResults the analyzed query
- * @param FieldMetadata $meta the meta-information about the field
- * @param array $map the list of relations
- * @param string $data data
- * @param string $displayedData data that will be displayed (maybe be chunked)
- * @param string $nowrap 'nowrap' if the content should not be wrapped
- * @param string $whereComparison data for the where clause
- * @param array $transformOptions options for transformation
- * @param bool $isFieldTruncated whether the field is truncated
- * @param string $originalLength of a truncated column, or ''
+ * @param string $class css classes for the td element
+ * @param bool $conditionField whether the column is a part of the where clause
+ * @param FieldMetadata $meta the meta-information about the field
+ * @param array $map the list of relations
+ * @param string $data data
+ * @param string $displayedData data that will be displayed (maybe be chunked)
+ * @param string $nowrap 'nowrap' if the content should not be wrapped
+ * @param string $whereComparison data for the where clause
+ * @param array $transformOptions options for transformation
+ * @param bool $isFieldTruncated whether the field is truncated
+ * @param string $originalLength of a truncated column, or ''
*
* @return string formatted data
*/
private function getRowData(
string $class,
bool $conditionField,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
FieldMetadata $meta,
array $map,
$data,
@@ -4195,8 +4180,8 @@ class Results
$transformationPlugin !== null
);
- if (! empty($analyzedSqlResults['statement']->expr)) {
- foreach ($analyzedSqlResults['statement']->expr as $expr) {
+ if (! empty($statementInfo->statement->expr)) {
+ foreach ($statementInfo->statement->expr as $expr) {
if (empty($expr->alias) || empty($expr->column)) {
continue;
}
diff --git a/libraries/classes/ParseAnalyze.php b/libraries/classes/ParseAnalyze.php
index 1a01f885ac..083ceae893 100644
--- a/libraries/classes/ParseAnalyze.php
+++ b/libraries/classes/ParseAnalyze.php
@@ -23,26 +23,26 @@ class ParseAnalyze
* @param string $sqlQuery the query to parse
* @param string $db the current database
*
- * @return array
+ * @return array
+ * @psalm-return array{StatementInfo, string, string}
*/
- public static function sqlQuery($sqlQuery, $db)
+ public static function sqlQuery(string $sqlQuery, string $db): array
{
// @todo: move to returned results (also in all the calling chain)
$GLOBALS['unparsed_sql'] = $sqlQuery;
- // Get details about the SQL query.
- $analyzedSqlResults = Query::getAll($sqlQuery);
+ $info = Query::getAll($sqlQuery);
$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($analyzedSqlResults['select_tables'])) {
+ if (! empty($info['select_tables'])) {
// Previous table and database name is stored to check if it changed.
$previousDb = $db;
- if (count($analyzedSqlResults['select_tables']) > 1) {
+ if (count($info['select_tables']) > 1) {
/**
* @todo if there are more than one table name in the Select:
@@ -52,25 +52,21 @@ class ParseAnalyze
*/
$table = '';
} else {
- $table = $analyzedSqlResults['select_tables'][0][0];
- if (! empty($analyzedSqlResults['select_tables'][0][1])) {
- $db = $analyzedSqlResults['select_tables'][0][1];
+ $table = $info['select_tables'][0][0] ?? '';
+ if (isset($info['select_tables'][0][1])) {
+ $db = $info['select_tables'][0][1];
}
}
- // There is no point checking if a reload is required if we already decided
+ // There is no point checking if a reloading is required if we already decided
// to reload. Also, no reload is required for AJAX requests.
$response = ResponseRenderer::getInstance();
- if (empty($analyzedSqlResults['reload']) && ! $response->isAjax()) {
+ if (empty($info['reload']) && ! $response->isAjax()) {
// NOTE: Database names are case-insensitive.
- $analyzedSqlResults['reload'] = strcasecmp($db, $previousDb) != 0;
+ $info['reload'] = strcasecmp($db, $previousDb) !== 0;
}
}
- return [
- $analyzedSqlResults,
- $db,
- $table,
- ];
+ return [StatementInfo::fromArray($info), $db, $table];
}
}
diff --git a/libraries/classes/Sql.php b/libraries/classes/Sql.php
index e1d5e1dc6f..6e1cd870df 100644
--- a/libraries/classes/Sql.php
+++ b/libraries/classes/Sql.php
@@ -82,24 +82,27 @@ class Sql
/**
* Handle remembered sorting order, only for single table query
*
- * @param string $db database name
- * @param string $table table name
- * @param array $analyzedSqlResults the analyzed query results
- * @param string $fullSqlQuery SQL query
+ * @param string $db database name
+ * @param string $table table name
+ * @param string $fullSqlQuery SQL query
*/
private function handleSortOrder(
$db,
$table,
- array &$analyzedSqlResults,
+ StatementInfo $statementInfo,
&$fullSqlQuery
- ): void {
+ ): StatementInfo {
+ if ($statementInfo->statement === null || $statementInfo->parser === null) {
+ return $statementInfo;
+ }
+
$tableObject = new Table($table, $db);
- if (empty($analyzedSqlResults['order'])) {
+ if (empty($statementInfo->order)) {
// Retrieving the name of the column we should sort after.
$sortCol = $tableObject->getUiProp(Table::PROP_SORTED_COLUMN);
if (empty($sortCol)) {
- return;
+ return $statementInfo;
}
// Remove the name of the table from the retrieved field name.
@@ -111,38 +114,42 @@ class Sql
// Create the new query.
$fullSqlQuery = Query::replaceClause(
- $analyzedSqlResults['statement'],
- $analyzedSqlResults['parser']->list,
+ $statementInfo->statement,
+ $statementInfo->parser->list,
'ORDER BY ' . $sortCol
);
// TODO: Avoid reparsing the query.
- $analyzedSqlResults = Query::getAll($fullSqlQuery);
+ $statementInfo = StatementInfo::fromArray(Query::getAll($fullSqlQuery));
} else {
// Store the remembered table into session.
$tableObject->setUiProp(
Table::PROP_SORTED_COLUMN,
Query::getClause(
- $analyzedSqlResults['statement'],
- $analyzedSqlResults['parser']->list,
+ $statementInfo->statement,
+ $statementInfo->parser->list,
'ORDER BY'
)
);
}
+
+ return $statementInfo;
}
/**
* Append limit clause to SQL query
*
- * @param array $analyzedSqlResults the analyzed query results
- *
* @return string limit clause appended SQL query
*/
- private function getSqlWithLimitClause(array $analyzedSqlResults)
+ private function getSqlWithLimitClause(StatementInfo $statementInfo)
{
+ if ($statementInfo->statement === null || $statementInfo->parser === null) {
+ return '';
+ }
+
return Query::replaceClause(
- $analyzedSqlResults['statement'],
- $analyzedSqlResults['parser']->list,
+ $statementInfo->statement,
+ $statementInfo->parser->list,
'LIMIT ' . $_SESSION['tmpval']['pos'] . ', '
. $_SESSION['tmpval']['max_rows']
);
@@ -341,103 +348,86 @@ class Sql
}
/**
- * Function to check whether to remember the sorting order or not
- *
- * @param array $analyzedSqlResults the analyzed query and other variables set
- * after analyzing the query
+ * Function to check whether to remember the sorting order or not.
*/
- private function isRememberSortingOrder(array $analyzedSqlResults): bool
+ private function isRememberSortingOrder(StatementInfo $statementInfo): bool
{
- return isset($analyzedSqlResults['select_expr'], $analyzedSqlResults['select_tables'])
- && $GLOBALS['cfg']['RememberSorting']
- && ! ($analyzedSqlResults['is_count']
- || $analyzedSqlResults['is_export']
- || $analyzedSqlResults['is_func']
- || $analyzedSqlResults['is_analyse'])
- && $analyzedSqlResults['select_from']
- && (empty($analyzedSqlResults['select_expr'])
- || ((count($analyzedSqlResults['select_expr']) === 1)
- && ($analyzedSqlResults['select_expr'][0] === '*')))
- && count($analyzedSqlResults['select_tables']) === 1;
+ return $GLOBALS['cfg']['RememberSorting']
+ && ! ($statementInfo->isCount
+ || $statementInfo->isExport
+ || $statementInfo->isFunction
+ || $statementInfo->isAnalyse)
+ && $statementInfo->selectFrom
+ && (empty($statementInfo->selectExpression)
+ || ((count($statementInfo->selectExpression) === 1)
+ && ($statementInfo->selectExpression[0] === '*')))
+ && count($statementInfo->selectTables) === 1;
}
/**
- * Function to check whether the LIMIT clause should be appended or not
- *
- * @param array $analyzedSqlResults the analyzed query and other variables set
- * after analyzing the query
+ * Function to check whether the LIMIT clause should be appended or not.
*/
- private function isAppendLimitClause(array $analyzedSqlResults): bool
+ private function isAppendLimitClause(StatementInfo $statementInfo): bool
{
// 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($analyzedSqlResults['parser'])
- && count($analyzedSqlResults['parser']->errors) === 0)
+ return (isset($statementInfo->parser)
+ && count($statementInfo->parser->errors) === 0)
&& ($_SESSION['tmpval']['max_rows'] !== 'all')
- && ! ($analyzedSqlResults['is_export']
- || $analyzedSqlResults['is_analyse'])
- && ($analyzedSqlResults['select_from']
- || $analyzedSqlResults['is_subquery'])
- && empty($analyzedSqlResults['limit']);
+ && ! ($statementInfo->isExport
+ || $statementInfo->isAnalyse)
+ && ($statementInfo->selectFrom
+ || $statementInfo->isSubquery)
+ && empty($statementInfo->limit);
}
/**
* Function to check whether this query is for just browsing
*
- * @param array $analyzedSqlResults the analyzed query and other variables set
- * after analyzing the query
- * @param bool|null $findRealEnd whether the real end should be found
+ * @param bool|null $findRealEnd whether the real end should be found
*/
- public static function isJustBrowsing(array $analyzedSqlResults, ?bool $findRealEnd): bool
+ public static function isJustBrowsing(StatementInfo $statementInfo, ?bool $findRealEnd): bool
{
- return ! $analyzedSqlResults['is_group']
- && ! $analyzedSqlResults['is_func']
- && empty($analyzedSqlResults['union'])
- && empty($analyzedSqlResults['distinct'])
- && $analyzedSqlResults['select_from']
- && (count($analyzedSqlResults['select_tables']) === 1)
- && (empty($analyzedSqlResults['statement']->where)
- || (count($analyzedSqlResults['statement']->where) === 1
- && $analyzedSqlResults['statement']->where[0]->expr === '1'))
- && empty($analyzedSqlResults['group'])
+ return ! $statementInfo->isGroup
+ && ! $statementInfo->isFunction
+ && empty($statementInfo->union)
+ && empty($statementInfo->distinct)
+ && $statementInfo->selectFrom
+ && (count($statementInfo->selectTables) === 1)
+ && (empty($statementInfo->statement->where)
+ || (count($statementInfo->statement->where) === 1
+ && $statementInfo->statement->where[0]->expr === '1'))
+ && empty($statementInfo->group)
&& ! isset($findRealEnd)
- && ! $analyzedSqlResults['is_subquery']
- && ! $analyzedSqlResults['join']
- && empty($analyzedSqlResults['having']);
+ && ! $statementInfo->isSubquery
+ && ! $statementInfo->join
+ && empty($statementInfo->having);
}
/**
- * Function to check whether the related transformation information should be deleted
- *
- * @param array $analyzedSqlResults the analyzed query and other variables set
- * after analyzing the query
+ * Function to check whether the related transformation information should be deleted.
*/
- private function isDeleteTransformationInfo(array $analyzedSqlResults): bool
+ private function isDeleteTransformationInfo(StatementInfo $statementInfo): bool
{
- return ! empty($analyzedSqlResults['querytype'])
- && (($analyzedSqlResults['querytype'] === 'ALTER')
- || ($analyzedSqlResults['querytype'] === 'DROP'));
+ return ! empty($statementInfo->queryType)
+ && (($statementInfo->queryType === 'ALTER')
+ || ($statementInfo->queryType === 'DROP'));
}
/**
* Function to check whether the user has rights to drop the database
*
- * @param array $analyzedSqlResults the analyzed query and other variables set
- * after analyzing the query
- * @param bool $allowUserDropDatabase whether the user is allowed to drop db
- * @param bool $isSuperUser whether this user is a superuser
+ * @param bool $allowUserDropDatabase whether the user is allowed to drop db
+ * @param bool $isSuperUser whether this user is a superuser
*/
public function hasNoRightsToDropDatabase(
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$allowUserDropDatabase,
$isSuperUser
): bool {
- return ! $allowUserDropDatabase
- && isset($analyzedSqlResults['drop_database'])
- && $analyzedSqlResults['drop_database']
- && ! $isSuperUser;
+ return ! $allowUserDropDatabase && $statementInfo->dropDatabase && ! $isSuperUser;
}
/**
@@ -675,11 +665,10 @@ class Sql
* Function to count the total number of rows for the same 'SELECT' query without
* the 'LIMIT' clause that may have been programmatically added
*
- * @param int|string $numRows 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 $analyzedSqlResults the analyzed query and other variables set after analyzing the query
+ * @param int|string $numRows 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
* @psalm-param int|numeric-string $numRows
*
* @return int|string unlimited number of rows
@@ -690,14 +679,14 @@ class Sql
bool $justBrowsing,
string $db,
string $table,
- array $analyzedSqlResults
+ StatementInfo $statementInfo
) {
/* Shortcut for not analyzed/empty query */
- if ($analyzedSqlResults === []) {
+ if ($statementInfo->statement === null || $statementInfo->parser === null) {
return 0;
}
- if (! $this->isAppendLimitClause($analyzedSqlResults)) {
+ if (! $this->isAppendLimitClause($statementInfo)) {
// if we did not append a limit, set this to get a correct
// "Showing rows..." message
// $_SESSION['tmpval']['max_rows'] = 'all';
@@ -707,7 +696,7 @@ class Sql
// result are less than max_rows to display, there is no need
// to count total rows for that query again
$unlimNumRows = $_SESSION['tmpval']['pos'] + $numRows;
- } elseif ($analyzedSqlResults['querytype'] === 'SELECT' || $analyzedSqlResults['is_subquery']) {
+ } elseif ($statementInfo->queryType === 'SELECT' || $statementInfo->isSubquery) {
// c o u n t q u e r y
// If we are "just browsing", there is only one table (and no join),
@@ -736,8 +725,8 @@ class Sql
->countRecords(true);
}
} else {
- $statement = $analyzedSqlResults['statement'];
- $tokenList = $analyzedSqlResults['parser']->list;
+ $statement = $statementInfo->statement;
+ $tokenList = $statementInfo->parser->list;
$replaces = [
// Remove ORDER BY to decrease unnecessary sorting time
[
@@ -770,7 +759,6 @@ class Sql
/**
* Function to handle all aspects relating to executing the query
*
- * @param array $analyzedSqlResults analyzed sql results
* @param string $fullSqlQuery full sql query
* @param bool $isGotoFile whether to go to a file
* @param string $db current database
@@ -788,7 +776,7 @@ class Sql
* }
*/
private function executeTheQuery(
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$fullSqlQuery,
$isGotoFile,
string $db,
@@ -847,13 +835,13 @@ class Sql
// Gets the number of rows affected/returned
// (This must be done immediately after the query because
// mysql_affected_rows() reports about the last query done)
- $numRows = $this->getNumberOfRowsAffectedOrChanged($analyzedSqlResults['is_affected'], $result);
+ $numRows = $this->getNumberOfRowsAffectedOrChanged($statementInfo->isAffected, $result);
$profilingResults = Profiling::getInformation($this->dbi);
- $justBrowsing = self::isJustBrowsing($analyzedSqlResults, $findRealEnd ?? null);
+ $justBrowsing = self::isJustBrowsing($statementInfo, $findRealEnd ?? null);
- $unlimNumRows = $this->countQueryResults($numRows, $justBrowsing, $db, $table ?? '', $analyzedSqlResults);
+ $unlimNumRows = $this->countQueryResults($numRows, $justBrowsing, $db, $table ?? '', $statementInfo);
$this->cleanupRelations($db, $table ?? '', $_POST['dropped_column'] ?? null, ! empty($_POST['purge']));
@@ -887,17 +875,16 @@ class Sql
/**
* Delete related transformation information
*
- * @param string $db current database
- * @param string $table current table
- * @param array $analyzedSqlResults analyzed sql results
+ * @param string $db current database
+ * @param string $table current table
*/
- private function deleteTransformationInfo(string $db, string $table, array $analyzedSqlResults): void
+ private function deleteTransformationInfo(string $db, string $table, StatementInfo $statementInfo): void
{
- if (! isset($analyzedSqlResults['statement'])) {
+ if (! isset($statementInfo->statement)) {
return;
}
- $statement = $analyzedSqlResults['statement'];
+ $statement = $statementInfo->statement;
if ($statement instanceof AlterStatement) {
if (
! empty($statement->altered[0])
@@ -914,19 +901,18 @@ class Sql
/**
* Function to get the message for the no rows returned case
*
- * @param string|null $messageToShow message to show
- * @param array $analyzedSqlResults analyzed sql results
- * @param int|string $numRows number of rows
+ * @param string|null $messageToShow message to show
+ * @param int|string $numRows number of rows
*/
private function getMessageForNoRowsReturned(
?string $messageToShow,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$numRows
): Message {
- if ($analyzedSqlResults['querytype'] === 'DELETE"') {
+ if ($statementInfo->queryType === 'DELETE"') {
$message = Message::getMessageForDeletedRows($numRows);
- } elseif ($analyzedSqlResults['is_insert']) {
- if ($analyzedSqlResults['querytype'] === 'REPLACE') {
+ } elseif ($statementInfo->isInsert) {
+ if ($statementInfo->queryType === 'REPLACE') {
// For REPLACE we get DELETED + INSERTED row count,
// so we have to call it affected
$message = Message::getMessageForAffectedRows($numRows);
@@ -946,7 +932,7 @@ class Sql
$inserted->addParam($insertId + $numRows - 1);
$message->addMessage($inserted);
}
- } elseif ($analyzedSqlResults['is_affected']) {
+ } elseif ($statementInfo->isAffected) {
$message = Message::getMessageForAffectedRows($numRows);
// Ok, here is an explanation for the !$is_select.
@@ -956,7 +942,7 @@ class Sql
// fact that $message_to_show is sent for every case.
// The $message_to_show containing a success message and sent with
// the form should not have priority over errors
- } elseif ($messageToShow && $analyzedSqlResults['querytype'] !== 'SELECT') {
+ } elseif ($messageToShow && $statementInfo->queryType !== 'SELECT') {
$message = Message::rawSuccess(htmlspecialchars($messageToShow));
} elseif (! empty($GLOBALS['show_as_php'])) {
$message = Message::success(__('Showing as PHP code'));
@@ -996,7 +982,6 @@ class Sql
* 6-> When searching using the SEARCH tab which returns zero results
* 7-> When changing the structure of the table except change operation
*
- * @param array $analyzedSqlResults analyzed sql results
* @param string $db current database
* @param string|null $table current table
* @param string|null $messageToShow message to show
@@ -1012,7 +997,7 @@ class Sql
* @return string html
*/
private function getQueryResponseForNoResultsReturned(
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
string $db,
?string $table,
?string $messageToShow,
@@ -1024,14 +1009,14 @@ class Sql
$sqlQuery,
?string $completeQuery
): string {
- if ($this->isDeleteTransformationInfo($analyzedSqlResults)) {
- $this->deleteTransformationInfo($db, $table ?? '', $analyzedSqlResults);
+ if ($this->isDeleteTransformationInfo($statementInfo)) {
+ $this->deleteTransformationInfo($db, $table ?? '', $statementInfo);
}
if (isset($extraData['error'])) {
$message = Message::rawError($extraData['error']);
} else {
- $message = $this->getMessageForNoRowsReturned($messageToShow, $analyzedSqlResults, $numRows);
+ $message = $this->getMessageForNoRowsReturned($messageToShow, $statementInfo, $numRows);
}
$queryMessage = Generator::getMessage($message, $GLOBALS['sql_query'], 'success');
@@ -1056,7 +1041,7 @@ class Sql
$response = ResponseRenderer::getInstance();
$response->addJSON($extraData ?? []);
- if (empty($analyzedSqlResults['is_select']) || isset($extraData['error'])) {
+ if (empty($statementInfo->isSelect) || isset($extraData['error'])) {
return $queryMessage;
}
@@ -1078,7 +1063,7 @@ class Sql
$numRows,
null,
$result,
- $analyzedSqlResults,
+ $statementInfo,
true
);
@@ -1120,7 +1105,7 @@ class Sql
'db' => $db,
'table' => $table,
'sql_query' => $sqlQuery,
- 'is_procedure' => ! empty($analyzedSqlResults['procedure']),
+ 'is_procedure' => ! empty($statementInfo->isProcedure),
]);
}
@@ -1170,7 +1155,6 @@ class Sql
* @param int|string $numRows number of rows
* @param array|null $showTable table definitions
* @param ResultInterface|false|null $result result of the executed query
- * @param array $analyzedSqlResults analyzed sql results
* @param bool $isLimitedDisplay Show only limited operations or not
* @psalm-param int|numeric-string $unlimNumRows
* @psalm-param int|numeric-string $numRows
@@ -1183,14 +1167,14 @@ class Sql
$numRows,
?array $showTable,
$result,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$isLimitedDisplay = false
): string {
$printView = isset($_POST['printview']) && $_POST['printview'] == '1' ? '1' : null;
$tableHtml = '';
$isBrowseDistinct = ! empty($_POST['is_browse_distinct']);
- if ($analyzedSqlResults['is_procedure']) {
+ if ($statementInfo->isProcedure) {
do {
if ($result === null) {
$result = $this->dbi->storeResult();
@@ -1210,17 +1194,17 @@ class Sql
$displayResultsObject->setProperties(
$numRows,
$fieldsMeta,
- $analyzedSqlResults['is_count'],
- $analyzedSqlResults['is_export'],
- $analyzedSqlResults['is_func'],
- $analyzedSqlResults['is_analyse'],
+ $statementInfo->isCount,
+ $statementInfo->isExport,
+ $statementInfo->isFunction,
+ $statementInfo->isAnalyse,
$numRows,
$fieldsCount,
$GLOBALS['querytime'],
$GLOBALS['text_dir'],
- $analyzedSqlResults['is_maint'],
- $analyzedSqlResults['is_explain'],
- $analyzedSqlResults['is_show'],
+ $statementInfo->isMaint,
+ $statementInfo->isExplain,
+ $statementInfo->isShow,
$showTable,
$printView,
$editable,
@@ -1240,7 +1224,7 @@ class Sql
$tableHtml .= $displayResultsObject->getTable(
$result,
$displayParts,
- $analyzedSqlResults,
+ $statementInfo,
$isLimitedDisplay
);
}
@@ -1258,17 +1242,17 @@ class Sql
$displayResultsObject->setProperties(
$unlimNumRows,
$fieldsMeta,
- $analyzedSqlResults['is_count'],
- $analyzedSqlResults['is_export'],
- $analyzedSqlResults['is_func'],
- $analyzedSqlResults['is_analyse'],
+ $statementInfo->isCount,
+ $statementInfo->isExport,
+ $statementInfo->isFunction,
+ $statementInfo->isAnalyse,
$numRows,
$fieldsCount,
$GLOBALS['querytime'],
$GLOBALS['text_dir'],
- $analyzedSqlResults['is_maint'],
- $analyzedSqlResults['is_explain'],
- $analyzedSqlResults['is_show'],
+ $statementInfo->isMaint,
+ $statementInfo->isExplain,
+ $statementInfo->isShow,
$showTable,
$printView,
$editable,
@@ -1279,7 +1263,7 @@ class Sql
$tableHtml .= $displayResultsObject->getTable(
$result,
$displayParts,
- $analyzedSqlResults,
+ $statementInfo,
$isLimitedDisplay
);
}
@@ -1366,7 +1350,6 @@ class Sql
* Function to display results when the executed query returns non empty results
*
* @param ResultInterface|false|null $result executed query results
- * @param array $analyzedSqlResults analysed sql results
* @param string $db current database
* @param string|null $table current table
* @param array|null $sqlData sql data
@@ -1385,7 +1368,7 @@ class Sql
*/
private function getQueryResponseForResultsReturned(
$result,
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
string $db,
?string $table,
?array $sqlData,
@@ -1432,7 +1415,7 @@ class Sql
$updatableView = false;
- $statement = $analyzedSqlResults['statement'] ?? null;
+ $statement = $statementInfo->statement;
if ($statement instanceof SelectStatement) {
if ($statement->expr && $statement->expr[0]->expr === '*' && $table) {
$_table = new Table($table, $db);
@@ -1440,9 +1423,9 @@ class Sql
}
if (
- $analyzedSqlResults['join']
- || $analyzedSqlResults['is_subquery']
- || count($analyzedSqlResults['select_tables']) !== 1
+ $statementInfo->join
+ || $statementInfo->isSubquery
+ || count($statementInfo->selectTables) !== 1
) {
$justOneTable = false;
}
@@ -1526,7 +1509,7 @@ class Sql
$numRows,
$GLOBALS['showtable'],
$result,
- $analyzedSqlResults
+ $statementInfo
);
$bookmarkSupportHtml = '';
@@ -1563,7 +1546,6 @@ class Sql
/**
* Function to execute the query and send the response
*
- * @param array|null $analyzedSqlResults analysed sql results
* @param bool $isGotoFile whether goto file or not
* @param string $db current database
* @param string|null $table current table
@@ -1579,7 +1561,7 @@ class Sql
* @param string|null $completeQuery complete query
*/
public function executeQueryAndSendQueryResponse(
- $analyzedSqlResults,
+ ?StatementInfo $statementInfo,
$isGotoFile,
string $db,
?string $table,
@@ -1594,19 +1576,15 @@ class Sql
$sqlQuery,
$completeQuery
): string {
- if ($analyzedSqlResults == null) {
+ if ($statementInfo === null) {
// Parse and analyze the query
- [
- $analyzedSqlResults,
- $db,
- $tableFromSql,
- ] = ParseAnalyze::sqlQuery($sqlQuery, $db);
+ [$statementInfo, $db, $tableFromSql] = ParseAnalyze::sqlQuery($sqlQuery, $db);
$table = $tableFromSql ?: $table;
}
return $this->executeQueryAndGetQueryResponse(
- $analyzedSqlResults, // analyzed_sql_results
+ $statementInfo,
$isGotoFile, // is_gotofile
$db, // db
$table, // table
@@ -1626,7 +1604,6 @@ class Sql
/**
* Function to execute the query and send the response
*
- * @param array $analyzedSqlResults analysed sql results
* @param bool $isGotoFile whether goto file or not
* @param string $db current database
* @param string|null $table current table
@@ -1644,7 +1621,7 @@ class Sql
* @return string html
*/
public function executeQueryAndGetQueryResponse(
- array $analyzedSqlResults,
+ StatementInfo $statementInfo,
$isGotoFile,
string $db,
?string $table,
@@ -1668,13 +1645,12 @@ class Sql
// Handling is also not required if we came from the "Sort by key"
// drop-down.
if (
- $analyzedSqlResults !== []
- && $this->isRememberSortingOrder($analyzedSqlResults)
- && empty($analyzedSqlResults['union'])
+ $this->isRememberSortingOrder($statementInfo)
+ && empty($statementInfo->union)
&& ! isset($_POST['sort_by_key'])
) {
if (! isset($_SESSION['sql_from_query_box'])) {
- $this->handleSortOrder($db, $table, $analyzedSqlResults, $sqlQuery);
+ $statementInfo = $this->handleSortOrder($db, $table, $statementInfo, $sqlQuery);
} else {
unset($_SESSION['sql_from_query_box']);
}
@@ -1694,8 +1670,8 @@ class Sql
$fullSqlQuery = $sqlQuery;
// Do append a "LIMIT" clause?
- if ($this->isAppendLimitClause($analyzedSqlResults)) {
- $fullSqlQuery = $this->getSqlWithLimitClause($analyzedSqlResults);
+ if ($this->isAppendLimitClause($statementInfo)) {
+ $fullSqlQuery = $this->getSqlWithLimitClause($statementInfo);
}
$GLOBALS['reload'] = $this->hasCurrentDbChanged($db);
@@ -1708,7 +1684,7 @@ class Sql
$profilingResults,
$extraData,
] = $this->executeTheQuery(
- $analyzedSqlResults,
+ $statementInfo,
$fullSqlQuery,
$isGotoFile,
$db,
@@ -1725,9 +1701,9 @@ class Sql
$warningMessages = $this->operations->getWarningMessagesArray();
// No rows returned -> move back to the calling page
- if (($numRows == 0 && $unlimNumRows == 0) || $analyzedSqlResults['is_affected']) {
+ if (($numRows == 0 && $unlimNumRows == 0) || $statementInfo->isAffected) {
$htmlOutput = $this->getQueryResponseForNoResultsReturned(
- $analyzedSqlResults,
+ $statementInfo,
$db,
$table,
$messageToShow,
@@ -1743,7 +1719,7 @@ class Sql
// At least one row is returned -> displays a table with results
$htmlOutput = $this->getQueryResponseForResultsReturned(
$result,
- $analyzedSqlResults,
+ $statementInfo,
$db,
$table,
$sqlData,
diff --git a/libraries/classes/StatementInfo.php b/libraries/classes/StatementInfo.php
new file mode 100644
index 0000000000..e36959d555
--- /dev/null
+++ b/libraries/classes/StatementInfo.php
@@ -0,0 +1,232 @@
+>
+ * @psalm-var list
+ */
+ public $selectTables;
+ /**
+ * @var array
+ * @psalm-var list
+ */
+ public $selectExpression;
+
+ /**
+ * @param string|false $queryType
+ * @param array> $selectTables
+ * @param array $selectExpression
+ * @psalm-param list $selectTables
+ * @psalm-param list $selectExpression
+ */
+ private function __construct(
+ bool $distinct,
+ bool $dropDatabase,
+ bool $group,
+ bool $having,
+ bool $isAffected,
+ bool $isAnalyse,
+ bool $isCount,
+ bool $isDelete,
+ bool $isExplain,
+ bool $isExport,
+ bool $isFunction,
+ bool $isGroup,
+ bool $isInsert,
+ bool $isMaint,
+ bool $isProcedure,
+ bool $isReplace,
+ bool $isSelect,
+ bool $isShow,
+ bool $isSubquery,
+ bool $join,
+ bool $limit,
+ bool $offset,
+ bool $order,
+ $queryType,
+ bool $reload,
+ bool $selectFrom,
+ bool $union,
+ ?SqlParser\Parser $parser,
+ ?SqlParser\Statement $statement,
+ array $selectTables,
+ array $selectExpression
+ ) {
+ $this->distinct = $distinct;
+ $this->dropDatabase = $dropDatabase;
+ $this->group = $group;
+ $this->having = $having;
+ $this->isAffected = $isAffected;
+ $this->isAnalyse = $isAnalyse;
+ $this->isCount = $isCount;
+ $this->isDelete = $isDelete;
+ $this->isExplain = $isExplain;
+ $this->isExport = $isExport;
+ $this->isFunction = $isFunction;
+ $this->isGroup = $isGroup;
+ $this->isInsert = $isInsert;
+ $this->isMaint = $isMaint;
+ $this->isProcedure = $isProcedure;
+ $this->isReplace = $isReplace;
+ $this->isSelect = $isSelect;
+ $this->isShow = $isShow;
+ $this->isSubquery = $isSubquery;
+ $this->join = $join;
+ $this->limit = $limit;
+ $this->offset = $offset;
+ $this->order = $order;
+ $this->queryType = $queryType;
+ $this->reload = $reload;
+ $this->selectFrom = $selectFrom;
+ $this->union = $union;
+ $this->parser = $parser;
+ $this->statement = $statement;
+ $this->selectTables = $selectTables;
+ $this->selectExpression = $selectExpression;
+ }
+
+ /**
+ * @param array|string|null>|bool|string|Parser|Statement> $info
+ * @psalm-param array{
+ * distinct: bool,
+ * drop_database: bool,
+ * group: bool,
+ * having: bool,
+ * is_affected: bool,
+ * is_analyse: bool,
+ * is_count: bool,
+ * is_delete: bool,
+ * is_explain: bool,
+ * is_export: bool,
+ * is_func: bool,
+ * is_group: bool,
+ * is_insert: bool,
+ * is_maint: bool,
+ * is_procedure: bool,
+ * is_replace: bool,
+ * is_select: bool,
+ * is_show: bool,
+ * is_subquery: bool,
+ * join: bool,
+ * limit: bool,
+ * offset: bool,
+ * order: bool,
+ * querytype: (
+ * 'ALTER'|'ANALYZE'|'CALL'|'CHECK'|'CHECKSUM'|'CREATE'|'DELETE'|'DROP'|
+ * 'EXPLAIN'|'INSERT'|'LOAD'|'OPTIMIZE'|'REPAIR'|'REPLACE'|'SELECT'|'SET'|'SHOW'|'UPDATE'|false
+ * ),
+ * reload: bool,
+ * select_from: bool,
+ * union: bool,
+ * parser?: Parser,
+ * statement?: Statement,
+ * select_tables?: list,
+ * select_expr?: list
+ * } $info
+ */
+ public static function fromArray(array $info): self
+ {
+ return new self(
+ $info['distinct'],
+ $info['drop_database'],
+ $info['group'],
+ $info['having'],
+ $info['is_affected'],
+ $info['is_analyse'],
+ $info['is_count'],
+ $info['is_delete'],
+ $info['is_explain'],
+ $info['is_export'],
+ $info['is_func'],
+ $info['is_group'],
+ $info['is_insert'],
+ $info['is_maint'],
+ $info['is_procedure'],
+ $info['is_replace'],
+ $info['is_select'],
+ $info['is_show'],
+ $info['is_subquery'],
+ $info['join'],
+ $info['limit'],
+ $info['offset'],
+ $info['order'],
+ $info['querytype'],
+ $info['reload'],
+ $info['select_from'],
+ $info['union'],
+ $info['parser'] ?? null,
+ $info['statement'] ?? null,
+ $info['select_tables'] ?? [],
+ $info['select_expr'] ?? []
+ );
+ }
+}
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index aee6f67131..49e7987a9e 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -2770,26 +2770,11 @@ parameters:
count: 2
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getBulkLinks\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getColumnParams\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getCommentForRow\\(\\) has parameter \\$commentsMap with no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataCellForGeometryColumns\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataCellForGeometryColumns\\(\\) has parameter \\$transformOptions with no value type specified in iterable type array\\.$#"
count: 1
@@ -2800,11 +2785,6 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataCellForNonNumericColumns\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataCellForNonNumericColumns\\(\\) has parameter \\$transformOptions with no value type specified in iterable type array\\.$#"
count: 1
@@ -2815,21 +2795,11 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataCellForNumericColumns\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataCellForNumericColumns\\(\\) has parameter \\$transformOptions with no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataForResettingColumnOrder\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getDataForResettingColumnOrder\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@@ -2850,16 +2820,6 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getResultsOperations\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getRowData\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getRowData\\(\\) has parameter \\$transformOptions with no value type specified in iterable type array\\.$#"
count: 1
@@ -2875,11 +2835,6 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getRowValues\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getRowValues\\(\\) has parameter \\$colOrder with no value type specified in iterable type array\\.$#"
count: 1
@@ -2920,31 +2875,11 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTable\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableBody\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableCommentsArray\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableCommentsArray\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableHeaders\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableHeaders\\(\\) has parameter \\$sortDirection with no value type specified in iterable type array\\.$#"
count: 1
@@ -2960,11 +2895,6 @@ parameters:
count: 2
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableHeadersForColumns\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getTableHeadersForColumns\\(\\) has parameter \\$sortDirection with no value type specified in iterable type array\\.$#"
count: 1
@@ -2985,11 +2915,6 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:getUrlSqlQuery\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:handleNonPrintableContents\\(\\) has parameter \\$transformOptions with no value type specified in iterable type array\\.$#"
count: 1
@@ -3010,21 +2935,6 @@ parameters:
count: 1
path: libraries/classes/Display/Results.php
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:isSelect\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:setHighlightedColumnGlobalField\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Display\\\\Results\\:\\:setMessageInformation\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Display/Results.php
-
-
message: "#^Offset 3 does not exist on array\\{string\\|null, string\\|null, string\\|null\\}\\.$#"
count: 1
@@ -5370,11 +5280,6 @@ parameters:
count: 1
path: libraries/classes/OutputBuffering.php
- -
- message: "#^Method PhpMyAdmin\\\\ParseAnalyze\\:\\:sqlQuery\\(\\) return type has no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/ParseAnalyze.php
-
-
message: "#^Method PhpMyAdmin\\\\Partitioning\\\\Maintenance\\:\\:analyze\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@@ -7510,31 +7415,11 @@ parameters:
count: 1
path: libraries/classes/Setup/Index.php
- -
- message: "#^Cannot access property \\$where on mixed\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:countQueryResults\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:countQueryResults\\(\\) should return int\\|numeric\\-string but returns mixed\\.$#"
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:deleteTransformationInfo\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:executeQueryAndGetQueryResponse\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:executeQueryAndGetQueryResponse\\(\\) has parameter \\$extraData with no value type specified in iterable type array\\.$#"
count: 1
@@ -7545,11 +7430,6 @@ parameters:
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:executeQueryAndSendQueryResponse\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:executeQueryAndSendQueryResponse\\(\\) has parameter \\$extraData with no value type specified in iterable type array\\.$#"
count: 1
@@ -7560,11 +7440,6 @@ parameters:
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:executeTheQuery\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:executeTheQuery\\(\\) has parameter \\$extraData with no value type specified in iterable type array\\.$#"
count: 1
@@ -7590,26 +7465,11 @@ parameters:
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getHtmlForSqlQueryResultsTable\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getHtmlForSqlQueryResultsTable\\(\\) has parameter \\$showTable with no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getMessageForNoRowsReturned\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getQueryResponseForNoResultsReturned\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getQueryResponseForNoResultsReturned\\(\\) has parameter \\$extraData with no value type specified in iterable type array\\.$#"
count: 1
@@ -7620,11 +7480,6 @@ parameters:
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getQueryResponseForResultsReturned\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getQueryResponseForResultsReturned\\(\\) has parameter \\$profilingResults with no value type specified in iterable type array\\.$#"
count: 1
@@ -7635,41 +7490,11 @@ parameters:
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getSqlWithLimitClause\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:getValuesForColumn\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:handleSortOrder\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:hasNoRightsToDropDatabase\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:isAppendLimitClause\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:isDeleteTransformationInfo\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Sql\\:\\:isRememberSortingOrder\\(\\) has parameter \\$analyzedSqlResults with no value type specified in iterable type array\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Method PhpMyAdmin\\\\Sql\\:\\:resultSetContainsUniqueKey\\(\\) has parameter \\$fieldsMeta with no value type specified in iterable type array\\.$#"
count: 1
@@ -7715,11 +7540,6 @@ parameters:
count: 1
path: libraries/classes/Sql.php
- -
- message: "#^Parameter \\#1 \\$var of function count expects array\\|Countable, mixed given\\.$#"
- count: 1
- path: libraries/classes/Sql.php
-
-
message: "#^Parameter \\#2 \\$foreign_field of method PhpMyAdmin\\\\ConfigStorage\\\\Relation\\:\\:foreignDropdown\\(\\) expects string, mixed given\\.$#"
count: 1
@@ -9327,7 +9147,7 @@ parameters:
-
message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:dataProviderForTestGetDataCellForNonNumericColumns\\(\\) return type has no value type specified in iterable type array\\.$#"
- count: 4
+ count: 3
path: test/classes/Display/ResultsTest.php
-
@@ -9350,11 +9170,6 @@ parameters:
count: 2
path: test/classes/Display/ResultsTest.php
- -
- message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:dataProviderForTestSetHighlightedColumnGlobalField\\(\\) return type has no value type specified in iterable type array\\.$#"
- count: 1
- path: test/classes/Display/ResultsTest.php
-
-
message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:dataProviderGetSortOrderHiddenInputs\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
@@ -9370,11 +9185,6 @@ parameters:
count: 1
path: test/classes/Display/ResultsTest.php
- -
- message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:testGetDataCellForNonNumericColumns\\(\\) has parameter \\$analyzed_sql_results with no value type specified in iterable type array\\.$#"
- count: 1
- path: test/classes/Display/ResultsTest.php
-
-
message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:testGetDataCellForNonNumericColumns\\(\\) has parameter \\$map with no value type specified in iterable type array\\.$#"
count: 1
@@ -9450,16 +9260,6 @@ parameters:
count: 1
path: test/classes/Display/ResultsTest.php
- -
- message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:testSetHighlightedColumnGlobalField\\(\\) has parameter \\$analyzed_sql with no value type specified in iterable type array\\.$#"
- count: 1
- path: test/classes/Display/ResultsTest.php
-
- -
- message: "#^Method PhpMyAdmin\\\\Tests\\\\Display\\\\ResultsTest\\:\\:testSetHighlightedColumnGlobalField\\(\\) has parameter \\$output with no value type specified in iterable type array\\.$#"
- count: 1
- path: test/classes/Display/ResultsTest.php
-
-
message: "#^Parameter \\#1 \\$string of function htmlspecialchars_decode expects string, mixed given\\.$#"
count: 1
@@ -10370,16 +10170,6 @@ parameters:
count: 1
path: test/classes/SqlTest.php
- -
- message: "#^Parameter \\#1 \\$analyzedSqlResults of method PhpMyAdmin\\\\Sql\\:\\:hasNoRightsToDropDatabase\\(\\) expects array, mixed given\\.$#"
- count: 3
- path: test/classes/SqlTest.php
-
- -
- message: "#^Parameter \\#1 \\$analyzedSqlResults of static method PhpMyAdmin\\\\Sql\\:\\:isJustBrowsing\\(\\) expects array\\, mixed given\\.$#"
- count: 3
- path: test/classes/SqlTest.php
-
-
message: "#^Method PhpMyAdmin\\\\Tests\\\\StorageEngineTest\\:\\:providerGetEngine\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 8c3604bc45..4d1ade41a3 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -9,6 +9,7 @@ parameters:
bootstrapFiles:
- test/phpstan-constants.php
stubFiles:
+ - test/stubs/Query.stub
- test/stubs/uploadprogress.stub
excludePaths:
- examples/openid.php
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 3bc713879a..ba3a269359 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -2251,7 +2251,7 @@
$GLOBALS['cfg']['AllowUserDropDatabase']
-
+
$GLOBALS['cfg']['AllowUserDropDatabase']
$GLOBALS['cfg']['MemoryLimit']
$GLOBALS['format']
@@ -2259,14 +2259,12 @@
$GLOBALS['import_file']
$GLOBALS['import_notice']
$GLOBALS['local_import_file']
- $GLOBALS['table']
$_POST['bkm_label']
$_POST['bkm_label']
$_POST['bookmark_variable']
$_POST['sql_query']
$_POST['sql_query']
$_SESSION['Import_message']['go_back_url']
- $analyzed_sql_results
$die['error']
$die['sql']
$importHandle ?? null
@@ -2276,15 +2274,11 @@
$GLOBALS['urlParams']
$parameter
-
+
$_FILES['import_file']['name']
$_FILES['import_file']['name']
$_FILES['import_file']['tmp_name']
$_SESSION['Import_message']['go_back_url']
- $analyzed_sql_results['offset']
- $analyzed_sql_results['offset']
- $analyzed_sql_results['reload']
- $analyzed_sql_results['reload']
$die['error']
$die['sql']
@@ -2300,7 +2294,7 @@
$_SESSION['Import_message']['message']
$_SESSION['Import_message']['message']
-
+
$GLOBALS['MAX_FILE_SIZE']
$GLOBALS['active_page']
$GLOBALS['ajax_reload']
@@ -2323,12 +2317,8 @@
$GLOBALS['msg']
$GLOBALS['my_die']
$GLOBALS['noplugin']
- $GLOBALS['offset']
- $GLOBALS['offset']
$GLOBALS['read_multiply']
$GLOBALS['reload']
- $GLOBALS['reload']
- $GLOBALS['reload']
$GLOBALS['reset_charset']
$GLOBALS['result']
$GLOBALS['run_query']
@@ -2336,8 +2326,6 @@
$GLOBALS['skip_queries']
$GLOBALS['sql_file']
$GLOBALS['sql_query_disabled']
- $GLOBALS['table']
- $GLOBALS['table']
$GLOBALS['timeout_passed']
$GLOBALS['timestamp']
$GLOBALS['urlParams']['local_import_file']
@@ -3102,13 +3090,11 @@
$GLOBALS['cfg']['AllowUserDropDatabase']
-
+
$GLOBALS['cfg']['AllowUserDropDatabase']
$GLOBALS['db']
$GLOBALS['db']
$GLOBALS['db']
- $GLOBALS['db']
- $GLOBALS['db']
$GLOBALS['disp_message'] ?? null
$GLOBALS['errorUrl']
$GLOBALS['errorUrl']
@@ -3117,19 +3103,16 @@
$GLOBALS['message_to_show'] ?? null
$GLOBALS['sql_query']
$GLOBALS['sql_query']
- $GLOBALS['table']
- $GLOBALS['table']
$_GET['sql_query']
$_GET['sql_signature']
$_POST['bkm_fields']
- $analyzed_sql_results
$GLOBALS['ajax_reload']['reload']
$_POST['bkm_fields']['bkm_label']
$_POST['bkm_fields']['bkm_label']
-
+
$GLOBALS['ajax_reload']
$GLOBALS['back']
$GLOBALS['db']
@@ -3144,7 +3127,6 @@
$GLOBALS['sql_query']
$GLOBALS['sql_query']
$GLOBALS['sql_query']
- $GLOBALS['table']
$GLOBALS['table_from_sql']
$GLOBALS['unlim_num_rows']
$GLOBALS['unlim_num_rows']
@@ -3887,16 +3869,12 @@
-
- $analyzed_sql_results ?? ''
+
$sval
$sval
-
- $analyzed_sql_results ?? ''
-
@@ -4274,7 +4252,7 @@
-
+
$_POST['db']
$_POST['table']
$_POST['where_clause']
@@ -4285,7 +4263,6 @@
$dataLabel
$dataLabel
$foreignData['foreign_field']
- $foreignData['foreign_field']
$properties['type']
$selected_operator
$this->columnNames[$column_index]
@@ -5094,8 +5071,7 @@
-
- $db
+
$table
$table
@@ -5995,19 +5971,15 @@
$delUrlParams
-
+
+ $statementInfo->statement->expr
+ $statementInfo->statement->where
+
+
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['pos'] / $_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['query']
$_SESSION['tmpval']['query']
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['select_tables']
- $analyzedSqlResults['statement']
- $analyzedSqlResults['statement']
- $analyzedSqlResults['statement']
- $analyzedSqlResults['statement']->from
$clause
$clauseIsUnique
$clauseIsUnique
@@ -6037,6 +6009,7 @@
$sortExpressionNoDirection[$indexInExpression]
$sortExpressionNoDirection[$indexInExpression]
$sqlQuery
+ $statementInfo->statement->from
$total
$urlParams['where_clause']
$whereClause
@@ -6046,15 +6019,14 @@
(int) $this->properties['unlim_num_rows'] / $_SESSION['tmpval']['max_rows']
empty($field->database) ? $this->properties['db'] : $field->database
-
- $analyzedSqlResults
+
$linkingUrlParams
$row
$sortDirection
$sortExpression
$urlParams
-
+
$_SESSION['tmpval']['display_binary']
$_SESSION['tmpval']['display_binary']
$_SESSION['tmpval']['display_binary']
@@ -6078,7 +6050,6 @@
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['max_rows']
- $_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['pftext']
$_SESSION['tmpval']['pftext']
$_SESSION['tmpval']['pftext']
@@ -6088,8 +6059,6 @@
$_SESSION['tmpval']['pos']
$_SESSION['tmpval']['pos']
$_SESSION['tmpval']['pos']
- $_SESSION['tmpval']['pos']
- $_SESSION['tmpval']['pos']
$_SESSION['tmpval']['possible_as_geometry']
$_SESSION['tmpval']['query']
$_SESSION['tmpval']['query']
@@ -6196,7 +6165,7 @@
$row[$sortedColumnIndex]
$row[$sortedColumnIndex]
-
+
$GLOBALS['row']
$GLOBALS['theme']
$_SESSION['tmpval']['geoOption']
@@ -6214,16 +6183,11 @@
$expr
$field
$file
- $firstShownRec
- $firstShownRec
- $firstShownRec
$hiddenFields['session_max_rows']
$i
$i
$identifier
$index
- $lastShownRec
- $lastShownRec
$linkingUrlParams[$new_param['param_info']]
$m
$meta->name
@@ -6238,7 +6202,6 @@
$query['relational_display']
$rel
$relationalDisplay
- $rowCount
$rowInfo[mb_strtolower($fieldsMeta[$m]->orgname)]
$sessionMaxRows
$sessionMaxRows
@@ -6251,11 +6214,14 @@
$whereClauseMap[$rowNumber][$meta->orgtable]
$whereClauseMap[$rowNumber][$this->properties['table']]
+
+ Message
+
new $className()
new $this->transformationInfo[$dbLower][$tblLower][$nameLower][1]()
-
+
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['pos']
@@ -6266,27 +6232,17 @@
$displaySize[0]
$displaySize[1]
$file
- $firstShownRec
- $firstShownRec
$sortExpressionNoDirection[$indexInExpression]
-
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['statement']->expr
- $analyzedSqlResults['statement']->from
- $analyzedSqlResults['statement']->from
- $analyzedSqlResults['statement']->from[0]->table
- $analyzedSqlResults['statement']->limit
- $analyzedSqlResults['statement']->limit->offset
- $analyzedSqlResults['statement']->limit->rowCount
- $analyzedSqlResults['statement']->where
+
$expr->alias
$expr->column
$expr->column
$expr->identifiers
$field->database
$field->table
+ $statementInfo->statement->from[0]->table
+ $statementInfo->statement->limit->offset
$map
@@ -6325,10 +6281,20 @@
(string) $fieldsMeta[$i]->name
(string) $fieldsMeta[$i]->name
+
+ empty($statementInfo->statement->from)
+
$firstStatement->order
isset($meta->internalMediaType)
+
+ $afterCount
+ $posNext
+ $preCount
+ $sortedColumnMessage
+ $total
+
@@ -7647,23 +7613,12 @@
$server['ssl']
$server['ssl_verify']
-
+
$GLOBALS['special_message']
$GLOBALS['special_message']
$alt
$defaultFunction
$field['True_Type']
- $queryBase
- $queryBase
- $queryBase
- $sqlQuery
- $sqlQuery
- $sqlQuery
- $sqlQuery
- $sqlQuery
- $sqlQuery
- $sqlQuery
- $sqlQuery
$subvalue
$title
$value
@@ -7683,17 +7638,14 @@
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['pos']
-
+
$GLOBALS['data']
$alt
$defaultFunction
$defaultFunction
$defaultFunction
- $queryBase
- $sqlQuery
$subvalue
$title
- $urlParams['sql_query']
$value
$value
@@ -7703,10 +7655,9 @@
getDisplay
-
+
$GLOBALS['using_bookmark_message']->getDisplay()
$attributes['class']
- $sqlQuery
$value
@@ -9070,20 +9021,6 @@
$content
-
-
- $analyzedSqlResults['select_tables']
- $db
-
-
- $analyzedSqlResults['select_tables'][0]
- $analyzedSqlResults['select_tables'][0]
-
-
- $db
- $table
-
-
$row['Table']
@@ -13034,41 +12971,12 @@
$unlimNumRows
-
+
$_POST[$requestIndex]
$_POST['bkm_label']
$_POST['dropped_column'] ?? null
$_POST['table_create_time'] ?? null
- $analyzedSqlResults
- $analyzedSqlResults['is_affected']
- $analyzedSqlResults['is_analyse']
- $analyzedSqlResults['is_analyse']
- $analyzedSqlResults['is_count']
- $analyzedSqlResults['is_count']
- $analyzedSqlResults['is_explain']
- $analyzedSqlResults['is_explain']
- $analyzedSqlResults['is_export']
- $analyzedSqlResults['is_export']
- $analyzedSqlResults['is_func']
- $analyzedSqlResults['is_func']
- $analyzedSqlResults['is_maint']
- $analyzedSqlResults['is_maint']
- $analyzedSqlResults['is_show']
- $analyzedSqlResults['is_show']
- $analyzedSqlResults['parser']->errors
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['select_expr']
- $analyzedSqlResults['select_tables']
- $analyzedSqlResults['select_tables']
- $analyzedSqlResults['select_tables']
- $analyzedSqlResults['statement']
- $analyzedSqlResults['statement']
- $analyzedSqlResults['statement']
- $analyzedSqlResults['statement']->where
$columns[$indexColumnName]['Extra']
- $db
$extraData['error']
$fieldInfoResult[0]['Type']
$foreignData['foreign_field']
@@ -13076,19 +12984,15 @@
$oneResult['Duration']
$oneResult['Status']
$sortCol
- $statement
- $table
- $tokenList
$unlimNumRows
$unlimNumRows
Message::sanitize($warning)
-
- $analyzedSqlResults
+
$showTable
$showTable
-
+
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['max_rows']
$_SESSION['tmpval']['max_rows']
@@ -13096,8 +13000,6 @@
$_SESSION['tmpval']['pos']
$_SESSION['tmpval']['pos']
$_SESSION['tmpval']['pos']
- $analyzedSqlResults['select_expr'][0]
- $analyzedSqlResults['statement']->where[0]
$fieldInfoResult[0]['Type']
$oneResult['Duration']
$oneResult['Duration']
@@ -13106,6 +13008,7 @@
$oneResult['Duration']
$oneResult['Duration']
$oneResult['Status']
+ $statementInfo->statement->where[0]
$_SESSION['tmpval']['pos']
@@ -13114,7 +13017,7 @@
$columns[$indexColumnName]
-
+
$maxRows
$oneFieldMeta
$oneMeta
@@ -13126,11 +13029,6 @@
$profiling['total_time']
$resultSetColumnNames[]
$sortCol
- $statement
- $statement
- $statement
- $table
- $tokenList
$unlimNumRows
$unlimNumRows
$unlimNumRows
@@ -13153,16 +13051,10 @@
$oneResult['Duration']
$profiling['chart'][$status]
-
- $analyzedSqlResults['parser']->errors
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['parser']->list
- $analyzedSqlResults['statement']->where
- $analyzedSqlResults['statement']->where[0]->expr
+
$oneFieldMeta->table
$oneMeta->name
+ $statementInfo->statement->where[0]->expr
$pos
@@ -15146,42 +15038,10 @@
-
- $analyzedSqlResults
- $analyzedSqlResults
- $analyzedSqlResults['is_analyse']
- $analyzedSqlResults['is_analyse']
- $analyzedSqlResults['is_count']
- $analyzedSqlResults['is_count']
- $analyzedSqlResults['is_explain']
- $analyzedSqlResults['is_explain']
- $analyzedSqlResults['is_export']
- $analyzedSqlResults['is_export']
- $analyzedSqlResults['is_func']
- $analyzedSqlResults['is_func']
- $analyzedSqlResults['is_maint']
- $analyzedSqlResults['is_maint']
- $analyzedSqlResults['is_show']
- $analyzedSqlResults['is_show']
+
$output
$output
-
- $analyzedSqlResults['is_analyse']
- $analyzedSqlResults['is_analyse']
- $analyzedSqlResults['is_count']
- $analyzedSqlResults['is_count']
- $analyzedSqlResults['is_explain']
- $analyzedSqlResults['is_explain']
- $analyzedSqlResults['is_export']
- $analyzedSqlResults['is_export']
- $analyzedSqlResults['is_func']
- $analyzedSqlResults['is_func']
- $analyzedSqlResults['is_maint']
- $analyzedSqlResults['is_maint']
- $analyzedSqlResults['is_show']
- $analyzedSqlResults['is_show']
-
$_SESSION['tmpval']['display_binary']
$_SESSION['tmpval']['display_binary']
@@ -15200,8 +15060,7 @@
$output
$output
-
- array
+
array
array
array
@@ -16149,18 +16008,6 @@
-
- $this->parseAndAnalyze('DROP DATABASE db')
- $this->parseAndAnalyze('DROP TABLE tbl')
- $this->parseAndAnalyze('SELECT * FROM db.tbl')
- $this->parseAndAnalyze('SELECT * FROM tbl WHERE 1')
- $this->parseAndAnalyze('SELECT * from tbl')
- $this->parseAndAnalyze('SELECT * from tbl1, tbl2 LIMIT 0, 10')
-
-
- $analyzed_sql_results
- $analyzed_sql_results
-
array
diff --git a/psalm.xml b/psalm.xml
index 467c942d19..cf26119f58 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -26,6 +26,7 @@
+
@@ -305,6 +306,7 @@
text_dir: string,
token_mismatch: bool,
token_provided: bool,
+ unparsed_sql?: string,
urlParams: array,
username: string,
xml_export_triggers: bool,
diff --git a/test/classes/Display/ResultsTest.php b/test/classes/Display/ResultsTest.php
index 051a5a6ce8..c2956979bb 100644
--- a/test/classes/Display/ResultsTest.php
+++ b/test/classes/Display/ResultsTest.php
@@ -15,8 +15,8 @@ use PhpMyAdmin\ParseAnalyze;
use PhpMyAdmin\Plugins\Transformations\Output\Text_Plain_External;
use PhpMyAdmin\Plugins\Transformations\Text_Plain_Link;
use PhpMyAdmin\Plugins\TransformationsPlugin;
-use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Utils\Query;
+use PhpMyAdmin\StatementInfo;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Transformations;
@@ -82,18 +82,12 @@ class ResultsTest extends AbstractTestCase
*/
public function testisSelect(): void
{
- $parser = new Parser('SELECT * FROM pma');
$this->assertTrue(
$this->callFunction(
$this->object,
DisplayResults::class,
'isSelect',
- [
- [
- 'statement' => $parser->statements[0],
- 'select_from' => true,
- ],
- ]
+ [StatementInfo::fromArray(Query::getAll('SELECT * FROM pma'))]
)
);
}
@@ -368,45 +362,21 @@ class ResultsTest extends AbstractTestCase
);
}
- /**
- * Data provider for testSetHighlightedColumnGlobalField
- *
- * @return array parameters and output
- */
- public function dataProviderForTestSetHighlightedColumnGlobalField(): array
- {
- $parser = new Parser('SELECT * FROM db_name WHERE `db_name`.`tbl`.id > 0 AND `id` < 10');
-
- return [
- [
- ['statement' => $parser->statements[0]],
- [
- 'db_name' => 'true',
- 'tbl' => 'true',
- 'id' => 'true',
- ],
- ],
- ];
- }
-
- /**
- * Test setHighlightedColumnGlobalField
- *
- * @param array $analyzed_sql the analyzed query
- * @param array $output setting value of setHighlightedColumnGlobalField
- *
- * @dataProvider dataProviderForTestSetHighlightedColumnGlobalField
- */
- public function testSetHighlightedColumnGlobalField(array $analyzed_sql, array $output): void
+ public function testSetHighlightedColumnGlobalField(): void
{
+ $query = 'SELECT * FROM db_name WHERE `db_name`.`tbl`.id > 0 AND `id` < 10';
$this->callFunction(
$this->object,
DisplayResults::class,
'setHighlightedColumnGlobalField',
- [$analyzed_sql]
+ [StatementInfo::fromArray(Query::getAll($query))]
);
- $this->assertEquals($output, $this->object->properties['highlight_columns']);
+ $this->assertEquals([
+ 'db_name' => 'true',
+ 'tbl' => 'true',
+ 'id' => 'true',
+ ], $this->object->properties['highlight_columns']);
}
/**
@@ -633,7 +603,6 @@ class ResultsTest extends AbstractTestCase
* bool,
* TransformationsPlugin|null,
* array,
- * array,
* string
* }}
*/
@@ -684,7 +653,6 @@ class ResultsTest extends AbstractTestCase
false,
null,
['https://www.example.com/'],
- [],
'class="disableAjax">[BLOB - 4 B]'
. '' . "\n",
],
@@ -698,7 +666,6 @@ class ResultsTest extends AbstractTestCase
false,
$transformation_plugin,
[],
- [],
'
'
. '1001'
. ' | ' . "\n",
@@ -713,7 +680,6 @@ class ResultsTest extends AbstractTestCase
false,
$transformation_plugin,
[],
- [],
'' . "\n"
@@ -730,7 +696,6 @@ class ResultsTest extends AbstractTestCase
false,
null,
[],
- [],
' | foo bar baz | ' . "\n",
@@ -745,7 +710,6 @@ class ResultsTest extends AbstractTestCase
false,
$transformation_plugin_external,
[],
- [],
'foo bar baz | ' . "\n",
@@ -760,7 +724,6 @@ class ResultsTest extends AbstractTestCase
false,
null,
[],
- [],
'2020-09-20 16:35:00 | ' . "\n",
@@ -769,16 +732,15 @@ class ResultsTest extends AbstractTestCase
}
/**
- * @param string $protectBinary all|blob|noblob|no
- * @param string|null $column the relevant column in data row
- * @param string $class the html class for column
- * @param object $meta the meta-information about the field
- * @param array $map the list of relations
- * @param array $_url_params the parameters for generate url
- * @param bool $condition_field the column should highlighted or not
- * @param array $transform_options the transformation parameters
- * @param array $analyzed_sql_results the analyzed query
- * @param string $output the output of this function
+ * @param string $protectBinary all|blob|noblob|no
+ * @param string|null $column the relevant column in data row
+ * @param string $class the html class for column
+ * @param object $meta the meta-information about the field
+ * @param array $map the list of relations
+ * @param array $_url_params the parameters for generate url
+ * @param bool $condition_field the column should highlighted or not
+ * @param array $transform_options the transformation parameters
+ * @param string $output the output of this function
*
* @dataProvider dataProviderForTestGetDataCellForNonNumericColumns
*/
@@ -792,7 +754,6 @@ class ResultsTest extends AbstractTestCase
bool $condition_field,
?TransformationsPlugin $transformation_plugin,
array $transform_options,
- array $analyzed_sql_results,
string $output
): void {
$_SESSION['tmpval']['display_binary'] = true;
@@ -800,6 +761,7 @@ class ResultsTest extends AbstractTestCase
$_SESSION['tmpval']['relational_display'] = false;
$GLOBALS['cfg']['LimitChars'] = 50;
$GLOBALS['cfg']['ProtectBinary'] = $protectBinary;
+ $statementInfo = $this->createStub(StatementInfo::class);
$this->assertStringContainsString(
$output,
$this->callFunction(
@@ -815,7 +777,7 @@ class ResultsTest extends AbstractTestCase
$condition_field,
$transformation_plugin,
$transform_options,
- $analyzed_sql_results,
+ $statementInfo,
]
)
);
@@ -906,7 +868,7 @@ class ResultsTest extends AbstractTestCase
'disabled',
false,
$query,
- Query::getAll($query),
+ StatementInfo::fromArray(Query::getAll($query)),
]
);
@@ -1319,7 +1281,7 @@ class ResultsTest extends AbstractTestCase
$object = new DisplayResults($this->dbi, $GLOBALS['db'], $GLOBALS['table'], 1, '', $query);
$object->properties['unique_id'] = 1234567890;
- [$analyzedSqlResults] = ParseAnalyze::sqlQuery($query, $GLOBALS['db']);
+ [$statementInfo] = ParseAnalyze::sqlQuery($query, $GLOBALS['db']);
$fieldsMeta = [
new FieldMetadata(
MYSQLI_TYPE_DECIMAL,
@@ -1333,17 +1295,17 @@ class ResultsTest extends AbstractTestCase
$object->setProperties(
3,
$fieldsMeta,
- $analyzedSqlResults['is_count'],
- $analyzedSqlResults['is_export'],
- $analyzedSqlResults['is_func'],
- $analyzedSqlResults['is_analyse'],
+ $statementInfo->isCount,
+ $statementInfo->isExport,
+ $statementInfo->isFunction,
+ $statementInfo->isAnalyse,
3,
count($fieldsMeta),
1.234,
'ltr',
- $analyzedSqlResults['is_maint'],
- $analyzedSqlResults['is_explain'],
- $analyzedSqlResults['is_show'],
+ $statementInfo->isMaint,
+ $statementInfo->isExplain,
+ $statementInfo->isShow,
null,
null,
true,
@@ -1376,7 +1338,7 @@ class ResultsTest extends AbstractTestCase
]);
$this->assertNotFalse($dtResult);
- $actual = $object->getTable($dtResult, $displayParts, $analyzedSqlResults);
+ $actual = $object->getTable($dtResult, $displayParts, $statementInfo);
$template = new Template();
@@ -1599,7 +1561,7 @@ class ResultsTest extends AbstractTestCase
$object = new DisplayResults($dbi, $GLOBALS['db'], $GLOBALS['table'], 1, '', $query);
$object->properties['unique_id'] = 1234567890;
- [$analyzedSqlResults] = ParseAnalyze::sqlQuery($query, $GLOBALS['db']);
+ [$statementInfo] = ParseAnalyze::sqlQuery($query, $GLOBALS['db']);
$fieldsMeta = [
new FieldMetadata(
MYSQLI_TYPE_LONG,
@@ -1614,17 +1576,17 @@ class ResultsTest extends AbstractTestCase
$object->setProperties(
2,
$fieldsMeta,
- $analyzedSqlResults['is_count'],
- $analyzedSqlResults['is_export'],
- $analyzedSqlResults['is_func'],
- $analyzedSqlResults['is_analyse'],
+ $statementInfo->isCount,
+ $statementInfo->isExport,
+ $statementInfo->isFunction,
+ $statementInfo->isAnalyse,
2,
count($fieldsMeta),
1.234,
'ltr',
- $analyzedSqlResults['is_maint'],
- $analyzedSqlResults['is_explain'],
- $analyzedSqlResults['is_show'],
+ $statementInfo->isMaint,
+ $statementInfo->isExplain,
+ $statementInfo->isShow,
null,
null,
true,
@@ -1657,7 +1619,7 @@ class ResultsTest extends AbstractTestCase
]);
$this->assertNotFalse($dtResult);
- $actual = $object->getTable($dtResult, $displayParts, $analyzedSqlResults);
+ $actual = $object->getTable($dtResult, $displayParts, $statementInfo);
$template = new Template();
diff --git a/test/classes/ParseAnalyzeTest.php b/test/classes/ParseAnalyzeTest.php
new file mode 100644
index 0000000000..4e35a7a202
--- /dev/null
+++ b/test/classes/ParseAnalyzeTest.php
@@ -0,0 +1,59 @@
+setAjax(false);
+
+ $GLOBALS['unparsed_sql'] = '';
+
+ $actual = ParseAnalyze::sqlQuery('SELECT * FROM `sakila`.`actor`', 'sakila_test');
+
+ /** @psalm-suppress TypeDoesNotContainType */
+ $this->assertSame('SELECT * FROM `sakila`.`actor`', $GLOBALS['unparsed_sql']);
+ $this->assertCount(3, $actual);
+ $this->assertInstanceOf(StatementInfo::class, $actual[0]);
+ $this->assertSame('sakila', $actual[1]);
+ $this->assertSame('actor', $actual[2]);
+ $this->assertTrue($actual[0]->reload);
+ $this->assertNotEmpty($actual[0]->selectTables);
+ $this->assertSame([['actor', 'sakila']], $actual[0]->selectTables);
+ $this->assertNotEmpty($actual[0]->selectExpression);
+ $this->assertSame(['*'], $actual[0]->selectExpression);
+ }
+
+ public function testSqlQuery2(): void
+ {
+ $GLOBALS['lang'] = 'en';
+ ResponseRenderer::getInstance()->setAjax(false);
+
+ $GLOBALS['unparsed_sql'] = '';
+
+ $actual = ParseAnalyze::sqlQuery('SELECT `first_name`, `title` FROM `actor`, `film`', 'sakila');
+
+ /** @psalm-suppress TypeDoesNotContainType */
+ $this->assertSame('SELECT `first_name`, `title` FROM `actor`, `film`', $GLOBALS['unparsed_sql']);
+ $this->assertCount(3, $actual);
+ $this->assertInstanceOf(StatementInfo::class, $actual[0]);
+ $this->assertSame('sakila', $actual[1]);
+ $this->assertSame('', $actual[2]);
+ $this->assertFalse($actual[0]->reload);
+ $this->assertNotEmpty($actual[0]->selectTables);
+ $this->assertSame([['actor', null], ['film', null]], $actual[0]->selectTables);
+ $this->assertNotEmpty($actual[0]->selectExpression);
+ $this->assertSame(['`first_name`', '`title`'], $actual[0]->selectExpression);
+ }
+}
diff --git a/test/classes/SqlTest.php b/test/classes/SqlTest.php
index b464cbfe8a..6cc393239d 100644
--- a/test/classes/SqlTest.php
+++ b/test/classes/SqlTest.php
@@ -72,11 +72,12 @@ class SqlTest extends AbstractTestCase
$GLOBALS['_SESSION']['tmpval']['pos'] = 1;
$GLOBALS['_SESSION']['tmpval']['max_rows'] = 2;
- $analyzed_sql_results = $this->parseAndAnalyze('SELECT * FROM test LIMIT 0, 10');
- $this->assertEquals(
- 'SELECT * FROM test LIMIT 1, 2 ',
- $this->callFunction($this->sql, Sql::class, 'getSqlWithLimitClause', [&$analyzed_sql_results])
- );
+ $this->assertEquals('SELECT * FROM test LIMIT 1, 2 ', $this->callFunction(
+ $this->sql,
+ Sql::class,
+ 'getSqlWithLimitClause',
+ [ParseAnalyze::sqlQuery('SELECT * FROM test LIMIT 0, 10', $GLOBALS['db'])[0]]
+ ));
}
/**
@@ -89,31 +90,31 @@ class SqlTest extends AbstractTestCase
$this->assertTrue(
$this->callFunction($this->sql, Sql::class, 'isRememberSortingOrder', [
- $this->parseAndAnalyze('SELECT * FROM tbl'),
+ ParseAnalyze::sqlQuery('SELECT * FROM tbl', $GLOBALS['db'])[0],
])
);
$this->assertFalse(
$this->callFunction($this->sql, Sql::class, 'isRememberSortingOrder', [
- $this->parseAndAnalyze('SELECT col FROM tbl'),
+ ParseAnalyze::sqlQuery('SELECT col FROM tbl', $GLOBALS['db'])[0],
])
);
$this->assertFalse(
$this->callFunction($this->sql, Sql::class, 'isRememberSortingOrder', [
- $this->parseAndAnalyze('SELECT 1'),
+ ParseAnalyze::sqlQuery('SELECT 1', $GLOBALS['db'])[0],
])
);
$this->assertFalse(
$this->callFunction($this->sql, Sql::class, 'isRememberSortingOrder', [
- $this->parseAndAnalyze('SELECT col1, col2 FROM tbl'),
+ ParseAnalyze::sqlQuery('SELECT col1, col2 FROM tbl', $GLOBALS['db'])[0],
])
);
$this->assertFalse(
$this->callFunction($this->sql, Sql::class, 'isRememberSortingOrder', [
- $this->parseAndAnalyze('SELECT COUNT(*) from tbl'),
+ ParseAnalyze::sqlQuery('SELECT COUNT(*) from tbl', $GLOBALS['db'])[0],
])
);
}
@@ -128,13 +129,13 @@ class SqlTest extends AbstractTestCase
$this->assertTrue(
$this->callFunction($this->sql, Sql::class, 'isAppendLimitClause', [
- $this->parseAndAnalyze('SELECT * FROM tbl'),
+ ParseAnalyze::sqlQuery('SELECT * FROM tbl', $GLOBALS['db'])[0],
])
);
$this->assertFalse(
$this->callFunction($this->sql, Sql::class, 'isAppendLimitClause', [
- $this->parseAndAnalyze('SELECT * from tbl LIMIT 0, 10'),
+ ParseAnalyze::sqlQuery('SELECT * from tbl LIMIT 0, 10', $GLOBALS['db'])[0],
])
);
}
@@ -145,17 +146,17 @@ class SqlTest extends AbstractTestCase
$GLOBALS['_SESSION']['tmpval']['max_rows'] = 10;
$this->assertTrue(Sql::isJustBrowsing(
- $this->parseAndAnalyze('SELECT * FROM db.tbl'),
+ ParseAnalyze::sqlQuery('SELECT * FROM db.tbl', $GLOBALS['db'])[0],
null
));
$this->assertTrue(Sql::isJustBrowsing(
- $this->parseAndAnalyze('SELECT * FROM tbl WHERE 1'),
+ ParseAnalyze::sqlQuery('SELECT * FROM tbl WHERE 1', $GLOBALS['db'])[0],
null
));
$this->assertFalse(Sql::isJustBrowsing(
- $this->parseAndAnalyze('SELECT * from tbl1, tbl2 LIMIT 0, 10'),
+ ParseAnalyze::sqlQuery('SELECT * from tbl1, tbl2 LIMIT 0, 10', $GLOBALS['db'])[0],
null
));
}
@@ -167,19 +168,19 @@ class SqlTest extends AbstractTestCase
{
$this->assertTrue(
$this->callFunction($this->sql, Sql::class, 'isDeleteTransformationInfo', [
- $this->parseAndAnalyze('ALTER TABLE tbl DROP COLUMN col'),
+ ParseAnalyze::sqlQuery('ALTER TABLE tbl DROP COLUMN col', $GLOBALS['db'])[0],
])
);
$this->assertTrue(
$this->callFunction($this->sql, Sql::class, 'isDeleteTransformationInfo', [
- $this->parseAndAnalyze('DROP TABLE tbl'),
+ ParseAnalyze::sqlQuery('DROP TABLE tbl', $GLOBALS['db'])[0],
])
);
$this->assertFalse(
$this->callFunction($this->sql, Sql::class, 'isDeleteTransformationInfo', [
- $this->parseAndAnalyze('SELECT * from tbl'),
+ ParseAnalyze::sqlQuery('SELECT * from tbl', $GLOBALS['db'])[0],
])
);
}
@@ -191,7 +192,7 @@ class SqlTest extends AbstractTestCase
{
$this->assertTrue(
$this->sql->hasNoRightsToDropDatabase(
- $this->parseAndAnalyze('DROP DATABASE db'),
+ ParseAnalyze::sqlQuery('DROP DATABASE db', $GLOBALS['db'])[0],
false,
false
)
@@ -199,7 +200,7 @@ class SqlTest extends AbstractTestCase
$this->assertFalse(
$this->sql->hasNoRightsToDropDatabase(
- $this->parseAndAnalyze('DROP TABLE tbl'),
+ ParseAnalyze::sqlQuery('DROP TABLE tbl', $GLOBALS['db'])[0],
false,
false
)
@@ -207,7 +208,7 @@ class SqlTest extends AbstractTestCase
$this->assertFalse(
$this->sql->hasNoRightsToDropDatabase(
- $this->parseAndAnalyze('SELECT * from tbl'),
+ ParseAnalyze::sqlQuery('SELECT * from tbl', $GLOBALS['db'])[0],
false,
false
)
@@ -342,16 +343,6 @@ class SqlTest extends AbstractTestCase
);
}
- /**
- * @return mixed
- */
- private function parseAndAnalyze(string $sqlQuery)
- {
- [$analyzedSqlResults] = ParseAnalyze::sqlQuery($sqlQuery, $GLOBALS['db']);
-
- return $analyzedSqlResults;
- }
-
public function dataProviderCountQueryResults(): array
{
// sql query
@@ -552,8 +543,6 @@ class SqlTest extends AbstractTestCase
$_SESSION['tmpval'] = $sessionTmpVal;
- $analyzed_sql_results = $sqlQuery === null ? [] : $this->parseAndAnalyze($sqlQuery);
-
$result = $this->callFunction(
$this->sql,
Sql::class,
@@ -563,7 +552,7 @@ class SqlTest extends AbstractTestCase
$justBrowsing,
'my_dataset',// db
'company_users',// table
- $analyzed_sql_results,
+ ParseAnalyze::sqlQuery($sqlQuery ?? '', $GLOBALS['db'])[0],
]
);
$this->assertSame($expectedNumRows, $result);
diff --git a/test/classes/StatementInfoTest.php b/test/classes/StatementInfoTest.php
new file mode 100644
index 0000000000..21e41a96be
--- /dev/null
+++ b/test/classes/StatementInfoTest.php
@@ -0,0 +1,159 @@
+statements[0];
+ $info = [
+ 'distinct' => false,
+ 'drop_database' => false,
+ 'group' => false,
+ 'having' => false,
+ 'is_affected' => false,
+ 'is_analyse' => false,
+ 'is_count' => false,
+ 'is_delete' => false,
+ 'is_explain' => false,
+ 'is_export' => false,
+ 'is_func' => false,
+ 'is_group' => false,
+ 'is_insert' => false,
+ 'is_maint' => false,
+ 'is_procedure' => false,
+ 'is_replace' => false,
+ 'is_select' => true,
+ 'is_show' => false,
+ 'is_subquery' => false,
+ 'join' => false,
+ 'limit' => false,
+ 'offset' => false,
+ 'order' => false,
+ 'querytype' => 'SELECT',
+ 'reload' => false,
+ 'select_from' => true,
+ 'union' => false,
+ 'parser' => $parser,
+ 'statement' => $statement,
+ 'select_tables' => [['actor', null]],
+ 'select_expr' => ['*'],
+ ];
+
+ $statementInfo = StatementInfo::fromArray($info);
+
+ $this->assertFalse($statementInfo->distinct);
+ $this->assertFalse($statementInfo->dropDatabase);
+ $this->assertFalse($statementInfo->group);
+ $this->assertFalse($statementInfo->having);
+ $this->assertFalse($statementInfo->isAffected);
+ $this->assertFalse($statementInfo->isAnalyse);
+ $this->assertFalse($statementInfo->isCount);
+ $this->assertFalse($statementInfo->isDelete);
+ $this->assertFalse($statementInfo->isExplain);
+ $this->assertFalse($statementInfo->isExport);
+ $this->assertFalse($statementInfo->isFunction);
+ $this->assertFalse($statementInfo->isGroup);
+ $this->assertFalse($statementInfo->isInsert);
+ $this->assertFalse($statementInfo->isMaint);
+ $this->assertFalse($statementInfo->isProcedure);
+ $this->assertFalse($statementInfo->isReplace);
+ $this->assertTrue($statementInfo->isSelect);
+ $this->assertFalse($statementInfo->isShow);
+ $this->assertFalse($statementInfo->isSubquery);
+ $this->assertFalse($statementInfo->join);
+ $this->assertFalse($statementInfo->limit);
+ $this->assertFalse($statementInfo->offset);
+ $this->assertFalse($statementInfo->order);
+ $this->assertSame('SELECT', $statementInfo->queryType);
+ $this->assertFalse($statementInfo->reload);
+ $this->assertTrue($statementInfo->selectFrom);
+ $this->assertFalse($statementInfo->union);
+ $this->assertNotNull($statementInfo->parser);
+ $this->assertNotNull($statementInfo->statement);
+ $this->assertNotEmpty($statementInfo->selectTables);
+ $this->assertNotEmpty($statementInfo->selectExpression);
+ $this->assertSame($info['parser'], $statementInfo->parser);
+ $this->assertSame($info['statement'], $statementInfo->statement);
+ $this->assertSame($info['select_tables'], $statementInfo->selectTables);
+ $this->assertSame($info['select_expr'], $statementInfo->selectExpression);
+ }
+
+ public function testFromArrayWithEmptyStatement(): void
+ {
+ $info = [
+ 'distinct' => false,
+ 'drop_database' => false,
+ 'group' => false,
+ 'having' => false,
+ 'is_affected' => false,
+ 'is_analyse' => false,
+ 'is_count' => false,
+ 'is_delete' => false,
+ 'is_explain' => false,
+ 'is_export' => false,
+ 'is_func' => false,
+ 'is_group' => false,
+ 'is_insert' => false,
+ 'is_maint' => false,
+ 'is_procedure' => false,
+ 'is_replace' => false,
+ 'is_select' => false,
+ 'is_show' => false,
+ 'is_subquery' => false,
+ 'join' => false,
+ 'limit' => false,
+ 'offset' => false,
+ 'order' => false,
+ 'querytype' => false,
+ 'reload' => false,
+ 'select_from' => false,
+ 'union' => false,
+ ];
+
+ $statementInfo = StatementInfo::fromArray($info);
+
+ $this->assertFalse($statementInfo->distinct);
+ $this->assertFalse($statementInfo->dropDatabase);
+ $this->assertFalse($statementInfo->group);
+ $this->assertFalse($statementInfo->having);
+ $this->assertFalse($statementInfo->isAffected);
+ $this->assertFalse($statementInfo->isAnalyse);
+ $this->assertFalse($statementInfo->isCount);
+ $this->assertFalse($statementInfo->isDelete);
+ $this->assertFalse($statementInfo->isExplain);
+ $this->assertFalse($statementInfo->isExport);
+ $this->assertFalse($statementInfo->isFunction);
+ $this->assertFalse($statementInfo->isGroup);
+ $this->assertFalse($statementInfo->isInsert);
+ $this->assertFalse($statementInfo->isMaint);
+ $this->assertFalse($statementInfo->isProcedure);
+ $this->assertFalse($statementInfo->isReplace);
+ $this->assertFalse($statementInfo->isSelect);
+ $this->assertFalse($statementInfo->isShow);
+ $this->assertFalse($statementInfo->isSubquery);
+ $this->assertFalse($statementInfo->join);
+ $this->assertFalse($statementInfo->limit);
+ $this->assertFalse($statementInfo->offset);
+ $this->assertFalse($statementInfo->order);
+ $this->assertFalse($statementInfo->queryType);
+ $this->assertFalse($statementInfo->reload);
+ $this->assertFalse($statementInfo->selectFrom);
+ $this->assertFalse($statementInfo->union);
+ $this->assertNull($statementInfo->parser);
+ $this->assertNull($statementInfo->statement);
+ $this->assertEmpty($statementInfo->selectTables);
+ $this->assertEmpty($statementInfo->selectExpression);
+ }
+}
diff --git a/test/stubs/Query.stub b/test/stubs/Query.stub
new file mode 100644
index 0000000000..9a09dacd5c
--- /dev/null
+++ b/test/stubs/Query.stub
@@ -0,0 +1,53 @@
+,
+ * select_expr?: list
+ * }
+ */
+ public static function getAll($query);
+}