DB IO Placeholder convert fixers and updates

Add more checks in phpunit for this,

Update the placeholder check and convert and move all regex into the
placeholder convert support class
Move $ placeholder count function to the SQL\PgSQL class

Note: further moves of PgSQL only stuff have to be done for SQLite
SQL class add
This commit is contained in:
Clemens Schwaighofer
2024-11-20 18:58:59 +09:00
parent 529b6a75ba
commit ae044bee6f
6 changed files with 728 additions and 194 deletions

View File

@@ -37,8 +37,9 @@ namespace tests;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use CoreLibs\Logging\Logger\Level;
use CoreLibs\Logging;
use CoreLibs\DB\Options\Convert;
use CoreLibs\DB\Support\ConvertPlaceholder;
/**
* Test class for DB\IO + DB\SQL\PgSQL
@@ -117,7 +118,7 @@ final class CoreLibsDBIOTest extends TestCase
);
}
// define basic connection set valid and one invalid
self::$log = new \CoreLibs\Logging\Logging([
self::$log = new Logging\Logging([
// 'log_folder' => __DIR__ . DIRECTORY_SEPARATOR . 'log',
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
'log_file_id' => 'CoreLibs-DB-IO-Test',
@@ -570,11 +571,11 @@ final class CoreLibsDBIOTest extends TestCase
);
$db->dbClose();
// second conenction with log set NOT debug
$log = new \CoreLibs\Logging\Logging([
$log = new Logging\Logging([
// 'log_folder' => __DIR__ . DIRECTORY_SEPARATOR . 'log',
'log_folder' => DIRECTORY_SEPARATOR . 'tmp',
'log_file_id' => 'CoreLibs-DB-IO-Test',
'log_level' => \CoreLibs\Logging\Logger\Level::Notice,
'log_level' => Logging\Logger\Level::Notice,
]);
$db = new \CoreLibs\DB\IO(
self::$db_config[$connection],
@@ -3293,6 +3294,7 @@ final class CoreLibsDBIOTest extends TestCase
'query' => 'INSERT INTO table_with_primary_key (row_int, uid) '
. 'VALUES ($1, $2) RETURNING table_with_primary_key_id',
'returning_id' => true,
'placeholder_converted' => [],
],
],
// update
@@ -3327,6 +3329,7 @@ final class CoreLibsDBIOTest extends TestCase
'query' => 'UPDATE table_with_primary_key SET row_int = $1, '
. 'row_varchar = $2 WHERE uid = $3',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// select
@@ -3356,6 +3359,7 @@ final class CoreLibsDBIOTest extends TestCase
'count' => 1,
'query' => 'SELECT row_int, uid FROM table_with_primary_key WHERE uid = $1',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// any query but with no parameters
@@ -3388,6 +3392,7 @@ final class CoreLibsDBIOTest extends TestCase
'count' => 0,
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// no statement name (25)
@@ -3411,6 +3416,7 @@ final class CoreLibsDBIOTest extends TestCase
'count' => 0,
'query' => '',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// no query (prepare 11)
@@ -3435,6 +3441,7 @@ final class CoreLibsDBIOTest extends TestCase
'count' => 0,
'query' => '',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// no db connection (prepare/execute 16)
@@ -3464,6 +3471,7 @@ final class CoreLibsDBIOTest extends TestCase
'count' => 0,
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// prepare with different statement name
@@ -3489,6 +3497,7 @@ final class CoreLibsDBIOTest extends TestCase
'count' => 0,
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'returning_id' => false,
'placeholder_converted' => [],
],
],
// insert wrong data count compared to needed (execute 23)
@@ -3514,10 +3523,12 @@ final class CoreLibsDBIOTest extends TestCase
'query' => 'INSERT INTO table_with_primary_key (row_int, uid) VALUES '
. '($1, $2) RETURNING table_with_primary_key_id',
'returning_id' => true,
'placeholder_converted' => [],
],
],
// execute does not return a result (22)
// TODO execute does not return a result
// TODO prepared statement with placeholder params auto convert
];
}
@@ -3662,7 +3673,7 @@ final class CoreLibsDBIOTest extends TestCase
}
// check dbGetPrepareCursorValue
foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) {
foreach (['pk_name', 'count', 'query', 'returning_id', 'placeholder_converted'] as $key) {
$this->assertEquals(
$prepare_cursor[$key],
$db->dbGetPrepareCursorValue($stm_name, $key),
@@ -5031,8 +5042,151 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbClose();
}
// query placeholder convert
// MARK: QUERY PLACEHOLDERS
// test query placeholder detection for all possible sets
// ::dbPrepare
/**
* placeholder sql
*
* @return array
*/
public function providerDbCountQueryParams(): array
{
return [
'one place holder' => [
'query' => 'SELECT row_varchar FROM table_with_primary_key WHERE row_varchar = $1',
'count' => 1,
'convert' => false,
],
'one place holder, json call' => [
'query' => "SELECT row_varchar FROM table_with_primary_key WHERE row_jsonb->>'data' = $1",
'count' => 1,
'convert' => false,
],
'one place holder, <> compare' => [
'query' => "SELECT row_varchar FROM table_with_primary_key WHERE row_varchar <> $1",
'count' => 1,
'convert' => false,
],
'one place holder, named' => [
'query' => "SELECT row_varchar FROM table_with_primary_key WHERE row_varchar <> :row_varchar",
'count' => 1,
'convert' => true,
],
'no replacement' => [
'query' => "SELECT row_varchar FROM table_with_primary_key WHERE row_varchar = '$1'",
'count' => 0,
'convert' => false,
],
'insert' => [
'query' => "INSERT INTO table_with_primary_key (row_varchar, row_jsonb, row_int) VALUES ($1, $2, $3)",
'count' => 3,
'convert' => false,
],
'update' => [
'query' => "UPDATE table_with_primary_key SET row_varchar = $1, row_jsonb = $2, row_int = $3 WHERE row_numeric = $4",
'count' => 4,
'convert' => false,
],
'multiple, multline' => [
'query' => <<<SQL
SELECT
row_varchar
FROM
table_with_primary_key
WHERE
row_varchar = $1 AND row_int = $2
AND row_numeric = ANY($3)
SQL,
'count' => 3,
'convert' => false,
],
'two digit numbers' => [
'query' => <<<SQL
INSERT INTO table_with_primary_key (
row_int, row_numeric, row_varchar, row_varchar_literal, row_json,
row_jsonb, row_bytea, row_timestamp, row_date, row_interval
) VALUES (
$1, $2, $3, $4, $5,
$6, $7, $8, $9, $10
)
SQL,
'count' => 10,
'convert' => false,
],
'things in brackets' => [
'query' => <<<SQL
SELECT row_varchar
FROM table_with_primary_key
WHERE
row_varchar = $1 AND
(row_int = ANY($2) OR row_int = $3)
AND row_varchar_literal = $4
SQL,
'count' => 4,
'convert' => false,
],
'number compare' => [
'query' => <<<SQL
SELECT row_varchar
FROM table_with_primary_key
WHERE
row_int >= $1 OR row_int <= $2 OR
row_int > $3 OR row_int < $4
OR row_int = $5 OR row_int <> $6
SQL,
'count' => 6,
'convert' => false,
]
];
}
/**
* Placeholder check and convert tests
*
* @covers ::dbPrepare
* @covers ::__dbCountQueryParams
* @onvers ::convertPlaceholderInQuery
* @dataProvider providerDbCountQueryParams
* @testdox Query replacement count test [$_dataName]
*
* @param string $query
* @param int $count
* @return void
*/
public function testDbCountQueryParams(string $query, int $count, bool $convert): void
{
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
);
$id = sha1($query);
$db->dbSetConvertPlaceholder($convert);
$db->dbPrepare($id, $query);
// print "\n**\n";
// print "PCount: " . $db->dbGetPrepareCursorValue($id, 'count') . "\n";
// print "\n**\n";
$this->assertEquals(
$count,
$db->dbGetPrepareCursorValue($id, 'count'),
'DB count params'
);
$placeholder = ConvertPlaceholder::convertPlaceholderInQuery($query, null, 'pg');
// print "RES: " . print_r($placeholder, true) . "\n";
$this->assertEquals(
$count,
$placeholder['needed'],
'convert params'
);
}
/**
* query placeholder convert
*
* @return array
*/
public function queryPlaceholderReplaceProvider(): array
{
// WHERE row_varchar = $1
@@ -5076,7 +5230,9 @@ final class CoreLibsDBIOTest extends TestCase
WHERE row_varchar = $1
SQL,
'expected_params' => ['string a'],
]
],
// TODO: test with multiple entries
// TODO: test with same entry ($1, $1, :var, :var)
];
}
@@ -5178,6 +5334,8 @@ final class CoreLibsDBIOTest extends TestCase
// - data debug
// dbDumpData
// MARK: ASYNC
// ASYNC at the end because it has 1s timeout
// - asynchronous executions
// dbExecAsync, dbCheckAsync