summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Newnham <mark@newnhams.com>2026-02-19 19:27:59 -0700
committerMark Newnham <mark@newnhams.com>2026-02-19 19:27:59 -0700
commitf72a88fc785056416eea3933d61d4cf2603b09ff (patch)
tree3cee0d260f15e04da9fb236a2269571de3c3717f
parentd3831ef214ddc313c10260de685dcfcf6f1a4365 (diff)
parent8ac6fa21f4dab9a3b8435674411b8fac4457259d (diff)
downloadadodb-f72a88fc785056416eea3933d61d4cf2603b09ff.tar.gz
adodb-f72a88fc785056416eea3933d61d4cf2603b09ff.tar.bz2
adodb-f72a88fc785056416eea3933d61d4cf2603b09ff.zip
Merge branch 'master' of https://github.com/ADOdb/ADOdb into 1174-oci8-metaforeignkeys-fails-if-the-foreign-key-contains-more-than-one-column
-rw-r--r--adodb.inc.php53
-rw-r--r--drivers/adodb-db2.inc.php83
-rw-r--r--drivers/adodb-mssqlnative.inc.php182
-rw-r--r--drivers/adodb-mysqli.inc.php139
-rw-r--r--drivers/adodb-oci8.inc.php10
-rw-r--r--drivers/adodb-postgres64.inc.php76
6 files changed, 409 insertions, 134 deletions
diff --git a/adodb.inc.php b/adodb.inc.php
index 4b9b37bb..485ae4ea 100644
--- a/adodb.inc.php
+++ b/adodb.inc.php
@@ -756,6 +756,15 @@ if (!defined('_ADODB_LAYER')) {
/** @var string a specified locale. */
var $locale;
+ /**
+ * Setting true forces {@see metaColumns()} to read the db for
+ * each access of a table instead of using cached version.
+ * Currently only works on mssqlnative
+ *
+ * @var bool
+ */
+ public bool $cachedSchemaFlush = false;
+
/**
* Default Constructor.
@@ -3380,29 +3389,43 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * List columns names in a table as an array.
- * @param table table name to query
+ * List columns names in a table as an array
+ *
+ * @param string $table table name to query
+ * @param bool $numIndexes return numeric keys
+ * @param bool $useattnum discarded in base class
*
- * @return array of column names for current table.
+ * @return false|array of column names for current table.
*/
- function MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for postgres */) {
+ public function MetaColumnNames(
+ string $table,
+ bool $numIndexes=false,
+ bool $useattnum=false
+ ) : mixed {
+
$objarr = $this->MetaColumns($table);
if (!is_array($objarr)) {
return false;
}
- $arr = array();
- if ($numIndexes) {
- $i = 0;
- if ($useattnum) {
- foreach($objarr as $v)
- $arr[$v->attnum] = $v->name;
- } else
- foreach($objarr as $v) $arr[$i++] = $v->name;
- } else
- foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
+ if ($useattnum) {
+ /*
+ * Assume we want a numeric array to
+ * match the postgres option
+ */
+ $numIndexes = true;
+ }
- return $arr;
+ $columnNames = [];
+ foreach($objarr as $v) {
+ $columnNames[strtoupper($v->name)] = $v->name;
+ }
+
+ if ($numIndexes) {
+ return array_values($columnNames);
+ }
+
+ return $columnNames;
}
/**
diff --git a/drivers/adodb-db2.inc.php b/drivers/adodb-db2.inc.php
index cedab5b9..4ecfdb1c 100644
--- a/drivers/adodb-db2.inc.php
+++ b/drivers/adodb-db2.inc.php
@@ -852,7 +852,7 @@ class ADODB_db2 extends ADOConnection {
$schema = '';
$this->_findschema($table,$schema);
- $metaTables = $this->metaTables('T','',$table);
+ $metaTables = $this->metaTables('T', $owner, $table);
if ($metaTables == false) {
return false;
@@ -881,6 +881,9 @@ class ADODB_db2 extends ADOConnection {
foreach ($results as $r)
{
+ $r = array_change_key_case($r, CASE_UPPER);
+
+
/*
[CONSTNAME] => SQL250829011849680
@@ -900,22 +903,46 @@ class ADODB_db2 extends ADOConnection {
[DEFINER] => DB2INST1
)
*/
- $referenceTable = trim($r['REFTABNAME']);
- if (!array_key_exists($referenceTable,$foreignKeys)) {
+ $casing = $upper ? CASE_UPPER : CASE_LOWER;
+
+ $referenceTable = trim($r['REFTABNAME']);
+
+ if ($casing == CASE_UPPER) {
+ $referenceTable = strtoupper($referenceTable);
+ } else {
+ $referenceTable = strtolower($referenceTable);
+ }
+
+ if (!array_key_exists($referenceTable, $foreignKeys)) {
$foreignKeys[$referenceTable] = array();
}
- $pkColnames = array_filter(preg_split('/ +/', $r['PK_COLNAMES']));
+
+ $pkColnames = array_filter(preg_split('/ +/', $r['PK_COLNAMES']) );
$fkColnames = array_filter(preg_split('/ +/', $r['FK_COLNAMES']));
- foreach ($pkColnames as $i=>$pkColname) {
+ foreach ($pkColnames as $i => $pkColname) {
$pkColname = trim($pkColname);
$fkColname = trim($fkColnames[$i]);
- if ($baseFetchMode == ADODB_FETCH_ASSOC) {
- $foreignKeys[$referenceTable][$pkColname] = $fkColname;
+
+ if ($casing == CASE_UPPER) {
+ $pkColname = strtoupper($pkColname);
+ $fkColname = strtoupper($fkColname);
} else {
- $foreignKeys[$referenceTable][] = sprintf('%s=%s',$pkColname,$fkColname);
+ $pkColname = strtolower($pkColname);
+ $fkColname = strtolower($fkColname);
+ }
+
+ if ($baseFetchMode == ADODB_FETCH_ASSOC || $associative) {
+ $foreignKeys[$referenceTable][$fkColname] = $pkColname;
+
+ } else {
+ $foreignKeys[$referenceTable][] = sprintf(
+ '%s=%s',
+ $fkColname,
+ $pkColname
+ );
}
}
@@ -1056,9 +1083,14 @@ class ADODB_db2 extends ADOConnection {
$indices = array();
$primaryKeyName = '';
- $table = $this->getTableCasedValue($table);
-
+ $table = $this->metaTables('T','',$table);
+
+ if ($table == false) {
+ return false;
+ }
+ $table = $table[0];
+
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$this->setFetchMode(ADODB_FETCH_NUM);
@@ -1072,23 +1104,24 @@ class ADODB_db2 extends ADOConnection {
$this->setFetchMode($savem);
$ADODB_FETCH_MODE = $savem;
- if (empty($rows))
+ if (empty($rows)) {
return false;
+ }
+
- foreach ($rows as $r)
- {
+ foreach ($rows as $r) {
- $primaryIndex = $r[7] == 'P'?1:0;
- if (!$primary)
+ $primaryIndex = $r[7] == 'P' ? 1 : 0;
+ if (!$primary) {
/*
* Primary key not requested, ignore that one
*/
- if ($r[7] == 'P')
+ if ($r[7] == 'P') {
continue;
-
+ }
+ }
$indexName = $this->getMetaCasedValue($r[1]);
- if (!isset($indices[$indexName]))
- {
+ if (!isset($indices[$indexName])) {
$unique = ($r[7] == 'U')?1:0;
$indices[$indexName] = array('unique'=>$unique,
'primary'=>$primaryIndex,
@@ -1096,10 +1129,10 @@ class ADODB_db2 extends ADOConnection {
);
}
$cols = explode('+',$r[6]);
- foreach ($cols as $colIndex=>$col)
- {
- if ($colIndex == 0)
+ foreach ($cols as $colIndex => $col) {
+ if ($colIndex == 0) {
continue;
+ }
$columnName = $this->getMetaCasedValue($col);
$indices[$indexName]['columns'][] = $columnName;
}
@@ -1308,7 +1341,7 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
//$table = $this->getTableCasedValue($table);
$colname = "%";
- $qid = db2_columns($this->_connectionID, null, $schema, $table, $colname);
+ $qid = db2_columns($this->_connectionID, '', $schema, $table, $colname);
if (empty($qid))
{
if ($this->debug)
@@ -2031,10 +2064,10 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
switch($ADODB_ASSOC_CASE)
{
case ADODB_ASSOC_CASE_LOWER:
- $value = strtolower($value);
+ $value = strtolower($value ?? '');
break;
case ADODB_ASSOC_CASE_UPPER:
- $value = strtoupper($value);
+ $value = strtoupper($value ?? '');
break;
}
return $value;
diff --git a/drivers/adodb-mssqlnative.inc.php b/drivers/adodb-mssqlnative.inc.php
index accc3c8c..5d225653 100644
--- a/drivers/adodb-mssqlnative.inc.php
+++ b/drivers/adodb-mssqlnative.inc.php
@@ -64,7 +64,7 @@ class ADODB_mssqlnative extends ADOConnection {
var $hasAffectedRows = true;
var $poorAffectedRows = false;
var $metaDatabasesSQL = "select name from sys.sysdatabases where name <> 'master'";
- var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))";
+
var $metaColumnsSQL =
"select c.name,
t.name as type,
@@ -100,7 +100,6 @@ class ADODB_mssqlnative extends ADOConnection {
var $_dropSeqSQL = "DROP SEQUENCE %s";
var $connectionInfo = array('ReturnDatesAsStrings'=>true);
- var $cachedSchemaFlush = false;
var $sequences = false;
var $mssql_version = '';
@@ -727,8 +726,26 @@ class ADODB_mssqlnative extends ADOConnection {
}
+ /**
+ * List indexes on a table as an array
+ *
+ * @param string $table table name to query
+ * @param bool $primary true to only show primary keys. Not actually used for most databases
+ * @param string $owner Discarded for this driver
+ *
+ * @return array of indexes on current table
+ */
function MetaIndexes($table,$primary=false, $owner = false)
{
+
+ global $ADODB_FETCH_MODE;
+
+ $metaTables = $this->metaTables('T',$owner,$table);
+
+ if (!$metaTables) {
+ return false;
+ }
+
$table = $this->qstr($table);
$sql = "SELECT i.name AS ind_name, C.name AS col_name, USER_NAME(O.uid) AS Owner, c.colid, k.Keyno,
@@ -740,7 +757,7 @@ class ADODB_mssqlnative extends ADOConnection {
WHERE LEFT(i.name, 8) <> '_WA_Sys_' AND o.status >= 0 AND O.Name LIKE $table
ORDER BY O.name, I.Name, K.keyno";
- global $ADODB_FETCH_MODE;
+
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
@@ -759,11 +776,18 @@ class ADODB_mssqlnative extends ADOConnection {
$indexes = array();
while ($row = $rs->FetchRow()) {
- if (!$primary && $row[5]) continue;
+ if (!$primary && $row[5]) {
+ continue;
+ }
$indexes[$row[0]]['unique'] = $row[6];
$indexes[$row[0]]['columns'][] = $row[1];
}
+
+ if (count($indexes) == 0) {
+ return false;
+ }
+
return $indexes;
}
@@ -771,8 +795,37 @@ class ADODB_mssqlnative extends ADOConnection {
{
global $ADODB_FETCH_MODE;
- $save = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $tableName = $this->MetaTables('T','',$table);
+ if (!$tableName) {
+ return false;
+ }
+
+ $referenceSchema = $this->database;
+
+ if ( !empty($owner) ) {
+ /*
+ * SQL Server is using this for schema, so call metaDatabases to see if
+ * the schema exists
+ */
+ $alternateDb = array_map('strtolower', $this->MetaDatabases());
+ if (!in_array(strtolower($owner), $alternateDb)) {
+ return false;
+ }
+ $referenceSchema = $owner;
+ }
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC) {
+ $associative = true;
+ }
+
+ $saveFetchModes = [
+ $ADODB_FETCH_MODE,
+ $this->fetchMode
+ ];
+
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ $this->SetFetchMode(ADODB_FETCH_ASSOC);
+
$table = $this->qstr(strtoupper($table));
$sql =
@@ -784,47 +837,101 @@ class ADODB_mssqlnative extends ADOConnection {
where upper(object_name(fkeyid)) = $table
order by constraint_name, referenced_table_name, keyno";
- $constraints = $this->GetArray($sql);
+ $constraintList = $this->GetArray($sql);
- $ADODB_FETCH_MODE = $save;
+ $ADODB_FETCH_MODE = $saveFetchModes[0];
+ $this->SetFetchMode($saveFetchModes[1]);
- $arr = false;
- foreach($constraints as $constr) {
- //print_r($constr);
- $arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
- }
- if (!$arr) return false;
+ if (!$constraintList || count($constraintList) == 0) {
+ return false;
+ }
- $arr2 = false;
+ $sortKeys = [];
+
+ foreach ($constraintList as $element) {
+
+ /*
+ * Standardize the returned data keys
+ */
+ $element = array_change_key_case($element, CASE_UPPER);
+
+ /*
+ * Change the values to match the requested return type
+ */
+ if ($upper) {
+ $element = array_map('strtoupper', $element);
+ } else {
+ $element = array_map('strtolower', $element);
+ }
+
+ $id = $element['CONSTRAINT_NAME'];
+
+ if (!array_key_exists($id, $sortKeys)) {
+ $sortKeys[$id] = new \stdClass();
+ $sortKeys[$id]->tableName = $element['REFERENCED_TABLE_NAME'];
+ $sortKeys[$id]->assocKeys = [];
+ $sortKeys[$id]->numKeys = [];
+ }
+
+ $sortKeys[$id]->assocKeys[$element['COLUMN_NAME']] = $element['REFERENCED_COLUMN_NAME'];
+ $sortKeys[$id]->numKeys[] = sprintf(
+ '%s=%s',
+ $element['COLUMN_NAME'],
+ $element['REFERENCED_COLUMN_NAME']
+ );
+ }
+
+ /*
+ * Now the array is built, pick off the right elements
+ */
+ $foreignKeys = [];
+ foreach ($sortKeys as $sortObject) {
+ if ($associative) {
+ $foreignKeys[$sortObject->tableName] = $sortObject->assocKeys;
+ } else {
+ $foreignKeys[$sortObject->tableName] = $sortObject->numKeys;
+ }
+ }
+
+ return $foreignKeys;
- foreach($arr as $k => $v) {
- foreach($v as $a => $b) {
- if ($upper) $a = strtoupper($a);
- if (is_array($arr2[$a])) { // a previous foreign key was define for this reference table, we merge the new one
- $arr2[$a] = array_merge($arr2[$a], $b);
- } else {
- $arr2[$a] = $b;
- }
- }
- }
- return $arr2;
}
- //From: Fernando Moreira <FMoreira@imediata.pt>
- function MetaDatabases()
+ /**
+ * Returns a list of current visible databases
+ *
+ * @return array
+ */
+ public function MetaDatabases()
{
+ global $ADODB_FETCH_MODE;
+
+ $saveFetchModes = [
+ $ADODB_FETCH_MODE,
+ $this->fetchMode
+ ];
+
+ $saveDatabaseName = $this->database;
+
+ $this->SetFetchMode(ADODB_FETCH_NUM);
+
$this->SelectDB("master");
+
$rs = $this->Execute($this->metaDatabasesSQL);
$rows = $rs->GetRows();
- $ret = array();
- for($i=0;$i<count($rows);$i++) {
- $ret[] = $rows[$i][0];
- }
- $this->SelectDB($this->database);
- if($ret)
- return $ret;
- else
- return false;
+
+ $ADODB_FETCH_MODE = $saveFetchModes[0];
+ $this->fetchMode = $saveFetchModes[1];
+
+ /*
+ * Flatten and lowercase the array
+ */
+ $ret = array_map('strtolower',array_merge(...$rows));
+
+ $this->SelectDB($saveDatabaseName);
+
+ return $ret ? $ret : false;
+
}
// "Stein-Aksel Basma" <basma@accelero.no>
@@ -868,6 +975,7 @@ class ADODB_mssqlnative extends ADOConnection {
}
return $ret;
}
+
function MetaColumns($table, $upper=true, $schema=false){
/*
diff --git a/drivers/adodb-mysqli.inc.php b/drivers/adodb-mysqli.inc.php
index 8e194352..23fb15fd 100644
--- a/drivers/adodb-mysqli.inc.php
+++ b/drivers/adodb-mysqli.inc.php
@@ -918,71 +918,114 @@ class ADODB_mysqli extends ADOConnection {
global $ADODB_FETCH_MODE;
if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC
- || $this->fetchMode == ADODB_FETCH_ASSOC)
+ || $this->fetchMode == ADODB_FETCH_ASSOC) {
$associative = true;
+ }
+ $saveModes = [
+ $ADODB_FETCH_MODE,
+ $this->fetchMode
+ ];
+
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ if ($this->fetchMode !== false) {
+ $this->setFetchMode(ADODB_FETCH_ASSOC);
+ }
- $savem = $ADODB_FETCH_MODE;
- $this->setFetchMode(ADODB_FETCH_ASSOC);
+ $referenceSchema = $this->database;
if ( !empty($owner) ) {
- $table = "$owner.$table";
+ /*
+ * MySQL is using this for schema, so call metaDatabases to see if
+ * the schema exists
+ */
+ $alternateDb = array_map('strtolower', $this->MetaDatabases());
+ if (!in_array(strtolower($owner), $alternateDb)) {
+ $ADODB_FETCH_MODE = $saveModes[0];
+ if ($saveModes[1] !== false) {
+ $this->SetFetchMode($saveModes[1]);
+ }
+ return false;
+ }
+ $referenceSchema = $owner;
}
- $showCreate = $this->getRow(
- sprintf('SHOW CREATE TABLE `%s`', $table)
- );
+ $p1 = $this->param('p1');
+ $p2 = $this->param('p2');
+
+ $bind = [
+ 'p1' => $referenceSchema,
+ 'p2' => $table
+ ];
+
+ $sql = "
+SELECT *
+ FROM information_schema.key_column_usage
+ WHERE referenced_table_schema=$p1
+ AND referenced_table_name IS NOT NULL
+ AND table_name = $p2
+ ORDER BY referenced_table_name,constraint_name, position_in_unique_constraint";
+
+ $constraintList = $this->getAll($sql, $bind);
+
+ $ADODB_FETCH_MODE = $saveModes[0];
+ if ($saveModes[1] !== false) {
+ $this->SetFetchMode($saveModes[1]);
+ }
+
+ if (!$constraintList || count($constraintList) == 0) {
+ return false;
+ }
+
+ $sortKeys = [];
+
+ foreach ($constraintList as $element) {
- if ( !$showCreate || !is_array($showCreate) ) {
/*
- * Invalid table or owner provided
+ * Standardize the returned data keys
*/
- $this->setFetchMode($savem);
- return false;
- }
+ $element = array_change_key_case($element, CASE_UPPER);
- $a_create_table = array_change_key_case($showCreate, CASE_UPPER);
+ /*
+ * Change the values to match the requested return type
+ */
+ if ($upper) {
+ $element = array_map('strtoupper', $element);
+ } else {
+ $element = array_map('strtolower', $element);
+ }
- $this->setFetchMode($savem);
+ $id = $element['CONSTRAINT_NAME'];
- $create_sql = $a_create_table["CREATE TABLE"] ?? $a_create_table["CREATE VIEW"];
+ if (!array_key_exists($id, $sortKeys)) {
+ $sortKeys[$id] = new \stdClass();
+ $sortKeys[$id]->tableName = $element['REFERENCED_TABLE_NAME'];
+ $sortKeys[$id]->assocKeys = [];
+ $sortKeys[$id]->numKeys = [];
+ }
- $matches = array();
+ $sortKeys[$id]->assocKeys[$element['COLUMN_NAME']] = $element['REFERENCED_COLUMN_NAME'];
+ $sortKeys[$id]->numKeys[] = sprintf(
+ '%s=%s',
+ $element['COLUMN_NAME'],
+ $element['REFERENCED_COLUMN_NAME']
+ );
+ }
- if (!preg_match_all(
- "/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/",
- $create_sql,
- $matches
- )
- ) {
- return false;
- }
-
- $foreign_keys = array();
- $num_keys = count($matches[0]);
- for ( $i = 0; $i < $num_keys; $i ++ ) {
- $my_field = explode('`, `', $matches[1][$i]);
- $ref_table = $matches[2][$i];
- $ref_field = explode('`, `', $matches[3][$i]);
+ /*
+ * Now the array is built, pick off the right elements
+ */
+ $foreignKeys = [];
+ foreach ($sortKeys as $sortObject) {
+ if ($associative) {
+ $foreignKeys[$sortObject->tableName] = $sortObject->assocKeys;
+ } else {
+ $foreignKeys[$sortObject->tableName] = $sortObject->numKeys;
+ }
+ }
- if ( $upper ) {
- $ref_table = strtoupper($ref_table);
- }
- // see https://sourceforge.net/p/adodb/bugs/100/
- if (!isset($foreign_keys[$ref_table])) {
- $foreign_keys[$ref_table] = array();
- }
- $num_fields = count($my_field);
- for ( $j = 0; $j < $num_fields; $j ++ ) {
- if ( $associative ) {
- $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
- } else {
- $foreign_keys[$ref_table][] = $my_field[$j] . '=' . $ref_field[$j];
- }
- }
- }
+ return $foreignKeys;
- return $foreign_keys;
}
/**
diff --git a/drivers/adodb-oci8.inc.php b/drivers/adodb-oci8.inc.php
index bb424562..b88c1f78 100644
--- a/drivers/adodb-oci8.inc.php
+++ b/drivers/adodb-oci8.inc.php
@@ -65,7 +65,15 @@ class ADODB_oci8 extends ADOConnection {
var $concat_operator='||';
var $sysDate = "TRUNC(SYSDATE)";
var $sysTimeStamp = 'SYSDATE'; // requires oracle 9 or later, otherwise use SYSDATE
- var $metaDatabasesSQL = "SELECT USERNAME FROM ALL_USERS WHERE USERNAME NOT IN ('SYS','SYSTEM','DBSNMP','OUTLN') ORDER BY 1";
+ var $metaDatabasesSQL = "
+SELECT LOWER(USERNAME) FROM ALL_USERS
+ WHERE USERNAME NOT IN ('SYS','SYSTEM','OUTLN','DBSNMP',
+'APPQOSSYS','AUDSYS','CTXSYS','DVSYS','GSMADMIN_INTERNAL',
+'LBACSYS','MDSYS','OJVMSYS','ORDDATA','ORDPLUGINS','ORDSYS',
+'SI_INFORMTN_SCHEMA','WMSYS','XDB','XS\$NULL','BAASSYS'
+,'DBSFWUSER','DGPDB_INT','DIP','DVF','GGSHAREDCAP','GGSYS','GSMCATUSER'
+,'GSMUSER','MDDATA','OLAPSYS','PDBADMIN','REMOTE_SCHEDULER_AGENT','SYS\$UMF','SYSBACKUP'
+,'SYSDG','SYSKM','SYSRAC','VECSYS') ORDER BY 1";
var $_stmt;
var $_commit = OCI_COMMIT_ON_SUCCESS;
var $_initdate = true; // init date to YYYY-MM-DD
diff --git a/drivers/adodb-postgres64.inc.php b/drivers/adodb-postgres64.inc.php
index b9678bd3..57f6955c 100644
--- a/drivers/adodb-postgres64.inc.php
+++ b/drivers/adodb-postgres64.inc.php
@@ -524,10 +524,14 @@ class ADODB_postgres64 extends ADOConnection{
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ if ($this->fetchMode !== false) {
+ $savem = $this->SetFetchMode(false);
+ }
$rs = $this->Execute($this->_generateMetaColumnsSQL($table, $schema));
- if (isset($savem)) $this->SetFetchMode($savem);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
$ADODB_FETCH_MODE = $save;
if ($rs === false) {
@@ -540,11 +544,15 @@ class ADODB_postgres64 extends ADOConnection{
// not support OUTER JOINS. So here is the clumsy way.
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
-
+ if (isset($savem)) {
+ $this->SetFetchMode(ADODB_FETCH_ASSOC);
+ }
$rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
// fetch all result in once for performance.
$keys = $rskey->GetArray();
- if (isset($savem)) $this->SetFetchMode($savem);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
$ADODB_FETCH_MODE = $save;
$rskey->Close();
@@ -556,15 +564,24 @@ class ADODB_postgres64 extends ADOConnection{
$rsdefa = array();
if (!empty($this->metaDefaultsSQL)) {
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ if (isset($savem)) {
+ $this->SetFetchMode(ADODB_FETCH_ASSOC);
+ }
$sql = sprintf($this->metaDefaultsSQL, ($table));
$rsdef = $this->Execute($sql);
- if (isset($savem)) $this->SetFetchMode($savem);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
$ADODB_FETCH_MODE = $save;
if ($rsdef) {
while (!$rsdef->EOF) {
- $num = $rsdef->fields['num'];
- $s = $rsdef->fields['def'];
+
+ $fields = array_change_key_case($rsdef->fields, CASE_LOWER);
+
+ $num = $fields['num'];
+ $s = $fields['def'];
+
if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
$s = substr($s, 1);
$s = substr($s, 0, strlen($s) - 1);
@@ -605,7 +622,10 @@ class ADODB_postgres64 extends ADOConnection{
// Freek
if (is_array($keys)) {
- foreach($keys as $key) {
+
+ foreach($keys as $key) {
+ $key = array_change_key_case($key, CASE_LOWER);
+
if ($fld->name == $key['column_name'] && $key['primary_key'] == 't') {
$fld->primary_key = true;
}
@@ -628,6 +648,46 @@ class ADODB_postgres64 extends ADOConnection{
return $retarr ?: false;
}
+
+ /**
+ * List columns names in a table as an array.
+ * @param string $table table name to query
+ * @param bool $numIndexes return numeric keys
+ * @param bool $useattnum For postgres, use the attnum
+ *
+ * @return false|array of column names for current table.
+ */
+ public function MetaColumnNames(
+ string $table,
+ bool $numIndexes=false,
+ bool $useattnum=false
+ ) : mixed {
+
+ $objarr = $this->MetaColumns($table);
+ if (!is_array($objarr)) {
+ return false;
+ }
+
+ $columnNames = [];
+ foreach($objarr as $v) {
+ if ($useattnum) {
+ /*
+ * overrides associative keys
+ */
+ $columnNames[$v->attnum] = $v->name;
+ } else {
+ $columnNames[strtoupper($v->name)] = $v->name;
+ }
+ }
+
+ if ($numIndexes && !$useattnum) {
+ return array_values($columnNames);
+ }
+
+ return $columnNames;
+
+ }
+
function param($name, $type='C')
{
if (!$name) {