From 8aee448c593c7a8b2ff18d98e39f4f1189eaba25 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Wed, 9 Apr 2025 11:35:02 +0900 Subject: [PATCH] Update DB IO for query hash storage and parameter count The parameter count methods in the PgSQL class have changed - the function returns a unique list of $ parameters The count is now done in the DB IO part where it counts over the unique array Query hash is stored like the query for the current run one (reset on dbExec call). The method to create the hash is renamed to dbBuildQueryHash instead of "Get". The dbGetQueryHash function now just returns the last set query hash. There is a matching dbResetQueryHash for unsetting the query hash. --- 4dev/tests/DB/CoreLibsDBIOTest.php | 4 +- www/admin/class_test.db.encryption.php | 26 ++++++++-- www/lib/CoreLibs/DB/IO.php | 51 ++++++++++++++----- .../DB/SQL/Interface/SqlFunctions.php | 4 +- www/lib/CoreLibs/DB/SQL/PgSQL.php | 13 +---- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/4dev/tests/DB/CoreLibsDBIOTest.php b/4dev/tests/DB/CoreLibsDBIOTest.php index 4ed9cabd..f9e66c6a 100644 --- a/4dev/tests/DB/CoreLibsDBIOTest.php +++ b/4dev/tests/DB/CoreLibsDBIOTest.php @@ -5009,8 +5009,8 @@ final class CoreLibsDBIOTest extends TestCase ) ), ($params === null ? - $db->dbGetQueryHash($query) : - $db->dbGetQueryHash($query, $params) + $db->dbBuildQueryHash($query) : + $db->dbBuildQueryHash($query, $params) ), 'Failed assertdbGetQueryHash ' ); diff --git a/www/admin/class_test.db.encryption.php b/www/admin/class_test.db.encryption.php index 7a0a827d..0d8da1cb 100644 --- a/www/admin/class_test.db.encryption.php +++ b/www/admin/class_test.db.encryption.php @@ -42,7 +42,10 @@ print '
Class Test Master
'; print '

' . $PAGE_NAME . '

'; // encryption key -$key = CreateKey::generateRandomKey(); +$key_new = CreateKey::generateRandomKey(); +print "Secret Key NEW: " . $key_new . "
"; +// for reproducable test results +$key = 'e475c19b9a3c8363feb06b51f5b73f1dc9b6f20757d4ab89509bf5cc70ed30ec'; print "Secret Key: " . $key . "
"; // test text @@ -105,20 +108,35 @@ $res = $db->dbReturnRowParams( -- in DB encryption pg_digest_bytea, pg_digest_text, pg_hmac_bytea, pg_hmac_text, - pg_crypt_bytea, pg_crypt_text + pg_crypt_bytea, pg_crypt_text, + encode(pg_crypt_bytea, 'hex') AS pg_crypt_bytea_hex, + pgp_sym_decrypt(pg_crypt_bytea, $2) AS from_pg_crypt_bytea, + pgp_sym_decrypt(decode(pg_crypt_text, 'hex'), $2) AS from_pg_crypt_text FROM test_encryption WHERE cuuid = $1 SQL, [ - $cuuid + $cuuid, $key ] ); print "RES:
" . Support::prAr($res) . "

"; -// do compare +if ($res === false) { + echo "Failed to run query
"; +} else { + if (hash_equals($string_hashed, $res['pg_digest_text'])) { + print "libsodium and pgcrypto hash match
"; + } + if (hash_equals($string_hmac, $res['pg_hmac_text'])) { + print "libsodium and pgcrypto hash hmac match
"; + } +} + + +// do compare for PHP and pgcrypto settings print ""; diff --git a/www/lib/CoreLibs/DB/IO.php b/www/lib/CoreLibs/DB/IO.php index 9f60d38a..d66a7d9c 100644 --- a/www/lib/CoreLibs/DB/IO.php +++ b/www/lib/CoreLibs/DB/IO.php @@ -303,6 +303,8 @@ class IO private string $query = ''; /** @var array current params for query */ private array $params = []; + /** @var string current hash build from query and params */ + private string $query_hash = ''; // if we do have a convert call, store the convert data in here, else it will be empty /** @var array{}|array{original:array{query:string,params:array},type:''|'named'|'numbered'|'question_mark',found:int,matches:array,params_lookup:array,query:string,params:array} */ private array $placeholder_converted = []; @@ -1319,7 +1321,7 @@ class IO */ private function __dbCountQueryParams(string $query): int { - return $this->db_functions->__dbCountQueryParams($query); + return count($this->db_functions->__dbGetQueryParams($query)); } /** @@ -1382,6 +1384,8 @@ class IO $this->query = $query; // current params $this->params = $params; + // empty on new + $this->query_hash = ''; // no query set if (empty($this->query)) { $this->__dbError(11); @@ -1441,7 +1445,7 @@ class IO $this->returning_id = true; } // import protection, hash needed - $query_hash = $this->dbGetQueryHash($this->query, $this->params); + $query_hash = $this->dbBuildQueryHash($this->query, $this->params); // QUERY PARAMS: run query params check and rewrite if ($this->dbGetConvertPlaceholder() === true) { try { @@ -1475,7 +1479,8 @@ class IO return false; } } - + // set query hash + $this->query_hash = $query_hash; // $this->debug('DB IO', 'Q: ' . $this->query . ', RETURN: ' . $this->returning_id); // for DEBUG, only on first time ;) $this->__dbDebug( @@ -1959,7 +1964,7 @@ class IO { // set start array if ($query) { - $array = $this->cursor_ext[$this->dbGetQueryHash($query)] ?? []; + $array = $this->cursor_ext[$this->dbBuildQueryHash($query)] ?? []; } else { $array = $this->cursor_ext; } @@ -2361,7 +2366,7 @@ class IO return false; } // create hash from query ... - $query_hash = $this->dbGetQueryHash($query, $params); + $query_hash = $this->dbBuildQueryHash($query, $params); // pre declare array if (!isset($this->cursor_ext[$query_hash])) { $this->cursor_ext[$query_hash] = [ @@ -2940,7 +2945,7 @@ class IO public function dbCacheReset(string $query, array $params = []): bool { $this->__dbErrorReset(); - $query_hash = $this->dbGetQueryHash($query, $params); + $query_hash = $this->dbBuildQueryHash($query, $params); // clears cache for this query if (empty($this->cursor_ext[$query_hash]['query'])) { $this->__dbWarning(18, context: [ @@ -2982,7 +2987,7 @@ class IO if ($query === null) { return $this->cursor_ext; } - $query_hash = $this->dbGetQueryHash($query, $params); + $query_hash = $this->dbBuildQueryHash($query, $params); if ( !empty($this->cursor_ext) && isset($this->cursor_ext[$query_hash]) @@ -3012,7 +3017,7 @@ class IO $this->__dbError(11); return false; } - $query_hash = $this->dbGetQueryHash($query, $params); + $query_hash = $this->dbBuildQueryHash($query, $params); if ( !empty($this->cursor_ext) && isset($this->cursor_ext[$query_hash]) @@ -3038,7 +3043,7 @@ class IO $this->__dbError(11); return false; } - $query_hash = $this->dbGetQueryHash($query, $params); + $query_hash = $this->dbBuildQueryHash($query, $params); if ( !empty($this->cursor_ext) && isset($this->cursor_ext[$query_hash]) @@ -3064,7 +3069,7 @@ class IO */ public function dbResetQueryCalled(string $query, array $params = []): void { - $this->query_called[$this->dbGetQueryHash($query, $params)] = 0; + $this->query_called[$this->dbBuildQueryHash($query, $params)] = 0; } /** @@ -3077,7 +3082,7 @@ class IO */ public function dbGetQueryCalled(string $query, array $params = []): int { - $query_hash = $this->dbGetQueryHash($query, $params); + $query_hash = $this->dbBuildQueryHash($query, $params); if (!empty($this->query_called[$query_hash])) { return $this->query_called[$query_hash]; } else { @@ -4046,7 +4051,7 @@ class IO } /** - * Returns hash for query + * Creates hash for query and parameters * Hash is used in all internal storage systems for return data * * @param string $query The query to create the hash from @@ -4054,7 +4059,7 @@ class IO * data to create a unique call one, optional * @return string Hash, as set by hash long */ - public function dbGetQueryHash(string $query, array $params = []): string + public function dbBuildQueryHash(string $query, array $params = []): string { return Hash::hashLong( $query . ( @@ -4104,6 +4109,26 @@ class IO $this->params = []; } + /** + * get the current set query hash + * + * @return string Current Query hash + */ + public function dbGetQueryHash(): string + { + return $this->query_hash; + } + + /** + * reset query hash + * + * @return void + */ + public function dbResetQueryHash(): void + { + $this->query_hash = ''; + } + /** * Returns the placeholder convert set or empty * diff --git a/www/lib/CoreLibs/DB/SQL/Interface/SqlFunctions.php b/www/lib/CoreLibs/DB/SQL/Interface/SqlFunctions.php index 8ccfa9a6..5dda8fa9 100644 --- a/www/lib/CoreLibs/DB/SQL/Interface/SqlFunctions.php +++ b/www/lib/CoreLibs/DB/SQL/Interface/SqlFunctions.php @@ -379,9 +379,9 @@ interface SqlFunctions * Undocumented function * * @param string $query - * @return int + * @return array */ - public function __dbCountQueryParams(string $query): int; + public function __dbGetQueryParams(string $query): array; } // __END__ diff --git a/www/lib/CoreLibs/DB/SQL/PgSQL.php b/www/lib/CoreLibs/DB/SQL/PgSQL.php index 352b6a5e..c05195c2 100644 --- a/www/lib/CoreLibs/DB/SQL/PgSQL.php +++ b/www/lib/CoreLibs/DB/SQL/PgSQL.php @@ -978,7 +978,7 @@ class PgSQL implements Interface\SqlFunctions } /** - * Get the all the $ params, unique list + * Get the all the $ params, as a unique list * * @param string $query * @return array @@ -1004,17 +1004,6 @@ class PgSQL implements Interface\SqlFunctions ); return array_unique(array_filter($matches[ConvertPlaceholder::MATCHING_POS])); } - - /** - * Count placeholder queries. $ only - * - * @param string $query - * @return int - */ - public function __dbCountQueryParams(string $query): int - { - return count($this->__dbGetQueryParams($query)); - } } // __END__