Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/infrastructure/storage/connection/AphrontIsolatedDatabaseConnection.php
12241 views
1
<?php
2
3
final class AphrontIsolatedDatabaseConnection
4
extends AphrontDatabaseConnection {
5
6
private $configuration;
7
private static $nextInsertID;
8
private $insertID;
9
10
private $transcript = array();
11
12
private $allResults;
13
private $affectedRows;
14
15
public function __construct(array $configuration) {
16
$this->configuration = $configuration;
17
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);
22
}
23
}
24
25
public function openConnection() {
26
return;
27
}
28
29
public function close() {
30
return;
31
}
32
33
public function escapeUTF8String($string) {
34
return '<S>';
35
}
36
37
public function escapeBinaryString($string) {
38
return '<B>';
39
}
40
41
public function escapeColumnName($name) {
42
return '<C>';
43
}
44
45
public function escapeMultilineComment($comment) {
46
return '<K>';
47
}
48
49
public function escapeStringForLikeClause($value) {
50
return '<L>';
51
}
52
53
private function getConfiguration($key, $default = null) {
54
return idx($this->configuration, $key, $default);
55
}
56
57
public function getInsertID() {
58
return $this->insertID;
59
}
60
61
public function getAffectedRows() {
62
return $this->affectedRows;
63
}
64
65
public function selectAllResults() {
66
return $this->allResults;
67
}
68
69
public function executeQuery(PhutilQueryString $query) {
70
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).
74
75
$display_query = $query->getMaskedString();
76
$raw_query = $query->getUnmaskedString();
77
78
$keywords = array(
79
'INSERT',
80
'UPDATE',
81
'DELETE',
82
'START',
83
'SAVEPOINT',
84
'COMMIT',
85
'ROLLBACK',
86
);
87
$preg_keywords = array();
88
foreach ($keywords as $key => $word) {
89
$preg_keywords[] = preg_quote($word, '/');
90
}
91
$preg_keywords = implode('|', $preg_keywords);
92
93
if (!preg_match('/^[\s<>K]*('.$preg_keywords.')\s*/i', $raw_query)) {
94
throw new AphrontNotSupportedQueryException(
95
pht(
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),
100
$display_query));
101
}
102
103
$this->transcript[] = $display_query;
104
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.
108
109
$this->allResults = array();
110
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;
118
}
119
120
public function executeRawQueries(array $raw_queries) {
121
$results = array();
122
foreach ($raw_queries as $id => $raw_query) {
123
$results[$id] = array();
124
}
125
return $results;
126
}
127
128
public function getQueryTranscript() {
129
return $this->transcript;
130
}
131
132
}
133
134