-
-
Notifications
You must be signed in to change notification settings - Fork 22
Open
Labels
Description
I'm having troubles selecting rows based on datetime calculation on a Postgres database.
The query I'm trying to build looks like:
SELECT *
FROM "news"
WHERE "created_on_datetime" > NOW()- INTERVAL '1 YEAR'
ORDER BY "created_on_datetime" DESC;A simple code example to reproduce could be:
$newsModel = new News();
$filter = ['created_on_datetime > NOW() - INTERVAL \'1 YEAR\''];
$news = $newsModel->find($filter);From the debug lines I've added to the cortex code, the generated query is:
SELECT "id","title","content","author","created_on_datetime" FROM "news" WHERE "created_on_datetime" > NOW() - "INTERVAL" '1 YEAR'Note the double quotes added automatically around the INTERVAL keyword. (Without them the query works fine.
Those leads to the Postgres error:
Error in query (7): ERROR: type "INTERVAL" does not exist
LINE 1: ...M "news" WHERE "created_on_datetime" > NOW() - "INTERVAL"...
I've tracked the quotes adder down to the function sql_quoteCondition()
Lines 2683 to 2706 in 364caaa
| /** | |
| * quote identifiers in condition | |
| * @param string $cond | |
| * @param object $db | |
| * @return string | |
| */ | |
| public function sql_quoteCondition($cond, $db) { | |
| // https://www.debuggex.com/r/6AXwJ1Y3Aac8aocQ/3 | |
| // https://regex101.com/r/yM5vK4/1 | |
| // this took me lots of sleepless nights | |
| $out = preg_replace_callback('/'. | |
| '\w+\((?:(?>[^()]+)|\((?:(?>[^()]+)|^(?R))*\))*\)|'. // exclude SQL function names "foo(" | |
| '(?:(\b(?<!:)'. // exclude bind parameter ":foo" | |
| '[a-zA-Z_](?:[\w\-_.]+\.?))'. // match only identifier, exclude values | |
| '(?=[\s<>=!)]|$))/i', // only when part of condition or within brackets | |
| function($match) use($db) { | |
| if (!isset($match[1])) | |
| return $match[0]; | |
| if (preg_match('/\b(AND|OR|IN|LIKE|NOT|HAVING|SELECT|FROM|WHERE)\b/i',$match[1])) | |
| return $match[1]; | |
| return $db->quotekey($match[1]); | |
| }, $cond); | |
| return $out ?: $cond; | |
| } |
Here is a regex101 fork, were we clearly see the INTERVAL captured as a column name.
https://regex101.com/r/AP2mRH/1
I'm on:
/**
* Cortex - the flexible data mapper for the PHP Fat-Free Framework
* […]
* @package DB
* @version 1.6.0
* @date 03.02.2019
* @since 24.04.2012
*/I hope this one will not give you more sleepless nights 😉