diff options
| author | Mark Newnham <mark@newnhams.com> | 2026-02-19 19:27:59 -0700 |
|---|---|---|
| committer | Mark Newnham <mark@newnhams.com> | 2026-02-19 19:27:59 -0700 |
| commit | f72a88fc785056416eea3933d61d4cf2603b09ff (patch) | |
| tree | 3cee0d260f15e04da9fb236a2269571de3c3717f | |
| parent | d3831ef214ddc313c10260de685dcfcf6f1a4365 (diff) | |
| parent | 8ac6fa21f4dab9a3b8435674411b8fac4457259d (diff) | |
| download | adodb-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.php | 53 | ||||
| -rw-r--r-- | drivers/adodb-db2.inc.php | 83 | ||||
| -rw-r--r-- | drivers/adodb-mssqlnative.inc.php | 182 | ||||
| -rw-r--r-- | drivers/adodb-mysqli.inc.php | 139 | ||||
| -rw-r--r-- | drivers/adodb-oci8.inc.php | 10 | ||||
| -rw-r--r-- | drivers/adodb-postgres64.inc.php | 76 |
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) { |
