From 5a0b09a9169a229ec4c8898aa1051e9e1e4a371c Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Thu, 5 Jan 2023 17:26:26 +0900 Subject: [PATCH] Add DB\IO get prepare cursor array entries --- 4dev/tests/CoreLibsDBIOTest.php | 170 ++++++++++++++++++++++++++++++-- www/admin/class_test.db.php | 5 + www/lib/CoreLibs/DB/IO.php | 59 +++++++++++ 3 files changed, 227 insertions(+), 7 deletions(-) diff --git a/4dev/tests/CoreLibsDBIOTest.php b/4dev/tests/CoreLibsDBIOTest.php index 1f74c0f6..4f843e73 100644 --- a/4dev/tests/CoreLibsDBIOTest.php +++ b/4dev/tests/CoreLibsDBIOTest.php @@ -2770,7 +2770,7 @@ final class CoreLibsDBIOTest extends TestCase } // - prepared query execute - // dbPrepare, dbExecute, dbFetchArray + // dbPrepare, dbExecute, dbFetchArray, dbGetPrepareCursorValue /** * Undocumented function @@ -2795,6 +2795,7 @@ final class CoreLibsDBIOTest extends TestCase // 11: read query (if insert/update) // 11: execute data to check (array) // 12: insert data + // 13: prepated cursor array data match values return [ // insert 'prepare query insert' => [ @@ -2818,6 +2819,14 @@ final class CoreLibsDBIOTest extends TestCase ], // insert data (for select) '', + // get prepared data + [ + 'pk_name' => 'table_with_primary_key_id', + 'count' => 2, + 'query' => 'INSERT INTO table_with_primary_key (row_int, uid) ' + . 'VALUES ($1, $2) RETURNING table_with_primary_key_id', + 'returning_id' => true, + ], ], // update 'prepare query update' => [ @@ -2844,6 +2853,14 @@ final class CoreLibsDBIOTest extends TestCase // "INSERT INTO table_with_primary_key (row_int, uid) VALUES " . "(111, 'TEST A')", + // + [ + 'pk_name' => '', + 'count' => 3, + 'query' => 'UPDATE table_with_primary_key SET row_int = $1, ' + . 'row_varchar = $2 WHERE uid = $3', + 'returning_id' => false, + ], ], // select 'prepare select query' => [ @@ -2865,7 +2882,14 @@ final class CoreLibsDBIOTest extends TestCase ], ], // - $insert_query + $insert_query, + // + [ + 'pk_name' => '', + 'count' => 1, + 'query' => 'SELECT row_int, uid FROM table_with_primary_key WHERE uid = $1', + 'returning_id' => false, + ], ], // any query but with no parameters 'prepare select query no parameter' => [ @@ -2890,7 +2914,14 @@ final class CoreLibsDBIOTest extends TestCase ], ], // - $insert_query + $insert_query, + // + [ + 'pk_name' => '', + 'count' => 0, + 'query' => 'SELECT row_int, uid FROM table_with_primary_key', + 'returning_id' => false, + ], ], // no statement name (25) 'empty statement' => [ @@ -2907,6 +2938,13 @@ final class CoreLibsDBIOTest extends TestCase [], // '', + // + [ + 'pk_name' => '', + 'count' => 0, + 'query' => '', + 'returning_id' => false, + ], ], // no query (prepare 11) // no prepared cursor found with statement name (execute 24) @@ -2924,6 +2962,13 @@ final class CoreLibsDBIOTest extends TestCase [], // '', + // + [ + 'pk_name' => '', + 'count' => 0, + 'query' => '', + 'returning_id' => false, + ], ], // no db connection (prepare/execute 16) // TODO no db connection test @@ -2944,8 +2989,15 @@ final class CoreLibsDBIOTest extends TestCase // no query but data for data only compare '', [], - //, - $insert_query + // + $insert_query, + // + [ + 'pk_name' => '', + 'count' => 0, + 'query' => 'SELECT row_int, uid FROM table_with_primary_key', + 'returning_id' => false, + ], ], // insert wrong data count compared to needed (execute 23) 'wrong parmeter count' => [ @@ -2962,7 +3014,15 @@ final class CoreLibsDBIOTest extends TestCase '', [], // - '' + '', + // + [ + 'pk_name' => 'table_with_primary_key_id', + 'count' => 2, + 'query' => 'INSERT INTO table_with_primary_key (row_int, uid) VALUES ' + . '($1, $2) RETURNING table_with_primary_key_id', + 'returning_id' => true, + ], ], // execute does not return a result (22) // TODO execute does not return a result @@ -2975,6 +3035,7 @@ final class CoreLibsDBIOTest extends TestCase * @covers ::dbPrepare * @covers ::dbExecute * @covers ::dbFetchArray + * @covers ::dbGetPrepareCursorValue * @dataProvider preparedProvider * @testdox prepared query $stm_name with $expected_prepare (warning $warning_prepare/error $error_prepare) and $expected_execute (warning $warning_execute/error $error_execute) [$_dataName] * @@ -2991,6 +3052,7 @@ final class CoreLibsDBIOTest extends TestCase * @param string $expected_data_query * @param array $expected_data * @param string $insert_data + * @param array $prepare_cursor * @return void */ public function testDbPrepared( @@ -3006,7 +3068,8 @@ final class CoreLibsDBIOTest extends TestCase string $error_execute, string $expected_data_query, array $expected_data, - string $insert_data + string $insert_data, + array $prepare_cursor, ): void { // self::$log->setLogLevelAll('debug', true); // self::$log->setLogLevelAll('print', true); @@ -3116,6 +3179,15 @@ final class CoreLibsDBIOTest extends TestCase ); } + // check dbGetPrepareCursorValue + foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) { + $this->assertEquals( + $prepare_cursor[$key], + $db->dbGetPrepareCursorValue($stm_name, $key), + 'Prepared cursor: ' . $key . ': failed assertion' + ); + } + // reset all data $db->dbExec("TRUNCATE table_with_primary_key"); $db->dbExec("TRUNCATE table_without_primary_key"); @@ -3123,6 +3195,90 @@ final class CoreLibsDBIOTest extends TestCase $db->dbClose(); } + // dedicated error checks for prepare cursor return + + /** + * Undocumented function + * + * @return array + */ + public function preparedProviderValue(): array + { + // 1: query (can be empty for do not set) + // 2: stm name + // 3: key + // 4: expected error return + return [ + 'no error' => [ + "SELECT row_int, uid FROM table_with_primary_key", + 'read', + 'pk_name', + '' + ], + 'statement name empty' => [ + '', + '', + '', + '101', + ], + 'key empty' => [ + '', + 'read', + '', + '102', + ], + 'key invalid' => [ + '', + 'read', + 'invalid', + '102', + ], + 'statement name not found' => [ + '', + 'invalid', + 'pk_name', + '103', + ], + ]; + } + + /** + * test return prepare cursor errors + * + * @covers ::dbGetPrepareCursorValue + * @dataProvider preparedProviderValue + * @testdox prepared query $stm_name with $key expect error id $error_id [$_dataName] + * + * @param string $query + * @param string $stm_name + * @param string $key + * @param string $error_id + * @return void + */ + public function testDbGetPrepareCursorValue( + string $query, + string $stm_name, + string $key, + $error_id + ): void { + $db = new \CoreLibs\DB\IO( + self::$db_config['valid'], + self::$log + ); + if (!empty($query)) { + $db->dbPrepare($stm_name, $query); + $db->dbExecute($stm_name); + } + $db->dbGetPrepareCursorValue($stm_name, $key); + // match check error + $last_error = $db->dbGetLastError(); + $this->assertEquals( + $error_id, + $last_error, + 'get prepare cursor value error check' + ); + } + // - schema set/get tests // dbGetSchema, dbSetSchema diff --git a/www/admin/class_test.db.php b/www/admin/class_test.db.php index ee19d98a..1634f651 100644 --- a/www/admin/class_test.db.php +++ b/www/admin/class_test.db.php @@ -145,6 +145,11 @@ print "PREPARE INSERT[ins_test_foo] STATUS: " . Support::printToString($status) print "PREPARE INSERT PREVIOUS INSERTED: " . print_r($db->dbReturnRow("SELECT test_foo_id, test FROM test_foo " . "WHERE test_foo_id = " . $db->dbGetInsertPK()), true) . "
"; + +print "PREPARE CURSOR RETURN:
"; +foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) { + print "KEY: " . $key . ': ' . $db->dbGetPrepareCursorValue('ins_test_foo', $key) . "
"; +} // returning test with multiple entries // $status = $db->db_exec( // "INSERT INTO test_foo (test) VALUES " diff --git a/www/lib/CoreLibs/DB/IO.php b/www/lib/CoreLibs/DB/IO.php index 540e4a92..b55b7259 100644 --- a/www/lib/CoreLibs/DB/IO.php +++ b/www/lib/CoreLibs/DB/IO.php @@ -452,6 +452,11 @@ class IO '71' => 'Failed to set search path/schema', '80' => 'Trying to set an empty encoding', '81' => 'Failed to set client encoding', + // for prepared cursor return + '101' => 'Statement name empty for get prepare cursor', + '102' => 'Key empty for get prepare cursir', + '103' => 'No prepared cursor with this name', + '104' => 'No Key with this name in the prepared cursor array' ]; // load the core DB functions wrapper class @@ -3066,6 +3071,60 @@ class IO return $this->field_names; } + /** + * Returns the value for given key in statement + * Will write error if statemen id does not exist + * or key is invalid + * + * @param string $stm_name The name of the stored statement + * @param string $key Key field name in prepared cursor array + * Allowed are: pk_name, count, query, returning_id + * @return null|string|int|bool Entry from each of the valid keys + * Will return false on error + * Not ethat returnin_id also can return false + * but will not set an error entry + */ + public function dbGetPrepareCursorValue(string $stm_name, string $key) + { + // if no statement name + if (empty($stm_name)) { + $this->__dbError( + 101, + false, + 'No statement name given' + ); + return false; + } + // if not a valid key + if (!in_array($key, ['pk_name', 'count', 'query', 'returning_id'])) { + $this->__dbError( + 102, + false, + 'Invalid key name' + ); + return false; + } + // statement name not in prepared list + if (empty($this->prepare_cursor[$stm_name])) { + $this->__dbError( + 103, + false, + 'Statement name does not exist in prepare cursor array' + ); + return false; + } + // key doest not exists, this will never hit as we filter out invalid ones + if (!isset($this->prepare_cursor[$stm_name][$key])) { + $this->__dbError( + 104, + false, + 'Key does not exist in prepare cursor array' + ); + return false; + } + return $this->prepare_cursor[$stm_name][$key]; + } + // *************************** // ERROR AND WARNING DATA // ***************************