diff --git a/lib/adodb/adodb-datadict.inc.php b/lib/adodb/adodb-datadict.inc.php index 7ec6e886ac0..5156b1f9119 100644 --- a/lib/adodb/adodb-datadict.inc.php +++ b/lib/adodb/adodb-datadict.inc.php @@ -202,6 +202,12 @@ class ADODB_DataDict { */ public $blobAllowsDefaultValue; + + /** + * @var string String to use to quote identifiers and names + */ + public $quote; + function getCommentSQL($table,$col) { return false; diff --git a/lib/adodb/adodb-exceptions.inc.php b/lib/adodb/adodb-exceptions.inc.php index 560286a1847..36566de4378 100644 --- a/lib/adodb/adodb-exceptions.inc.php +++ b/lib/adodb/adodb-exceptions.inc.php @@ -30,6 +30,9 @@ var $params = ''; var $host = ''; var $database = ''; + /** @var string A message text. */ + var $msg = ''; + function __construct($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection) { switch($fn) { diff --git a/lib/adodb/adodb-perf.inc.php b/lib/adodb/adodb-perf.inc.php index d9d8a993783..b8804dff28c 100644 --- a/lib/adodb/adodb-perf.inc.php +++ b/lib/adodb/adodb-perf.inc.php @@ -237,6 +237,9 @@ class adodb_perf { var $createTableSQL = false; var $maxLength = 2000; + /** @var array Settings data. */ + var $settings = []; + // Sets the tablename to be used static function table($newtable = false) { diff --git a/lib/adodb/adodb-xmlschema.inc.php b/lib/adodb/adodb-xmlschema.inc.php index 32b8afa1e61..ac13d34ec72 100644 --- a/lib/adodb/adodb-xmlschema.inc.php +++ b/lib/adodb/adodb-xmlschema.inc.php @@ -235,6 +235,15 @@ class dbTable extends dbObject { */ var $drop_field = array(); + /** + * @var array Platform-specific options + * @access private + */ + var $currentPlatform = true; + + /** @var dbData Stores information about table data. */ + var $data; + /** * Iniitializes a new table object. * @@ -773,6 +782,9 @@ class dbData extends dbObject { var $row; + /** @var string Field name */ + var $current_field; + /** * Initializes the new dbIndex object. * @@ -1282,6 +1294,9 @@ class adoSchema { */ var $continueOnError; + /** @var dbTable A table object. */ + var $obj; + /** * Creates an adoSchema object * diff --git a/lib/adodb/adodb-xmlschema03.inc.php b/lib/adodb/adodb-xmlschema03.inc.php index a03386b3cc3..83a0a788e9b 100644 --- a/lib/adodb/adodb-xmlschema03.inc.php +++ b/lib/adodb/adodb-xmlschema03.inc.php @@ -259,6 +259,8 @@ class dbTable extends dbObject { */ var $currentPlatform = true; + /** @var dbData Stores information about table data. */ + var $data; /** * Iniitializes a new table object. @@ -830,6 +832,9 @@ class dbData extends dbObject { var $row; + /** @var string Field name */ + var $current_field; + /** * Initializes the new dbData object. * @@ -1401,6 +1406,9 @@ class adoSchema { */ var $existingData; + /** @var dbTable A table object. */ + var $obj; + /** * Creates an adoSchema object * diff --git a/lib/adodb/adodb.inc.php b/lib/adodb/adodb.inc.php index 100928a467d..bf32b01f060 100644 --- a/lib/adodb/adodb.inc.php +++ b/lib/adodb/adodb.inc.php @@ -198,7 +198,7 @@ if (!defined('_ADODB_LAYER')) { /** * ADODB version as a string. */ - $ADODB_vers = 'v5.22.4 2022-10-28'; + $ADODB_vers = 'v5.22.5 2023-04-03'; /** * Determines whether recordset->RecordCount() is used. @@ -221,8 +221,12 @@ if (!defined('_ADODB_LAYER')) { // CLASS ADOFieldObject //============================================================================================== /** - * Helper class for FetchFields -- holds info on a column + * Helper class for FetchFields -- holds info on a column. + * + * Note: Dynamic properties are required here, as some drivers may require + * the object to hold database-specific field metadata. */ + #[\AllowDynamicProperties] class ADOFieldObject { var $name = ''; var $max_length=0; @@ -387,10 +391,7 @@ if (!defined('_ADODB_LAYER')) { */ function getdirname($hash) { global $ADODB_CACHE_DIR; - if (!isset($this->notSafeMode)) { - $this->notSafeMode = !ini_get('safe_mode'); - } - return ($this->notSafeMode) ? $ADODB_CACHE_DIR.'/'.substr($hash,0,2) : $ADODB_CACHE_DIR; + return $ADODB_CACHE_DIR . '/' . substr($hash, 0, 2); } /** @@ -405,7 +406,7 @@ if (!defined('_ADODB_LAYER')) { global $ADODB_CACHE_PERMS; $dir = $this->getdirname($hash); - if ($this->notSafeMode && !file_exists($dir)) { + if (!file_exists($dir)) { $oldu = umask(0); if (!@mkdir($dir, empty($ADODB_CACHE_PERMS) ? 0771 : $ADODB_CACHE_PERMS)) { if(!is_dir($dir) && $debug) { @@ -458,7 +459,14 @@ if (!defined('_ADODB_LAYER')) { // var $dataProvider = 'native'; var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql - var $database = ''; /// Name of database to be used. + + /** + * @var string Current database name. + * + * This used to be stored in the $databaseName property, which was marked + * as deprecated in 4.66 and removed in 5.22.5. + */ + public $database = ''; /** * @var string If the driver is PDO, then the dsnType is e.g. sqlsrv, otherwise empty @@ -485,8 +493,33 @@ if (!defined('_ADODB_LAYER')) { var $leftBracket = '['; /// left square bracked for t-sql styled column names var $rightBracket = ']'; /// right square bracked for t-sql styled column names var $charSet=false; /// character set to use - only for interbase, postgres and oci8 + + /** @var string SQL statement to get databases */ var $metaDatabasesSQL = ''; + + /** @var string SQL statement to get database tables */ var $metaTablesSQL = ''; + + /** @var string SQL statement to get table columns. */ + var $metaColumnsSQL; + + /** + * SQL statement to get the last IDENTITY value inserted into an IDENTITY + * column in the same scope. + * @see https://learn.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql + * @var string + */ + var $identitySQL; + + /** @var string SQL statement to create a Sequence . */ + var $_genSeqSQL; + + /** @var string SQL statement to drop a Sequence. */ + var $_dropSeqSQL; + + /** @var string SQL statement to generate a Sequence ID. */ + var $_genIDSQL; + var $uniqueOrderBy = false; /// All order by columns have to be unique var $emptyDate = ' '; var $emptyTimeStamp = ' '; @@ -584,6 +617,10 @@ if (!defined('_ADODB_LAYER')) { var $null2null = 'null'; // in autoexecute/getinsertsql/getupdatesql, this value will be converted to a null var $bulkBind = false; // enable 2D Execute array + + /** @var string SQL statement executed by some drivers after successful connection. */ + public $connectStmt = ''; + // // PRIVATE VARS // @@ -591,14 +628,34 @@ if (!defined('_ADODB_LAYER')) { var $_transOK = null; /** @var resource Identifier for the native database connection */ var $_connectionID = false; - var $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will - /// then returned by the errorMsg() function - var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8 + + /** + * Stores the last returned error message. + * @see ADOConnection::errorMsg() + * @var string|false + */ + var $_errorMsg = false; + + /** + * Stores the last returned error code. + * Not guaranteed to be used. Only some drivers actually populate it. + * @var int|false + */ + var $_errorCode = false; + var $_queryID = false; /// This variable keeps the last created result link identifier var $_isPersistentConnection = false; /// A boolean variable to state whether its a persistent connection or normal connection. */ var $_bindInputArray = false; /// set to true if ADOConnection.Execute() permits binding of array parameters. - var $_evalAll = false; + + /** + * Eval string used to filter data. + * Only used in the deprecated Text driver. + * @see https://adodb.org/dokuwiki/doku.php?id=v5:database:text#workaround + * @var string + */ + var $evalAll = false; + var $_affected = false; var $_logsql = false; var $_transmode = ''; // transaction mode @@ -633,6 +690,12 @@ if (!defined('_ADODB_LAYER')) { */ public $customMetaTypes = array(); + /** @var ADORecordSet Recordset used to retrieve MetaType information */ + var $_metars; + + /** @var string a specified locale. */ + var $locale; + /** * Default Constructor. @@ -2418,7 +2481,7 @@ if (!defined('_ADODB_LAYER')) { * - userid * - setFetchMode (adodb 4.23) * - * When not in safe mode, we create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR). + * We create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR). * Assuming that we can have 50,000 files per directory with good performance, * then we can scale to 12.8 million unique cached recordsets. Wow! */ @@ -2559,34 +2622,32 @@ if (!defined('_ADODB_LAYER')) { } - /* - - - $forceUpdate . - */ /** - * Similar to PEAR DB's autoExecute(), except that $mode can be 'INSERT' - * or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE. - * If $mode == 'UPDATE', then $where is compulsory as a safety measure. + * Simple interface to insert and update records. * - * @param $table - * @param $fields_values - * @param string $mode - * @param false $where - * @param bool $forceUpdate If true, perform update even if the data has not changed. - * @param bool $magic_quotes This param is not used since 5.21.0. - * It remains for backwards compatibility. + * Automatically generate and execute INSERT and UPDATE statements + * on a given table, similar to PEAR DB's autoExecute(). + * + * @param string $table Name of the table to process. + * @param array $fields_values Associative array of field names => values. + * @param string|int $mode Execution mode: 'INSERT' (default), 'UPDATE' or + * one of the DB_AUTOQUERY_xx constants. + * @param string $where SQL where clause (mandatory in UPDATE mode as a safety measure) + * @param bool $forceUpdate If true, update all provided fields, even if they have not changed; + * otherwise only modified fields are updated. + * @param bool $magic_quotes This param is not used since 5.21.0. + * It remains for backwards compatibility. * * @return bool * * @noinspection PhpUnusedParameterInspection */ - function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $forceUpdate = true, $magic_quotes = false) { + function autoExecute($table, $fields_values, $mode = 'INSERT', $where = '', $forceUpdate = true, $magic_quotes = false) { if (empty($fields_values)) { $this->outp_throw('AutoExecute: Empty fields array', 'AutoExecute'); return false; } - if ($where === false && ($mode == 'UPDATE' || $mode == 2 /* DB_AUTOQUERY_UPDATE */) ) { + if (empty($where) && ($mode == 'UPDATE' || $mode == 2 /* DB_AUTOQUERY_UPDATE */)) { $this->outp_throw('AutoExecute: Illegal mode=UPDATE with empty WHERE clause', 'AutoExecute'); return false; } @@ -2598,7 +2659,7 @@ if (!defined('_ADODB_LAYER')) { } $rs->tableName = $table; - if ($where !== false) { + if (!empty($where)) { $sql .= " WHERE $where"; } $rs->sql = $sql; @@ -3881,6 +3942,12 @@ class ADORecordSet implements IteratorAggregate { * public variables */ var $dataProvider = "native"; + + /** + * @var string Table name (used in _adodb_getupdatesql() and _adodb_getinsertsql())- + */ + public $tableName = ''; + /** @var bool|array */ var $fields = false; /// holds the current row data var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob @@ -3925,6 +3992,8 @@ class ADORecordSet implements IteratorAggregate { public $customActualTypes; public $customMetaTypes; + /** @var int Only used in _adodb_getinsertsql() */ + public $insertSig; /** * @var ADOFieldObject[] Field metadata cache @@ -3932,6 +4001,12 @@ class ADORecordSet implements IteratorAggregate { */ protected $fieldObjectsCache; + /** + * @var int Defines the Fetch Mode for a recordset + * See the ADODB_FETCH_* constants + */ + public $adodbFetchMode; + /** * Constructor * @@ -4273,9 +4348,7 @@ class ADORecordSet implements IteratorAggregate { switch ($showArrayMethod) { case 0: - if ($fetchMode == ADODB_FETCH_ASSOC - || $fetchMode == ADODB_FETCH_BOTH) - { + if ($fetchMode != ADODB_FETCH_NUM) { /* * The driver should have already handled the key * casing, but in case it did not. We will check and force @@ -5747,6 +5820,7 @@ class ADORecordSet implements IteratorAggregate { } include_once($path); $class = "ADODB2_$drivername"; + /** @var ADODB_DataDict $dict */ $dict = new $class(); $dict->dataProvider = $conn->dataProvider; $dict->connection = $conn; diff --git a/lib/adodb/datadict/datadict-postgres.inc.php b/lib/adodb/datadict/datadict-postgres.inc.php index d403cee3056..89bcc0adb32 100644 --- a/lib/adodb/datadict/datadict-postgres.inc.php +++ b/lib/adodb/datadict/datadict-postgres.inc.php @@ -160,7 +160,8 @@ class ADODB2_postgres extends ADODB_DataDict $sql = array(); $not_null = false; list($lines,$pkey) = $this->_genFields($flds); - $alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' '; + $alter = 'ALTER TABLE ' . $tabname . $this->addCol; + $alter .= (float)@$this->serverInfo['version'] < 9.6 ? ' ' : ' IF NOT EXISTS '; foreach($lines as $v) { if (($not_null = preg_match('/NOT NULL/i',$v))) { $v = preg_replace('/NOT NULL/i','',$v); diff --git a/lib/adodb/drivers/adodb-ads.inc.php b/lib/adodb/drivers/adodb-ads.inc.php index b9d4adb522f..8b877b6dfbc 100644 --- a/lib/adodb/drivers/adodb-ads.inc.php +++ b/lib/adodb/drivers/adodb-ads.inc.php @@ -97,7 +97,7 @@ class ADODB_ads extends ADOConnection $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword, $this->curmode); } $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); - if (isset($this->connectStmt)) { + if ($this->connectStmt) { $this->Execute($this->connectStmt); } @@ -127,7 +127,7 @@ class ADODB_ads extends ADOConnection if ($this->_connectionID && $this->autoRollback) { @ads_rollback($this->_connectionID); } - if (isset($this->connectStmt)) { + if ($this->connectStmt) { $this->Execute($this->connectStmt); } diff --git a/lib/adodb/drivers/adodb-db2.inc.php b/lib/adodb/drivers/adodb-db2.inc.php index 16c4054f174..e214d2d7e10 100644 --- a/lib/adodb/drivers/adodb-db2.inc.php +++ b/lib/adodb/drivers/adodb-db2.inc.php @@ -77,16 +77,6 @@ class ADODB_db2 extends ADOConnection { */ public $nameQuote = '"'; - /* - * Executed after successful connection - */ - public $connectStmt = ''; - - /* - * Holds the current database name - */ - private $databaseName = ''; - /* * Holds information about the stored procedure request * currently being built @@ -113,7 +103,7 @@ class ADODB_db2 extends ADOConnection { private function doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persistent=false) { - + if (!function_exists('db2_connect')) { ADOConnection::outp("DB2 extension not installed."); return null; @@ -184,7 +174,7 @@ class ADODB_db2 extends ADOConnection { null, $db2Options); - + $this->_errorMsg = @db2_conn_errormsg(); if ($this->_connectionID && $this->connectStmt) @@ -207,7 +197,7 @@ class ADODB_db2 extends ADOConnection { private function unpackParameters($argDSN, $argUsername, $argPassword, $argDatabasename) { - + $connectionParameters = array('dsn'=>'', 'uid'=>'', 'pwd'=>'', @@ -257,7 +247,7 @@ class ADODB_db2 extends ADOConnection { $errorMessage = 'Supply uncatalogued connection parameters '; $errorMessage.= 'in either the database or DSN arguments, '; $errorMessage.= 'but not both'; - + if ($this->debug) ADOConnection::outp($errorMessage); return null; @@ -282,7 +272,7 @@ class ADODB_db2 extends ADOConnection { { $errorMessage = 'For uncatalogued connections, provide '; $errorMessage.= 'both UID and PWD in the connection string'; - + if ($this->debug) ADOConnection::outp($errorMessage); return null; @@ -307,7 +297,7 @@ class ADODB_db2 extends ADOConnection { } elseif ($argDatabasename) { - $this->databaseName = $argDatabasename; + $this->database = $argDatabasename; $argDSN .= ';database=' . $argDatabasename; $argDatabasename = ''; $useCataloguedConnection = false; @@ -317,7 +307,7 @@ class ADODB_db2 extends ADOConnection { { $errorMessage = 'Uncatalogued connection parameters '; $errorMessage.= 'must contain a database= argument'; - + if ($this->debug) ADOConnection::outp($errorMessage); return null; @@ -347,9 +337,9 @@ class ADODB_db2 extends ADOConnection { } if ($argDatabasename) - $this->databaseName = $argDatabasename; - elseif (!$this->databaseName) - $this->databaseName = $this->getDatabasenameFromDsn($argDSN); + $this->database = $argDatabasename; + elseif (!$this->database) + $this->database = $this->getDatabasenameFromDsn($argDSN); $connectionParameters = array('dsn'=>$argDSN, @@ -1003,7 +993,7 @@ class ADODB_db2 extends ADOConnection { */ public function metaDatabases(){ - $dbName = $this->getMetaCasedValue($this->databaseName); + $dbName = $this->getMetaCasedValue($this->database); return (array)$dbName; @@ -1580,9 +1570,6 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2 */ function _query(&$sql,$inputarr=false) { - - $this->_error = ''; - $db2Options = array(); /* * Use DB2 Internal case handling for best speed @@ -1618,10 +1605,10 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2 { $this->_errorMsg = @db2_stmt_errormsg(); $this->_errorCode = @db2_stmt_error(); - + if ($this->debug) ADOConnection::outp($this->_errorMsg); - + return false; } } @@ -1995,14 +1982,13 @@ class ADORecordSet_db2 extends ADORecordSet { $ok = @db2_free_result($this->_queryID); if (!$ok) { - $this->_errorMsg = @db2_stmt_errormsg($this->_queryId); - $this->_errorCode = @db2_stmt_error(); + $this->connection->_errorMsg = @db2_stmt_errormsg($this->_queryID); + $this->connection->_errorCode = @db2_stmt_error(); if ($this->debug) - ADOConnection::outp($this->_errorMsg); + ADOConnection::outp($this->connection->_errorMsg); return false; } - } } diff --git a/lib/adodb/drivers/adodb-informix72.inc.php b/lib/adodb/drivers/adodb-informix72.inc.php index 79e5138a9ce..759bd5c8f8e 100644 --- a/lib/adodb/drivers/adodb-informix72.inc.php +++ b/lib/adodb/drivers/adodb-informix72.inc.php @@ -80,12 +80,9 @@ class ADODB_informix72 extends ADOConnection { function ServerInfo() { - if (isset($this->version)) return $this->version; - - $arr['description'] = $this->GetOne("select DBINFO('version','full') from systables where tabid = 1"); - $arr['version'] = $this->GetOne("select DBINFO('version','major') || DBINFO('version','minor') from systables where tabid = 1"); - $this->version = $arr; - return $arr; + $arr['description'] = $this->GetOne("select DBINFO('version','full') from systables where tabid = 1"); + $arr['version'] = $this->GetOne("select DBINFO('version','major') || DBINFO('version','minor') from systables where tabid = 1"); + return $arr; } diff --git a/lib/adodb/drivers/adodb-mssql.inc.php b/lib/adodb/drivers/adodb-mssql.inc.php index 8fb92249ccd..269dd7ed38c 100644 --- a/lib/adodb/drivers/adodb-mssql.inc.php +++ b/lib/adodb/drivers/adodb-mssql.inc.php @@ -541,7 +541,6 @@ order by constraint_name, referenced_table_name, keyno"; function SelectDB($dbName) { $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions if ($this->_connectionID) { return @mssql_select_db($dbName); } diff --git a/lib/adodb/drivers/adodb-mssqlnative.inc.php b/lib/adodb/drivers/adodb-mssqlnative.inc.php index 41bb7e3e86e..f7e1bcc1672 100644 --- a/lib/adodb/drivers/adodb-mssqlnative.inc.php +++ b/lib/adodb/drivers/adodb-mssqlnative.inc.php @@ -440,7 +440,6 @@ class ADODB_mssqlnative extends ADOConnection { function SelectDB($dbName) { $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions if ($this->_connectionID) { $rs = $this->Execute('USE '.$dbName); if($rs) { diff --git a/lib/adodb/drivers/adodb-mysqli.inc.php b/lib/adodb/drivers/adodb-mysqli.inc.php index 4948f185112..545c694824c 100644 --- a/lib/adodb/drivers/adodb-mysqli.inc.php +++ b/lib/adodb/drivers/adodb-mysqli.inc.php @@ -932,7 +932,7 @@ class ADODB_mysqli extends ADOConnection { $SQL = "SELECT column_name, column_type FROM information_schema.columns - WHERE table_schema='{$this->databaseName}' + WHERE table_schema='{$this->database}' AND table_name='$table'"; $schemaArray = $this->getAssoc($SQL); @@ -1017,7 +1017,6 @@ class ADODB_mysqli extends ADOConnection { { // $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID); $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions if ($this->_connectionID) { $result = @mysqli_select_db($this->_connectionID, $dbName); @@ -1207,6 +1206,14 @@ class ADODB_mysqli extends ADOConnection { // Commented out for reasons of performance. You should retrieve every recordset yourself. // if (!mysqli_next_result($this->connection->_connectionID)) return false; + // When SQL is empty, mysqli_query() throws exception on PHP 8 (#945) + if (!$sql) { + if ($this->debug) { + ADOConnection::outp("Empty query"); + } + return false; + } + if (is_array($sql)) { // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but diff --git a/lib/adodb/drivers/adodb-oci8.inc.php b/lib/adodb/drivers/adodb-oci8.inc.php index c1f4e502053..ca78772191f 100644 --- a/lib/adodb/drivers/adodb-oci8.inc.php +++ b/lib/adodb/drivers/adodb-oci8.inc.php @@ -321,10 +321,6 @@ END; protected function _insertID($table = '', $column = '') { - - if (!$this->seqField) - return false; - if ($this->schema) { $t = strpos($table,'.'); @@ -1151,10 +1147,11 @@ END; } else $hasref = false; + /** @var ADORecordset_oci8 $rs */ $rs = $this->Execute($stmt); if ($rs) { if ($rs->databaseType == 'array') { - oci_free_cursor($stmt[4]); + oci_free_statement($stmt[4]); } elseif ($hasref) { $rs->_refcursor = $stmt[4]; @@ -1604,6 +1601,9 @@ class ADORecordset_oci8 extends ADORecordSet { var $bind=false; var $_fieldobjs; + /** @var resource Cursor reference */ + var $_refcursor; + function __construct($queryID,$mode=false) { if ($mode === false) { diff --git a/lib/adodb/drivers/adodb-odbc.inc.php b/lib/adodb/drivers/adodb-odbc.inc.php index a9705e2d80c..508711a3032 100644 --- a/lib/adodb/drivers/adodb-odbc.inc.php +++ b/lib/adodb/drivers/adodb-odbc.inc.php @@ -81,7 +81,9 @@ class ADODB_odbc extends ADOConnection { if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword); else $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,$this->curmode); $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); + if ($this->connectStmt) { + $this->Execute($this->connectStmt); + } return $this->_connectionID != false; } @@ -102,7 +104,9 @@ class ADODB_odbc extends ADOConnection { $this->_errorMsg = $this->getChangedErrorMsg($last_php_error); if ($this->_connectionID && $this->autoRollback) @odbc_rollback($this->_connectionID); - if (isset($this->connectStmt)) $this->Execute($this->connectStmt); + if ($this->connectStmt) { + $this->Execute($this->connectStmt); + } return $this->_connectionID != false; } diff --git a/lib/adodb/drivers/adodb-odbc_mssql.inc.php b/lib/adodb/drivers/adodb-odbc_mssql.inc.php index 9f53d3d7c3d..1f8b98d2691 100644 --- a/lib/adodb/drivers/adodb-odbc_mssql.inc.php +++ b/lib/adodb/drivers/adodb-odbc_mssql.inc.php @@ -49,8 +49,12 @@ class ADODB_odbc_mssql extends ADODB_odbc { var $ansiOuter = true; // for mssql7 or later var $identitySQL = 'select SCOPE_IDENTITY()'; // 'select SCOPE_IDENTITY'; # for mssql 2000 var $hasInsertID = true; - var $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL OFF'; # When SET CONCAT_NULL_YIELDS_NULL is ON, - # concatenating a null value with a string yields a NULL result + /** + * When SET CONCAT_NULL_YIELDS_NULL is ON, concatenating a null value with + * a string yields a NULL result. + * @var string SQL statement executed after successful connection. + */ + public $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL OFF'; # // crashes php... function ServerInfo() diff --git a/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php b/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php index 79fa32516fa..86f7f8c31a5 100644 --- a/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php +++ b/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php @@ -26,10 +26,11 @@ include_once(ADODB_DIR."/drivers/adodb-odbc_mssql.inc.php"); class ADODB_odbc_mssql2012 extends ADODB_odbc_mssql { - /* - * Makes behavior similar to prior versions of SQL Server - */ - var $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL ON'; + /** + * Makes behavior similar to prior versions of SQL Server. + * @var string SQL statement executed after successful connection. + */ + public $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL ON'; } class ADORecordSet_odbc_mssql2012 extends ADORecordSet_odbc_mssql diff --git a/lib/adodb/drivers/adodb-odbtp.inc.php b/lib/adodb/drivers/adodb-odbtp.inc.php index 41bd0873bac..e3f814810c5 100644 --- a/lib/adodb/drivers/adodb-odbtp.inc.php +++ b/lib/adodb/drivers/adodb-odbtp.inc.php @@ -46,6 +46,15 @@ class ADODB_odbtp extends ADOConnection{ var $_canPrepareSP = false; var $_dontPoolDBC = true; + /** @var string DBMS name. */ + var $odbc_name; + + /** @var bool */ + var $_canSelectDb = false; + + /** @var mixed */ + var $_lastAffectedRows; + function ServerInfo() { return array('description' => @odbtp_get_attr( ODB_ATTR_DBMSNAME, $this->_connectionID), @@ -304,7 +313,6 @@ class ADODB_odbtp extends ADOConnection{ return false; } $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions return true; } diff --git a/lib/adodb/drivers/adodb-pdo.inc.php b/lib/adodb/drivers/adodb-pdo.inc.php index eee0beff988..0fbe3e2f732 100644 --- a/lib/adodb/drivers/adodb-pdo.inc.php +++ b/lib/adodb/drivers/adodb-pdo.inc.php @@ -82,9 +82,17 @@ class ADODB_pdo extends ADOConnection { var $_errormsg = false; var $_errorno = false; - var $stmt = false; + var $_stmt = false; + + /** @var ADODB_pdo_base */ var $_driver; + /** @var PDO */ + var $_connectionID; + + /** @var PDOStatement */ + var $_queryID; + /* * Describe parameters passed directly to the PDO driver * @@ -661,6 +669,9 @@ class ADODB_pdo extends ADOConnection { } +/** + * Base class for Database-specific PDO drivers. + */ class ADODB_pdo_base extends ADODB_pdo { var $sysDate = "'?'"; @@ -779,6 +790,9 @@ class ADORecordSet_pdo extends ADORecordSet { var $databaseType = "pdo"; var $dataProvider = "pdo"; + /** @var PDOStatement */ + var $_queryID; + function __construct($id,$mode=false) { if ($mode === false) { @@ -919,4 +933,7 @@ class ADORecordSet_pdo extends ADORecordSet { } -class ADORecordSet_array_pdo extends ADORecordSet_array {} +class ADORecordSet_array_pdo extends ADORecordSet_array { + /** @var PDOStatement */ + var $_queryID; +} diff --git a/lib/adodb/drivers/adodb-pdo_firebird.inc.php b/lib/adodb/drivers/adodb-pdo_firebird.inc.php index 0ee5e02b6c9..f8847c3cc98 100644 --- a/lib/adodb/drivers/adodb-pdo_firebird.inc.php +++ b/lib/adodb/drivers/adodb-pdo_firebird.inc.php @@ -32,14 +32,6 @@ class ADODB_pdo_firebird extends ADODB_pdo var $arrayClass = 'ADORecordSet_array_pdo_firebird'; - function _init($parentDriver) - { - $this->pdoDriver = $parentDriver; - //$parentDriver->_bindInputArray = true; - //$parentDriver->hasTransactions = false; // // should be set to false because of PDO SQLite driver not supporting changing autocommit mode - //$parentDriver->hasInsertID = true; - } - /** * Gets the version iformation from the server * @@ -243,12 +235,6 @@ class ADODB_pdo_firebird extends ADODB_pdo return $this->Execute("DROP SEQUENCE $seqname"); } - - public function _affectedrows() - { - return fbird_affected_rows($this->_transactionID ? $this->_transactionID : $this->_connectionID); - } - public function genId($seqname = 'adodbseq', $startID = 1) { $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE"); diff --git a/lib/adodb/drivers/adodb-pdo_mysql.inc.php b/lib/adodb/drivers/adodb-pdo_mysql.inc.php index c8812453fd7..a00c8595bc7 100644 --- a/lib/adodb/drivers/adodb-pdo_mysql.inc.php +++ b/lib/adodb/drivers/adodb-pdo_mysql.inc.php @@ -57,7 +57,7 @@ class ADODB_pdo_mysql extends ADODB_pdo { return $date . ' + INTERVAL ' . $fraction . ' SECOND'; // return "from_unixtime(unix_timestamp($date)+$fraction)"; } - + /** * Get a list of indexes on the specified table. * @@ -266,7 +266,6 @@ class ADODB_pdo_mysql extends ADODB_pdo { function SelectDB($dbName) { $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions $try = $this->Execute('use ' . $dbName); return ($try !== false); } @@ -275,7 +274,7 @@ class ADODB_pdo_mysql extends ADODB_pdo { function SelectLimit($sql, $nrows=-1, $offset=-1, $inputarr=false, $secs=0) { $nrows = (int) $nrows; - $offset = (int) $offset; + $offset = (int) $offset; $offsetStr =($offset>=0) ? "$offset," : ''; // jason judge, see PHPLens Issue No: 9220 if ($nrows < 0) { diff --git a/lib/adodb/drivers/adodb-pdo_sqlsrv.inc.php b/lib/adodb/drivers/adodb-pdo_sqlsrv.inc.php index ed73f3a247f..de5fbba022f 100644 --- a/lib/adodb/drivers/adodb-pdo_sqlsrv.inc.php +++ b/lib/adodb/drivers/adodb-pdo_sqlsrv.inc.php @@ -36,10 +36,15 @@ class ADODB_pdo_sqlsrv extends ADODB_pdo $parentDriver->fmtDate = "'Y-m-d'"; } - function BeginTrans() + function setTransactionMode( $transaction_mode ) { - $returnval = parent::BeginTrans(); - return $returnval; + $this->_transmode = $transaction_mode; + if (empty($transaction_mode)) { + $this->_connectionID->query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); + return; + } + if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; + $this->_connectionID->query("SET TRANSACTION ".$transaction_mode); } function MetaColumns($table, $normalize = true) @@ -54,8 +59,7 @@ class ADODB_pdo_sqlsrv extends ADODB_pdo function SelectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs2cache = 0) { - $ret = ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); - return $ret; + return ADOConnection::SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache); } function ServerInfo() @@ -167,15 +171,5 @@ class ADORecordSet_array_pdo_sqlsrv extends ADORecordSet_array_pdo return $o; } - - function SetTransactionMode( $transaction_mode ) - { - $this->_transmode = $transaction_mode; - if (empty($transaction_mode)) { - $this->_connectionID->query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); - return; - } - if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode; - $this->_connectionID->query("SET TRANSACTION ".$transaction_mode); - } + } diff --git a/lib/adodb/drivers/adodb-postgres64.inc.php b/lib/adodb/drivers/adodb-postgres64.inc.php index 33ef47cb94f..fa8e5fba7aa 100644 --- a/lib/adodb/drivers/adodb-postgres64.inc.php +++ b/lib/adodb/drivers/adodb-postgres64.inc.php @@ -84,6 +84,9 @@ class ADODB_postgres64 extends ADOConnection{ /** @var int $_pnum Number of the last assigned query parameter {@see param()} */ var $_pnum = 0; + var $version; + var $_nestedSQL = false; + // The last (fmtTimeStamp is not entirely correct: // PostgreSQL also has support for time zones, // and writes these time in this format: "2001-03-01 18:59:26+02". @@ -656,14 +659,16 @@ class ADODB_postgres64 extends ADOConnection{ return $false; } + // Get column names indexed by attnum so we can lookup the index key $col_names = $this->MetaColumnNames($table,true,true); - // 3rd param is use attnum, - // see https://sourceforge.net/p/adodb/bugs/45/ $indexes = array(); while ($row = $rs->FetchRow()) { $columns = array(); foreach (explode(' ', $row[2]) as $col) { - $columns[] = $col_names[$col]; + // When index attribute (pg_index.indkey) is an expression, $col == 0 + // @see https://www.postgresql.org/docs/current/catalog-pg-index.html + // so there is no matching column name - set it to null (see #940). + $columns[] = $col_names[$col] ?? null; } $indexes[$row[0]] = array( @@ -752,8 +757,7 @@ class ADODB_postgres64 extends ADOConnection{ # PHP does not handle 'hex' properly ('x74657374' is returned as 't657374') # https://bugs.php.net/bug.php?id=59831 states this is in fact not a bug, # so we manually set bytea_output - if (!empty($this->connection->noBlobs) - && version_compare($info['version'], '9.0', '>=') + if (version_compare($info['version'], '9.0', '>=') && version_compare($info['client'], '9.2', '<') ) { $this->Execute('set bytea_output=escape'); diff --git a/lib/adodb/drivers/adodb-sybase.inc.php b/lib/adodb/drivers/adodb-sybase.inc.php index b8db0747970..5eb217a84d2 100644 --- a/lib/adodb/drivers/adodb-sybase.inc.php +++ b/lib/adodb/drivers/adodb-sybase.inc.php @@ -95,7 +95,9 @@ class ADODB_sybase extends ADOConnection { // http://www.isug.com/Sybase_FAQ/ASE/section6.1.html#6.1.4 function RowLock($tables,$where,$col='top 1 null as ignore') { - if (!$this->_hastrans) $this->BeginTrans(); + if (!$this->hasTransactions) { + $this->BeginTrans(); + } $tables = str_replace(',',' HOLDLOCK,',$tables); return $this->GetOne("select $col from $tables HOLDLOCK where $where"); @@ -104,7 +106,6 @@ class ADODB_sybase extends ADOConnection { function SelectDB($dbName) { $this->database = $dbName; - $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions if ($this->_connectionID) { return @sybase_select_db($dbName); } diff --git a/lib/adodb/readme_moodle.txt b/lib/adodb/readme_moodle.txt index bd23859ef63..be981c8fbe1 100644 --- a/lib/adodb/readme_moodle.txt +++ b/lib/adodb/readme_moodle.txt @@ -23,7 +23,3 @@ Removed: Added: * index.html - prevent directory browsing on misconfigured servers * readme_moodle.txt - this file ;-) - -Notes: - * 2023-02-10 Applied patch https://github.com/ADOdb/ADOdb/pull/928 to avoid PHP 8.2 deprecations. - See MDL-76413 for more details. \ No newline at end of file diff --git a/lib/adodb/tohtml.inc.php b/lib/adodb/tohtml.inc.php index b3c08e320d1..a36fdf6b84e 100644 --- a/lib/adodb/tohtml.inc.php +++ b/lib/adodb/tohtml.inc.php @@ -113,7 +113,8 @@ GLOBAL $gSQLMaxRows,$gSQLBlockRows,$ADODB_ROUND; else $v = round($v,$ADODB_ROUND); case 'I': - $vv = stripslashes((trim($v))); + $vv = $v ? stripslashes(trim($v)) : ''; + $vv = $vv ?: ' '; if (strlen($vv) == 0) $vv .= ' '; $s .= " ".$vv ."\n"; diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index 22ca2646189..7ac7d515dc3 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -4,7 +4,7 @@ adodb AdoDB Database abstraction library for MySQL, PostgreSQL, MSSQL, Oracle, Interbase, Foxpro, Access, ADO, Sybase, DB2 and ODBC. - 5.22.4 + 5.22.5 BSD/LGPL 3-Clause/2.1+ https://github.com/ADOdb/ADOdb