Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 /** @var PgSql\Result|resource|null */ 39 protected $result; 40 /** @var current row as array.*/ 41 protected $current; 42 protected $blobs = array(); 43 44 /** @var string Name of cursor or '' if none */ 45 protected $cursorname; 46 47 /** @var pgsql_native_moodle_database Postgres database resource */ 48 protected $db; 49 50 /** @var bool True if there are no more rows to fetch from the cursor */ 51 protected $lastbatch; 52 53 /** 54 * Build a new recordset to iterate over. 55 * 56 * When using cursors, $result will be null initially. 57 * 58 * @param resource|PgSql\Result|null $result A pg_query() result object to create a recordset from. 59 * @param pgsql_native_moodle_database $db Database object (only required when using cursors) 60 * @param string $cursorname Name of cursor or '' if none 61 */ 62 public function __construct($result, pgsql_native_moodle_database $db = null, $cursorname = '') { 63 if ($cursorname && !$db) { 64 throw new coding_exception('When specifying a cursor, $db is required'); 65 } 66 $this->result = $result; 67 $this->db = $db; 68 $this->cursorname = $cursorname; 69 70 // When there is a cursor, do the initial fetch. 71 if ($cursorname) { 72 $this->fetch_cursor_block(); 73 } 74 75 // Find out if there are any blobs. 76 $numfields = pg_num_fields($this->result); 77 for ($i = 0; $i < $numfields; $i++) { 78 $type = $this->db->pg_field_type($this->result, $i); 79 if ($type == 'bytea') { 80 $this->blobs[] = pg_field_name($this->result, $i); 81 } 82 } 83 84 $this->current = $this->fetch_next(); 85 } 86 87 /** 88 * Fetches the next block of data when using cursors. 89 * 90 * @throws coding_exception If you call this when the fetch buffer wasn't freed yet 91 */ 92 protected function fetch_cursor_block() { 93 if ($this->result) { 94 throw new coding_exception('Unexpected non-empty result when fetching from cursor'); 95 } 96 list($this->result, $this->lastbatch) = $this->db->fetch_from_cursor($this->cursorname); 97 if (!$this->result) { 98 throw new coding_exception('Unexpected failure when fetching from cursor'); 99 } 100 } 101 102 public function __destruct() { 103 $this->close(); 104 } 105 106 private function fetch_next() { 107 if (!$this->result) { 108 return false; 109 } 110 if (!$row = pg_fetch_assoc($this->result)) { 111 // There are no more rows in this result. 112 pg_free_result($this->result); 113 $this->result = null; 114 115 // If using a cursor, can we fetch the next block? 116 if ($this->cursorname && !$this->lastbatch) { 117 $this->fetch_cursor_block(); 118 if (!$row = pg_fetch_assoc($this->result)) { 119 pg_free_result($this->result); 120 $this->result = null; 121 return false; 122 } 123 } else { 124 return false; 125 } 126 } 127 128 if ($this->blobs) { 129 foreach ($this->blobs as $blob) { 130 $row[$blob] = $row[$blob] !== null ? pg_unescape_bytea($row[$blob]) : null; 131 } 132 } 133 134 return $row; 135 } 136 137 public function current(): stdClass { 138 return (object)$this->current; 139 } 140 141 #[\ReturnTypeWillChange] 142 public function key() { 143 // return first column value as key 144 if (!$this->current) { 145 return false; 146 } 147 $key = reset($this->current); 148 return $key; 149 } 150 151 public function next(): void { 152 $this->current = $this->fetch_next(); 153 } 154 155 public function valid(): bool { 156 return !empty($this->current); 157 } 158 159 public function close() { 160 if ($this->result) { 161 pg_free_result($this->result); 162 $this->result = null; 163 } 164 $this->current = null; 165 $this->blobs = null; 166 167 // If using cursors, close the cursor. 168 if ($this->cursorname) { 169 $this->db->close_cursor($this->cursorname); 170 $this->cursorname = null; 171 } 172 } 173 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body