4
* @phutil-external-symbol class mysqli
6
final class AphrontMySQLiDatabaseConnection
7
extends AphrontBaseMySQLDatabaseConnection {
9
public function escapeUTF8String($string) {
10
$this->validateUTF8String($string);
11
return $this->escapeBinaryString($string);
14
public function escapeBinaryString($string) {
15
return $this->requireConnection()->escape_string($string);
18
public function getInsertID() {
19
return $this->requireConnection()->insert_id;
22
public function getAffectedRows() {
23
return $this->requireConnection()->affected_rows;
26
protected function closeConnection() {
27
$this->requireConnection()->close();
30
protected function connect() {
31
if (!class_exists('mysqli', false)) {
33
'About to call new mysqli(), but the PHP MySQLi extension is not '.
37
$user = $this->getConfiguration('user');
38
$host = $this->getConfiguration('host');
39
$port = $this->getConfiguration('port');
40
$database = $this->getConfiguration('database');
42
$pass = $this->getConfiguration('pass');
43
if ($pass instanceof PhutilOpaqueEnvelope) {
44
$pass = $pass->openEnvelope();
47
// If the host is "localhost", the port is ignored and mysqli attempts to
48
// connect over a socket.
50
if ($host === 'localhost' || $host === null) {
62
$errno = $conn->connect_errno;
64
$error = $conn->connect_error;
65
throw new AphrontConnectionQueryException(
66
"Attempt to connect to {$user}@{$host} failed with error ".
67
"#{$errno}: {$error}.", $errno);
70
$ok = @$conn->set_charset('utf8mb4');
72
$ok = $conn->set_charset('utf8');
78
protected function rawQuery($raw_query) {
79
return @$this->requireConnection()->query($raw_query);
82
protected function rawQueries(array $raw_queries) {
83
$conn = $this->requireConnection();
88
foreach ($raw_queries as $key => $raw_query) {
90
// End line in front of semicolon to allow single line comments at the
92
$have_result = $conn->multi_query(implode("\n;\n\n", $raw_queries));
94
$have_result = $conn->next_result();
97
array_shift($raw_queries);
99
$result = $conn->store_result();
100
if (!$result && !$this->getErrorCode($conn)) {
103
$results[$key] = $this->processResult($result);
106
if ($conn->more_results()) {
107
throw new Exception('There are some results left in the result set.');
113
protected function freeResult($result) {
114
$result->free_result();
117
protected function fetchAssoc($result) {
118
return $result->fetch_assoc();
121
protected function getErrorCode($connection) {
122
return $connection->errno;
125
protected function getErrorDescription($connection) {
126
return $connection->error;
129
public function supportsAsyncQueries() {
130
return defined('MYSQLI_ASYNC');
133
public function asyncQuery($raw_query) {
134
$this->checkWrite($raw_query);
135
$async = $this->beginAsyncConnection();
136
$async->query($raw_query, MYSQLI_ASYNC);
140
public static function resolveAsyncQueries(array $conns, array $asyncs) {
141
assert_instances_of($conns, 'AphrontMySQLiDatabaseConnection');
142
assert_instances_of($asyncs, 'mysqli');
144
$read = $error = $reject = array();
145
foreach ($asyncs as $async) {
146
$read[] = $error[] = $reject[] = $async;
149
if (!mysqli::poll($read, $error, $reject, 0)) {
154
foreach ($read as $async) {
155
$key = array_search($async, $asyncs, $strict = true);
156
$conn = $conns[$key];
157
$conn->endAsyncConnection($async);
158
$results[$key] = $conn->processResult($async->reap_async_query());