ThingEngineer / PHP-MySQLi-Database-Class

Wrapper for a PHP MySQL class, which utilizes MySQLi and prepared statements.
Other
3.29k stars 1.35k forks source link

Unable to run rawQuery Truncate without error #956

Open twheeler-work opened 3 years ago

twheeler-work commented 3 years ago

The $table var would be empty causing it to break.

EXAMPLE USE: $db->rawQuery('TRUNCATE tableName');

FIX: Add truncate to the preg match list.

preg_matchall( "/(truncate|from|into|update|join) [\'\´]?([a-zA-Z0-9-]+)[\'\´]?/i", $query, $matches );

RyadPasha commented 2 years ago

The rawAddPrefix function has many bugs, first thing is that only the first table in the query gets prefixed, (so if using query with a JOIN clause for example only first table will get prefixed), also a lot of statements such as (DROP TABLE, TRUNCATE TABLE, CREATE TABLE, LOCK TABLE, FLASHBACK TABLE, ALTER TABLE, ANALYZE TABLE, DESCRIBE and EXPLAIN) are not supported .. You can fix all these bug by replacing that function with mines:

/**
 * Prefix add raw SQL query.
 *
 * @author Mohamed Riyad <https://github.com/RyadPasha>
 * @param string $query User-provided query to execute.
 * @return string Contains the returned rows from the query.
 */
public function rawAddPrefix($query){
    $query = preg_replace(['/[\r\n]+/', '/\s+/'], ' ', $query); // Replace multiple line breaks/spaces with a single space
    if (preg_match_all("/(FROM|INTO|UPDATE|JOIN|DROP TABLE|TRUNCATE TABLE|CREATE TABLE|LOCK TABLE|FLASHBACK TABLE|ALTER TABLE|ANALYZE TABLE|DESCRIBE|EXPLAIN) [\\'\\´\\`]?(?!SELECT|DELETE|INSERT|REPLACE|UPDATE)([a-zA-Z0-9_-]+)[\\'\\´\\`]?/i", $query, $matches)) {
        for ($i = 0; $i < count($matches[0]); $i++) {
            list($from_table, $from, $table) = $matches;
            $query = str_replace($table[$i], self::$prefix.$table[$i], $query);
        }
    }
    return $query;
}
putaprost commented 1 year ago

I don't think this can work. I found it best for me to remove rawAddPrefix function. I had a longer query, and the preg_match_all gave me two identical table names. In the loop it was run twice, so, for example i had, tbl_cars, and then tbl_tbl_cars. I tried to use array unique on the $table array, and it was all ok, everything looked ok. But then, i realized i had a field name in the query, that contained the table name, sometihng like cars_id. And even with array unique on the $table array, i was getting SELECT tbl_cars.tbl_cars_id instead of tbl_cars.cars_id. It can probably can be fixed, because i think you allways have a . (dot) before the column name, but i have no ideea what else can happend after this so i disabled this function. If anyone needs it, it could work, if you are carefull and dont use the table name in any of the fields name.

It's something on these lines,

   public function rawAddPrefix($query) {
       $query = str_replace(PHP_EOL, '', $query);
        $query = preg_replace('/\s+/', ' ', $query);
        preg_match_all("/(FROM|INTO|UPDATE|JOIN|DROP TABLE|TRUNCATE TABLE|CREATE TABLE|LOCK TABLE|FLASHBACK TABLE|ALTER TABLE|ANALYZE TABLE|DESCRIBE|EXPLAIN) [\\'\\´\\`]?(?!SELECT|DELETE|INSERT|REPLACE|UPDATE)([a-zA-Z0-9_-]+)[\\'\\´\\`]?/i", $query, $matches);
        $matches_unique = array_unique($matches[2]);

        foreach ($matches_unique as $table) {
            $query = str_replace($table, self::$prefix . $table, $query);
        }
        return $query;

    }