phpmyadmin / phpmyadmin/sql-parser

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

Aperta
#552 5 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

question
Lingua principale
PHP
Stelle
485
Fork
119
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

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

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con la riproduzione di Parser nell’issue e verifica come viene popolato SelectStatement::$expr quando viene selezionata una clausola CASE. Confronta i tipi Expression e CaseExpression e verifica il contratto previsto rieseguendo lo script fornito; il lavoro è completato quando il TypeError segnalato non si verifica più e l’elenco delle espressioni rimane correttamente tipizzato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
php
Ambito
databases
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.