Compare commits

..

5 Commits

Author SHA1 Message Date
Clemens Schwaighofer
4c28e6d0ec Change DB\IO Returning check regex
Better regex to only get last returning in query, with proper parameter
check
2023-01-26 16:37:22 +09:00
Clemens Schwaighofer
66b7e81463 Bug fix in DB\IO for EOM string build queries with returning
on EOM string build queries it was not checked that RETURNING could have
no space in front.

Fixed and updated test calls
2023-01-25 16:47:31 +09:00
Clemens Schwaighofer
cf58f86802 Remove not needed ?? '' in ACL\Login 2023-01-16 14:29:25 +09:00
Clemens Schwaighofer
ff644310cd Readme file update 2023-01-11 09:22:18 +09:00
Clemens Schwaighofer
58988b9c0f Rename edit schemes pages to schemas 2023-01-11 09:12:56 +09:00
7 changed files with 248 additions and 64 deletions

View File

@@ -155,37 +155,57 @@ final class CoreLibsDBIOTest extends TestCase
$db->dbExec("DROP TABLE table_without_primary_key");
$db->dbExec("DROP TABLE test_meta");
}
$base_table = "uid VARCHAR, " // uid is for internal reference tests
. "row_int INT, "
. "row_numeric NUMERIC, "
. "row_varchar VARCHAR, "
. "row_varchar_literal VARCHAR, "
. "row_json JSON, "
. "row_jsonb JSONB, "
. "row_bytea BYTEA, "
. "row_timestamp TIMESTAMP WITHOUT TIME ZONE, "
. "row_date DATE, "
. "row_interval INTERVAL, "
. "row_array_int INT ARRAY, "
. "row_array_varchar VARCHAR ARRAY"
. ") WITHOUT OIDS";
// uid is for internal reference tests
$base_table = <<<EOM
uid VARCHAR,
row_int INT,
row_numeric NUMERIC,
row_varchar VARCHAR,
row_varchar_literal VARCHAR,
row_json JSON,
row_jsonb JSONB,
row_bytea BYTEA,
row_timestamp TIMESTAMP WITHOUT TIME ZONE,
row_date DATE,
row_interval INTERVAL,
row_array_int INT ARRAY,
row_array_varchar VARCHAR ARRAY
)
WITHOUT OIDS
EOM;
// create the tables
$db->dbExec(
"CREATE TABLE table_with_primary_key ("
// primary key name is table + '_id'
<<<EOM
CREATE TABLE table_with_primary_key (
table_with_primary_key_id SERIAL PRIMARY KEY,
$base_table
EOM
/* "CREATE TABLE table_with_primary_key ("
// primary key name is table + '_id'
. "table_with_primary_key_id SERIAL PRIMARY KEY, "
. $base_table
. $base_table */
);
$db->dbExec(
"CREATE TABLE table_without_primary_key ("
. $base_table
<<<EOM
CREATE TABLE table_without_primary_key (
$base_table
EOM
/* "CREATE TABLE table_without_primary_key ("
. $base_table */
);
// create simple table for meta test
$db->dbExec(
"CREATE TABLE test_meta ("
<<<EOM
CREATE TABLE test_meta (
row_1 VARCHAR,
row_2 INT
) WITHOUT OIDS
EOM
/* "CREATE TABLE test_meta ("
. "row_1 VARCHAR, "
. "row_2 INT"
. ") WITHOUT OIDS"
. ") WITHOUT OIDS" */
);
// set some test schema
$db->dbExec("CREATE SCHEMA IF NOT EXISTS testschema");
@@ -3893,6 +3913,38 @@ final class CoreLibsDBIOTest extends TestCase
]
]
],
// same but as EOM
'single insert (PK), EOM string' => [
<<<EOM
INSERT INTO table_with_primary_key (
row_varchar, row_varchar_literal, row_int, row_date
) VALUES (
'Text', 'Other', 123, '2022-03-01'
)
RETURNING row_varchar, row_varchar_literal, row_int, row_date
EOM,
null,
null,
null,
[
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
// 'table_with_primary_key_id' => "/^\d+$/",
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
],
[
0 => [
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
// 'table_with_primary_key_id' => "/^\d+$/",
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
]
]
],
// double insert (PK)
'dobule insert (PK)' => [
"INSERT INTO table_with_primary_key "
@@ -3910,14 +3962,14 @@ final class CoreLibsDBIOTest extends TestCase
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
],
1 => [
'row_varchar' => 'Foxtrott',
'row_varchar_literal' => 'Tango',
'row_int' => 789,
'row_date' => '1982-10-15',
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
'table_with_primary_key_id' => $table_with_primary_key_id + 4,
],
],
[
@@ -3926,14 +3978,14 @@ final class CoreLibsDBIOTest extends TestCase
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
'table_with_primary_key_id' => $table_with_primary_key_id + 2,
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
],
1 => [
'row_varchar' => 'Foxtrott',
'row_varchar_literal' => 'Tango',
'row_int' => 789,
'row_date' => '1982-10-15',
'table_with_primary_key_id' => $table_with_primary_key_id + 3,
'table_with_primary_key_id' => $table_with_primary_key_id + 4,
],
]
],
@@ -3961,7 +4013,35 @@ final class CoreLibsDBIOTest extends TestCase
'row_date' => '2022-03-01',
]
]
]
],
// same as above but as EOM string
'single insert (No PK), EOM string' => [
<<<EOM
INSERT INTO table_without_primary_key (
row_varchar, row_varchar_literal, row_int, row_date
) VALUES (
'Text', 'Other', 123, '2022-03-01'
)
RETURNING row_varchar, row_varchar_literal, row_int, row_date
EOM,
null,
null,
null,
[
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
],
[
0 => [
'row_varchar' => 'Text',
'row_varchar_literal' => 'Other',
'row_int' => 123,
'row_date' => '2022-03-01',
]
]
],
];
}
@@ -4008,11 +4088,13 @@ final class CoreLibsDBIOTest extends TestCase
$this->assertEquals(
$expected_ret_ext,
$returning_ext
$returning_ext,
'Returning extended failed'
);
$this->assertEquals(
$expected_ret_arr,
$returning_arr
$returning_arr,
'Returning Array failed'
);
// print "EXT: " . print_r($returning_ext, true) . "\n";

View File

@@ -0,0 +1,7 @@
-- Fix for edit_schemes.php DB settings
-- will not change file name only visual name
UPDATE edit_page SET name = 'Edit Schemas' WHERE filename = 'edit_schemes.php';
-- will change BOTH, must have file name renamed too
UPDATE edit_page SET name = 'Edit Schemas', filename = 'edit_schemas.php' WHERE filename = 'edit_schemes.php';

View File

@@ -2,19 +2,20 @@
## Code Standard
* Uses PSR-12
* tab indent instead of 4 spaces indent
* Warning at 120 character length, error at 240 character length
* Uses PSR-12
* tab indent instead of 4 spaces indent
* Warning at 120 character length, error at 240 character length
## General information
Base PHP class files to setup any project
* login
* database wrapper
* basic helper class for debugging and other features
* admin/frontend split
* domain controlled database/settings split
* dynamic layout groups
* login
* database wrapper
* basic helper class for debugging and other features
* admin/frontend split
* domain controlled database/settings split
* dynamic layout groups
## NOTE
@@ -50,7 +51,6 @@ pslam is setup but not configured
With phpunit (`4dev/checking/phpunit.sh`)
`phpunit -c $phpunit.xml 4dev/tests/`
## Other Notes
### Session used
@@ -58,29 +58,38 @@ With phpunit (`4dev/checking/phpunit.sh`)
The following classes use _SESSION
The main one is ACL\Login, this class will fail without a session started
* \CoreLibs\ACL\Login
* \CoreLibs\Admin\Backend
* \CoreLibs\Output\Form\Generate
* \CoreLibs\Output\Form\Token
* \CoreLibs\Template\SmartyExtend
* \CoreLibs\ACL\Login
* \CoreLibs\Admin\Backend
* \CoreLibs\Output\Form\Generate
* \CoreLibs\Output\Form\Token
* \CoreLibs\Template\SmartyExtend
### Class extends
The following classes extend these classes
* \CoreLibs\ACL\Login extends \CoreLibs\DB\IO
* \CoreLibs\Admin\Backend extends \CoreLibs\DB\IO
* \CoreLibs\DB\Extended\ArrayIO extends \CoreLibs\DB\IO
* \CoreLibs\Output\Form\Generate extends \CoreLibs\DB\Extended\ArrayIO
* \CoreLibs\Template\SmartyExtend extends SmartyBC
* \CoreLibs\ACL\Login extends \CoreLibs\DB\IO
* \CoreLibs\Admin\Backend extends \CoreLibs\DB\IO
* \CoreLibs\DB\Extended\ArrayIO extends \CoreLibs\DB\IO
* \CoreLibs\Output\Form\Generate extends \CoreLibs\DB\Extended\ArrayIO
* \CoreLibs\Template\SmartyExtend extends SmartyBC
### Class used
The following classes use the following classes
* \CoreLibs\ACL\Login uses \CoreLibs\Debug\Logger, \CoreLibs\Language\L10n
* \CoreLibs\DB\IO uses \CoreLibs\Debug\Logger, \CoreLibs\DB\SQL\PgSQL
* \CoreLibs\Admin\Backend uses \CoreLibs\Debug\Logger, \CoreLibs\Language\L10n
* \CoreLibs\Output\Form\Generate uses \CoreLibs\Debug\Logger, \CoreLibs\Language\L10n
* \CoreLibs\ACL\Login uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
* \CoreLibs\DB\IO uses \CoreLibs\Debug\Logging, \CoreLibs\DB\SQL\PgSQL
* \CoreLibs\Admin\Backend uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
* \CoreLibs\Output\Form\Generate uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
* \CoreLibs\Template\SmartyExtend uses \CoreLibs\Language\L10n
* \CoreLibs\Language\L10n uses FileReader, GetTextReader
* \CoreLibs\Admin\EditBase uses \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n
### Class internal load
Loads classes internal (not passed in, not extend)
* \CoreLibs\Admin\EditBase loads \CoreLibs\Template\SmartyExtend, \CoreLibs\Output\Form\Generate
* \CoreLibs\Output\From\Generate loads \CoreLibs\Debug\Logging, \CoreLibs\Language\L10n if not passed on
* \CoreLibs\Output\From\Generate loads \CoreLibs\Output\From\TableArrays

View File

@@ -118,7 +118,8 @@ print "<b>TRUNCATE test_foobar</b><br>";
$query = "TRUNCATE test_foobar";
$db->dbExec($query);
$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO TEST " . time() . "') RETURNING test");
$status = $db->dbExec("INSERT INTO test_foo (test, number_a) VALUES "
. "('FOO TEST " . time() . "', 1) RETURNING test, number_a");
print "DIRECT INSERT STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "DB OBJECT: <pre>" . print_r($status, true) . "</pre>| "
@@ -127,6 +128,29 @@ print "DIRECT INSERT STATUS: " . Support::printToString($status) . " |<br>"
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
var_dump($db->dbGetReturningExt());
// same as above but use an EOM string
$some_time = time();
$query = <<<EOM
INSERT INTO test_foo (
test, number_a
) VALUES (
'EOM FOO TEST $some_time', 1
)
RETURNING test, number_a
EOM;
$status = $db->dbExec($query);
print "EOM STRING DIRECT INSERT STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "DB OBJECT: <pre>" . print_r($status, true) . "</pre>| "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
var_dump($db->dbGetReturningExt());
// should throw deprecated error
// $db->getReturningExt();
print "DIRECT INSERT PREVIOUS INSERTED: "
@@ -137,7 +161,7 @@ print "DIRECT INSERT PREVIOUS INSERTED: "
$db->dbPrepare("ins_test_foo", "INSERT INTO test_foo (test) VALUES ($1) RETURNING test");
$status = $db->dbExecute("ins_test_foo", ['BAR TEST ' . time()]);
print "PREPARE INSERT[ins_test_foo] STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "QUERY: " . $db->dbGetPrepareCursorValue('ins_test_foo', 'query') . " |<br>"
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "<br>";
@@ -150,6 +174,23 @@ print "PREPARE CURSOR RETURN:<br>";
foreach (['pk_name', 'count', 'query', 'returning_id'] as $key) {
print "KEY: " . $key . ': ' . $db->dbGetPrepareCursorValue('ins_test_foo', $key) . "<br>";
}
$query = <<<EOM
INSERT INTO test_foo (
test
) VALUES (
$1
)
RETURNING test
EOM;
$db->dbPrepare("ins_test_foo_eom", $query);
$status = $db->dbExecute("ins_test_foo_eom", ['EOM BAR TEST ' . time()]);
print "EOM STRING PREPARE INSERT[ins_test_foo_eom] STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetPrepareCursorValue('ins_test_foo_eom', 'query') . " |<br>"
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// returning test with multiple entries
// $status = $db->db_exec(
// "INSERT INTO test_foo (test) VALUES "
@@ -172,6 +213,26 @@ print "DIRECT MULTIPLE INSERT WITH RETURN STATUS: " . Support::printToString($st
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
$t_1 = time();
$t_2 = time();
$t_3 = time();
$query = <<<EOM
INSERT INTO test_foo (
test
) VALUES
('EOM BAR 1 $t_1'),
('EOM BAR 2 $t_2'),
('EOM BAR 3 $t_3')
RETURNING test_foo_id, test
EOM;
$status = $db->dbExec($query);
print "EOM STRING DIRECT MULTIPLE INSERT WITH RETURN STATUS: " . Support::printToString($status) . " |<br>"
. "QUERY: " . $db->dbGetQuery() . " |<br>"
. "PRIMARY KEYS: " . print_r($db->dbGetInsertPK(), true) . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING EXT[test]: " . print_r($db->dbGetReturningExt('test'), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "<br>";
// no returning, but not needed ;
$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO; TEST " . time() . "')");
print "DIRECT INSERT NO RETURN STATUS: " . Support::printToString($status) . " |<br>"
@@ -240,6 +301,24 @@ if ($db->dbPrepare('sel_test_foo', $q_prep) === false) {
. $db->dbGetLastError() . "/" . $db->dbGetLastWarning() . "/"
. "<pre>" . print_r($db->dbGetCombinedErrorHistory(), true) . "</pre><br>";
}
echo "<hr>";
print "EOM STYLE STRINGS<br>";
$test_bar = $db->dbEscapeLiteral('SOMETHING DIFFERENT');
// Test EOM block
$q = <<<EOM
SELECT test_foo_id, test, some_bool, string_a, number_a,
-- comment
number_a_numeric, some_time
FROM test_foo
WHERE test = $test_bar
ORDER BY test_foo_id DESC LIMIT 5
EOM;
while (is_array($res = $db->dbReturn($q))) {
print "ROW: <pre>" . print_r($res, true) . "</pre><br>";
}
echo "<hr>";
// NOTE: try to replacate connection still exists if script is run a second time
// open pg bouncer connection
$db_pgb = new CoreLibs\DB\IO($DB_CONFIG['test_pgbouncer'], $log);

View File

@@ -1633,7 +1633,7 @@ EOM;
$this->session->checkActiveSession() === true &&
!empty($_SESSION['DEFAULT_LOCALE'])
) {
$locale = $_SESSION['DEFAULT_LOCALE'] ?? '';
$locale = $_SESSION['DEFAULT_LOCALE'];
} else {
$locale = (defined('SITE_LOCALE') && !empty(SITE_LOCALE)) ?
SITE_LOCALE :

View File

@@ -266,16 +266,18 @@ class IO
// 1: read new, keep at end, clean before new run
// 2: read new, clean at the end (temporary cache)
// 3: never cache
/** @var int */
/** @var int use cache (default) in dbReturn */
public const USE_CACHE = 0;
/** @var int */
/** @var int reset cache and read new in dbReturn */
public const READ_NEW = 1;
/** @var int */
/** @var int clear cache after read in dbeEturn */
public const CLEAR_CACHE = 2;
/** @var int */
/** @var int do not use any cache in dbReturn */
public const NO_CACHE = 3;
/** @var string */
/** @var string default hash type */
public const ERROR_HASH_TYPE = 'adler32';
/** @var string regex to get returning with matches at position 1 */
public const REGEX_RETURNING = '/\s?returning(?: (.+?));?$/i';
// recommend to set private/protected and only allow setting via method
// can bet set from outside
@@ -1007,7 +1009,7 @@ class IO
$this->pk_name_table[$table] : 'NULL';
}
if (
!preg_match("/ returning /i", $this->query) &&
!preg_match(self::REGEX_RETURNING, $this->query) &&
$this->pk_name && $this->pk_name != 'NULL'
) {
// check if this query has a ; at the end and remove it
@@ -1016,7 +1018,9 @@ class IO
$this->query = !is_string($__query) ? $this->query : $__query;
$this->query .= " RETURNING " . $this->pk_name;
$this->returning_id = true;
} elseif (preg_match("/ returning (.*)/i", $this->query, $matches)) {
} elseif (
preg_match(self::REGEX_RETURNING, $this->query, $matches)
) {
if ($this->pk_name && $this->pk_name != 'NULL') {
// add the primary key if it is not in the returning set
if (!preg_match("/$this->pk_name/", $matches[1])) {
@@ -1030,7 +1034,7 @@ class IO
// if we have an UPDATE and RETURNING, flag for true, but do not add anything
if (
$this->__checkQueryForUpdate($this->query) &&
preg_match("/ returning (.*)/i", $this->query, $matches)
preg_match(self::REGEX_RETURNING, $this->query, $matches)
) {
$this->returning_id = true;
}
@@ -2288,11 +2292,14 @@ class IO
$this->prepare_cursor[$stm_name]['pk_name'] = $pk_name;
}
// if no returning, then add it
if (!preg_match("/ returning /i", $query) && $this->prepare_cursor[$stm_name]['pk_name']) {
if (
!preg_match(self::REGEX_RETURNING, $query) &&
$this->prepare_cursor[$stm_name]['pk_name']
) {
$query .= " RETURNING " . $this->prepare_cursor[$stm_name]['pk_name'];
$this->prepare_cursor[$stm_name]['returning_id'] = true;
} elseif (
preg_match("/ returning (.*)/i", $query, $matches) &&
preg_match(self::REGEX_RETURNING, $query, $matches) &&
$this->prepare_cursor[$stm_name]['pk_name']
) {
// if returning exists but not pk_name, add it