3 // Note: This code is identical to SafariPerfMonitor's db.php
5 error_reporting(E_ALL | E_STRICT);
7 function ends_with($str, $key) {
8 return strrpos($str, $key) == strlen($str) - strlen($key);
11 function ctype_alnum_underscore($str) {
12 return ctype_alnum(str_replace('_', '', $str));
15 function &array_ensure_item_has_array(&$array, $key) {
16 if (!array_key_exists($key, $array))
17 $array[$key] = array();
21 function array_get($array, $key, $default = NULL) {
22 if (!array_key_exists($key, $array))
29 function config($key) {
32 $_config = json_decode(file_get_contents(dirname(__FILE__) . '/config.json'), true);
33 return $_config[$key];
37 ini_set('display_errors', 'On');
41 private $connection = false;
43 function __destruct() {
44 if ($this->connection)
45 pg_close($this->connection);
46 $this->connection = false;
49 function is_true($value) {
54 $databaseConfig = config('database');
55 $this->connection = pg_connect('host=' . $databaseConfig['host'] . ' port=' . $databaseConfig['port']
56 . ' dbname=' . $databaseConfig['name'] . ' user=' . $databaseConfig['username'] . ' password=' . $databaseConfig['password']);
57 return $this->connection ? true : false;
60 private function prefixed_column_names($columns, $prefix = NULL) {
62 return join(', ', $columns);
63 return $prefix . '_' . join(', ' . $prefix . '_', $columns);
66 private function prefixed_name($column, $prefix = NULL) {
67 return $prefix ? $prefix . '_' . $column : $column;
70 private function prepare_params($params, &$placeholders, &$values) {
71 $column_names = array_keys($params);
73 $i = count($values) + 1;
74 foreach ($column_names as $name) {
75 assert(ctype_alnum_underscore($name));
76 array_push($placeholders, '$' . $i);
77 array_push($values, $params[$name]);
84 function insert_row($table, $prefix, $params, $returning = 'id') {
85 $placeholders = array();
87 $column_names = $this->prepare_params($params, $placeholders, $values);
89 assert(!$prefix || ctype_alnum_underscore($prefix));
90 $column_names = $this->prefixed_column_names($column_names, $prefix);
91 $placeholders = join(', ', $placeholders);
94 $returning_column_name = $this->prefixed_name($returning, $prefix);
95 $rows = $this->query_and_fetch_all("INSERT INTO $table ($column_names) VALUES ($placeholders) RETURNING $returning_column_name", $values);
96 return $rows ? $rows[0][$returning_column_name] : NULL;
99 return $this->query_and_get_affected_rows("INSERT INTO $table ($column_names) VALUES ($placeholders)", $values) == 1;
102 function select_or_insert_row($table, $prefix, $select_params, $insert_params = NULL, $returning = 'id') {
105 $select_placeholders = array();
106 $select_column_names = $this->prepare_params($select_params, $select_placeholders, $values);
107 $select_values = array_slice($values, 0);
109 if ($insert_params === NULL)
110 $insert_params = $select_params;
111 $insert_placeholders = array();
112 $insert_column_names = $this->prepare_params($insert_params, $insert_placeholders, $values);
114 assert(!!$returning);
115 assert(!$prefix || ctype_alnum_underscore($prefix));
116 $returning_column_name = $returning == '*' ? '*' : $this->prefixed_name($returning, $prefix);
117 $select_column_names = $this->prefixed_column_names($select_column_names, $prefix);
118 $select_placeholders = join(', ', $select_placeholders);
119 $query = "SELECT $returning_column_name FROM $table WHERE ($select_column_names) = ($select_placeholders)";
121 $insert_column_names = $this->prefixed_column_names($insert_column_names, $prefix);
122 $insert_placeholders = join(', ', $insert_placeholders);
123 $rows = $this->query_and_fetch_all("INSERT INTO $table ($insert_column_names) SELECT $insert_placeholders WHERE NOT EXISTS
124 ($query) RETURNING $returning_column_name", $values);
126 $rows = $this->query_and_fetch_all($query, $select_values);
128 return $rows ? ($returning == '*' ? $rows[0] : $rows[0][$returning_column_name]) : NULL;
131 function select_first_row($table, $prefix, $params, $order_by = NULL) {
132 $placeholders = array();
134 $column_names = join(', ', $this->prepare_params($params, $placeholders, $values));
135 $placeholders = join(', ', $placeholders);
136 $query = "SELECT * FROM $table WHERE ($column_names) = ($placeholders)";
138 assert(!ctype_alnum_underscore($order_by));
139 $query .= ' ORDER BY ' . $this->prefixed_name($order_by, $prefix);
141 $rows = $this->query_and_fetch_all($query . ' LIMIT 1', $values);
143 return $rows ? $rows[0] : NULL;
146 function query_and_get_affected_rows($query, $params = array()) {
147 if (!$this->connection)
149 $result = pg_query_params($this->connection, $query, $params);
152 return pg_affected_rows($result);
155 function query_and_fetch_all($query, $params = array()) {
156 if (!$this->connection)
158 $result = pg_query_params($this->connection, $query, $params);
161 return pg_fetch_all($result);
164 function fetch_table($table_name, $column_to_be_ordered_by = null) {
165 if (!$this->connection || !ctype_alnum_underscore($table_name) || ($column_to_be_ordered_by && !ctype_alnum_underscore($column_to_be_ordered_by)))
168 if ($column_to_be_ordered_by)
169 $clauses .= 'ORDER BY ' . $column_to_be_ordered_by;
170 return $this->query_and_fetch_all("SELECT * FROM $table_name $clauses");
173 function begin_transaction() {
174 return $this->connection and pg_query($this->connection, "BEGIN");
177 function commit_transaction() {
178 return $this->connection and pg_query($this->connection, 'COMMIT');
181 function rollback_transaction() {
182 return $this->connection and pg_query($this->connection, 'ROLLBACK');