Compare commits

...

4 Commits

Author SHA1 Message Date
Clemens Schwaighofer
bcde36ac17 DB IO Cache reset should not be an error
If the query is not found, do not throw an error, just show a warning
2025-01-20 10:45:31 +09:00
Clemens Schwaighofer
8bde34ec7d Fix bug in DB IO prepared statement with INSERT and auto RETURNING add
INSERT will get a RETURNING added automatically if it has a primary key
This was not checked when query was compared for prepared statements.

Also added a prepared statement status checker
2025-01-17 17:52:41 +09:00
Clemens Schwaighofer
a345d71306 De-depricate the ACL Login loginCheckEditAccessId method
This is still used a lot, and there is no reason to deprecate it so early.

First all the other logic should be brought in to make this an easy
conversion.
2025-01-17 14:43:13 +09:00
Clemens Schwaighofer
0ff6294faa Fix ACL Login cuid <-> id pk lookups
Used the wrong SESSION var for lookup
2025-01-17 14:34:41 +09:00
6 changed files with 200 additions and 10 deletions

View File

@@ -3692,7 +3692,7 @@ final class CoreLibsDBIOTest extends TestCase
*
* @return array
*/
public function preparedProviderValue(): array
public function providerDbGetPrepareCursorValue(): array
{
// 1: query (can be empty for do not set)
// 2: stm name
@@ -3736,7 +3736,7 @@ final class CoreLibsDBIOTest extends TestCase
* test return prepare cursor errors
*
* @covers ::dbGetPrepareCursorValue
* @dataProvider preparedProviderValue
* @dataProvider providerDbGetPrepareCursorValue
* @testdox prepared query $stm_name with $key expect error id $error_id [$_dataName]
*
* @param string $query
@@ -3769,6 +3769,94 @@ final class CoreLibsDBIOTest extends TestCase
);
}
/**
* Undocumented function
*
* @return array
*/
public function providerDbPreparedCursorStatus(): array
{
return [
'empty statement pararm' => [
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'stm_name' => 'test_stm_a',
'check_stm_name' => '',
'check_query' => '',
'expected' => false
],
'different stm_name' => [
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'stm_name' => 'test_stm_b',
'check_stm_name' => 'other_name',
'check_query' => '',
'expected' => 0
],
'same stm_name' => [
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'stm_name' => 'test_stm_c',
'check_stm_name' => 'test_stm_c',
'check_query' => '',
'expected' => 1
],
'same stm_name and query' => [
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'stm_name' => 'test_stm_d',
'check_stm_name' => 'test_stm_d',
'check_query' => 'SELECT row_int, uid FROM table_with_primary_key',
'expected' => 2
],
'same stm_name and different query' => [
'query' => 'SELECT row_int, uid FROM table_with_primary_key',
'stm_name' => 'test_stm_e',
'check_stm_name' => 'test_stm_e',
'check_query' => 'SELECT row_int, uid, row_int FROM table_with_primary_key',
'expected' => 1
],
'insert query test' => [
'query' => 'INSERT INTO table_with_primary_key (row_int, uid) VALUES ($1, $2)',
'stm_name' => 'test_stm_f',
'check_stm_name' => 'test_stm_f',
'check_query' => 'INSERT INTO table_with_primary_key (row_int, uid) VALUES ($1, $2)',
'expected' => 2
]
];
}
/**
* test cursor status for prepared statement
*
* @covers ::dbPreparedCursorStatus
* @dataProvider providerDbPreparedCursorStatus
* @testdox Check prepared $stm_name ($check_stm_name) status is $expected [$_dataName]
*
* @param string $query
* @param string $stm_name
* @param string $check_stm_name
* @param string $check_query
* @param bool|int $expected
* @return void
*/
public function testDbPreparedCursorStatus(
string $query,
string $stm_name,
string $check_stm_name,
string $check_query,
bool|int $expected
): void {
$db = new \CoreLibs\DB\IO(
self::$db_config['valid'],
self::$log
);
$db->dbPrepare($stm_name, $query);
// $db->dbExecute($stm_name);
$this->assertEquals(
$expected,
$db->dbPreparedCursorStatus($check_stm_name, $check_query),
'check prepared stement cursor status'
);
unset($db);
}
// - schema set/get tests
// dbGetSchema, dbSetSchema

View File

@@ -707,6 +707,17 @@ if (
} else {
print "[PGB] [3] pgb_sel_test_foo prepare OK<br>";
}
$stm_status = $db->dbPreparedCursorStatus('');
print "[PGB] Empty statement name: " . $log->prAr($stm_status) . "<br>";
$stm_status = $db->dbPreparedCursorStatus('pgb_sel_test_foobar');
print "[PGB] Prepared name not match status: $stm_status<br>";
$stm_status = $db->dbPreparedCursorStatus('pgb_sel_test_foo');
print "[PGB] Prepared name match status: $stm_status<br>";
$stm_status = $db->dbPreparedCursorStatus('pgb_sel_test_foo', $q_prep);
print "[PGB] prepared exists and query match status: $stm_status<br>";
$stm_status = $db->dbPreparedCursorStatus('pgb_sel_test_foo', "SELECT * FROM test_foo");
print "[PGB] prepared exists and query not match status: $stm_status<br>";
$db_pgb->dbClose();
# db write class test

View File

@@ -57,6 +57,51 @@ fclose($fp);
$out = \CoreLibs\DeprecatedHelper\Deprecated84::str_getcsv("A,B,C");
print "str_getcsv: <pre>" . print_r($out, true) . "</pre>";
/**
* temporary different CSV function, because fgetcsv seems to be broken on some systems
* (does not read out japanese text)
*
* @param string $string full line for csv split
* @param string $encoding optional, if given, converts string to the internal encoding
* before we do anything
* @param string $delimiter sepperate character, default ','
* @param string $enclosure string line marker, default '"'
* @param string $flag INTERN | EXTERN. if INTERN uses the PHP function, else uses explode
* @return array<int,string|null> array with split data from input line
*/
function mtParseCSV(
string $string,
string $encoding = '',
string $delimiter = ',',
string $enclosure = '"',
string $flag = 'INTERN'
): array {
$lines = [];
if ($encoding) {
$string = \CoreLibs\Convert\Encoding::convertEncoding(
$string,
'UTF-8',
$encoding
);
}
if ($flag == 'INTERN') {
// split with PHP function
$lines = str_getcsv($string, $delimiter, $enclosure);
} else {
// split up with delimiter
$lines = explode(',', $string) ?: [];
}
// strip " from beginning and end of line
for ($i = 0; $i < count($lines); $i++) {
// remove line breaks
$lines[$i] = preg_replace("/\r\n?/", '', (string)$lines[$i]) ?? '';
// lingering " at the beginning and end of the line
$lines[$i] = preg_replace("/^\"/", '', (string)$lines[$i]) ?? '';
$lines[$i] = preg_replace("/\"$/", '', (string)$lines[$i]) ?? '';
}
return $lines;
}
print "</body></html>";
// __END__

View File

@@ -117,7 +117,7 @@ if (isset($login->loginGetAcl()['unit'])) {
if ($login->loginCheckEditAccessCuid($edit_access_cuid)) {
print "Set new:" . $edit_access_cuid . "<br>";
} else {
print "Load default unit id: " . $login->loginGetAcl()['unit_id'] . "<br>";
print "Load default unit id: " . $login->loginGetAcl()['unit_cuid'] . "<br>";
}
} else {
print "Something went wrong with the login<br>";
@@ -140,4 +140,17 @@ $login->writeLog(
write_type:'JSON'
);
echo "<hr>";
print "<h3>Legacy Lookups</h3>";
$edit_access_id = 1;
$edit_access_cuid = $login->loginGetEditAccessCuidFromId($edit_access_id);
$edit_access_id_rev = null;
if (is_string($edit_access_cuid)) {
$edit_access_id_rev = $login->loginGetEditAccessIdFromCuid($edit_access_cuid);
}
print "EA ID: " . $edit_access_id . "<br>";
print "EA CUID: " . $log->prAr($edit_access_cuid) . "<br>";
print "REV EA CUID: " . $log->prAr($edit_access_id_rev) . "<br>";
print "</body></html>";

View File

@@ -3217,7 +3217,7 @@ HTML;
* @return int|null same edit access id if ok
* or the default edit access id
* if given one is not valid
* @deprecated Please switch to using edit access cuid check with ->loginCheckEditAccessValidCuid()
* @#deprecated Please switch to using edit access cuid check with ->loginCheckEditAccessValidCuid()
*/
public function loginCheckEditAccessId(?int $edit_access_id): ?int
{
@@ -3290,10 +3290,10 @@ HTML;
*/
public function loginGetEditAccessCuidFromId(int $id): string|false
{
if (!isset($_SESSION['LOGIN_UNIT_ACL_LEVEL'][$id])) {
if (!isset($_SESSION['LOGIN_UNIT_LEGACY'][$id])) {
return false;
}
return (string)$_SESSION['LOGIN_UNIT_ACL_LEVEL'][$id]['cuid'];
return (string)$_SESSION['LOGIN_UNIT_LEGACY'][$id]['cuid'];
}
/**
@@ -3304,10 +3304,10 @@ HTML;
*/
public function loginGetEditAccessIdFromCuid(string $cuid): int|false
{
if (!isset($_SESSION['LOGIN_UNIT_LEGACY'][$cuid])) {
if (!isset($_SESSION['LOGIN_UNIT'][$cuid])) {
return false;
}
return $_SESSION['LOGIN_UNIT_LEGACY'][$cuid];
return $_SESSION['LOGIN_UNIT'][$cuid]['id'];
}
/**

View File

@@ -2946,7 +2946,7 @@ class IO
$query_hash = $this->dbGetQueryHash($query, $params);
// clears cache for this query
if (empty($this->cursor_ext[$query_hash]['query'])) {
$this->__dbError(18, context: [
$this->__dbWarning(18, context: [
'query' => $query,
'params' => $params,
'hash' => $query_hash,
@@ -3141,6 +3141,7 @@ class IO
'pk_name' => '',
'count' => 0,
'query' => '',
'query_raw' => $query,
'result' => null,
'returning_id' => false,
'placeholder_converted' => [],
@@ -3237,11 +3238,12 @@ class IO
}
} else {
// if we try to use the same statement name for a differnt query, error abort
if ($this->prepare_cursor[$stm_name]['query'] != $query) {
if ($this->prepare_cursor[$stm_name]['query_raw'] != $query) {
// thrown error
$this->__dbError(26, false, context: [
'statement_name' => $stm_name,
'prepared_query' => $this->prepare_cursor[$stm_name]['query'],
'prepared_query_raw' => $this->prepare_cursor[$stm_name]['query_raw'],
'query' => $query,
'pk_name' => $pk_name,
]);
@@ -4364,6 +4366,37 @@ class IO
return $this->prepare_cursor[$stm_name][$key];
}
/**
* Checks if a prepared query eixsts
*
* @param string $stm_name Statement to check
* @param string $query [default=''] If set then query must also match
* @return false|int<0,2> False on missing stm_name
* 0: ok, 1: stm_name matchin, 2: stm_name and query matching
*/
public function dbPreparedCursorStatus(string $stm_name, string $query = ''): false|int
{
if (empty($stm_name)) {
$this->__dbError(
101,
false,
'No statement name given'
);
return false;
}
// does not exist
$return_value = 0;
if (!empty($this->prepare_cursor[$stm_name]['query_raw'])) {
// statement name eixts
$return_value = 1;
if ($this->prepare_cursor[$stm_name]['query_raw'] == $query) {
// query also matches
$return_value = 2;
}
}
return $return_value;
}
// ***************************
// ERROR AND WARNING DATA
// ***************************