Skip to content

Commit

Permalink
MDL-68164 dml: Cache postgres field type metadata in MUC
Browse files Browse the repository at this point in the history
  • Loading branch information
brendanheywood committed Sep 7, 2021
1 parent 443a980 commit 66a923f
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 9 deletions.
35 changes: 33 additions & 2 deletions lib/dml/pgsql_native_moodle_database.php
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,37 @@ public function close_cursor($cursorname) {
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.
*
Expand Down Expand Up @@ -980,7 +1011,7 @@ public function get_records_sql($sql, array $params = null, $limitfrom = 0, $lim
$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);
}
Expand Down Expand Up @@ -1021,7 +1052,7 @@ public function get_fieldset_sql($sql, array $params=null) {

$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));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/dml/pgsql_native_moodle_recordset.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function __construct($result, pgsql_native_moodle_database $db = null, $c
// 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);
}
Expand Down
16 changes: 12 additions & 4 deletions lib/dml/tests/dml_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -493,7 +501,7 @@ public function test_add_sql_debugging() {
-- 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);

Expand Down
2 changes: 1 addition & 1 deletion lib/dml/tests/pgsql_native_moodle_database_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion lib/dml/tests/pgsql_native_recordset_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
* @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;
Expand Down
2 changes: 2 additions & 0 deletions lib/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ information provided here is intended especially for developers.
rendered. The default icon for "select" types has also changed to a dropdown caret ("t/expanded").
* The function message_send() in messagelib.php now returns false if there is an error sending the message to the
message processor (MDL-70046).
* 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.
Expand Down

0 comments on commit 66a923f

Please sign in to comment.