See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Native postgresql recordset. 19 * 20 * @package core_dml 21 * @copyright 2008 Petr Skoda (http://skodak.org) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 require_once (__DIR__.'/moodle_recordset.php'); 28 29 /** 30 * pgsql specific moodle recordset class 31 * 32 * @package core_dml 33 * @copyright 2008 Petr Skoda (http://skodak.org) 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class pgsql_native_moodle_recordset extends moodle_recordset { 37 38 protected $result; 39 /** @var current row as array.*/ 40 protected $current; 41 protected $blobs = array(); 42 43 /** @var string Name of cursor or '' if none */ 44 protected $cursorname; 45 46 /** @var pgsql_native_moodle_database Postgres database resource */ 47 protected $db; 48 49 /** @var bool True if there are no more rows to fetch from the cursor */ 50 protected $lastbatch; 51 52 /** 53 * Build a new recordset to iterate over. 54 * 55 * When using cursors, $result will be null initially. 56 * 57 * @param resource|null $result A pg_query() result object to create a recordset from. 58 * @param pgsql_native_moodle_database $db Database object (only required when using cursors) 59 * @param string $cursorname Name of cursor or '' if none 60 */ 61 public function __construct($result, pgsql_native_moodle_database $db = null, $cursorname = '') { 62 if ($cursorname && !$db) { 63 throw new coding_exception('When specifying a cursor, $db is required'); 64 } 65 $this->result = $result; 66 $this->db = $db; 67 $this->cursorname = $cursorname; 68 69 // When there is a cursor, do the initial fetch. 70 if ($cursorname) { 71 $this->fetch_cursor_block(); 72 } 73 74 // Find out if there are any blobs. 75 $numfields = pg_num_fields($this->result); 76 for ($i = 0; $i < $numfields; $i++) { 77 $type = $this->db->pg_field_type($this->result, $i); 78 if ($type == 'bytea') { 79 $this->blobs[] = pg_field_name($this->result, $i); 80 } 81 } 82 83 $this->current = $this->fetch_next(); 84 } 85 86 /** 87 * Fetches the next block of data when using cursors. 88 * 89 * @throws coding_exception If you call this when the fetch buffer wasn't freed yet 90 */ 91 protected function fetch_cursor_block() { 92 if ($this->result) { 93 throw new coding_exception('Unexpected non-empty result when fetching from cursor'); 94 } 95 list($this->result, $this->lastbatch) = $this->db->fetch_from_cursor($this->cursorname); 96 if (!$this->result) { 97 throw new coding_exception('Unexpected failure when fetching from cursor'); 98 } 99 } 100 101 public function __destruct() { 102 $this->close(); 103 } 104 105 private function fetch_next() { 106 if (!$this->result) { 107 return false; 108 } 109 if (!$row = pg_fetch_assoc($this->result)) { 110 // There are no more rows in this result. 111 pg_free_result($this->result); 112 $this->result = null; 113 114 // If using a cursor, can we fetch the next block? 115 if ($this->cursorname && !$this->lastbatch) { 116 $this->fetch_cursor_block(); 117 if (!$row = pg_fetch_assoc($this->result)) { 118 pg_free_result($this->result); 119 $this->result = null; 120 return false; 121 } 122 } else { 123 return false; 124 } 125 } 126 127 if ($this->blobs) { 128 foreach ($this->blobs as $blob) { 129 $row[$blob] = $row[$blob] !== null ? pg_unescape_bytea($row[$blob]) : null; 130 } 131 } 132 133 return $row; 134 } 135 136 public function current(): stdClass { 137 return (object)$this->current; 138 } 139 140 #[\ReturnTypeWillChange] 141 public function key() { 142 // return first column value as key 143 if (!$this->current) { 144 return false; 145 } 146 $key = reset($this->current); 147 return $key; 148 } 149 150 public function next(): void { 151 $this->current = $this->fetch_next(); 152 } 153 154 public function valid(): bool { 155 return !empty($this->current); 156 } 157 158 public function close() { 159 if ($this->result) { 160 pg_free_result($this->result); 161 $this->result = null; 162 } 163 $this->current = null; 164 $this->blobs = null; 165 166 // If using cursors, close the cursor. 167 if ($this->cursorname) { 168 $this->db->close_cursor($this->cursorname); 169 $this->cursorname = null; 170 } 171 } 172 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body