3 final class AphrontIsolatedDatabaseConnection
4 extends AphrontDatabaseConnection
{
6 private $configuration;
7 private static $nextInsertID;
10 private $transcript = array();
13 private $affectedRows;
15 public function __construct(array $configuration) {
16 $this->configuration
= $configuration;
18 if (self
::$nextInsertID === null) {
19 // Generate test IDs into a distant ID space to reduce the risk of
20 // collisions and make them distinctive.
21 self
::$nextInsertID = 55555000000 +
mt_rand(0, 1000);
25 public function openConnection() {
29 public function close() {
33 public function escapeUTF8String($string) {
37 public function escapeBinaryString($string) {
41 public function escapeColumnName($name) {
45 public function escapeMultilineComment($comment) {
49 public function escapeStringForLikeClause($value) {
53 private function getConfiguration($key, $default = null) {
54 return idx($this->configuration
, $key, $default);
57 public function getInsertID() {
58 return $this->insertID
;
61 public function getAffectedRows() {
62 return $this->affectedRows
;
65 public function selectAllResults() {
66 return $this->allResults
;
69 public function executeQuery(PhutilQueryString
$query) {
71 // NOTE: "[\s<>K]*" allows any number of (properly escaped) comments to
72 // appear prior to the allowed keyword, since this connection escapes
73 // them as "<K>" (above).
75 $display_query = $query->getMaskedString();
76 $raw_query = $query->getUnmaskedString();
87 $preg_keywords = array();
88 foreach ($keywords as $key => $word) {
89 $preg_keywords[] = preg_quote($word, '/');
91 $preg_keywords = implode('|', $preg_keywords);
93 if (!preg_match('/^[\s<>K]*('.$preg_keywords.')\s*/i', $raw_query)) {
94 throw new AphrontNotSupportedQueryException(
96 "Database isolation currently only supports some queries. You are ".
97 "trying to issue a query which does not begin with an allowed ".
98 "keyword (%s): '%s'.",
99 implode(', ', $keywords),
103 $this->transcript
[] = $display_query;
105 // NOTE: This method is intentionally simplified for now, since we're only
106 // using it to stub out inserts/updates. In the future it will probably need
107 // to grow more powerful.
109 $this->allResults
= array();
111 // NOTE: We jitter the insert IDs to keep tests honest; a test should cover
112 // the relationship between objects, not their exact insertion order. This
113 // guarantees that IDs are unique but makes it impossible to hard-code tests
114 // against this specific implementation detail.
115 self
::$nextInsertID +
= mt_rand(1, 10);
116 $this->insertID
= self
::$nextInsertID;
117 $this->affectedRows
= 1;
120 public function executeRawQueries(array $raw_queries) {
122 foreach ($raw_queries as $id => $raw_query) {
123 $results[$id] = array();
128 public function getQueryTranscript() {
129 return $this->transcript
;