Remove product literal strings in "pht()", part 18
[phabricator.git] / src / infrastructure / storage / connection / mysql / AphrontMySQLDatabaseConnection.php
blob40a2c6c3576bc578909d382c2729d1e885626486
1 <?php
3 final class AphrontMySQLDatabaseConnection
4 extends AphrontBaseMySQLDatabaseConnection {
6 public function escapeUTF8String($string) {
7 $this->validateUTF8String($string);
8 return $this->escapeBinaryString($string);
11 public function escapeBinaryString($string) {
12 return mysql_real_escape_string($string, $this->requireConnection());
15 public function getInsertID() {
16 return mysql_insert_id($this->requireConnection());
19 public function getAffectedRows() {
20 return mysql_affected_rows($this->requireConnection());
23 protected function closeConnection() {
24 mysql_close($this->requireConnection());
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()'));
39 $user = $this->getConfiguration('user');
40 $host = $this->getConfiguration('host');
41 $port = $this->getConfiguration('port');
43 if ($port) {
44 $host .= ':'.$port;
47 $database = $this->getConfiguration('database');
49 $pass = $this->getConfiguration('pass');
50 if ($pass instanceof PhutilOpaqueEnvelope) {
51 $pass = $pass->openEnvelope();
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);
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);
72 throw $ex;
75 if ($timeout) {
76 ini_set($timeout_ini, $old_timeout);
79 if (!$conn) {
80 $errno = mysql_errno();
81 $error = mysql_error();
82 $this->throwConnectionException($errno, $error, $user, $host);
85 if ($database !== null) {
86 $ret = @mysql_select_db($database, $conn);
87 if (!$ret) {
88 $this->throwQueryException($conn);
92 $ok = @mysql_set_charset('utf8mb4', $conn);
93 if (!$ok) {
94 mysql_set_charset('binary', $conn);
97 return $conn;
100 protected function rawQuery($raw_query) {
101 return @mysql_query($raw_query, $this->requireConnection());
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
110 protected function rawQueries(array $raw_queries) {
111 $conn = $this->requireConnection();
112 $results = array();
114 if (!function_exists('mysql_multi_query')) {
115 foreach ($raw_queries as $key => $raw_query) {
116 $results[$key] = $this->processResult($this->rawQuery($raw_query));
118 return $results;
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);
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;
133 mysql_next_result($conn);
136 if (!$processed_all) {
137 throw new Exception(
138 pht('There are some results left in the result set.'));
141 return $results;
144 protected function freeResult($result) {
145 mysql_free_result($result);
148 public function supportsParallelQueries() {
149 // fb_parallel_query() doesn't support results with different columns.
150 return false;
154 * @phutil-external-symbol function fb_parallel_query
156 public function executeParallelQueries(
157 array $queries,
158 array $conns = array()) {
159 assert_instances_of($conns, __CLASS__);
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);
167 $host = $conn->getConfiguration('host');
168 $port = 0;
169 $match = null;
170 if (preg_match('/(.+):(.+)/', $host, $match)) {
171 list(, $host, $port) = $match;
174 $pass = $conn->getConfiguration('pass');
175 if ($pass instanceof PhutilOpaqueEnvelope) {
176 $pass = $pass->openEnvelope();
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'),
189 $profiler = PhutilServiceProfiler::getInstance();
190 $call_id = $profiler->beginServiceCall(
191 array(
192 'type' => 'multi-query',
193 'queries' => $queries,
194 'write' => $is_write,
197 $map = fb_parallel_query($map);
199 $profiler->endServiceCall($call_id, array());
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;
213 continue;
215 $results[$id] = $map['result'][$pos];
216 $pos++;
218 return $results;
221 protected function fetchAssoc($result) {
222 return mysql_fetch_assoc($result);
225 protected function getErrorCode($connection) {
226 return mysql_errno($connection);
229 protected function getErrorDescription($connection) {
230 return mysql_error($connection);