diff --git a/.phan/config.php b/.phan/config.php
index 848e87e9..68c3202a 100644
--- a/.phan/config.php
+++ b/.phan/config.php
@@ -70,14 +70,14 @@ return [
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
- // Change this to include the folders you wish to analyze
- // (and the folders of their dependencies)
- 'www',
- // To speed up analysis, we recommend going back later and
- // limiting this to only the vendor/ subdirectories your
- // project depends on.
- // `phan --init` will generate a list of folders for you
- //'www/vendor',
+ // Change this to include the folders you wish to analyze
+ // (and the folders of their dependencies)
+ 'www',
+ // To speed up analysis, we recommend going back later and
+ // limiting this to only the vendor/ subdirectories your
+ // project depends on.
+ // `phan --init` will generate a list of folders for you
+ //'www/vendor',
],
diff --git a/www/admin/class_test.db.php b/www/admin/class_test.db.php
index 72cc1027..3c4bc184 100644
--- a/www/admin/class_test.db.php
+++ b/www/admin/class_test.db.php
@@ -65,74 +65,104 @@ while (is_array($res = $db->dbReturn("SELECT * FROM max_test"))) {
// }
print "
";
-$status = $db->dbExec("INSERT INTO foo (test) VALUES ('FOO TEST " . time() . "') RETURNING test");
+
+// truncate test_foo table before testing
+print "TRUNCATE test_foo
";
+$query = "TRUNCATE test_foo";
+$db->dbExec($query);
+print "TRUNCATE test_foobar
";
+$query = "TRUNCATE test_foobar";
+$db->dbExec($query);
+
+$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO TEST " . time() . "') RETURNING test");
print "DIRECT INSERT STATUS: $status | "
. "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) . "
";
// should throw deprecated error
// $db->getReturningExt();
print "DIRECT INSERT PREVIOUS INSERTED: "
- . print_r($db->dbReturnRow("SELECT foo_id, test FROM foo WHERE foo_id = " . $db->dbGetInsertPK()), true) . "
";
-$db->dbPrepare("ins_foo", "INSERT INTO foo (test) VALUES ($1)");
-$status = $db->dbExecute("ins_foo", array('BAR TEST ' . time()));
-print "PREPARE INSERT STATUS: $status | "
+ . print_r($db->dbReturnRow("SELECT test_foo_id, test FROM test_foo "
+ . "WHERE test_foo_id = " . $db->dbGetInsertPK()), true) . "
";
+
+// PREPARED INSERT
+$db->dbPrepare("ins_test_foo", "INSERT INTO test_foo (test) VALUES ($1) RETURNING test");
+$status = $db->dbExecute("ins_test_foo", array('BAR TEST ' . time()));
+print "PREPARE INSERT[ins_test_foo] STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING RETURN: " . print_r($db->dbGetReturningArray(), true) . "
";
print "PREPARE INSERT PREVIOUS INSERTED: "
- . print_r($db->dbReturnRow("SELECT foo_id, test FROM foo WHERE foo_id = " . $db->dbGetInsertPK()), true) . "
";
+ . print_r($db->dbReturnRow("SELECT test_foo_id, test FROM test_foo "
+ . "WHERE test_foo_id = " . $db->dbGetInsertPK()), true) . "
";
// returning test with multiple entries
// $status = $db->db_exec(
-// "INSERT INTO foo (test) VALUES "
+// "INSERT INTO test_foo (test) VALUES "
// . "('BAR 1 " . time() . "'), "
// . "('BAR 2 " . time() . "'), "
// . "('BAR 3 " . time() . "') "
-// . "RETURNING foo_id"
+// . "RETURNING test_foo_id"
// );
$status = $db->dbExec(
- "INSERT INTO foo (test) VALUES "
+ "INSERT INTO test_foo (test) VALUES "
. "('BAR 1 " . time() . "'), "
. "('BAR 2 " . time() . "'), "
. "('BAR 3 " . time() . "') "
- . "RETURNING foo_id, test"
+ . "RETURNING test_foo_id, test"
);
-print "DIRECT MULTIPLE INSERT STATUS: $status | "
+print "DIRECT MULTIPLE INSERT WITH RETURN STATUS: $status | "
. "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) . "
";
// no returning, but not needed ;
-$status = $db->dbExec("INSERT INTO foo (test) VALUES ('FOO; TEST " . time() . "');");
-print "DIRECT INSERT STATUS: $status | "
+$status = $db->dbExec("INSERT INTO test_foo (test) VALUES ('FOO; TEST " . time() . "');");
+print "DIRECT INSERT NO RETURN STATUS: $status | "
. "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "
";
// UPDATE WITH RETURNING
-$status = $db->dbExec("UPDATE foo SET test = 'SOMETHING DIFFERENT' WHERE foo_id = 3688452 RETURNING test");
-print "UPDATE STATUS: $status | "
+$status = $db->dbExec("UPDATE test_foo SET test = 'SOMETHING DIFFERENT' WHERE test_foo_id = 3688452 RETURNING test");
+print "UPDATE WITH RETURN STATUS: $status | "
. "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
. "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "
";
+
+
+// INSERT WITH NO RETURNING
+$status = $db->dbExec("INSERT INTO test_foobar (type, integer) VALUES ('WITH DATA', 123)");
+print "INSERT WITH NO PRIMARY KEY NO RETURNING STATUS: $status | "
+ . "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
+ . "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
+ . "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "
";
+
+$status = $db->dbExec("INSERT INTO test_foobar (type, integer) VALUES ('WITH DATA', 123) RETURNING type, integer");
+print "INSERT WITH NO PRIMARY KEY WITH RETURNING STATUS: $status | "
+ . "PRIMARY KEY: " . $db->dbGetInsertPK() . " | "
+ . "RETURNING EXT: " . print_r($db->dbGetReturningExt(), true) . " | "
+ . "RETURNING ARRAY: " . print_r($db->dbGetReturningArray(), true) . "
";
+
print "";
-// REEAD PREPARE
+// READ PREPARE
if (
$db->dbPrepare(
- 'sel_foo',
- "SELECT foo_id, test, some_bool, string_a, number_a, number_a_numeric, some_time "
- . "FROM foo ORDER BY foo_id DESC LIMIT 5"
+ 'sel_test_foo',
+ "SELECT test_foo_id, test, some_bool, string_a, number_a, number_a_numeric, some_time "
+ . "FROM test_foo ORDER BY test_foo_id DESC LIMIT 5"
) === false
) {
- print "Error in sel_foo prepare
";
+ print "Error in sel_test_foo prepare
";
} else {
$max_rows = 6;
// do not run this in dbFetchArray directly as
// dbFetchArray(dbExecute(...))
// this will end in an endless loop
- $cursor = $db->dbExecute('sel_foo', []);
+ $cursor = $db->dbExecute('sel_test_foo', []);
$i = 1;
while (($res = $db->dbFetchArray($cursor, true)) !== false) {
print "DB PREP EXEC FETCH ARR: " . $i . ": " . print_r($res, true) . "
";
@@ -142,14 +172,16 @@ if (
# db write class test
-$table = 'foo';
+$table = 'test_foo';
print "TABLE META DATA: " . DgS::printAr($db->dbShowTableMetaData($table)) . "
";
+// insert first, then use primary key to update
$primary_key = ''; # unset
-$db_write_table = array('test', 'string_a', 'number_a', 'some_bool');
-// $db_write_table = array('test');
-$object_fields_not_touch = array();
-$object_fields_not_update = array();
-$data = array('test' => 'BOOL TEST SOMETHING ' . time(), 'string_a' => 'SOME TEXT', 'number_a' => 5);
+$db_write_table = ['test', 'string_a', 'number_a', 'some_bool'];
+$object_fields_not_touch = [];
+$object_fields_not_update = [];
+$data = [
+ 'test' => 'dbWriteDataExt: BOOL TEST SOMETHING ' . time(), 'string_a' => 'SOME TEXT', 'number_a' => 5
+];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -158,8 +190,10 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
-print "Wrote to DB tabel $table and got primary key $primary_key
";
-$data = array('test' => 'BOOL TEST ON ' . time(), 'string_a' => '', 'number_a' => 0, 'some_bool' => 1);
+print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key
";
+$data = [
+ 'test' => 'dbWriteDataExt: BOOL TEST ON ' . time(), 'string_a' => '', 'number_a' => 0, 'some_bool' => 1
+];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -168,8 +202,10 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
-print "Wrote to DB tabel $table and got primary key $primary_key
";
-$data = array('test' => 'BOOL TEST OFF ' . time(), 'string_a' => null, 'number_a' => null, 'some_bool' => 0);
+print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key
";
+$data = [
+ 'test' => 'dbWriteDataExt: BOOL TEST OFF ' . time(), 'string_a' => null, 'number_a' => null, 'some_bool' => 0
+];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -178,8 +214,10 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
-print "Wrote to DB tabel $table and got primary key $primary_key
";
-$data = array('test' => 'BOOL TEST UNSET ' . time());
+print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key
";
+$data = [
+ 'test' => 'dbWriteDataExt: BOOL TEST UNSET ' . time()
+];
$primary_key = $db->dbWriteDataExt(
$db_write_table,
$primary_key,
@@ -188,7 +226,7 @@ $primary_key = $db->dbWriteDataExt(
$object_fields_not_update,
$data
);
-print "Wrote to DB tabel $table and got primary key $primary_key
";
+print "Wrote to DB tabel $table with data " . print_r($data, true) . " and got primary key $primary_key
";
// return Array Test
$query = "SELECT type, sdate, integer FROM foobar";
@@ -196,7 +234,8 @@ $data = $db->dbReturnArray($query, true);
print "Full foobar list:
" . print_r($data, true) . "
";
# async test queries
-/* $db->dbExecAsync("SELECT test FROM foo, (SELECT pg_sleep(10)) as sub WHERE foo_id IN (27, 50, 67, 44, 10)");
+/*
+$db->dbExecAsync("SELECT test FROM test_foo, (SELECT pg_sleep(10)) as sub WHERE test_foo_id IN (27, 50, 67, 44, 10)");
echo "WAITING FOR ASYNC: ";
$chars = array('|', '/', '-', '\\');
while (($ret = $db->dbCheckAsync()) === true)
@@ -217,7 +256,7 @@ while ($res = $db->dbFetchArray())
echo "RES: " . $res['test'] . "
";
}
# test async insert
-$db->dbExecAsync("INSERT INTO foo (Test) VALUES ('ASYNC TEST " . time() . "')");
+$db->dbExecAsync("INSERT INTO test_foo (Test) VALUES ('ASYNC TEST " . time() . "')");
echo "WAITING FOR ASYNC INSERT: ";
while (($ret = $db->dbCheckAsync()) === true)
{
@@ -227,7 +266,12 @@ while (($ret = $db->dbCheckAsync()) === true)
}
print "
END STATUS: " . $ret . " | PK: " . $db->insert_id . "
";
print "ASYNC PREVIOUS INSERTED: "
- . print_r($db->dbReturnRow("SELECT foo_id, test FROM foo WHERE foo_id = " . $db->insert_id), true) . "
"; */
+ . print_r(
+ $db->dbReturnRow("SELECT test_foo_id, test FROM test_foo WHERE test_foo_id = "
+ . $db->insert_id),
+ true
+ ) . "
";
+*/
$to_db_version = '9.1.9';
print "VERSION DB: " . $db->dbVersion() . "
";
@@ -237,16 +281,17 @@ print "DB Version equal $to_db_version: " . $db->dbCompareVersion('=' . $to_db_v
print "DB Version bigger than $to_db_version: " . $db->dbCompareVersion('>=' . $to_db_version) . "
";
print "DB Version bigger $to_db_version: " . $db->dbCompareVersion('>' . $to_db_version) . "
";
-/* $q = "SELECT FOO FRO BAR";
-// $q = "Select * from foo";
-$foo = $db->dbExecAsync($q);
+/*
+$q = "Select * from test_foo";
+$test_foo = $db->dbExecAsync($q);
print "[ERR] Query: " . $q . "
";
-print "[ERR] RESOURCE: $foo
";
+print "[ERR] RESOURCE: $test_foo
";
while (($ret = $db->dbCheckAsync()) === true)
{
print "[ERR]: $ret
";
sleep(5);
-} */
+}
+*/
// search path check
$q = "SHOW search_path";
@@ -260,7 +305,7 @@ $status = $db->dbExec(
. "('TIME: " . time() . "', " . rand(1, 10) . ")"
);
print "OTHER SCHEMA INSERT STATUS: "
- . $status . " | PK NAME: " . $db->pk_name . ", PRIMARY KEY: " . $db->insert_id . "
";
+ . $status . " | PK NAME: " . $db->dbGetInsertPKName() . ", PRIMARY KEY: " . $db->dbGetInsertPK() . "
";
print "NULL TEST DB READ
";
$q = "SELECT uid, null_varchar, null_int FROM test_null_data WHERE uid = 'A'";
diff --git a/www/frontend/index.php b/www/frontend/index.php
index c4441331..a251ca17 100644
--- a/www/frontend/index.php
+++ b/www/frontend/index.php
@@ -3,3 +3,5 @@
declare(strict_types=1);
require 'config.php';
+
+// __END__
diff --git a/www/lib/CoreLibs/DB/Extended/ArrayIO.php b/www/lib/CoreLibs/DB/Extended/ArrayIO.php
index 0dc17f63..1594a30d 100644
--- a/www/lib/CoreLibs/DB/Extended/ArrayIO.php
+++ b/www/lib/CoreLibs/DB/Extended/ArrayIO.php
@@ -539,8 +539,8 @@ class ArrayIO extends \CoreLibs\DB\IO
// set primary key
if ($insert) {
// FIXME: this has to be fixes by fixing DB::IO clas
- $insert_id = $this->dbGetReturning();
- if (is_bool($insert_id) || is_array($insert_id)) {
+ $insert_id = $this->dbGetInsertPK();
+ if (is_array($insert_id)) {
$insert_id = 0;
}
$this->table_array[$this->pk_name]['value'] = $insert_id;
diff --git a/www/lib/CoreLibs/DB/IO.php b/www/lib/CoreLibs/DB/IO.php
index 875463ad..823e4c32 100644
--- a/www/lib/CoreLibs/DB/IO.php
+++ b/www/lib/CoreLibs/DB/IO.php
@@ -298,13 +298,10 @@ class IO extends \CoreLibs\Basic
public $num_fields; // how many fields has the query
/** @var array */
public $field_names = []; // array with the field names of the current query
- // FIXME: insert_id and insert_id_ext should not be such a mixed mess
- /** @var string|int|bool|array */
- public $insert_id; // last inserted ID
- /** @var string|int|bool|array */
- public $insert_id_ext; // extended insert ID (for data outside only primary key)
/** @var array */
- public $insert_id_arr; // always return as array, even if only one
+ private $insert_id_arr; // always return as array, even if only one
+ /** @var string */
+ private $insert_id_pk_name; // primary key name for insert recovery from insert_id_arr
/** @var string */
private $temp_sql;
// other vars
@@ -345,7 +342,7 @@ class IO extends \CoreLibs\Basic
public $pk_name_table = [];
// internal primary key name, for cross calls in async
/** @var string */
- public $pk_name;
+ private $pk_name;
// if we use RETURNING in the INSERT call
/** @var bool */
private $returning_id = false;
@@ -604,6 +601,14 @@ class IO extends \CoreLibs\Basic
if ($type) {
$prefix .= '{' . $type . '} ';
}
+ switch ($id) {
+ case 'DB_ERROR':
+ $prefix .= 'DB-Error:';
+ break;
+ case 'DB_WARNING':
+ $prefix .= 'DB-Warning:';
+ break;
+ }
if ($prefix) {
$prefix .= '- ';
}
@@ -637,9 +642,8 @@ class IO extends \CoreLibs\Basic
// write error msg ...
$this->__dbDebug(
'db',
- 'DB-Error ' . $this->error_id . ': '
- . $this->error_string[$this->error_id] . ($msg ? ', ' . $msg : '')
- . '',
+ $this->error_id . ': ' . $this->error_string[$this->error_id]
+ . ($msg ? ', ' . $msg : ''),
'DB_ERROR',
$where_called
);
@@ -649,9 +653,8 @@ class IO extends \CoreLibs\Basic
if ($this->warning_id) {
$this->__dbDebug(
'db',
- 'DB-Warning ' . $this->warning_id . ': '
- . $this->error_string[$this->warning_id]
- . ($msg ? ', ' . $msg : '') . '',
+ $this->warning_id . ': ' . $this->error_string[$this->warning_id]
+ . ($msg ? ', ' . $msg : ''),
'DB_WARNING',
$where_called
);
@@ -785,7 +788,7 @@ class IO extends \CoreLibs\Basic
// check if this query has a ; at the end and remove it
$__query = preg_replace("/(;\s*)$/", '', $this->query);
// must be query, if preg replace failed, use query as before
- $this->query = !is_string($__query) ? $this->query : $query;
+ $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)) {
@@ -868,83 +871,112 @@ class IO extends \CoreLibs\Basic
// count affected rows
$this->num_rows = $this->db_functions->__dbAffectedRows($this->cursor);
if (
+ // ONLY insert with set pk name
($this->__checkQueryForInsert($this->query, true) && $this->pk_name != 'NULL') ||
- ($this->__checkQueryForUpdate($this->query) && $this->returning_id)
+ // insert or update with returning add
+ ($this->__checkQueryForInsert($this->query) && $this->returning_id)
) {
- // set insert_id
- // if we do not have a returning, we try to get it via the primary key and another select
- if (!$this->returning_id) {
- $this->insert_id = $this->db_functions->__dbInsertId($this->query, $this->pk_name);
- $this->insert_id_ext = $this->insert_id;
- $this->insert_id_arr[] = $this->insert_id;
- } else {
- $this->insert_id = [];
- $this->insert_id_ext = [];
- $this->insert_id_arr = [];
- // echo "** PREPARE RETURNING FOR CURSOR: ".$this->cursor."
";
- // we have returning, now we need to check if we get one or many returned
- // we'll need to loop this, if we have multiple insert_id returns
- while (
- $_insert_id = $this->db_functions->__dbFetchArray(
- $this->cursor,
- $this->db_functions->__dbResultType(true)
- )
- ) {
- // echo "*** RETURNING: ".print_r($_insert_id, true)."
";
- $this->insert_id[] = $_insert_id;
- $this->insert_id_arr[] = $_insert_id;
- }
- // if we have only one, revert from array to single
- if (count($this->insert_id) == 1) {
- // $this->log->debug('SINGLE DATA CONVERT', count($this->insert_id[0])." => "
- // .array_key_exists($this->pk_name, $this->insert_id[0]));
- // $this->log->debug('PK DIRECT', (isset($this->insert_id[0][$this->pk_name]) ?
- // $this->insert_id[0][$this->pk_name] : '[NO PK NAME SET]' ));
- // if this has only the pk_name, then only return this,
- // else array of all data (but without the position)
- // example if insert_id[0]['foo'] && insert_id[0]['bar']
- // it will become insert_id['foo'] & insert_id['bar']
- // if only ['foo_id'] and it is the PK then the
- // PK is directly written to the insert_id
- if (
- // FIXME: everything should be an array
- /** @phpstan-ignore-next-line */
- count($this->insert_id[0]) > 1 ||
- /** @phpstan-ignore-next-line */
- !array_key_exists($this->pk_name, $this->insert_id[0])
- ) {
- $this->insert_id_ext = $this->insert_id[0];
- /** @phpstan-ignore-next-line */
- if (isset($this->insert_id[0][$this->pk_name])) {
- $this->insert_id = $this->insert_id[0][$this->pk_name];
- }
- } elseif (isset($this->insert_id[0][$this->pk_name])) {
- $this->insert_id = $this->insert_id[0][$this->pk_name];
- }
- } elseif (
- !is_array($this->insert_id) ||
- count($this->insert_id) == 0
- ) {
- // if we have non -> error
- // failed to get insert id
- $this->insert_id = '';
- $this->warning_id = 33;
- $this->__dbError($this->cursor, '[dbExec]');
- }
- // if we have multiple, do not set the insert_id different, keep as array
- }
- // this warning handling is only for pgsql
- // we returned an array of PKs instread of a single one
- if (is_array($this->insert_id)) {
- $this->warning_id = 32;
- $this->__dbError($this->cursor, '[dbExec]');
- }
+ $this->__dbSetInsertId(
+ $this->returning_id,
+ $this->query,
+ $this->pk_name,
+ $this->cursor
+ );
}
}
return true;
}
}
+ /**
+ * Get all returning variables
+ * try to primary get the OK into insert_id
+ * - one if single
+ * - array if many to return
+ * - if many this will also hold all non pk names too
+ * then try to fill insert_id_arr, this is always multi level
+ * - fill key: value as single array or multi array
+ * insert_id_ext
+ * - holds all returning as array
+ * TODO: Only use insert_id_arr and use functions to get ok array or single
+ * @param boolean $returning_id
+ * @param string $query
+ * @param string|null $pk_name
+ * @param resource $cursor
+ * @param string|null $stm_name If not null, is dbExecutre run
+ * @return void
+ */
+ private function __dbSetInsertId(
+ bool $returning_id,
+ string $query,
+ ?string $pk_name,
+ $cursor,
+ ?string $stm_name = null
+ ): void {
+ // $this->log->debug('DB SET INSERT ID', 'Ret: ' . ($returning_id ? 'Y' : 'N')
+ // . 'Q: ' . $query . ', PK: ' . $pk_name . ', S: ' . ($stm_name ?? '{-}'));
+ // as internval user only
+ $insert_id = null;
+ // reset internal array
+ $this->insert_id_arr = [];
+ // set the primary key name
+ $this->insert_id_pk_name = $pk_name ?? '';
+ // set insert_id
+ // if we do not have a returning
+ // we try to get it via the primary key and another select
+ if (!$returning_id) {
+ $insert_id = $this->db_functions->__dbInsertId($query, $pk_name);
+ $this->insert_id_arr[] = $insert_id;
+ // throw warning that no pk was found
+ if ($insert_id === false) {
+ $this->warning_id = 31;
+ $this->__dbError($cursor, '[dbExec]');
+ }
+ } elseif (
+ $stm_name === null ||
+ ($stm_name !== null && !empty($cursor))
+ ) {
+ // we have returning, now we need to check if we get one or many returned
+ // we'll need to loop this, if we have multiple insert_id returns
+ while (
+ is_array($insert_id = $this->db_functions->__dbFetchArray(
+ $cursor,
+ $this->db_functions->__dbResultType(true)
+ ))
+ ) {
+ $this->insert_id_arr[] = $insert_id;
+ }
+ // warning if we didn't get any returning data
+ if (count($this->insert_id_arr) == 0) {
+ // failed to get insert id
+ $this->warning_id = 33;
+ if ($stm_name === null) {
+ $this->__dbError($cursor, '[dbExec]');
+ } else {
+ $this->__dbError();
+ $this->__dbDebug(
+ 'db',
+ $stm_name . ': RETURNING returned no data',
+ 'DB_WARNING'
+ );
+ }
+ } elseif (count($this->insert_id_arr) > 1) {
+ // this error handling is only for INSERT (), (), ... sets
+ $this->warning_id = 32;
+ if ($stm_name === null) {
+ $this->__dbError($cursor, '[dbExec]');
+ } else {
+ $this->__dbError();
+ $this->__dbDebug(
+ 'db',
+ $stm_name . ': RETURNING returned an array (possible multiple insert)',
+ 'DB_WARNING'
+ );
+ }
+ }
+ }
+ }
+
// *************************************************************
// PUBLIC METHODS
// *************************************************************
@@ -1806,7 +1838,7 @@ class IO extends \CoreLibs\Basic
* runs a prepare query
* @param string $stm_name statement name for the query to run
* @param array $data data to run for this query, empty array for none
- * @return ?mixed false on error, or result on OK
+ * @return mixed false on error, or result on OK
*/
public function dbExecute(string $stm_name, array $data = [])
{
@@ -1862,89 +1894,21 @@ class IO extends \CoreLibs\Basic
return false;
}
if (
- $this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query'], true) &&
- $this->prepare_cursor[$stm_name]['pk_name'] != 'NULL'
+ // pure insert wth pk name
+ ($this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query'], true) &&
+ $this->prepare_cursor[$stm_name]['pk_name'] != 'NULL') ||
+ // insert or update with returning set
+ ($this->__checkQueryForInsert($this->prepare_cursor[$stm_name]['query']) &&
+ $this->prepare_cursor[$stm_name]['returning_id'] === true
+ )
) {
- if (!$this->prepare_cursor[$stm_name]['returning_id']) {
- $this->insert_id = $this->db_functions->__dbInsertId(
- $this->prepare_cursor[$stm_name]['query'],
- $this->prepare_cursor[$stm_name]['pk_name']
- );
- $this->insert_id_ext = $this->insert_id;
- $this->insert_id_arr[] = $this->insert_id;
- } elseif (!empty($result)) {
- $this->insert_id = [];
- $this->insert_id_ext = [];
- $this->insert_id_arr = [];
- // we have returning, now we need to check if we get one or many returned
- // we'll need to loop this, if we have multiple insert_id returns
- while (
- $_insert_id = $this->db_functions->__dbFetchArray(
- $result,
- $this->db_functions->__dbResultType(true)
- )
- ) {
- $this->insert_id[] = $_insert_id;
- $this->insert_id_arr[] = $_insert_id;
- }
- // if we have only one, revert from arry to single
- if (count($this->insert_id) == 1) {
- // $this->log->debug('SINGLE DATA CONVERT', count($this->insert_id[0])." => "
- // .array_key_exists($this->prepare_cursor[$stm_name]['pk_name'], $this->insert_id[0]));
- // $this->log->debug('PK DIRECT', $this->insert_id[0][$this->prepare_cursor[$stm_name]['pk_name']]);
- // if this has only the pk_name, then only return this,
- // else array of all data (but without the position)
- // example if insert_id[0]['foo'] && insert_id[0]['bar']
- // it will become insert_id['foo'] & insert_id['bar']
- // if only ['foo_id'] and it is the PK then the PK is directly
- // written to the insert_id
- if (
- // FIXME: all return insert_id should be array only
- /** @phpstan-ignore-next-line */
- count($this->insert_id[0]) > 1 ||
- /** @phpstan-ignore-next-line */
- !array_key_exists($this->prepare_cursor[$stm_name]['pk_name'], $this->insert_id[0])
- ) {
- $this->insert_id_ext = $this->insert_id[0];
- /** @phpstan-ignore-next-line */
- $this->insert_id = $this->insert_id[0][$this->prepare_cursor[$stm_name]['pk_name']];
- } elseif ($this->insert_id[0][$this->prepare_cursor[$stm_name]['pk_name']]) {
- $this->insert_id = $this->insert_id[0][$this->prepare_cursor[$stm_name]['pk_name']];
- }
- } elseif (count($this->insert_id) == 0) {
- // failed to get insert id
- $this->insert_id = '';
- $this->warning_id = 33;
- $this->__dbError();
- $this->__dbDebug(
- 'db',
- 'DB-Warning ' . $stm_name
- . ': insert id returned no data',
- 'DB_WARNING'
- );
- }
- }
- // this error handling is only for pgsql
- if (is_array($this->insert_id)) {
- $this->warning_id = 32;
- $this->__dbError();
- $this->__dbDebug(
- 'db',
- 'DB-Warning ' . $stm_name
- . ': insert id data returned as array',
- 'DB_WARNING'
- );
- } elseif (!$this->insert_id) {
- // NOTE should we keep this inside
- $this->warning_id = 31;
- $this->__dbError();
- $this->__dbDebug(
- 'db',
- 'DB-Warning ' . $stm_name
- . ': Could not get insert id',
- 'DB_WARNING'
- );
- }
+ $this->__dbSetInsertId(
+ $this->prepare_cursor[$stm_name]['returning_id'],
+ $this->prepare_cursor[$stm_name]['query'],
+ $this->prepare_cursor[$stm_name]['pk_name'],
+ $result,
+ $stm_name
+ );
}
return $result;
}
@@ -2251,7 +2215,7 @@ class IO extends \CoreLibs\Basic
return false;
}
if (!$primary_key['value']) {
- $primary_key['value'] = $this->insert_id;
+ $primary_key['value'] = $this->dbGetInsertPK();
}
// if there is not priamry key value field return false
return $primary_key['value'] ?? false;
@@ -2334,50 +2298,91 @@ class IO extends \CoreLibs\Basic
* Array for multiple return set
* Empty string for unset
* Null for error
+ * @deprecated Use ->dbGetInsertPK();
*/
public function dbGetReturning()
{
- // FIXME: this should be only an array
- return $this->insert_id;
+ return $this->dbGetInsertPK();
}
/**
- * alternative name, returns insert_id
- * @return array|string|int|bool|null Primary key value, most likely int
- * Array for multiple return set
- * Empty string for unset
- * Null for error
+ * returns current set primary key name for last run query
+ * Is empty string if not setable
+ *
+ * @return string Primary key name
+ */
+ public function dbGetInsertPKName(): string
+ {
+ return $this->insert_id_pk_name;
+ }
+
+ /**
+ * Returns current primary key for inserted row.
+ * Either a single element for a single insert or an array
+ * if multiple insert values where used.
+ *
+ * @return array|string|int|null Current insert query primary key
*/
public function dbGetInsertPK()
{
- // FIXME: this should be only an array
- return $this->dbGetReturning();
+ return $this->dbGetReturningExt($this->insert_id_pk_name);
}
/**
- * return the extended insert return string set
- * Most likely Array
- * @param string|null $key Optional key for insert_id_ext array
- * if found will return only this element,
- * else will return null
- * @return array|string|int|bool|null RETURNING values as array
- * Empty string for unset
- * Null for error
+ * Returns the full RETURNING array
+ * If no parameter given returns as is:
+ * Either as single array level for single insert
+ * Or nested array for multiple insert values
+ *
+ * If key was set only returns those values directly or as array
+ *
+ * On multiple insert return the position for which to return can be set too
+ *
+ * @param string|null $key
+ * @param integer|null $pos
+ * @return array|string|int|null
*/
- public function dbGetReturningExt($key = null)
+ public function dbGetReturningExt(?string $key = null, ?int $pos = null)
{
- // FIXME: this has to be better as in return
- if ($key !== null) {
- if (
- is_array($this->insert_id_ext) &&
- isset($this->insert_id_ext[$key])
- ) {
- return $this->insert_id_ext[$key];
+ // return as is if key is null
+ if ($key === null) {
+ if (count($this->insert_id_arr) == 1) {
+ // return as nul if not found
+ return $this->insert_id_arr[0] ?? null;
} else {
- return null;
+ return $this->insert_id_arr;
}
}
- return $this->insert_id_ext;
+ // no key string set
+ if (empty($key)) {
+ return null;
+ }
+ if (
+ count($this->insert_id_arr) == 1 &&
+ isset($this->insert_id_arr[0][$key])
+ ) {
+ return $this->insert_id_arr[0][$key];
+ } elseif (count($this->insert_id_arr) > 1) {
+ // do we try to find at one position
+ if ($pos !== null) {
+ if (isset($this->insert_id_arr[$pos][$key])) {
+ return $this->insert_id_arr[$pos][$key];
+ } else {
+ return null;
+ }
+ } else {
+ // find in all inside the array
+ $__arr = array_column($this->insert_id_arr, $key);
+ if (count($__arr)) {
+ return $__arr;
+ } else {
+ return null;
+ }
+ }
+ } else {
+ // not found
+ return null;
+ }
}
/**
@@ -2424,6 +2429,17 @@ class IO extends \CoreLibs\Basic
return $this->num_rows ?? null;
}
+ /**
+ * Sets error number that was last
+ * So we always have the last error number stored even if a new one is created
+ *
+ * @return int last error number
+ */
+ public function getHadError()
+ {
+ return $this->had_error;
+ }
+
// DEPEREACTED CALLS
/**
@@ -2446,7 +2462,7 @@ class IO extends \CoreLibs\Basic
public function getReturning()
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetReturning()', E_USER_DEPRECATED);
- return $this->dbGetReturning();
+ return $this->dbGetInsertPK();
}
/**
@@ -2457,7 +2473,7 @@ class IO extends \CoreLibs\Basic
public function getInsertPK()
{
trigger_error('Method ' . __METHOD__ . ' is deprecated, use dbGetInsertPK()', E_USER_DEPRECATED);
- return $this->dbGetReturning();
+ return $this->dbGetInsertPK();
}
/**
@@ -2495,16 +2511,6 @@ class IO extends \CoreLibs\Basic
return $this->dbGetNumRows();
}
- /**
- * Sets error number that was last
- * So we always have the last error number stored even if a new one is created
- *
- * @return int last error number
- */
- public function getHadError()
- {
- return $this->had_error;
- }
// end if db class
}
diff --git a/www/lib/CoreLibs/DB/SQL/PgSQL.php b/www/lib/CoreLibs/DB/SQL/PgSQL.php
index b6678143..653c77c6 100644
--- a/www/lib/CoreLibs/DB/SQL/PgSQL.php
+++ b/www/lib/CoreLibs/DB/SQL/PgSQL.php
@@ -262,10 +262,10 @@ class PgSQL
* this only works if db schema is after "no plural names. and pk name is table name + _id
* detects schema prefix in table name
* @param string $query query string
- * @param string $pk_name primary key name, if '' then auto detect
+ * @param string|null $pk_name primary key name, if '' then auto detect
* @return string|int|false primary key value
*/
- public function __dbInsertId(string $query, string $pk_name)
+ public function __dbInsertId(string $query, ?string $pk_name)
{
// only if an insert has been done
if (preg_match("/^insert /i", $query)) {
@@ -280,7 +280,7 @@ class PgSQL
$table = $_table;
}
// no PK name given at all
- if (!$pk_name) {
+ if (empty($pk_name)) {
// if name is plurar, make it singular
// if (preg_match("/.*s$/i", $table))
// $table = substr($table, 0, -1);
diff --git a/www/lib/CoreLibs/Output/Form/Generate.php b/www/lib/CoreLibs/Output/Form/Generate.php
index b2c44729..b2afca9d 100644
--- a/www/lib/CoreLibs/Output/Form/Generate.php
+++ b/www/lib/CoreLibs/Output/Form/Generate.php
@@ -1674,14 +1674,14 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO
. ' (' . $this->table_array[$key]['input_name'] . ') VALUES ('
. "'" . $this->dbEscapeString($this->table_array[$key]['input_value']) . "')";
$this->dbExec($q);
- if (!empty($this->table_array[$key]['where']) && is_numeric($this->insert_id)) {
+ if (!empty($this->table_array[$key]['where']) && is_numeric($this->dbGetInsertPK())) {
// make an update on the just inseted data with the where data als update values
$q = 'UPDATE ' . $this->table_array[$key]['table_name'] . ' SET ';
$q .= $this->table_array[$key]['where'] . ' ';
- $q .= 'WHERE ' . $this->table_array[$key]['pk_name'] . ' = ' . $this->insert_id;
+ $q .= 'WHERE ' . $this->table_array[$key]['pk_name'] . ' = ' . $this->dbGetInsertPK();
$this->dbExec($q);
}
- $this->table_array[$key]['value'] = $this->insert_id;
+ $this->table_array[$key]['value'] = $this->dbGetInsertPK();
} // set value from DB through select or insert
unset($this->table_array[$key]['input_value']);
} // if it is certain field type && if there is something in the temp field