MediaWiki  master
DatabaseMysqli.php
Go to the documentation of this file.
1 <?php
23 namespace Wikimedia\Rdbms;
24 
25 use mysqli;
26 use mysqli_result;
27 use IP;
28 use stdClass;
30 
44  protected function doQuery( $sql ) {
45  AtEase::suppressWarnings();
46  $res = $this->getBindingHandle()->query( $sql );
47  AtEase::restoreWarnings();
48 
49  return $res;
50  }
51 
58  protected function mysqlConnect( $realServer, $dbName ) {
59  if ( !function_exists( 'mysqli_init' ) ) {
60  throw $this->newExceptionAfterConnectError(
61  "MySQLi functions missing, have you compiled PHP with the --with-mysqli option?"
62  );
63  }
64 
65  // Other than mysql_connect, mysqli_real_connect expects an explicit port number
66  // e.g. "localhost:1234" or "127.0.0.1:1234"
67  // or Unix domain socket path
68  // e.g. "localhost:/socket_path" or "localhost:/foo/bar:bar:bar"
69  // colons are known to be used by Google AppEngine,
70  // see <https://cloud.google.com/sql/docs/mysql/connect-app-engine>
71  //
72  // We need to parse the port or socket path out of $realServer
73  $port = null;
74  $socket = null;
75  $hostAndPort = IP::splitHostAndPort( $realServer );
76  if ( $hostAndPort ) {
77  $realServer = $hostAndPort[0];
78  if ( $hostAndPort[1] ) {
79  $port = $hostAndPort[1];
80  }
81  } elseif ( substr_count( $realServer, ':/' ) == 1 ) {
82  // If we have a colon slash instead of a colon and a port number
83  // after the ip or hostname, assume it's the Unix domain socket path
84  list( $realServer, $socket ) = explode( ':', $realServer, 2 );
85  }
86 
87  $mysqli = mysqli_init();
88  // Make affectedRows() for UPDATE reflect the number of matching rows, regardless
89  // of whether any column values changed. This is what callers want to know and is
90  // consistent with what Postgres, SQLite, and SQL Server return.
91  $connFlags = MYSQLI_CLIENT_FOUND_ROWS;
92  if ( $this->getFlag( self::DBO_SSL ) ) {
93  $connFlags |= MYSQLI_CLIENT_SSL;
94  $mysqli->ssl_set(
95  $this->sslKeyPath,
96  $this->sslCertPath,
97  $this->sslCAFile,
98  $this->sslCAPath,
99  $this->sslCiphers
100  );
101  }
102  if ( $this->getFlag( self::DBO_COMPRESS ) ) {
103  $connFlags |= MYSQLI_CLIENT_COMPRESS;
104  }
105  if ( $this->getFlag( self::DBO_PERSISTENT ) ) {
106  $realServer = 'p:' . $realServer;
107  }
108 
109  if ( $this->utf8Mode ) {
110  // Tell the server we're communicating with it in UTF-8.
111  // This may engage various charset conversions.
112  $mysqli->options( MYSQLI_SET_CHARSET_NAME, 'utf8' );
113  } else {
114  $mysqli->options( MYSQLI_SET_CHARSET_NAME, 'binary' );
115  }
116  $mysqli->options( MYSQLI_OPT_CONNECT_TIMEOUT, 3 );
117 
118  if ( $mysqli->real_connect(
119  $realServer,
120  $this->user,
121  $this->password,
122  $dbName,
123  $port,
124  $socket,
125  $connFlags
126  ) ) {
127  return $mysqli;
128  }
129 
130  return null;
131  }
132 
136  protected function closeConnection() {
137  $conn = $this->getBindingHandle();
138 
139  return $conn->close();
140  }
141 
145  function insertId() {
146  $conn = $this->getBindingHandle();
147 
148  return (int)$conn->insert_id;
149  }
150 
154  function lastErrno() {
155  if ( $this->conn instanceof mysqli ) {
156  return $this->conn->errno;
157  } else {
158  return mysqli_connect_errno();
159  }
160  }
161 
165  protected function fetchAffectedRowCount() {
166  $conn = $this->getBindingHandle();
167 
168  return $conn->affected_rows;
169  }
170 
175  protected function mysqlFreeResult( $res ) {
176  $res->free_result();
177 
178  return true;
179  }
180 
185  protected function mysqlFetchObject( $res ) {
186  $object = $res->fetch_object();
187  if ( $object === null ) {
188  return false;
189  }
190 
191  return $object;
192  }
193 
198  protected function mysqlFetchArray( $res ) {
199  $array = $res->fetch_array();
200  if ( $array === null ) {
201  return false;
202  }
203 
204  return $array;
205  }
206 
211  protected function mysqlNumRows( $res ) {
212  return $res->num_rows;
213  }
214 
219  protected function mysqlNumFields( $res ) {
220  return $res->field_count;
221  }
222 
228  protected function mysqlFetchField( $res, $n ) {
229  $field = $res->fetch_field_direct( $n );
230 
231  // Add missing properties to result (using flags property)
232  // which will be part of function mysql-fetch-field for backward compatibility
233  $field->not_null = $field->flags & MYSQLI_NOT_NULL_FLAG;
234  $field->primary_key = $field->flags & MYSQLI_PRI_KEY_FLAG;
235  $field->unique_key = $field->flags & MYSQLI_UNIQUE_KEY_FLAG;
236  $field->multiple_key = $field->flags & MYSQLI_MULTIPLE_KEY_FLAG;
237  $field->binary = $field->flags & MYSQLI_BINARY_FLAG;
238  $field->numeric = $field->flags & MYSQLI_NUM_FLAG;
239  $field->blob = $field->flags & MYSQLI_BLOB_FLAG;
240  $field->unsigned = $field->flags & MYSQLI_UNSIGNED_FLAG;
241  $field->zerofill = $field->flags & MYSQLI_ZEROFILL_FLAG;
242 
243  return $field;
244  }
245 
251  protected function mysqlFieldName( $res, $n ) {
252  $field = $res->fetch_field_direct( $n );
253 
254  return $field->name;
255  }
256 
262  protected function mysqlFieldType( $res, $n ) {
263  $field = $res->fetch_field_direct( $n );
264 
265  return $field->type;
266  }
267 
273  protected function mysqlDataSeek( $res, $row ) {
274  return $res->data_seek( $row );
275  }
276 
281  protected function mysqlError( $conn = null ) {
282  if ( $conn === null ) {
283  return mysqli_connect_error();
284  } else {
285  return $conn->error;
286  }
287  }
288 
294  protected function mysqlRealEscapeString( $s ) {
295  $conn = $this->getBindingHandle();
296 
297  return $conn->real_escape_string( (string)$s );
298  }
299 
303  protected function getBindingHandle() {
304  return parent::getBindingHandle();
305  }
306 }
307 
311 class_alias( DatabaseMysqli::class, 'DatabaseMysqli' );
getFlag( $flag)
Returns a boolean whether the flag $flag is set for this connection.
Definition: Database.php:802
mysqlRealEscapeString( $s)
Escapes special characters in a string for use in an SQL statement.
Database abstraction object for PHP extension mysqli.
newExceptionAfterConnectError( $error)
Definition: Database.php:1634
const DBO_PERSISTENT
Definition: defines.php:14
static splitHostAndPort( $both)
Given a host/port string, like one might find in the host part of a URL per RFC 2732, split the hostname part and the port part and return an array with an element for each.
Definition: IP.php:253
mysqlConnect( $realServer, $dbName)
object resource null $conn
Database connection.
Definition: Database.php:69
const DBO_SSL
Definition: defines.php:17
const DBO_COMPRESS
Definition: defines.php:18
Database abstraction object for MySQL.