phpmyadmin / phpmyadmin/sql-parser

Incorrect type in SelectStatement::$expr when query has CASE-clause in selected fields

Ouverte
#552 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

question
Langage dominant
PHP
Étoiles
485
Forks
119
Métriques de merge des PR
Aucune PR mergée en 30 j

Description

The public field SelectStatement::$expr is defined in a PHP docblock as an Expression[]. When parsing a query with a CASE statement, a CaseExpression object is present in this list, despite CaseExpression not extending Expression. This causes issues when explicitly requiring the Expression type as should be returned by SelectStatement::$expr.

Reproduction case

<?php

declare(strict_types=1);

use PhpMyAdmin\SqlParser\Components\Expression;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Statements\SelectStatement;

include_once 'vendor/autoload.php';

$p = new Parser('SELECT a, CASE WHEN b IS NOT NULL THEN 1 ELSE 0 END as c FROM t');

$stmt = $p->statements[0];
if (! $stmt instanceof SelectStatement) {
    throw new Exception('Could not parse select statement');
}

function acceptExpression(Expression $e): void {}

$expressions = $stmt->expr;
foreach ($expressions as $expression) {
    acceptExpression($expression);
}
Expected behavior

I would expect this script to not error out as the $stmt->expr returns Expression[] according to its PHP docblock. Each element should therefore be compatible with Expression in my acceptExpression function.

Real behavior
$ php test.php
PHP Fatal error:  Uncaught TypeError: acceptExpression(): Argument #1 ($e) must be of type PhpMyAdmin\SqlParser\Components\Expression, PhpMyAdmin\SqlParser\Components\CaseExpression given, called in /path/to/test.php on line 22 and defined in /path/to/test.php:18
Stack trace:
#0 /path/to/test.php(22): acceptExpression()
#1 {main}
  thrown in /path/to/test.php on line 18

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Commencez par la reproduction de Parser dans l’issue et examinez comment SelectStatement::$expr est alimenté lorsqu’une clause CASE est sélectionnée. Comparez les types Expression et CaseExpression et vérifiez le contrat attendu en réexécutant le script fourni ; c’est terminé lorsque le TypeError signalé ne se produit plus et que la liste d’expressions reste correctement typée.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
php
Domaine
databases
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
À l'abandon
Clarté
Plutôt claire
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.