DB\IO Class updates, other Class fixes
Output\Form\Generate and ACL\Login have DB\IO method call name changes for pos/num rows methods. Use proper methods and not use the cursor full return check method DB\IO: Switched to new conenction busy check with sockt and timeout loop. So short blocked and psql error blocked ones are not blocking other calls. Moved the dbReturn cache read to a separte private method and cleaned up code for more clear view Moved all query hash creations to method to simple change hash creatio if needed. This method can be used for external correct query hash creation if needed. Variable name and code block clean up in dbReturn No data return (dbReturn or dbFetchArray) will change returned data row. Return as is. Moved methods around in code to group them together for next stage in sub class creation (planned) Renamed dbCursorPos to dbGetCursorPos and dbCursorNumRows to dbGetCursorNumRows Work on phpunit tests for DB\IO
This commit is contained in:
@@ -270,6 +270,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
// 0: connection array
|
||||
// 1: status after connection
|
||||
// 2: info string
|
||||
// 3: ???
|
||||
return [
|
||||
'invalid connection' => [
|
||||
self::$db_config['invalid'],
|
||||
@@ -413,18 +414,12 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
self::$db_config[$connection],
|
||||
self::$log
|
||||
);
|
||||
if ($set === null) {
|
||||
// equals to do nothing
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$db->dbSetDebug()
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$set === null ?
|
||||
$db->dbSetDebug() :
|
||||
$db->dbSetDebug($set)
|
||||
);
|
||||
}
|
||||
);
|
||||
// must always match
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
@@ -452,18 +447,12 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
self::$db_config[$connection],
|
||||
self::$log
|
||||
);
|
||||
if ($toggle === null) {
|
||||
// equals to do nothing
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$db->dbToggleDebug()
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$toggle === null ?
|
||||
$db->dbToggleDebug() :
|
||||
$db->dbToggleDebug($toggle)
|
||||
);
|
||||
}
|
||||
);
|
||||
// must always match
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
@@ -557,7 +546,10 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_flag,
|
||||
$db->dbSetMaxQueryCall($max_calls)
|
||||
// TODO special test with null call too
|
||||
$max_calls === null ?
|
||||
$db->dbSetMaxQueryCall() :
|
||||
$db->dbSetMaxQueryCall($max_calls)
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected_max_calls,
|
||||
@@ -615,6 +607,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
// 'UTF8'
|
||||
// ],
|
||||
// other tests includ perhaps mocking for error?
|
||||
// TODO actual data check
|
||||
];
|
||||
}
|
||||
|
||||
@@ -732,28 +725,33 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
return [
|
||||
'source "t" to true' => [
|
||||
't',
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'source "t" to true null flag' => [
|
||||
't',
|
||||
null,
|
||||
true,
|
||||
false
|
||||
],
|
||||
'source "true" to true' => [
|
||||
'true',
|
||||
false,
|
||||
true,
|
||||
false
|
||||
],
|
||||
'source "f" to false' => [
|
||||
'f',
|
||||
false,
|
||||
false
|
||||
false,
|
||||
],
|
||||
'source "false" to false' => [
|
||||
'false',
|
||||
false,
|
||||
false
|
||||
false,
|
||||
],
|
||||
'source anything to true' => [
|
||||
'something',
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
],
|
||||
'source empty to false' => [
|
||||
'',
|
||||
@@ -762,13 +760,13 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
],
|
||||
'source bool true to "t"' => [
|
||||
true,
|
||||
't',
|
||||
true,
|
||||
't',
|
||||
],
|
||||
'source bool false to "f"' => [
|
||||
false,
|
||||
'f',
|
||||
true,
|
||||
'f',
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -781,11 +779,11 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
* @testdox Have $source and convert ($reverse) to $expected [$_dataName]
|
||||
*
|
||||
* @param string|bool $source
|
||||
* @param bool|null $reverse
|
||||
* @param string|bool $expected
|
||||
* @param bool $reverse
|
||||
* @return void
|
||||
*/
|
||||
public function testDbBoolean($source, $expected, bool $reverse): void
|
||||
public function testDbBoolean($source, ?bool $reverse, $expected): void
|
||||
{
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
@@ -793,7 +791,9 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$db->dbBoolean($source, $reverse)
|
||||
$reverse === null ?
|
||||
$db->dbBoolean($source) :
|
||||
$db->dbBoolean($source, $reverse)
|
||||
);
|
||||
$db->dbClose();
|
||||
}
|
||||
@@ -818,6 +818,11 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
false,
|
||||
'41 years 9 mons 18 days'
|
||||
],
|
||||
'interval a null micro time' => [
|
||||
'41 years 9 mons 18 days',
|
||||
null,
|
||||
'41 years 9 mons 18 days'
|
||||
],
|
||||
'interval a-1' => [
|
||||
'41 years 9 mons 18 days 12:31:11',
|
||||
false,
|
||||
@@ -879,11 +884,11 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
* @testdox Have $source and convert ($show_micro) to $expected [$_dataName]
|
||||
*
|
||||
* @param string $source
|
||||
* @param bool $show_micro
|
||||
* @param bool|null $show_micro
|
||||
* @param string $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testDbTimeFormat(string $source, bool $show_micro, string $expected): void
|
||||
public function testDbTimeFormat(string $source, ?bool $show_micro, string $expected): void
|
||||
{
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
@@ -891,7 +896,9 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
);
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$db->dbTimeFormat($source, $show_micro)
|
||||
$show_micro === null ?
|
||||
$db->dbTimeFormat($source) :
|
||||
$db->dbTimeFormat($source, $show_micro)
|
||||
);
|
||||
$db->dbClose();
|
||||
}
|
||||
@@ -1232,6 +1239,38 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
]
|
||||
]
|
||||
],
|
||||
'simple table null schema' => [
|
||||
'test_meta',
|
||||
null,
|
||||
[
|
||||
'row_1' => [
|
||||
'num' => 1,
|
||||
'type' => 'varchar',
|
||||
'len' => -1,
|
||||
'not null' => false,
|
||||
'has default' => false,
|
||||
'array dims' => 0,
|
||||
'is enum' => false,
|
||||
'is base' => 1,
|
||||
'is composite' => false,
|
||||
'is pesudo' => false,
|
||||
'description' => '',
|
||||
],
|
||||
'row_2' => [
|
||||
'num' => 2,
|
||||
'type' => 'int4',
|
||||
'len' => 4,
|
||||
'not null' => false,
|
||||
'has default' => false,
|
||||
'array dims' => 0,
|
||||
'is enum' => false,
|
||||
'is base' => 1,
|
||||
'is composite' => false,
|
||||
'is pesudo' => false,
|
||||
'description' => '',
|
||||
]
|
||||
]
|
||||
],
|
||||
'table does not exist' => [
|
||||
'non_existing',
|
||||
'public',
|
||||
@@ -1248,11 +1287,11 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
* @testdox Check table $table in schema $schema with $expected [$_dataName]
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $schema
|
||||
* @param string|null $schema
|
||||
* @param array<mixed>|bool $expected
|
||||
* @return void
|
||||
*/
|
||||
public function testDbShowTableMetaData(string $table, string $schema, $expected): void
|
||||
public function testDbShowTableMetaData(string $table, ?string $schema, $expected): void
|
||||
{
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
@@ -1263,14 +1302,16 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$db->dbShowTableMetaData($table, $schema)
|
||||
$schema === null ?
|
||||
$db->dbShowTableMetaData($table) :
|
||||
$db->dbShowTableMetaData($table, $schema)
|
||||
);
|
||||
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// - db exec test for insert/update/select/etc
|
||||
// dbExec
|
||||
// dbExec, dbResetQueryCalled, dbGetQueryCalled
|
||||
|
||||
/**
|
||||
* provide queries with return results
|
||||
@@ -1280,7 +1321,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
public function queryDbExecProvider(): array
|
||||
{
|
||||
// 0: query
|
||||
// 1: optional primary key name
|
||||
// 1: optional primary key name, null for empty test
|
||||
// 2: expectes result (bool, object (>=8.1)/resource (<8.1))
|
||||
// 3: warning
|
||||
// 4: error
|
||||
@@ -1294,6 +1335,14 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
'',
|
||||
'',
|
||||
],
|
||||
// insert but null primary key
|
||||
'table with pk insert null' => [
|
||||
'INSERT INTO table_with_primary_key (row_date) VALUES (NOW())',
|
||||
null,
|
||||
'resource/object',
|
||||
'',
|
||||
'',
|
||||
],
|
||||
// insert to table with no pk (31?)
|
||||
'table with no pk insert' => [
|
||||
'INSERT INTO table_without_primary_key (row_date) VALUES (NOW())',
|
||||
@@ -1378,6 +1427,7 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
// NOTE: After an error was encountered, queries after this
|
||||
// will return a true connection busy although it was error
|
||||
// https://bugs.php.net/bug.php?id=36469
|
||||
// TODO: fix wron error 42 after error insert
|
||||
'invalid returning' => [
|
||||
'INSERT INTO table_with_primary_key (row_date) VALUES (NOW()) RETURNING invalid',
|
||||
'',
|
||||
@@ -1394,24 +1444,29 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
* tests (internal read data post exec group)
|
||||
*
|
||||
* @covers ::dbExec
|
||||
* @covers ::dbGetQueryCalled
|
||||
* @covers ::dbResetQueryCalled
|
||||
* @dataProvider queryDbExecProvider
|
||||
* @testdox dbExec $query and pk $pk_name with $expected_return (Warning: $warning/Error: $error) [$_dataName]
|
||||
*
|
||||
* @param string $query
|
||||
* @param string $pk_name
|
||||
* @param [type] $expected_return
|
||||
* @param string|null $pk_name
|
||||
* @param object|resource|bool $expected_return
|
||||
* @param string $warning
|
||||
* @param string $error
|
||||
* @param bool $run_many_times
|
||||
* @return void
|
||||
*/
|
||||
public function testDbExec(
|
||||
string $query,
|
||||
string $pk_name,
|
||||
?string $pk_name,
|
||||
$expected_return,
|
||||
string $warning,
|
||||
string $error,
|
||||
bool $run_many_times = false
|
||||
): void {
|
||||
self::$log->setLogLevelAll('debug', true);
|
||||
self::$log->setLogLevelAll('print', true);
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
self::$log
|
||||
@@ -1428,58 +1483,621 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
$this->assertEquals(
|
||||
$expected_return,
|
||||
// supress ANY errors here
|
||||
@$db->dbExec($query, $pk_name)
|
||||
$pk_name === null ?
|
||||
@$db->dbExec($query) :
|
||||
@$db->dbExec($query, $pk_name)
|
||||
);
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
} else {
|
||||
// if PHP or newer, must be Object PgSql\Result
|
||||
if (\CoreLibs\Check\PhpVersion::checkPHPVersion('8.1')) {
|
||||
$result = $pk_name === null ?
|
||||
$db->dbExec($query) :
|
||||
$db->dbExec($query, $pk_name);
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
$this->assertIsObject(
|
||||
$db->dbExec($query, $pk_name)
|
||||
$result
|
||||
);
|
||||
// also check that this is correct instance type
|
||||
$this->assertInstanceOf(
|
||||
'PgSql\Result',
|
||||
$db->dbExec($query, $pk_name)
|
||||
$result
|
||||
);
|
||||
} else {
|
||||
$this->assertIsResource(
|
||||
$db->dbExec($query, $pk_name)
|
||||
$pk_name === null ?
|
||||
$db->dbExec($query) :
|
||||
$db->dbExec($query, $pk_name)
|
||||
);
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
}
|
||||
}
|
||||
// if we have more than one run time
|
||||
// re-run same query and then catch error
|
||||
if ($run_many_times) {
|
||||
for ($i = 1; $i <= $db->dbGetMaxQueryCall() + 1; $i++) {
|
||||
$db->dbExec($query, $pk_name);
|
||||
$pk_name === null ?
|
||||
$db->dbExec($query) :
|
||||
$db->dbExec($query, $pk_name);
|
||||
}
|
||||
// will fail now
|
||||
$this->assertFalse(
|
||||
$db->dbExec($query, $pk_name)
|
||||
$pk_name === null ?
|
||||
$db->dbExec($query) :
|
||||
$db->dbExec($query, $pk_name)
|
||||
);
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
// check query called matching
|
||||
$current_count = $db->dbGetQueryCalled($query);
|
||||
$this->assertEquals(
|
||||
$db->dbGetMaxQueryCall() + 1,
|
||||
$current_count
|
||||
);
|
||||
// reset query called and check again
|
||||
$this->assertEquals(
|
||||
0,
|
||||
$db->dbResetQueryCalled($query)
|
||||
);
|
||||
}
|
||||
|
||||
// if string for warning or error is not empty check
|
||||
$this->assertEquals(
|
||||
$warning,
|
||||
$db->dbGetLastWarning()
|
||||
$last_warning
|
||||
);
|
||||
$this->assertEquals(
|
||||
$error,
|
||||
$db->dbGetLastError()
|
||||
$last_error
|
||||
);
|
||||
|
||||
// reset all data
|
||||
$db->dbExec("TRUNCATE table_with_primary_key");
|
||||
$db->dbExec("TRUNCATE table_without_primary_key");
|
||||
// close connection
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// - return one database row
|
||||
// dbReturnRow
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function returnRowProvider(): array
|
||||
{
|
||||
$insert_query = "INSERT INTO table_with_primary_key (row_int, uid) VALUES (1, 'A')";
|
||||
$read_query = "SELECT row_int, uid FROM table_with_primary_key WHERE uid = 'A'";
|
||||
// 0: query
|
||||
// 1: flag (assoc)
|
||||
// 2: result
|
||||
// 3: warning
|
||||
// 4: error
|
||||
// 5: insert query
|
||||
return [
|
||||
'valid select' => [
|
||||
$read_query,
|
||||
null,
|
||||
[
|
||||
'row_int' => 1,
|
||||
0 => 1,
|
||||
'uid' => 'A',
|
||||
1 => 'A'
|
||||
],
|
||||
'',
|
||||
'',
|
||||
$insert_query,
|
||||
],
|
||||
'valid select, assoc only false' => [
|
||||
$read_query,
|
||||
false,
|
||||
[
|
||||
'row_int' => 1,
|
||||
0 => 1,
|
||||
'uid' => 'A',
|
||||
1 => 'A'
|
||||
],
|
||||
'',
|
||||
'',
|
||||
$insert_query,
|
||||
],
|
||||
'valid select, assoc only true' => [
|
||||
$read_query,
|
||||
true,
|
||||
[
|
||||
'row_int' => 1,
|
||||
'uid' => 'A',
|
||||
],
|
||||
'',
|
||||
'',
|
||||
$insert_query,
|
||||
],
|
||||
'empty select' => [
|
||||
'',
|
||||
null,
|
||||
false,
|
||||
'',
|
||||
'11',
|
||||
$insert_query,
|
||||
],
|
||||
'insert query' => [
|
||||
$insert_query,
|
||||
null,
|
||||
false,
|
||||
'',
|
||||
'17',
|
||||
$insert_query
|
||||
],
|
||||
// invalid QUERY
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::dbReturnRow
|
||||
* @dataProvider returnRowProvider
|
||||
* @testdox dbReturnRow $query and assoc $flag_assoc with $expected (Warning: $warning/Error: $error) [$_dataName]
|
||||
*
|
||||
* @param string $query
|
||||
* @param bool|null $flag_assoc
|
||||
* @param array<mixed>|bool $expected
|
||||
* @param string $warning
|
||||
* @param string $error
|
||||
* @param string $insert_data
|
||||
* @return void
|
||||
*/
|
||||
public function testDbReturnRow(
|
||||
string $query,
|
||||
?bool $flag_assoc,
|
||||
$expected,
|
||||
string $warning,
|
||||
string $error,
|
||||
string $insert_data,
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
self::$log
|
||||
);
|
||||
// insert data before we can test, from expected array
|
||||
$db->dbExec($insert_data);
|
||||
// compare
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$flag_assoc === null ?
|
||||
$db->dbReturnRow($query) :
|
||||
$db->dbReturnRow($query, $flag_assoc)
|
||||
);
|
||||
// get last error/warnings
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
// print "ER: " . $last_error . "/" . $last_warning . "\n";
|
||||
// if string for warning or error is not empty check
|
||||
$this->assertEquals(
|
||||
$warning,
|
||||
$last_warning
|
||||
);
|
||||
$this->assertEquals(
|
||||
$error,
|
||||
$last_error
|
||||
);
|
||||
|
||||
// reset all data
|
||||
$db->dbExec("TRUNCATE table_with_primary_key");
|
||||
$db->dbExec("TRUNCATE table_without_primary_key");
|
||||
// close connection
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// - return all database rows
|
||||
// dbReturnArray
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function returnArrayProvider(): array
|
||||
{
|
||||
$insert_query = "INSERT INTO table_with_primary_key (row_int, uid) VALUES "
|
||||
. "(1, 'A'), (2, 'B')";
|
||||
$read_query = "SELECT row_int, uid FROM table_with_primary_key";
|
||||
// 0: query
|
||||
// 1: flag (assoc)
|
||||
// 2: result
|
||||
// 3: warning
|
||||
// 4: error
|
||||
// 5: insert query
|
||||
return [
|
||||
'valid select' => [
|
||||
$read_query,
|
||||
null,
|
||||
[
|
||||
[
|
||||
'row_int' => 1,
|
||||
'uid' => 'A',
|
||||
],
|
||||
[
|
||||
'row_int' => 2,
|
||||
'uid' => 'B',
|
||||
],
|
||||
],
|
||||
'',
|
||||
'',
|
||||
$insert_query,
|
||||
],
|
||||
'valid select, assoc ' => [
|
||||
$read_query,
|
||||
false,
|
||||
[
|
||||
[
|
||||
'row_int' => 1,
|
||||
0 => 1,
|
||||
'uid' => 'A',
|
||||
1 => 'A'
|
||||
],
|
||||
[
|
||||
'row_int' => 2,
|
||||
0 => 2,
|
||||
'uid' => 'B',
|
||||
1 => 'B'
|
||||
],
|
||||
],
|
||||
'',
|
||||
'',
|
||||
$insert_query,
|
||||
],
|
||||
'empty select' => [
|
||||
'',
|
||||
null,
|
||||
false,
|
||||
'',
|
||||
'11',
|
||||
$insert_query,
|
||||
],
|
||||
'insert query' => [
|
||||
$insert_query,
|
||||
null,
|
||||
false,
|
||||
'',
|
||||
'17',
|
||||
$insert_query
|
||||
],
|
||||
// invalid QUERY
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::dbReturnArray
|
||||
* @dataProvider returnArrayProvider
|
||||
* @testdox dbReturnArray $query and assoc $flag_assoc with $expected (Warning: $warning/Error: $error) [$_dataName]
|
||||
*
|
||||
* @param string $query
|
||||
* @param boolean|null $flag_assoc
|
||||
* @param array<mixed>|bool $expected
|
||||
* @param string $warning
|
||||
* @param string $error
|
||||
* @param string $insert_data
|
||||
* @return void
|
||||
*/
|
||||
public function testDbReturnArrray(
|
||||
string $query,
|
||||
?bool $flag_assoc,
|
||||
$expected,
|
||||
string $warning,
|
||||
string $error,
|
||||
string $insert_data,
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
self::$log
|
||||
);
|
||||
// insert data before we can test, from expected array
|
||||
$db->dbExec($insert_data);
|
||||
// compare
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$flag_assoc === null ?
|
||||
$db->dbReturnArray($query) :
|
||||
$db->dbReturnArray($query, $flag_assoc)
|
||||
);
|
||||
// get last error/warnings
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
// if string for warning or error is not empty check
|
||||
$this->assertEquals(
|
||||
$warning,
|
||||
$last_warning
|
||||
);
|
||||
$this->assertEquals(
|
||||
$error,
|
||||
$last_error
|
||||
);
|
||||
|
||||
// reset all data
|
||||
$db->dbExec("TRUNCATE table_with_primary_key");
|
||||
$db->dbExec("TRUNCATE table_without_primary_key");
|
||||
// close connection
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// - loop data return flow
|
||||
// dbReturn, dbCacheReset, dbCursorPos, dbCursorNumRows, dbGetCursorExt
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function dbReturnProvider(): array
|
||||
{
|
||||
$insert_query = "INSERT INTO table_with_primary_key (row_int, uid) VALUES "
|
||||
. "(1, 'A'), (2, 'B')";
|
||||
$read_query = "SELECT row_int, uid FROM table_with_primary_key";
|
||||
// 0: read query
|
||||
// 1: reset flag, null for default
|
||||
// 2: assoc flag, null for default
|
||||
// 3: expected return
|
||||
// 4: read first, read all flag
|
||||
// 5: read all check array
|
||||
// 6: warning
|
||||
// 7: error
|
||||
// 8: insert data
|
||||
return [
|
||||
'valid select' => [
|
||||
$read_query,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
'row_int' => 1,
|
||||
0 => 1,
|
||||
'uid' => 'A',
|
||||
1 => 'A'
|
||||
],
|
||||
true,
|
||||
[],
|
||||
'',
|
||||
'',
|
||||
$insert_query
|
||||
],
|
||||
'valid select, default cache, assoc only' => [
|
||||
$read_query,
|
||||
\CoreLibs\DB\IO::USE_CACHE,
|
||||
true,
|
||||
[
|
||||
'row_int' => 1,
|
||||
'uid' => 'A',
|
||||
],
|
||||
true,
|
||||
[],
|
||||
'',
|
||||
'',
|
||||
$insert_query
|
||||
],
|
||||
'empty select' => [
|
||||
'',
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
[],
|
||||
'',
|
||||
'11',
|
||||
$insert_query,
|
||||
],
|
||||
'insert query' => [
|
||||
$insert_query,
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
[],
|
||||
'',
|
||||
'17',
|
||||
$insert_query
|
||||
],
|
||||
// from here on a complex read all full tests
|
||||
'valid select, full read' => [
|
||||
$read_query,
|
||||
null,
|
||||
null,
|
||||
[
|
||||
'row_int' => 1,
|
||||
0 => 1,
|
||||
'uid' => 'A',
|
||||
1 => 'A'
|
||||
],
|
||||
false,
|
||||
[],
|
||||
'',
|
||||
'',
|
||||
$insert_query
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::dbReturn
|
||||
* @covers ::dbCacheReset
|
||||
* @covers ::dbGetCursorExt
|
||||
* @covers ::dbCursorPos
|
||||
* @covers ::dbCursorNumRows
|
||||
* @dataProvider dbReturnProvider
|
||||
* @testdox dbReturn $query and cache $flag_cache and assoc $flag_assoc with $expected (Warning: $warning/Error: $error) [$_dataName]
|
||||
*
|
||||
* @param string $query
|
||||
* @param integer|null $flag_cache
|
||||
* @param boolean|null $flag_assoc
|
||||
* @param array<mixed>|bool $expected
|
||||
* @param bool $read_first_only
|
||||
* @param array $cursor_ext_checks
|
||||
* @param string $warning
|
||||
* @param string $error
|
||||
* @param string $insert_data
|
||||
* @return void
|
||||
*/
|
||||
public function testDbReturn(
|
||||
string $query,
|
||||
?int $flag_cache,
|
||||
?bool $flag_assoc,
|
||||
$expected,
|
||||
bool $read_first_only,
|
||||
array $cursor_ext_checks,
|
||||
string $warning,
|
||||
string $error,
|
||||
string $insert_data,
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
self::$log
|
||||
);
|
||||
// insert data before we can test, from expected array
|
||||
$db->dbExec($insert_data);
|
||||
|
||||
// all checks below
|
||||
if ($read_first_only === true) {
|
||||
// simple assert first read, then discard result
|
||||
// compare
|
||||
$this->assertEquals(
|
||||
$expected,
|
||||
$flag_cache === null && $flag_assoc === null ?
|
||||
$db->dbReturn($query) :
|
||||
($flag_assoc === null ?
|
||||
$db->dbReturn($query, $flag_cache) :
|
||||
$db->dbReturn($query, $flag_cache, $flag_assoc)
|
||||
)
|
||||
);
|
||||
// get last error/warnings
|
||||
$last_warning = $db->dbGetLastWarning();
|
||||
$last_error = $db->dbGetLastError();
|
||||
// if string for warning or error is not empty check
|
||||
$this->assertEquals(
|
||||
$warning,
|
||||
$last_warning
|
||||
);
|
||||
$this->assertEquals(
|
||||
$error,
|
||||
$last_error
|
||||
);
|
||||
} else {
|
||||
// all tests here have valid returns already, error checks not needed
|
||||
// read all, and then do result compare
|
||||
// cursor ext data checks (field names, rows, pos, data)
|
||||
// do cache reset test
|
||||
$data = [];
|
||||
$pos = 0;
|
||||
while (
|
||||
is_array(
|
||||
$res = $flag_cache === null && $flag_assoc === null ?
|
||||
$db->dbReturn($query) :
|
||||
($flag_assoc === null ?
|
||||
$db->dbReturn($query, $flag_cache) :
|
||||
$db->dbReturn($query, $flag_cache, $flag_assoc)
|
||||
)
|
||||
)
|
||||
) {
|
||||
$data[] = $res;
|
||||
$pos++;
|
||||
// check cursor pos
|
||||
$this->assertEquals(
|
||||
$pos,
|
||||
$db->dbGetCursorPos($query)
|
||||
);
|
||||
}
|
||||
// does count match for returned data and the cursor num rows
|
||||
$this->assertEquals(
|
||||
count($data),
|
||||
$db->dbGetCursorNumRows($query)
|
||||
);
|
||||
// does data match
|
||||
// try get cursor data for non existing, must be null
|
||||
$this->assertNull(
|
||||
$db->dbGetCursorExt($query, 'nonexistingfield')
|
||||
);
|
||||
// does reset data work, query cursor must be null
|
||||
$db->dbCacheReset($query);
|
||||
$this->assertNull(
|
||||
$db->dbGetCursorExt($query)
|
||||
);
|
||||
}
|
||||
|
||||
// reset all data
|
||||
$db->dbExec("TRUNCATE table_with_primary_key");
|
||||
$db->dbExec("TRUNCATE table_without_primary_key");
|
||||
// close connection
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// - prepared query execute
|
||||
// dbPrepare, dbExecute, dbFetchArray
|
||||
|
||||
public function preparedProvider(): array
|
||||
{
|
||||
// 0: statement name
|
||||
// 1: query to prepare
|
||||
// 2: primary key name: null for default run
|
||||
// 3: arguments for query (double array 0: for select, 0..n for insert/update)
|
||||
// 4: expected prepare return
|
||||
// 5: prepare warning
|
||||
// 6: prepare error
|
||||
// 7: expected execute return
|
||||
// 8: execute warning
|
||||
// 9: execute error
|
||||
// 10: execute data to check (array)
|
||||
// 11: insert data
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
// bool|object|resource
|
||||
|
||||
public function testDbPrepared(
|
||||
string $stm_name,
|
||||
string $query,
|
||||
?string $pk_name,
|
||||
array $query_data,
|
||||
$expected_prepare,
|
||||
string $warning_prepare,
|
||||
string $error_prepare,
|
||||
$expected_execute,
|
||||
string $warning_execute,
|
||||
string $error_execute,
|
||||
array $excute_data,
|
||||
string $insert_data,
|
||||
): void {
|
||||
// self::$log->setLogLevelAll('debug', true);
|
||||
// self::$log->setLogLevelAll('print', true);
|
||||
$db = new \CoreLibs\DB\IO(
|
||||
self::$db_config['valid'],
|
||||
self::$log
|
||||
);
|
||||
// insert data before we can test, from expected array
|
||||
$db->dbExec($insert_data);
|
||||
|
||||
// reset all data
|
||||
$db->dbExec("TRUNCATE table_with_primary_key");
|
||||
$db->dbExec("TRUNCATE table_without_primary_key");
|
||||
// close connection
|
||||
$db->dbClose();
|
||||
}
|
||||
|
||||
// - db execution tests
|
||||
// dbReturn, dbCacheReset,
|
||||
// dbFetchArray, dbReturnRow, dbReturnArray,
|
||||
// dbCursorPos, dbCursorNumRows,
|
||||
// dbPrepare, dbExecute
|
||||
// dbExecAsync, dbCheckAsync
|
||||
// - encoding conversion on read
|
||||
// dbSetToEncoding, dbGetToEncoding
|
||||
@@ -1487,10 +2105,8 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
// dbDumpData
|
||||
// - internal read data (post exec)
|
||||
// dbGetReturning, dbGetInsertPKName, dbGetInsertPK, dbGetReturningExt,
|
||||
// dbGetReturningArray, dbGetCursorExt, dbGetNumRows, dbGetNumFields,
|
||||
// dbGetFieldNames, dbGetQuery
|
||||
// getHadError, getHadWarning,
|
||||
// dbResetQueryCalled, dbGetQueryCalled
|
||||
// dbGetReturningArray, dbGetNumRows, dbGetNumFields,
|
||||
// dbGetFieldNames, dbGetQuery, dbGetQueryHash, dbGetDbh
|
||||
// - complex write sets
|
||||
// dbWriteData, dbWriteDataExt
|
||||
// - deprecated tests [no need to test perhaps]
|
||||
@@ -1498,21 +2114,6 @@ final class CoreLibsDBIOTest extends TestCase
|
||||
// getCursorExt, getNumRows
|
||||
// - error handling
|
||||
// dbGetCombinedErrorHistory, dbGetLastError, dbGetLastWarning
|
||||
|
||||
/**
|
||||
* grouped DB IO test
|
||||
*
|
||||
* @testdox DB\IO Class tests
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDBIO()
|
||||
{
|
||||
$this->assertTrue(true, 'DB IO Tests not implemented');
|
||||
$this->markTestIncomplete(
|
||||
'DB\IO Tests have not yet been implemented'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
|
||||
@@ -55,16 +55,26 @@ echo "DB_CONFIG_SET constant: <pre>" . print_r(DB_CONFIG, true) . "</pre><br>";
|
||||
print "DB Client encoding: " . $db->dbGetEncoding() . "<br>";
|
||||
|
||||
while (is_array($res = $db->dbReturn("SELECT * FROM max_test", DbIo::USE_CACHE, true))) {
|
||||
print "TIME: " . $res['time'] . "<br>";
|
||||
print "UUD/TIME: " . $res['uid'] . "/" . $res['time'] . "<br>";
|
||||
}
|
||||
print "CACHED DATA: <pre>" . print_r($db->dbGetCursorExt(), true) . "</pre><br>";
|
||||
while (is_array($res = $db->dbReturn("SELECT * FROM max_test"))) {
|
||||
print "[CACHED] TIME: " . $res['time'] . "<br>";
|
||||
while (is_array($res = $db->dbReturn("SELECT * FROM max_test", DbIo::USE_CACHE))) {
|
||||
print "[CACHED] UID/TIME: " . $res['uid'] . "/" . $res['time'] . "<br>";
|
||||
// print "****RES: <pre>" . print_r($res, true) . "</pre><br>";
|
||||
}
|
||||
// print "CACHED REREAD DATA: <pre>" . print_r($db->dbGetCursorExt(), true) . "</pre><br>";
|
||||
while (is_array($res = $db->dbReturn("SELECT * FROM max_test", DbIo::NO_CACHE))) {
|
||||
print "[NO CACHE] UID.TIME: " . $res['uid'] . "/" . $res['time'] . "<br>";
|
||||
// print "****RES: <pre>" . print_r($res, true) . "</pre><br>";
|
||||
}
|
||||
print "NO CACHED DATA: <pre>" . print_r($db->dbGetCursorExt(), true) . "</pre><br>";
|
||||
// alternate check for valid data
|
||||
// while (($res = $db->dbReturn("SELECT * FROM max_test")) !== false) {
|
||||
// print "[CACHED] TIME: " . $res['time'] . "<br>";
|
||||
// }
|
||||
// while (is_array($res = $db->dbReturn("SELECT * FROM max_test", DbIo::USE_CACHE))) {
|
||||
// print "UUD/TIME: " . $res['uid'] . "/" . $res['time'] . "<br>";
|
||||
// }
|
||||
|
||||
print "<pre>";
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ $log = new CoreLibs\Debug\Logging([
|
||||
]);
|
||||
$basic = new CoreLibs\Basic($log);
|
||||
$_uids = new CoreLibs\Create\Uids();
|
||||
use CoreLibs\Create\Uids;
|
||||
$uids_class = 'CoreLibs\Create\Uids';
|
||||
|
||||
print "<html><head><title>TEST CLASS: UIDS</title><head>";
|
||||
@@ -57,6 +58,10 @@ print "S::UUIDV4: " . $uids_class::uuidv4() . "<br>";
|
||||
print "S::UNIQID (d): " . $uids_class::uniqId() . "<br>";
|
||||
print "S::UNIQID (md5): " . $uids_class::uniqId('md5') . "<br>";
|
||||
print "S::UNIQID (sha256): " . $uids_class::uniqId('sha256') . "<br>";
|
||||
// uniq ids
|
||||
print "UNIQU ID SHORT : " . Uids::uniqIdShort() . "<br>";
|
||||
print "UNIQU ID LONG : " . Uids::uniqIdLong() . "<br>";
|
||||
|
||||
// DEPRECATED
|
||||
/* print "D/UUIDV4: ".$basic->uuidv4()."<br>";
|
||||
print "/DUNIQID (d): ".$basic->uniqId()."<br>"; */
|
||||
|
||||
@@ -439,7 +439,7 @@ class Login extends \CoreLibs\DB\IO
|
||||
if (!is_array($res)) {
|
||||
$this->login_error = 1009;
|
||||
$this->permission_okay = false;
|
||||
} elseif (empty($this->dbGetCursorExt($q, 'num_rows'))) {
|
||||
} elseif (empty($this->dbGetCursorNumRows($q))) {
|
||||
// username is wrong, but we throw for wrong username
|
||||
// and wrong password the same error
|
||||
$this->login_error = 1010;
|
||||
|
||||
@@ -436,7 +436,6 @@ class IO
|
||||
'22' => 'Query Execute failed',
|
||||
'23' => 'Query Execute failed, data array does not match placeholders',
|
||||
'24' => 'Missing prepared query entry for execute.',
|
||||
'25' => 'Prepare query data is not in array format.',
|
||||
'30' => 'Query call in a possible endless loop. '
|
||||
. 'Was called more than ' . $this->MAX_QUERY_CALL . ' times',
|
||||
'31' => 'Could not fetch PK after query insert',
|
||||
@@ -885,14 +884,61 @@ class IO
|
||||
private function __dbCheckConnectionOk(int $timeout_seconds = 3): bool
|
||||
{
|
||||
// check that no other query is running right now
|
||||
// FIXME: do this in a loop? __dbConnectionBusySocketWait? max check timeout
|
||||
if ($this->db_functions->__dbConnectionBusy()) {
|
||||
// below does return false after error too
|
||||
// if ($this->db_functions->__dbConnectionBusy()) {
|
||||
if ($this->db_functions->__dbConnectionBusySocketWait($timeout_seconds)) {
|
||||
$this->__dbError(41);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* dbReturn
|
||||
* Read data from previous written data cache
|
||||
* @param string $query_hash The hash for the current query
|
||||
* @param boolean $assoc_only Only return assoc value (key named)
|
||||
* @return array Current position query data from cache
|
||||
*/
|
||||
private function __dbReturnCacheRead(string $query_hash, bool $assoc_only): array
|
||||
{
|
||||
// unset return value ...
|
||||
$return = [];
|
||||
// current cursor hash element
|
||||
$cursor_hash = $this->cursor_ext[$query_hash];
|
||||
// position in reading for current cursor hash
|
||||
$cursor_pos = $cursor_hash['pos'];
|
||||
// max fields in current cursor hash
|
||||
$max_fields = $cursor_hash['num_fields'] ?? 0;
|
||||
// read voer each field
|
||||
for ($pos = 0; $pos < $max_fields; $pos++) {
|
||||
// numbered pos element data (only exists in full read)
|
||||
$cursor_data_pos = $cursor_hash['data'][$cursor_pos][$pos] ?? null;
|
||||
// field name position from field names
|
||||
$field_name_pos = $cursor_hash['field_names'][$pos] ?? null;
|
||||
// field name data
|
||||
$cursor_data_name = $cursor_hash['data'][$cursor_pos][$field_name_pos] ?? null;
|
||||
// create mixed return array
|
||||
if (
|
||||
$assoc_only === false &&
|
||||
$cursor_data_pos !== null
|
||||
) {
|
||||
$return[$pos] = $cursor_data_pos;
|
||||
}
|
||||
// named part (is alreays read)
|
||||
if (!empty($field_name_pos)) {
|
||||
// read pos first, fallback to name if not set
|
||||
if ($cursor_data_pos !== null) {
|
||||
$return[$field_name_pos] = $cursor_data_pos;
|
||||
} else {
|
||||
$return[$field_name_pos] = $cursor_data_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->cursor_ext[$query_hash]['pos'] ++;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* sub function for dbExec and dbExecAsync
|
||||
* - checks query is set
|
||||
@@ -908,7 +954,7 @@ class IO
|
||||
private function __dbPrepareExec(string $query, string $pk_name)
|
||||
{
|
||||
// reset current cursor before exec
|
||||
$this->cursor = null;
|
||||
$this->cursor = false;
|
||||
// clear matches for regex lookups
|
||||
$matches = [];
|
||||
// to either use the returning method
|
||||
@@ -980,7 +1026,7 @@ class IO
|
||||
$this->__dbDebug('db', $this->query, '__dbPrepareExec', 'Q');
|
||||
}
|
||||
// import protection, hash needed
|
||||
$query_hash = Hash::__hashLong($this->query);
|
||||
$query_hash = $this->dbGetQueryHash($this->query);
|
||||
// if the array index does not exists set it 0
|
||||
if (!array_key_exists($query_hash, $this->query_called)) {
|
||||
$this->query_called[$query_hash] = 0;
|
||||
@@ -1129,13 +1175,11 @@ class IO
|
||||
$this->__dbWarning(
|
||||
33,
|
||||
false,
|
||||
$stm_name . ': RETURNING returned no data',
|
||||
'DB_WARNING'
|
||||
$stm_name . ': RETURNING returned no data'
|
||||
);
|
||||
}
|
||||
} elseif (count($this->insert_id_arr) > 1) {
|
||||
// this error handling is only for INSERT (), (), ... sets
|
||||
$this->warning_id = 32;
|
||||
if ($stm_name === null) {
|
||||
$this->__dbWarning(32, $cursor, '[dbExec]');
|
||||
} else {
|
||||
@@ -1346,7 +1390,7 @@ class IO
|
||||
{
|
||||
// set start array
|
||||
if ($query) {
|
||||
$array = $this->cursor_ext[Hash::__hashLong($query)] ?? [];
|
||||
$array = $this->cursor_ext[$this->dbGetQueryHash($query)] ?? [];
|
||||
} else {
|
||||
$array = $this->cursor_ext;
|
||||
}
|
||||
@@ -1585,7 +1629,8 @@ class IO
|
||||
* caches data, so next time called with IDENTICAL (!!!!)
|
||||
* [this means 1:1 bit to bit identical query] returns cached
|
||||
* data, or with reset flag set calls data from DB again
|
||||
* NOTE on $reset param:
|
||||
* NOTE on $cache param:
|
||||
* - if set to 0, if same query run again, will read from cache
|
||||
* - if set to 1, at the end of the query (last row returned),
|
||||
* the stored array will be deleted ...
|
||||
* - if set to 2, the data will be read new and cached
|
||||
@@ -1593,25 +1638,28 @@ class IO
|
||||
* - if set to 3, after EACH row, the data will be reset,
|
||||
* no caching is done except for basic (count, etc)
|
||||
* @param string $query Query string
|
||||
* @param int $reset reset status:
|
||||
* @param int $cache reset status: default: USE_CACHE
|
||||
* USE_CACHE/0: normal read from cache on second run
|
||||
* CLEAR_CACHE/1: read cache, clean at the end
|
||||
* READ_NEW/2: read new, clean at end
|
||||
* NO_CACHE/3: never cache
|
||||
* NO_CACHE/3: never cache [default]
|
||||
* @param bool $assoc_only True to only returned the named and not
|
||||
* index position ones
|
||||
* @return array<mixed>|bool return array data or false on error/end
|
||||
* @#suppress PhanTypeMismatchDimFetch
|
||||
*/
|
||||
public function dbReturn(string $query, int $reset = self::USE_CACHE, bool $assoc_only = false)
|
||||
{
|
||||
public function dbReturn(
|
||||
string $query,
|
||||
int $cache = self::USE_CACHE,
|
||||
bool $assoc_only = false
|
||||
) {
|
||||
$this->__dbErrorReset();
|
||||
if (!$query) {
|
||||
$this->__dbError(11);
|
||||
return false;
|
||||
}
|
||||
// create hash from query ...
|
||||
$query_hash = Hash::__hashLong($query);
|
||||
$query_hash = $this->dbGetQueryHash($query);
|
||||
// pre declare array
|
||||
if (!isset($this->cursor_ext[$query_hash])) {
|
||||
$this->cursor_ext[$query_hash] = [
|
||||
@@ -1635,9 +1683,10 @@ class IO
|
||||
}
|
||||
// init return als false
|
||||
$return = false;
|
||||
// if it is a call with reset in it we reset the cursor, so we get an uncached return
|
||||
// if it is a call with reset in it we reset the cursor,
|
||||
// so we get an uncached return
|
||||
// but only for the FIRST call (pos == 0)
|
||||
if ($reset && !$this->cursor_ext[$query_hash]['pos']) {
|
||||
if ($cache > self::USE_CACHE && !$this->cursor_ext[$query_hash]['pos']) {
|
||||
$this->cursor_ext[$query_hash]['cursor'] = null;
|
||||
}
|
||||
// $this->debug('MENU', 'Reset: '.$reset.', Cursor: '
|
||||
@@ -1687,6 +1736,7 @@ class IO
|
||||
$this->cursor_ext[$query_hash]['num_fields'] =
|
||||
$this->db_functions->__dbNumFields($this->cursor_ext[$query_hash]['cursor']);
|
||||
// set field names
|
||||
$this->cursor_ext[$query_hash]['field_names'] = [];
|
||||
for ($i = 0; $i < $this->cursor_ext[$query_hash]['num_fields']; $i++) {
|
||||
$this->cursor_ext[$query_hash]['field_names'][] =
|
||||
$this->db_functions->__dbFieldName(
|
||||
@@ -1702,7 +1752,10 @@ class IO
|
||||
$this->cursor_ext[$query_hash]['read_rows'] = 0;
|
||||
}
|
||||
// read data for further work ... but only if necessarry
|
||||
if ($this->cursor_ext[$query_hash]['read_rows'] == $this->cursor_ext[$query_hash]['num_rows']) {
|
||||
if (
|
||||
$this->cursor_ext[$query_hash]['read_rows'] ==
|
||||
$this->cursor_ext[$query_hash]['num_rows']
|
||||
) {
|
||||
$return = false;
|
||||
} else {
|
||||
$return = $this->__dbConvertEncoding(
|
||||
@@ -1717,7 +1770,7 @@ class IO
|
||||
}
|
||||
}
|
||||
// check if cached call or reset call ...
|
||||
if (!$return && !$reset) {
|
||||
if (!$return && $cache == self::USE_CACHE) {
|
||||
// check if end of output ...
|
||||
if ($this->cursor_ext[$query_hash]['pos'] >= $this->cursor_ext[$query_hash]['num_rows']) {
|
||||
$this->cursor_ext[$query_hash]['pos'] = 0;
|
||||
@@ -1727,62 +1780,25 @@ class IO
|
||||
$this->cursor_ext[$query_hash]['cursor'] = 1;
|
||||
$return = false;
|
||||
} else {
|
||||
// unset return value ...
|
||||
$return = [];
|
||||
for ($i = 0; $i < $this->cursor_ext[$query_hash]['num_fields']; $i++) {
|
||||
// FIXME: find out why phan throws all those array errors
|
||||
// create mixed return array
|
||||
if (
|
||||
$assoc_only === false &&
|
||||
isset($this->cursor_ext[$query_hash]['data'][$this->cursor_ext[$query_hash]['pos']][$i])
|
||||
) {
|
||||
$return[$i] =
|
||||
/** @phan-suppress-next-line PhanTypeArraySuspiciousNullable */
|
||||
$this->cursor_ext[$query_hash]['data']
|
||||
[$this->cursor_ext[$query_hash]['pos']][$i];
|
||||
}
|
||||
// named part
|
||||
if (!empty($this->cursor_ext[$query_hash]['field_names'][$i])) {
|
||||
if (
|
||||
isset(
|
||||
$this->cursor_ext[$query_hash]['data']
|
||||
[$this->cursor_ext[$query_hash]['pos']][$i]
|
||||
)
|
||||
) {
|
||||
/** @phan-suppress-next-line PhanTypeArraySuspiciousNullable */
|
||||
$return[$this->cursor_ext[$query_hash]['field_names'][$i]] =
|
||||
/** @phan-suppress-next-line PhanTypeArraySuspiciousNullable */
|
||||
$this->cursor_ext[$query_hash]['data']
|
||||
[$this->cursor_ext[$query_hash]['pos']][$i];
|
||||
} else {
|
||||
// throws PhanTypeMismatchDimFetch error, but in this
|
||||
// case we know we will access only named array parts
|
||||
/** @phan-suppress-next-line PhanTypeArraySuspiciousNullable */
|
||||
$return[$this->cursor_ext[$query_hash]['field_names'][$i]] =
|
||||
/** @phan-suppress-next-line PhanTypeMismatchDimFetch,PhanTypeArraySuspiciousNullable */
|
||||
$this->cursor_ext[$query_hash]['data'][$this->cursor_ext[$query_hash]
|
||||
/** @phan-suppress-next-line PhanTypeArraySuspiciousNullable */
|
||||
['pos']][$this->cursor_ext[$query_hash]['field_names'][$i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->cursor_ext[$query_hash]['pos'] ++;
|
||||
// cached data read
|
||||
$return = $this->__dbReturnCacheRead($query_hash, $assoc_only);
|
||||
}
|
||||
} else {
|
||||
// return row, if last && reset, then unset the hole hash array
|
||||
if (
|
||||
!$return &&
|
||||
($reset == self::CLEAR_CACHE || $reset == self::NO_CACHE) &&
|
||||
($cache == self::CLEAR_CACHE || $cache == self::NO_CACHE) &&
|
||||
$this->cursor_ext[$query_hash]['pos']
|
||||
) {
|
||||
// unset only the field names here of course
|
||||
$this->cursor_ext[$query_hash]['field_names'] = null;
|
||||
// unset data block only
|
||||
$this->cursor_ext[$query_hash]['data'] = [];
|
||||
$this->cursor_ext[$query_hash]['pos'] = 0;
|
||||
} elseif (
|
||||
!$return && $reset == self::READ_NEW &&
|
||||
!$return && $cache == self::READ_NEW &&
|
||||
$this->cursor_ext[$query_hash]['pos']
|
||||
) {
|
||||
// at end of read reset pos & set cursor to 1 (so it does not get lost in session transfer)
|
||||
// at end of read reset pos & set cursor to 1
|
||||
// (so it does not get lost in session transfer)
|
||||
$this->cursor_ext[$query_hash]['pos'] = 0;
|
||||
$this->cursor_ext[$query_hash]['cursor'] = 1;
|
||||
$return = false;
|
||||
@@ -1792,13 +1808,14 @@ class IO
|
||||
// internal position counter
|
||||
$this->cursor_ext[$query_hash]['pos'] ++;
|
||||
$this->cursor_ext[$query_hash]['read_rows'] ++;
|
||||
// if reset is <3 caching is done, else no
|
||||
if ($reset < self::NO_CACHE) {
|
||||
$temp = [];
|
||||
foreach ($return as $field_name => $data) {
|
||||
$temp[$field_name] = $data;
|
||||
}
|
||||
$this->cursor_ext[$query_hash]['data'][] = $temp;
|
||||
// if reset is < NO_CACHE level caching is done, else no
|
||||
if ($cache < self::NO_CACHE) {
|
||||
// why was this here?
|
||||
// $temp = [];
|
||||
// foreach ($return as $field_name => $data) {
|
||||
// $temp[$field_name] = $data;
|
||||
// }
|
||||
$this->cursor_ext[$query_hash]['data'][] = $return;
|
||||
}
|
||||
} // cached data if
|
||||
} // cached or not if
|
||||
@@ -1913,7 +1930,7 @@ class IO
|
||||
* @param bool $assoc_only if true, only name ref are returned
|
||||
* @return array<mixed>|bool array of hashes (row -> fields), false on error
|
||||
*/
|
||||
public function dbReturnArray(string $query, bool $assoc_only = false)
|
||||
public function dbReturnArray(string $query, bool $assoc_only = true)
|
||||
{
|
||||
$this->__dbErrorReset();
|
||||
if (!$query) {
|
||||
@@ -1931,17 +1948,18 @@ class IO
|
||||
}
|
||||
$rows = [];
|
||||
while (is_array($res = $this->dbFetchArray($cursor, $assoc_only))) {
|
||||
$data = [];
|
||||
for ($i = 0; $i < $this->num_fields; $i++) {
|
||||
$data[$this->field_names[$i]] = $res[$this->field_names[$i]] ?? null;
|
||||
}
|
||||
$rows[] = $data;
|
||||
// $data = [];
|
||||
// for ($i = 0; $i < $this->num_fields; $i++) {
|
||||
// $data[$this->field_names[$i]] = $res[$this->field_names[$i]] ?? null;
|
||||
// }
|
||||
// $rows[] = $data;
|
||||
$rows[] = $res;
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
// ***************************
|
||||
// CURSOR CACHE RESET
|
||||
// CURSOR EXT CACHE RESET
|
||||
// ***************************
|
||||
|
||||
/**
|
||||
@@ -1952,9 +1970,9 @@ class IO
|
||||
public function dbCacheReset(string $query): bool
|
||||
{
|
||||
$this->__dbErrorReset();
|
||||
$query_hash = Hash::__hashLong($query);
|
||||
$query_hash = $this->dbGetQueryHash($query);
|
||||
// clears cache for this query
|
||||
if (!$this->cursor_ext[$query_hash]['query']) {
|
||||
if (empty($this->cursor_ext[$query_hash]['query'])) {
|
||||
$this->__dbError(18);
|
||||
return false;
|
||||
}
|
||||
@@ -1963,22 +1981,55 @@ class IO
|
||||
}
|
||||
|
||||
// ***************************
|
||||
// CURSOR POSITON CHECK
|
||||
// CURSOR EXT DATA CHECK
|
||||
// ***************************
|
||||
|
||||
/**
|
||||
* returns the full array for cursor ext
|
||||
* or cursor for one query
|
||||
* or detail data fonr one query cursor data
|
||||
* @param string|null $query Query string, if not null convert to hash
|
||||
* and return set cursor ext for only this
|
||||
* if not found or null return null
|
||||
* @return array<mixed>|string|int|resource|object|null
|
||||
* Cursor Extended array full if no parameter
|
||||
* Key is hash string from query run
|
||||
* Or cursor data entry if query field is set
|
||||
* If nothing found return null
|
||||
*/
|
||||
public function dbGetCursorExt($query = null, string $query_field = '')
|
||||
{
|
||||
if ($query !== null) {
|
||||
$query_hash = $this->dbGetQueryHash($query);
|
||||
if (
|
||||
is_array($this->cursor_ext) &&
|
||||
isset($this->cursor_ext[$query_hash])
|
||||
) {
|
||||
if (empty($query_field)) {
|
||||
return $this->cursor_ext[$query_hash];
|
||||
} else {
|
||||
return $this->cursor_ext[$query_hash][$query_field] ?? null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return $this->cursor_ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current position the read out
|
||||
* @param string $query query to find in cursor_ext
|
||||
* @return int|bool query position (row pos), false on error
|
||||
*/
|
||||
public function dbCursorPos(string $query)
|
||||
public function dbGetCursorPos(string $query)
|
||||
{
|
||||
$this->__dbErrorReset();
|
||||
if (!$query) {
|
||||
$this->__dbError(11);
|
||||
return false;
|
||||
}
|
||||
$query_hash = Hash::__hashLong($query);
|
||||
$query_hash = $this->dbGetQueryHash($query);
|
||||
return (int)$this->cursor_ext[$query_hash]['pos'];
|
||||
}
|
||||
|
||||
@@ -1987,14 +2038,14 @@ class IO
|
||||
* @param string $query query to find in cursor_ext
|
||||
* @return int|bool query position (row pos), false on error
|
||||
*/
|
||||
public function dbCursorNumRows(string $query)
|
||||
public function dbGetCursorNumRows(string $query)
|
||||
{
|
||||
$this->__dbErrorReset();
|
||||
if (!$query) {
|
||||
$this->__dbError(11);
|
||||
return false;
|
||||
}
|
||||
$query_hash = Hash::__hashLong($query);
|
||||
$query_hash = $this->dbGetQueryHash($query);
|
||||
return (int)$this->cursor_ext[$query_hash]['num_rows'];
|
||||
}
|
||||
|
||||
@@ -2010,7 +2061,7 @@ class IO
|
||||
*/
|
||||
public function dbResetQueryCalled(string $query): void
|
||||
{
|
||||
$this->query_called[Hash::__hashLong($query)] = 0;
|
||||
$this->query_called[$this->dbGetQueryHash($query)] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2020,7 +2071,7 @@ class IO
|
||||
*/
|
||||
public function dbGetQueryCalled(string $query): int
|
||||
{
|
||||
$query_hash = Hash::__hashLong($query);
|
||||
$query_hash = $this->dbGetQueryHash($query);
|
||||
if ($this->query_called[$query_hash]) {
|
||||
return $this->query_called[$query_hash];
|
||||
} else {
|
||||
@@ -2122,7 +2173,7 @@ class IO
|
||||
}
|
||||
} else {
|
||||
// thrown warning
|
||||
$this->warning_id = 20;
|
||||
$this->__dbWarning(20, false, $stm_name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2146,14 +2197,7 @@ class IO
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!is_array($data)) {
|
||||
$this->__dbError(
|
||||
25,
|
||||
false,
|
||||
$stm_name . ': Prepared query Data has to be given in array form.'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// if the count does not match
|
||||
if ($this->prepare_cursor[$stm_name]['count'] != count($data)) {
|
||||
$this->__dbError(
|
||||
23,
|
||||
@@ -2623,6 +2667,48 @@ class IO
|
||||
return $this->to_encoding;
|
||||
}
|
||||
|
||||
// ***************************
|
||||
// QUERY DATA AND DB HANDLER
|
||||
// ***************************
|
||||
|
||||
/**
|
||||
* Return current database handler
|
||||
* @return object|resource|bool|int|null
|
||||
*/
|
||||
public function dbGetDbh()
|
||||
{
|
||||
return $this->dbh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns hash for query
|
||||
* Hash is used in all internal storage systems for return data
|
||||
* @param string $query The query to create the hash from
|
||||
* @return string Hash, as set by hash lpng
|
||||
*/
|
||||
public function dbGetQueryHash(string $query): string
|
||||
{
|
||||
return Hash::__hashLong($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current set query
|
||||
* @return string Current set query string
|
||||
*/
|
||||
public function dbGetQuery(): string
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear current query
|
||||
* @return void
|
||||
*/
|
||||
public function dbResetQuery(): void
|
||||
{
|
||||
$this->query = '';
|
||||
}
|
||||
|
||||
// ***************************
|
||||
// INTERNAL VARIABLES READ POST QUERY RUN
|
||||
// ***************************
|
||||
@@ -2732,37 +2818,6 @@ class IO
|
||||
return $this->insert_id_arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the full array for cursor ext
|
||||
* @param string|null $q Query string, if not null convert to hash
|
||||
* and return set cursor ext for only this
|
||||
* if not found or null return null
|
||||
* @return array<mixed>|string|int|resource|object|null
|
||||
* Cursor Extended array full if no parameter
|
||||
* Key is hash string from query run
|
||||
* Or cursor data entry if query field is set
|
||||
* If nothing found return null
|
||||
*/
|
||||
public function dbGetCursorExt($q = null, string $query_field = '')
|
||||
{
|
||||
if ($q !== null) {
|
||||
$query_hash = Hash::__hashLong($q);
|
||||
if (
|
||||
is_array($this->cursor_ext) &&
|
||||
isset($this->cursor_ext[$query_hash])
|
||||
) {
|
||||
if (empty($query_field)) {
|
||||
return $this->cursor_ext[$query_hash];
|
||||
} else {
|
||||
return $this->cursor_ext[$query_hash][$query_field];
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return $this->cursor_ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns current number of rows that where
|
||||
* affected by UPDATE/SELECT, etc
|
||||
@@ -2792,32 +2847,9 @@ class IO
|
||||
return $this->field_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current database handler
|
||||
* @return object|resource|bool|int|null
|
||||
*/
|
||||
public function dbGetDbh()
|
||||
{
|
||||
return $this->dbh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current set query
|
||||
* @return string Current set query string
|
||||
*/
|
||||
public function dbGetQuery(): string
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear current query
|
||||
* @return void
|
||||
*/
|
||||
public function dbResetQuery(): void
|
||||
{
|
||||
$this->query = '';
|
||||
}
|
||||
// ***************************
|
||||
// ERROR AND WARNING DATA
|
||||
// ***************************
|
||||
|
||||
/**
|
||||
* Sets error number that was last
|
||||
@@ -2871,9 +2903,10 @@ class IO
|
||||
return $this->error_history_long;
|
||||
}
|
||||
|
||||
/******************************** */
|
||||
// ***************************
|
||||
// DEPEREACTED CALLS
|
||||
/******************************** */
|
||||
// all call below are no longer in use and throw deprecated errors
|
||||
// ***************************
|
||||
|
||||
/**
|
||||
* returns the db init error
|
||||
|
||||
@@ -586,9 +586,10 @@ class PgSQL
|
||||
$socket = [pg_socket($this->dbh)];
|
||||
while ($busy) {
|
||||
// Will wait on that socket until that happens or the timeout is reached
|
||||
stream_select($socket, null, null, $timeout_seconds);
|
||||
stream_select($socket, $null, $null, $timeout_seconds);
|
||||
$busy = pg_connection_busy($this->dbh);
|
||||
}
|
||||
return $busy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2249,14 +2249,14 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
|
||||
while (is_array($res = $this->dbReturn($data_array['query']))) {
|
||||
/** @phan-suppress-next-line PhanTypeInvalidDimOffset */
|
||||
$this->log->debug('edit', 'Q[' . $this->dbGetQueryHash($data_array['query']) . '] pos: '
|
||||
. $this->dbGetCursorExt($data_array['query'], 'pos')
|
||||
. $this->dbGetCursorPos($data_array['query'])
|
||||
. ' | want: ' . ($data_array['preset'] ?? '-')
|
||||
. ' | set: ' . ($data['preset'][$el_name] ?? '-'));
|
||||
// first is default for this element
|
||||
if (
|
||||
isset($data_array['preset']) &&
|
||||
(!isset($data['preset'][$el_name]) || empty($data['preset'][$el_name])) &&
|
||||
($this->dbGetCursorExt($data_array['query'], 'pos') == $data_array['preset'])
|
||||
($this->dbGetCursorPos($data_array['query']) == $data_array['preset'])
|
||||
) {
|
||||
$data['preset'][$el_name] = $res[0];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user