diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index 93903984bcf..dd5095002c4 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -946,6 +946,37 @@ class pgsql_native_moodle_database extends moodle_database { return true; } + /** + * A faster version of pg_field_type + * + * The pg_field_type function in the php postgres driver internally makes an sql call + * to get the list of field types which it statically caches only for a single request. + * This wraps it in a cache keyed by oid to avoid these DB calls on every request. + * + * @param resource $result + * @param int $fieldnumber + * @return string Field type + */ + public function pg_field_type($result, int $fieldnumber) { + static $map; + $cache = $this->get_metacache(); + + // Getting the oid doesn't make an internal query. + $oid = pg_field_type_oid($result, $fieldnumber); + if (!$map) { + $map = $cache->get('oid2typname'); + } + if ($map === false) { + $map = []; + } + if (isset($map[$oid])) { + return $map[$oid]; + } + $map[$oid] = pg_field_type($result, $fieldnumber); + $cache->set('oid2typname', $map); + return $map[$oid]; + } + /** * Get a number of records as an array of objects using a SQL statement. * @@ -980,7 +1011,7 @@ class pgsql_native_moodle_database extends moodle_database { $numfields = pg_num_fields($result); $blobs = array(); for ($i = 0; $i < $numfields; $i++) { - $type = pg_field_type($result, $i); + $type = $this->pg_field_type($result, $i); if ($type == 'bytea') { $blobs[] = pg_field_name($result, $i); } @@ -1021,7 +1052,7 @@ class pgsql_native_moodle_database extends moodle_database { $return = pg_fetch_all_columns($result, 0); - if (pg_field_type($result, 0) == 'bytea') { + if ($this->pg_field_type($result, 0) == 'bytea') { foreach ($return as $key => $value) { $return[$key] = ($value === null ? $value : pg_unescape_bytea($value)); } diff --git a/lib/dml/pgsql_native_moodle_recordset.php b/lib/dml/pgsql_native_moodle_recordset.php index a6eed21d030..6679934424f 100644 --- a/lib/dml/pgsql_native_moodle_recordset.php +++ b/lib/dml/pgsql_native_moodle_recordset.php @@ -74,7 +74,7 @@ class pgsql_native_moodle_recordset extends moodle_recordset { // Find out if there are any blobs. $numfields = pg_num_fields($this->result); for ($i = 0; $i < $numfields; $i++) { - $type = pg_field_type($this->result, $i); + $type = $this->db->pg_field_type($this->result, $i); if ($type == 'bytea') { $this->blobs[] = pg_field_name($this->result, $i); } diff --git a/lib/dml/tests/dml_test.php b/lib/dml/tests/dml_test.php index 18d5085a14b..7337b3e050b 100644 --- a/lib/dml/tests/dml_test.php +++ b/lib/dml/tests/dml_test.php @@ -17,15 +17,23 @@ /** * DML layer tests. * - * @package core_dml - * @category phpunit + * @package core + * @subpackage dml * @copyright 2008 Nicolas Connault * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); -class core_dml_testcase extends database_driver_testcase { +/** + * DML layer tests. + * + * @package core + * @subpackage dml + * @copyright 2008 Nicolas Connault + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class dml_test extends database_driver_testcase { protected function setUp(): void { parent::setUp(); @@ -493,7 +501,7 @@ SELECT * FROM {users} -- line 74 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->one() -- line 83 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->two() -- line 92 of /lib/dml/tests/fixtures/test_dml_sql_debugging_fixture.php: call to test_dml_sql_debugging_fixture->three() --- line 489 of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four() +-- line 497 of /lib/dml/tests/dml_test.php: call to test_dml_sql_debugging_fixture->four() EOD; $this->assertEquals($this->unix_to_os_dirsep($expected), $out); diff --git a/lib/dml/tests/pgsql_native_moodle_database_test.php b/lib/dml/tests/pgsql_native_moodle_database_test.php index 824fa179a93..2129abf26c3 100644 --- a/lib/dml/tests/pgsql_native_moodle_database_test.php +++ b/lib/dml/tests/pgsql_native_moodle_database_test.php @@ -32,7 +32,7 @@ * @copyright 2020 Ruslan Kabalin * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class pgsql_native_moodle_database_testcase extends advanced_testcase { +class pgsql_native_moodle_database_test extends advanced_testcase { /** * Setup before class. diff --git a/lib/dml/tests/pgsql_native_recordset_test.php b/lib/dml/tests/pgsql_native_recordset_test.php index f187bbf17bb..bee1b5160af 100644 --- a/lib/dml/tests/pgsql_native_recordset_test.php +++ b/lib/dml/tests/pgsql_native_recordset_test.php @@ -36,7 +36,7 @@ require_once($CFG->dirroot.'/lib/dml/pgsql_native_moodle_database.php'); * @copyright 2017 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class pgsql_native_recordset_testcase extends basic_testcase { +class pgsql_native_recordset_test extends basic_testcase { /** @var pgsql_native_moodle_database Special database connection */ protected $specialdb; diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 040d8f31b69..e9517db4086 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -85,6 +85,8 @@ information provided here is intended especially for developers. - question_preview_popup_params() is moved to \qbank_previewquestion\helper::question_preview_popup_params() Calling these functions in the question will point to the plugin, but the deprecation message will be activated in MDL-72004. The deprecated codes are removed from the questionlib for those two methods. +* The postgres driver now wraps calls to pg_field_type() and caches them in databasemeta to save an invisible internal + DB call on every request. === 3.11.2 === * For security reasons, filelib has been updated so all requests now use emulated redirects.