936030e4bae752c8c120d4f77dab5b10dc5f4ede
[WebKit-https.git] / Websites / test-results / public / include / db.php
1 <?php
2
3 // Note: This code is identical to SafariPerfMonitor's db.php
4
5 error_reporting(E_ALL | E_STRICT);
6
7 function ends_with($str, $key) {
8     return strrpos($str, $key) == strlen($str) - strlen($key);
9 }
10
11 function ctype_alnum_underscore($str) {
12     return ctype_alnum(str_replace('_', '', $str));
13 }
14
15 function &array_ensure_item_has_array(&$array, $key) {
16     if (!array_key_exists($key, $array))
17         $array[$key] = array();
18     return $array[$key];
19 }
20
21 function array_get($array, $key, $default = NULL) {
22     if (!array_key_exists($key, $array))
23         return $default;
24     return $array[$key];
25 }
26
27 $_config = NULL;
28
29 function config($key) {
30     global $_config;
31     if (!$_config)
32         $_config = json_decode(file_get_contents(dirname(__FILE__) . '/../../config.json'), true);
33     return $_config[$key];
34 }
35
36 function configPath($key, $additional_path = '') {
37     $relative_path = config($key);
38     if (!$relative_path)
39         return NULL;
40     if ($additional_path)
41         $additional_path = '/' . $additional_path;
42     return realpath(dirname(__FILE__) . "/$relative_path") . $additional_path;
43 }
44
45 if (config('debug'))
46     ini_set('display_errors', 'On');
47
48 class Database
49 {
50     private $connection = false;
51
52     function __destruct() {
53         if ($this->connection)
54             pg_close($this->connection);
55         $this->connection = false;
56     }
57
58     function is_true($value) {
59         return $value == 't';
60     }
61
62     function connect() {
63         $databaseConfig = config('database');
64         $this->connection = pg_connect('host=' . $databaseConfig['host'] . ' port=' . $databaseConfig['port']
65             . ' dbname=' . $databaseConfig['name'] . ' user=' . $databaseConfig['username'] . ' password=' . $databaseConfig['password']);
66         return $this->connection ? true : false;
67     }
68
69     private function prefixed_column_names($columns, $prefix = NULL) {
70         if (!$prefix)
71             return join(', ', $columns);
72         return $prefix . '_' . join(', ' . $prefix . '_', $columns);
73     }
74
75     private function prefixed_name($column, $prefix = NULL) {
76         return $prefix ? $prefix . '_' . $column : $column;
77     }
78
79     private function prepare_params($params, &$placeholders, &$values) {
80         $column_names = array_keys($params);
81
82         $i = count($values) + 1;
83         foreach ($column_names as $name) {
84             assert(ctype_alnum_underscore($name));
85             array_push($placeholders, '$' . $i);
86             array_push($values, $params[$name]);
87             $i++;
88         }
89
90         return $column_names;
91     }
92
93     function insert_row($table, $prefix, $params, $returning = 'id') {
94         $placeholders = array();
95         $values = array();
96         $column_names = $this->prepare_params($params, $placeholders, $values);
97
98         assert(!$prefix || ctype_alnum_underscore($prefix));
99         $column_names = $this->prefixed_column_names($column_names, $prefix);
100         $placeholders = join(', ', $placeholders);
101
102         if ($returning) {
103             $returning_column_name = $this->prefixed_name($returning, $prefix);
104             $rows = $this->query_and_fetch_all("INSERT INTO $table ($column_names) VALUES ($placeholders) RETURNING $returning_column_name", $values);
105             return $rows ? $rows[0][$returning_column_name] : NULL;
106         }
107
108         return $this->query_and_get_affected_rows("INSERT INTO $table ($column_names) VALUES ($placeholders)", $values) == 1;
109     }
110
111     function select_or_insert_row($table, $prefix, $select_params, $insert_params = NULL, $returning = 'id') {
112         $values = array();
113
114         $select_placeholders = array();
115         $select_column_names = $this->prepare_params($select_params, $select_placeholders, $values);
116         $select_values = array_slice($values, 0);
117
118         if ($insert_params === NULL)
119             $insert_params = $select_params;
120         $insert_placeholders = array();
121         $insert_column_names = $this->prepare_params($insert_params, $insert_placeholders, $values);
122
123         assert(!!$returning);
124         assert(!$prefix || ctype_alnum_underscore($prefix));
125         $returning_column_name = $returning == '*' ? '*' : $this->prefixed_name($returning, $prefix);
126         $select_column_names = $this->prefixed_column_names($select_column_names, $prefix);
127         $select_placeholders = join(', ', $select_placeholders);
128         $query = "SELECT $returning_column_name FROM $table WHERE ($select_column_names) = ($select_placeholders)";
129
130         $insert_column_names = $this->prefixed_column_names($insert_column_names, $prefix);
131         $insert_placeholders = join(', ', $insert_placeholders);
132         $rows = $this->query_and_fetch_all("INSERT INTO $table ($insert_column_names) SELECT $insert_placeholders WHERE NOT EXISTS
133             ($query) RETURNING $returning_column_name", $values);
134         if (!$rows)
135             $rows = $this->query_and_fetch_all($query, $select_values);
136
137         return $rows ? ($returning == '*' ? $rows[0] : $rows[0][$returning_column_name]) : NULL;
138     }
139
140     function select_first_row($table, $prefix, $params, $order_by = NULL) {
141         $placeholders = array();
142         $values = array();
143         $column_names = join(', ', $this->prepare_params($params, $placeholders, $values));
144         $placeholders = join(', ', $placeholders);
145         $query = "SELECT * FROM $table WHERE ($column_names) = ($placeholders)";
146         if ($order_by) {
147             assert(!ctype_alnum_underscore($order_by));
148             $query .= ' ORDER BY ' . $this->prefixed_name($order_by, $prefix);
149         }
150         $rows = $this->query_and_fetch_all($query . ' LIMIT 1', $values);
151
152         return $rows ? $rows[0] : NULL;
153     }
154
155     function query_and_get_affected_rows($query, $params = array()) {
156         if (!$this->connection)
157             return 0;
158         $result = pg_query_params($this->connection, $query, $params);
159         if (!$result)
160             return 0;
161         return pg_affected_rows($result);
162     }
163
164     function query_and_fetch_all($query, $params = array()) {
165         if (!$this->connection)
166             return false;
167         $result = pg_query_params($this->connection, $query, $params);
168         if (!$result)
169             return false;
170         return pg_fetch_all($result);
171     }
172
173     function query($query, $params = array()) {
174         if (!$this->connection)
175             return FALSE;
176         return pg_query_params($this->connection, $query, $params);
177     }
178
179     function fetch_next_row($result) {
180         return pg_fetch_assoc($result);
181     }
182
183     function fetch_table($table_name, $column_to_be_ordered_by = null) {
184         if (!$this->connection || !ctype_alnum_underscore($table_name) || ($column_to_be_ordered_by && !ctype_alnum_underscore($column_to_be_ordered_by)))
185             return false;
186         $clauses = '';
187         if ($column_to_be_ordered_by)
188             $clauses .= 'ORDER BY ' . $column_to_be_ordered_by;
189         return $this->query_and_fetch_all("SELECT * FROM $table_name $clauses");
190     }
191
192     function begin_transaction() {
193         return $this->connection and pg_query($this->connection, "BEGIN");
194     }
195
196     function commit_transaction() {
197         return $this->connection and pg_query($this->connection, 'COMMIT');
198     }
199
200     function rollback_transaction() {
201         return $this->connection and pg_query($this->connection, 'ROLLBACK');
202     }
203
204 }
205
206 ?>