Git Product home page Git Product logo

Comments (9)

craigfrancis avatar craigfrancis commented on June 12, 2024 1

Yes, thank you (once I realised that composer was not updating).

from phpstan-dba.

staabm avatar staabm commented on June 12, 2024

for some reason the placeholder replacement does not work on your machine.
I cannot reproduce either in CI nor on my windows laptop.

could you dig a bit thru

/**
* @param array<string|int, scalar|null> $parameters
*/
private function replaceParameters(string $queryString, array $parameters): string
{
$replaceFirst = function (string $haystack, string $needle, string $replace) {
$pos = strpos($haystack, $needle);
if (false !== $pos) {
return substr_replace($haystack, $replace, $pos, \strlen($needle));
}
return $haystack;
};
foreach ($parameters as $placeholderKey => $value) {
if (\is_string($value)) {
// XXX escaping
$value = "'".$value."'";
} elseif (null === $value) {
$value = 'NULL';
} else {
$value = (string) $value;
}
if (\is_int($placeholderKey)) {
$queryString = $replaceFirst($queryString, '?', $value);
} else {
$queryString = str_replace($placeholderKey, $value, $queryString);
}
}
return $queryString;
}

to get a feeling why it fails in your setup?

from phpstan-dba.

staabm avatar staabm commented on June 12, 2024

I was able to reproduce this problem, when

    -
        class: staabm\PHPStanDba\Rules\SyntaxErrorInQueryMethodRule
        tags: [phpstan.rules.rule]
        arguments:
            classMethods:
                - 'rex_sql::setQuery#0'
                - 'rex_sql::setDBQuery#0'
                

is configured for a method, which actually takes a prepared statement and query-string separately

from phpstan-dba.

craigfrancis avatar craigfrancis commented on June 12, 2024

I think we are on the same page... and Pull Request 119 has stopped the error.

From my understanding, the checking of $pdo->prepare() does not call replaceParameters(), so the SQL is sent to the database with the placeholders (causing it to error).

In comparison $stmt->execute() (which is checked after this error has happened), does use replaceParameters(), and is fine.

I'm just wondering, could the parameters simply be replaced with the number 0? something like this:

$queryString = preg_replace('/(\?|\b:[a-zA-Z0-9_]+\b)/', '0', $queryString);

It's already using LIMIT 0, so it won't return any records... but I must confess I've not really checked it, and this approach might cause other issues.

e.g. While these are a bit contrived, WHERE question LIKE "%?" or WHERE meta_data LIKE "%:tag_name%". Because I'm not really doing proper parsing of the SQL string, those characters would be incorrectly replaced because they look like placeholders.

As an aside, I think there might have a similar issue with countPlaceholders() and extractNamedPlaceholders().

I wonder, if this is a problem, does it needs to do something similar to the pdo_parse_params() function, rather than simply using the BINDCHR regex (used later as PDO_PARSER_BIND)... as that supports escaped question marks (??), comments (/* What about X? */ or -- To fix?), and quoted string values (if I'm reading this correctly, using ANYNOEOF?).

from phpstan-dba.

staabm avatar staabm commented on June 12, 2024

You are right that the current parsing is a bit naive and can easily break in edge cases.

We might finally use a proper sql parser.


Regarding your inital problem: I guess your phpstan-dba config is wrongly mixing SyntaxErrorInPreparedStatementMethodRule and SyntaxErrorInQueryMethodRule.

Actually for pdo support you don't need additional rules configuration. The default config should work for pdo-only source analysis.

I'm just wondering, could the parameters simply be replaced with the number 0

Thats what SyntaxErrorInPreparedStatementMethodRule is doing when variables types are known:

public static function simulateParamValueType(Type $paramType): ?string

from phpstan-dba.

craigfrancis avatar craigfrancis commented on June 12, 2024

Just running a quick test (need to go in a bit)... I've used a script that only contains:

<?php

$pdo = new PDO('mysql:dbname=test;host=localhost', 'test', 'test', [PDO::ATTR_EMULATE_PREPARES => false]);

$stmt = $pdo->prepare('SELECT * FROM user WHERE id = ?');

And that triggered the 'Query error' in SyntaxErrorInQueryMethodRule.

Taking a guess, that might be due to the provided dba.neon file.

from phpstan-dba.

staabm avatar staabm commented on June 12, 2024

Just running a quick test (need to go in a bit)... I've used a script that only contains:

<?php

$pdo = new PDO('mysql:dbname=test;host=localhost', 'test', 'test', [PDO::ATTR_EMULATE_PREPARES => false]);

$stmt = $pdo->prepare('SELECT * FROM user WHERE id = ?');

And that triggered the 'Query error' in SyntaxErrorInQueryMethodRule.

Taking a guess, that might be due to the provided dba.neon file.

I think this example works on latest master. I think it was fixed with #119

at least running your example in a unit test seems to not produce a error, see #124

from phpstan-dba.

craigfrancis avatar craigfrancis commented on June 12, 2024

Yep, when I used #119, that fixed the error... and I suspect those checks are run when it get's to the $stmt->execute() (sorry, gtg, and I'm probably not going to be available for a few days).

from phpstan-dba.

staabm avatar staabm commented on June 12, 2024

Does the initial issue still reproduce or can we close the issue?

from phpstan-dba.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.