From 4c28e6d0ecb0f210704fda6b0f0f8aee220295b9 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Thu, 26 Jan 2023 16:37:22 +0900 Subject: [PATCH] Change DB\IO Returning check regex Better regex to only get last returning in query, with proper parameter check --- www/admin/class_test.db.php | 4 ++-- www/lib/CoreLibs/DB/IO.php | 27 +++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/www/admin/class_test.db.php b/www/admin/class_test.db.php index bb7a7452..4e07f6bb 100644 --- a/www/admin/class_test.db.php +++ b/www/admin/class_test.db.php @@ -161,7 +161,7 @@ print "DIRECT INSERT PREVIOUS INSERTED: " $db->dbPrepare("ins_test_foo", "INSERT INTO test_foo (test) VALUES ($1) RETURNING test"); $status = $db->dbExecute("ins_test_foo", ['BAR TEST ' . time()]); print "PREPARE INSERT[ins_test_foo] STATUS: " . Support::printToString($status) . " |
" - . "QUERY: " . $db->dbGetQuery() . " |
" + . "QUERY: " . $db->dbGetPrepareCursorValue('ins_test_foo', 'query') . " |
" . "PRIMARY KEY: " . $db->dbGetInsertPK() . " | " . "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | " . "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "
"; @@ -186,7 +186,7 @@ EOM; $db->dbPrepare("ins_test_foo_eom", $query); $status = $db->dbExecute("ins_test_foo_eom", ['EOM BAR TEST ' . time()]); print "EOM STRING PREPARE INSERT[ins_test_foo_eom] STATUS: " . Support::printToString($status) . " |
" - . "QUERY: " . $db->dbGetQuery() . " |
" + . "QUERY: " . $db->dbGetPrepareCursorValue('ins_test_foo_eom', 'query') . " |
" . "PRIMARY KEY: " . $db->dbGetInsertPK() . " | " . "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | " . "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "
"; diff --git a/www/lib/CoreLibs/DB/IO.php b/www/lib/CoreLibs/DB/IO.php index 16456572..d672464b 100644 --- a/www/lib/CoreLibs/DB/IO.php +++ b/www/lib/CoreLibs/DB/IO.php @@ -266,16 +266,18 @@ class IO // 1: read new, keep at end, clean before new run // 2: read new, clean at the end (temporary cache) // 3: never cache - /** @var int */ + /** @var int use cache (default) in dbReturn */ public const USE_CACHE = 0; - /** @var int */ + /** @var int reset cache and read new in dbReturn */ public const READ_NEW = 1; - /** @var int */ + /** @var int clear cache after read in dbeEturn */ public const CLEAR_CACHE = 2; - /** @var int */ + /** @var int do not use any cache in dbReturn */ public const NO_CACHE = 3; - /** @var string */ + /** @var string default hash type */ public const ERROR_HASH_TYPE = 'adler32'; + /** @var string regex to get returning with matches at position 1 */ + public const REGEX_RETURNING = '/\s?returning(?: (.+?));?$/i'; // recommend to set private/protected and only allow setting via method // can bet set from outside @@ -1007,7 +1009,7 @@ class IO $this->pk_name_table[$table] : 'NULL'; } if ( - !preg_match("/\s?returning /i", $this->query) && + !preg_match(self::REGEX_RETURNING, $this->query) && $this->pk_name && $this->pk_name != 'NULL' ) { // check if this query has a ; at the end and remove it @@ -1016,7 +1018,9 @@ class IO $this->query = !is_string($__query) ? $this->query : $__query; $this->query .= " RETURNING " . $this->pk_name; $this->returning_id = true; - } elseif (preg_match("/\s?returning (.*)/i", $this->query, $matches)) { + } elseif ( + preg_match(self::REGEX_RETURNING, $this->query, $matches) + ) { if ($this->pk_name && $this->pk_name != 'NULL') { // add the primary key if it is not in the returning set if (!preg_match("/$this->pk_name/", $matches[1])) { @@ -1030,7 +1034,7 @@ class IO // if we have an UPDATE and RETURNING, flag for true, but do not add anything if ( $this->__checkQueryForUpdate($this->query) && - preg_match("/\s?returning (.*)/i", $this->query, $matches) + preg_match(self::REGEX_RETURNING, $this->query, $matches) ) { $this->returning_id = true; } @@ -2288,11 +2292,14 @@ class IO $this->prepare_cursor[$stm_name]['pk_name'] = $pk_name; } // if no returning, then add it - if (!preg_match("/\s?returning /i", $query) && $this->prepare_cursor[$stm_name]['pk_name']) { + if ( + !preg_match(self::REGEX_RETURNING, $query) && + $this->prepare_cursor[$stm_name]['pk_name'] + ) { $query .= " RETURNING " . $this->prepare_cursor[$stm_name]['pk_name']; $this->prepare_cursor[$stm_name]['returning_id'] = true; } elseif ( - preg_match("/\s?returning (.*)/i", $query, $matches) && + preg_match(self::REGEX_RETURNING, $query, $matches) && $this->prepare_cursor[$stm_name]['pk_name'] ) { // if returning exists but not pk_name, add it