Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php
12242 views
1
<?php
2
3
final class AphrontMySQLDatabaseConnection
4
extends AphrontBaseMySQLDatabaseConnection {
5
6
public function escapeUTF8String($string) {
7
$this->validateUTF8String($string);
8
return $this->escapeBinaryString($string);
9
}
10
11
public function escapeBinaryString($string) {
12
return mysql_real_escape_string($string, $this->requireConnection());
13
}
14
15
public function getInsertID() {
16
return mysql_insert_id($this->requireConnection());
17
}
18
19
public function getAffectedRows() {
20
return mysql_affected_rows($this->requireConnection());
21
}
22
23
protected function closeConnection() {
24
mysql_close($this->requireConnection());
25
}
26
27
protected function connect() {
28
if (!function_exists('mysql_connect')) {
29
// We have to '@' the actual call since it can spew all sorts of silly
30
// noise, but it will also silence fatals caused by not having MySQL
31
// installed, which has bitten me on three separate occasions. Make sure
32
// such failures are explicit and loud.
33
throw new Exception(
34
pht(
35
'About to call %s, but the PHP MySQL extension is not available!',
36
'mysql_connect()'));
37
}
38
39
$user = $this->getConfiguration('user');
40
$host = $this->getConfiguration('host');
41
$port = $this->getConfiguration('port');
42
43
if ($port) {
44
$host .= ':'.$port;
45
}
46
47
$database = $this->getConfiguration('database');
48
49
$pass = $this->getConfiguration('pass');
50
if ($pass instanceof PhutilOpaqueEnvelope) {
51
$pass = $pass->openEnvelope();
52
}
53
54
$timeout = $this->getConfiguration('timeout');
55
$timeout_ini = 'mysql.connect_timeout';
56
if ($timeout) {
57
$old_timeout = ini_get($timeout_ini);
58
ini_set($timeout_ini, $timeout);
59
}
60
61
try {
62
$conn = @mysql_connect(
63
$host,
64
$user,
65
$pass,
66
$new_link = true,
67
$flags = 0);
68
} catch (Exception $ex) {
69
if ($timeout) {
70
ini_set($timeout_ini, $old_timeout);
71
}
72
throw $ex;
73
}
74
75
if ($timeout) {
76
ini_set($timeout_ini, $old_timeout);
77
}
78
79
if (!$conn) {
80
$errno = mysql_errno();
81
$error = mysql_error();
82
$this->throwConnectionException($errno, $error, $user, $host);
83
}
84
85
if ($database !== null) {
86
$ret = @mysql_select_db($database, $conn);
87
if (!$ret) {
88
$this->throwQueryException($conn);
89
}
90
}
91
92
$ok = @mysql_set_charset('utf8mb4', $conn);
93
if (!$ok) {
94
mysql_set_charset('binary', $conn);
95
}
96
97
return $conn;
98
}
99
100
protected function rawQuery($raw_query) {
101
return @mysql_query($raw_query, $this->requireConnection());
102
}
103
104
/**
105
* @phutil-external-symbol function mysql_multi_query
106
* @phutil-external-symbol function mysql_fetch_result
107
* @phutil-external-symbol function mysql_more_results
108
* @phutil-external-symbol function mysql_next_result
109
*/
110
protected function rawQueries(array $raw_queries) {
111
$conn = $this->requireConnection();
112
$results = array();
113
114
if (!function_exists('mysql_multi_query')) {
115
foreach ($raw_queries as $key => $raw_query) {
116
$results[$key] = $this->processResult($this->rawQuery($raw_query));
117
}
118
return $results;
119
}
120
121
if (!mysql_multi_query(implode("\n;\n\n", $raw_queries), $conn)) {
122
$ex = $this->processResult(false);
123
return array_fill_keys(array_keys($raw_queries), $ex);
124
}
125
126
$processed_all = false;
127
foreach ($raw_queries as $key => $raw_query) {
128
$results[$key] = $this->processResult(@mysql_fetch_result($conn));
129
if (!mysql_more_results($conn)) {
130
$processed_all = true;
131
break;
132
}
133
mysql_next_result($conn);
134
}
135
136
if (!$processed_all) {
137
throw new Exception(
138
pht('There are some results left in the result set.'));
139
}
140
141
return $results;
142
}
143
144
protected function freeResult($result) {
145
mysql_free_result($result);
146
}
147
148
public function supportsParallelQueries() {
149
// fb_parallel_query() doesn't support results with different columns.
150
return false;
151
}
152
153
/**
154
* @phutil-external-symbol function fb_parallel_query
155
*/
156
public function executeParallelQueries(
157
array $queries,
158
array $conns = array()) {
159
assert_instances_of($conns, __CLASS__);
160
161
$map = array();
162
$is_write = false;
163
foreach ($queries as $id => $query) {
164
$is_write = $is_write || $this->checkWrite($query);
165
$conn = idx($conns, $id, $this);
166
167
$host = $conn->getConfiguration('host');
168
$port = 0;
169
$match = null;
170
if (preg_match('/(.+):(.+)/', $host, $match)) {
171
list(, $host, $port) = $match;
172
}
173
174
$pass = $conn->getConfiguration('pass');
175
if ($pass instanceof PhutilOpaqueEnvelope) {
176
$pass = $pass->openEnvelope();
177
}
178
179
$map[$id] = array(
180
'sql' => $query,
181
'ip' => $host,
182
'port' => $port,
183
'username' => $conn->getConfiguration('user'),
184
'password' => $pass,
185
'db' => $conn->getConfiguration('database'),
186
);
187
}
188
189
$profiler = PhutilServiceProfiler::getInstance();
190
$call_id = $profiler->beginServiceCall(
191
array(
192
'type' => 'multi-query',
193
'queries' => $queries,
194
'write' => $is_write,
195
));
196
197
$map = fb_parallel_query($map);
198
199
$profiler->endServiceCall($call_id, array());
200
201
$results = array();
202
$pos = 0;
203
$err_pos = 0;
204
foreach ($queries as $id => $query) {
205
$errno = idx(idx($map, 'errno', array()), $err_pos);
206
$err_pos++;
207
if ($errno) {
208
try {
209
$this->throwQueryCodeException($errno, $map['error'][$id]);
210
} catch (Exception $ex) {
211
$results[$id] = $ex;
212
}
213
continue;
214
}
215
$results[$id] = $map['result'][$pos];
216
$pos++;
217
}
218
return $results;
219
}
220
221
protected function fetchAssoc($result) {
222
return mysql_fetch_assoc($result);
223
}
224
225
protected function getErrorCode($connection) {
226
return mysql_errno($connection);
227
}
228
229
protected function getErrorDescription($connection) {
230
return mysql_error($connection);
231
}
232
233
}
234
235