]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/libs/rdbms/database/resultwrapper/ResultWrapper.php
MediaWiki 1.30.2-scripts2
[autoinstalls/mediawiki.git] / includes / libs / rdbms / database / resultwrapper / ResultWrapper.php
1 <?php
2
3 namespace Wikimedia\Rdbms;
4
5 use stdClass;
6 use RuntimeException;
7
8 /**
9  * Result wrapper for grabbing data queried from an IDatabase object
10  *
11  * Note that using the Iterator methods in combination with the non-Iterator
12  * DB result iteration functions may cause rows to be skipped or repeated.
13  *
14  * By default, this will use the iteration methods of the IDatabase handle if provided.
15  * Subclasses can override methods to make it solely work on the result resource instead.
16  * If no database is provided, and the subclass does not override the DB iteration methods,
17  * then a RuntimeException will be thrown when iteration is attempted.
18  *
19  * The result resource field should not be accessed from non-Database related classes.
20  * It is database class specific and is stored here to associate iterators with queries.
21  *
22  * @ingroup Database
23  */
24 class ResultWrapper implements IResultWrapper {
25         /** @var resource|array|null Optional underlying result handle for subclass usage */
26         public $result;
27
28         /** @var IDatabase|null */
29         protected $db;
30
31         /** @var int */
32         protected $pos = 0;
33         /** @var stdClass|null */
34         protected $currentRow = null;
35
36         /**
37          * Create a row iterator from a result resource and an optional Database object
38          *
39          * Only Database-related classes should construct ResultWrapper. Other code may
40          * use the FakeResultWrapper subclass for convenience or compatibility shims, however.
41          *
42          * @param IDatabase|null $db Optional database handle
43          * @param ResultWrapper|array|resource $result Optional underlying result handle
44          */
45         public function __construct( IDatabase $db = null, $result ) {
46                 $this->db = $db;
47                 if ( $result instanceof ResultWrapper ) {
48                         $this->result = $result->result;
49                 } else {
50                         $this->result = $result;
51                 }
52         }
53
54         public function numRows() {
55                 return $this->getDB()->numRows( $this );
56         }
57
58         public function fetchObject() {
59                 return $this->getDB()->fetchObject( $this );
60         }
61
62         public function fetchRow() {
63                 return $this->getDB()->fetchRow( $this );
64         }
65
66         public function seek( $row ) {
67                 $this->getDB()->dataSeek( $this, $row );
68         }
69
70         public function free() {
71                 if ( $this->db ) {
72                         $this->db->freeResult( $this );
73                         $this->db = null;
74                 }
75                 $this->result = null;
76         }
77
78         /**
79          * @return IDatabase
80          * @throws RuntimeException
81          */
82         private function getDB() {
83                 if ( !$this->db ) {
84                         throw new RuntimeException( static::class . ' needs a DB handle for iteration.' );
85                 }
86
87                 return $this->db;
88         }
89
90         function rewind() {
91                 if ( $this->numRows() ) {
92                         $this->getDB()->dataSeek( $this, 0 );
93                 }
94                 $this->pos = 0;
95                 $this->currentRow = null;
96         }
97
98         function current() {
99                 if ( is_null( $this->currentRow ) ) {
100                         $this->next();
101                 }
102
103                 return $this->currentRow;
104         }
105
106         function key() {
107                 return $this->pos;
108         }
109
110         function next() {
111                 $this->pos++;
112                 $this->currentRow = $this->fetchObject();
113
114                 return $this->currentRow;
115         }
116
117         function valid() {
118                 return $this->current() !== false;
119         }
120 }
121
122 class_alias( ResultWrapper::class, 'ResultWrapper' );