-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdatabase.php
More file actions
255 lines (218 loc) · 8.5 KB
/
database.php
File metadata and controls
255 lines (218 loc) · 8.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
<?php
class Database {
private static $connection;
private static $prepared = array();
private static $quoted = array();
/**
* Connect to a database
*
* Will connect to the database if a connection does not yet exist. If
* one does exist, that is returned (regardless of arguments passed).
* If there's a global $DBCONFIG variable, then that can be used
* instead of passing connection paramters. If parameters are passed,
* they will supercede the $DBCONFIG variable.
*
* @param string $params The connection parameters
* @throws InvalidArgumentException
* @return resource
*/
public static function connect($params = null) {
global $DBCONFIG;
if (self::$connection) {
return self::$connection;
}
if (!$params) {
$params = $DBCONFIG;
}
if (!isset($params)) {
$msg = "No parameters were passed and \$DBCONFIG is empty";
throw new InvalidArgumentException($msg);
}
$connect_ary = array();
foreach ($params as $key => $value) {
$value = preg_replace('/( |\\\\)/', '\\\\\1', $value);
if (preg_match('/ /', $value)) {
$value = "'$value'";
}
$connect_ary[] = "$key=$value";
}
self::$connection = pg_connect(join(' ', $connect_ary));
return self::$connection;
}
/**
* Check whether a given statement name has been prepared.
*
* @param string $name The name of the prepared statement
* @return boolean
*/
public static function prepared($name) {
return array_key_exists($name, self::$prepared);
}
/**
* Execute a query and return the result
*
* Executes a query with optional parameters (which are automatically
* escaped). If a name is provided, then the query will be prepared
* and saved if necessary (or simply executed if it was already
* prepared). Unnamed queries are prepared and executed each time they
* are called. Note that the second and later times a named statement
* is called, the query string is disregarded (as the statement is
* already prepared). There is no way to reallocate a name for a
* query.
*
* @param string $str The query string to execute
* @param array $params The query parameters
* @param string $name The name of the query
* @throws DatabaseException
* @return resource
*/
public static function query($str, $params = array(), $name = null) {
$p =& self::$prepared;
if (($name && !array_key_exists($name, $p)) || !$name) {
if ($name) {
$p[$name] = true;
}
else {
$name = '';
}
error_log("Preparing query ($name): $str");
$prepped = pg_prepare(Database::connect(), $name, $str);
if ($prepped === false) {
$pgerr = pg_last_error();
if ($name) {
$msg = "Could not prepare query $name: $pgerr";
}
else {
$msg = "Could not prepare query: $pgerr";
}
throw new DatabaseException($msg);
}
}
error_log("Executing query $name");
$resource = pg_execute(Database::connect(), $name, $params);
if ($resource === false) {
$pgerr = pg_last_error();
if ($name) {
$msg = "Could not execute query $name: $pgerr";
}
else {
$msg = "Could not execute query: $pgerr";
}
throw new DatabaseException($msg);
}
return $resource;
}
/**
* Execute a query and fetch all results
*
* This function pre-loads all results from a query into an array and
* returns it. Note that this is not always memory-efficient to do,
* and if you're not going to use all of the results, it may not be
* useful at all. All of the same caveats from Database::query()
* apply. The individual result rows are associative arrays.
*
* @param string $str The query string
* @param array $params The query parameters
* @param string $name The name of the query
* @throws DatabaseException
* @return array
*/
public static function prefetch($str, $params = array(),
$name = null) {
$ret = array();
$resource = Database::query($str, $params, $name);
while ($row = pg_fetch_assoc($resource)) {
$ret[] = $row;
}
return $ret;
}
/**
* Execute a query and fetch all results
*
* This function performs the same function as Database::prefetch(),
* but returns an array of regular integer-indexed arrays. It is
* faster for cases when the names of the columns are not known to the
* query planner in advance of their execution (eg: 'SELECT * FROM
* table').
*
* @param string $str The query string
* @param array $params The query paramters
* @param string $name The query name
* @throws DatabaseException
* @return array
*/
public static function prefetch_int($str, $params = array(),
$name = null) {
$ret = array();
$r = Database::query($str, $params, $name);
while ($row = pg_fetch_row($r)) {
$ret[] = $row;
}
return $ret;
}
/**
* Prepare an identifier for safe use in a query
*
* This prepares a single identifier for use in a query and returns
* it. If you want to return multiple identifiers in a single query,
* see Database::quote_identifiers() (for which this is merely a
* wrapper).
*
* @param string $ident The identifier to quote
* @return string
*/
public static function quote_identifier($ident) {
$out = self::quote_identifiers($ident);
return $out[$ident];
}
/**
* Prepare identifiers for safe use in queries
*
* Emulate a PostgreSQL server function to quote identifiers
* (table/column/function/etc. names). This is replacing a function
* intended to be in the PHP core, which does not seem to actually
* exist. It behaves similarly to the PostgreSQL function, which is to
* say, only identifiers which *need* quoting are actually quoted.
* Simple identifiers such as 'a' are not quoted, but case-sensitive
* ones such as 'A' are (a, vs. "A").
*
* @return array
*/
public static function quote_identifiers() {
$ret = array();
$rem = array();
$fargs = array();
$in = func_get_args();
foreach ($in as $arg) {
if (is_array($arg)) {
$fargs = array_merge($fargs, $arg);
}
else {
array_push($fargs, $arg);
}
}
foreach ($fargs as $arg) {
if (array_key_exists($arg, self::$quoted)) {
$ret[$arg] = self::$quoted[$arg];
}
}
foreach ($fargs as $arg) {
if (array_key_exists($arg, self::$quoted)) {
$ret[$arg] = self::$quoted[$arg];
}
else {
array_push($rem, $arg);
}
}
foreach ($rem as $uq) {
$qv = preg_replace('/\"/', '""', $uq);
if (preg_match('/^[^a-z_][a-z0-9_]*$/', $qv) ||
preg_match('/"/', $qv)) {
$qv = "\"$qv\"";
}
self::$quoted[$uq] = $ret[$uq] = $qv;
}
return $ret;
}
}
?>