~ubuntu-branches/ubuntu/vivid/phabricator/vivid-proposed

« back to all changes in this revision

Viewing changes to libphutil/src/aphront/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2014-10-23 20:49:26 UTC
  • mfrom: (0.2.1) (0.1.1)
  • Revision ID: package-import@ubuntu.com-20141023204926-vq80u1op4df44azb
Tags: 0~git20141023-1
Initial release (closes: #703046)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
/**
 
4
 * @phutil-external-symbol class mysqli
 
5
 */
 
6
final class AphrontMySQLiDatabaseConnection
 
7
  extends AphrontBaseMySQLDatabaseConnection {
 
8
 
 
9
  public function escapeUTF8String($string) {
 
10
    $this->validateUTF8String($string);
 
11
    return $this->escapeBinaryString($string);
 
12
  }
 
13
 
 
14
  public function escapeBinaryString($string) {
 
15
    return $this->requireConnection()->escape_string($string);
 
16
  }
 
17
 
 
18
  public function getInsertID() {
 
19
    return $this->requireConnection()->insert_id;
 
20
  }
 
21
 
 
22
  public function getAffectedRows() {
 
23
    return $this->requireConnection()->affected_rows;
 
24
  }
 
25
 
 
26
  protected function closeConnection() {
 
27
    $this->requireConnection()->close();
 
28
  }
 
29
 
 
30
  protected function connect() {
 
31
    if (!class_exists('mysqli', false)) {
 
32
      throw new Exception(
 
33
        'About to call new mysqli(), but the PHP MySQLi extension is not '.
 
34
        'available!');
 
35
    }
 
36
 
 
37
    $user = $this->getConfiguration('user');
 
38
    $host = $this->getConfiguration('host');
 
39
    $port = $this->getConfiguration('port');
 
40
    $database = $this->getConfiguration('database');
 
41
 
 
42
    $pass = $this->getConfiguration('pass');
 
43
    if ($pass instanceof PhutilOpaqueEnvelope) {
 
44
      $pass = $pass->openEnvelope();
 
45
    }
 
46
 
 
47
    // If the host is "localhost", the port is ignored and mysqli attempts to
 
48
    // connect over a socket.
 
49
    if ($port) {
 
50
      if ($host === 'localhost' || $host === null) {
 
51
        $host = '127.0.0.1';
 
52
      }
 
53
    }
 
54
 
 
55
    $conn = @new mysqli(
 
56
      $host,
 
57
      $user,
 
58
      $pass,
 
59
      $database,
 
60
      $port);
 
61
 
 
62
    $errno = $conn->connect_errno;
 
63
    if ($errno) {
 
64
      $error = $conn->connect_error;
 
65
      throw new AphrontConnectionQueryException(
 
66
        "Attempt to connect to {$user}@{$host} failed with error ".
 
67
        "#{$errno}: {$error}.", $errno);
 
68
    }
 
69
 
 
70
    $ok = @$conn->set_charset('utf8mb4');
 
71
    if (!$ok) {
 
72
      $ok = $conn->set_charset('utf8');
 
73
    }
 
74
 
 
75
    return $conn;
 
76
  }
 
77
 
 
78
  protected function rawQuery($raw_query) {
 
79
    return @$this->requireConnection()->query($raw_query);
 
80
  }
 
81
 
 
82
  protected function rawQueries(array $raw_queries) {
 
83
    $conn = $this->requireConnection();
 
84
 
 
85
    $have_result = false;
 
86
    $results = array();
 
87
 
 
88
    foreach ($raw_queries as $key => $raw_query) {
 
89
      if (!$have_result) {
 
90
        // End line in front of semicolon to allow single line comments at the
 
91
        // end of queries.
 
92
        $have_result = $conn->multi_query(implode("\n;\n\n", $raw_queries));
 
93
      } else {
 
94
        $have_result = $conn->next_result();
 
95
      }
 
96
 
 
97
      array_shift($raw_queries);
 
98
 
 
99
      $result = $conn->store_result();
 
100
      if (!$result && !$this->getErrorCode($conn)) {
 
101
        $result = true;
 
102
      }
 
103
      $results[$key] = $this->processResult($result);
 
104
    }
 
105
 
 
106
    if ($conn->more_results()) {
 
107
      throw new Exception('There are some results left in the result set.');
 
108
    }
 
109
 
 
110
    return $results;
 
111
  }
 
112
 
 
113
  protected function freeResult($result) {
 
114
    $result->free_result();
 
115
  }
 
116
 
 
117
  protected function fetchAssoc($result) {
 
118
    return $result->fetch_assoc();
 
119
  }
 
120
 
 
121
  protected function getErrorCode($connection) {
 
122
    return $connection->errno;
 
123
  }
 
124
 
 
125
  protected function getErrorDescription($connection) {
 
126
    return $connection->error;
 
127
  }
 
128
 
 
129
  public function supportsAsyncQueries() {
 
130
    return defined('MYSQLI_ASYNC');
 
131
  }
 
132
 
 
133
  public function asyncQuery($raw_query) {
 
134
    $this->checkWrite($raw_query);
 
135
    $async = $this->beginAsyncConnection();
 
136
    $async->query($raw_query, MYSQLI_ASYNC);
 
137
    return $async;
 
138
  }
 
139
 
 
140
  public static function resolveAsyncQueries(array $conns, array $asyncs) {
 
141
    assert_instances_of($conns, 'AphrontMySQLiDatabaseConnection');
 
142
    assert_instances_of($asyncs, 'mysqli');
 
143
 
 
144
    $read = $error = $reject = array();
 
145
    foreach ($asyncs as $async) {
 
146
      $read[] = $error[] = $reject[] = $async;
 
147
    }
 
148
 
 
149
    if (!mysqli::poll($read, $error, $reject, 0)) {
 
150
      return array();
 
151
    }
 
152
 
 
153
    $results = array();
 
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());
 
159
    }
 
160
    return $results;
 
161
  }
 
162
 
 
163
}