1 <?php
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 class NeevoDriverPgSQL implements INeevoDriver {
30
31
32
33 private $resource;
34
35
36 private $affectedRows;
37
38
39 private $escapeMethod = false;
40
41
42 43 44 45 46
47 public function __construct(NeevoBaseStmt $statement = null){
48 if(!extension_loaded("pgsql"))
49 throw new NeevoDriverException("Cannot instantiate Neevo PgSQL driver - PHP extension 'pgsql' not loaded.");
50 if($statement instanceof NeevoBaseStmt)
51 parent::__construct($statement);
52 }
53
54
55 56 57 58 59 60
61 public function connect(array $config){
62
63 $defaults = array(
64 'resource' => null,
65 'persistent' => false,
66 'charset' => 'utf8'
67 );
68
69 $config += $defaults;
70
71 if(isset($config['string']))
72 $string = $config['string'];
73 else{
74
75 $string = '';
76 foreach(array('host', 'hostaddr', 'port', 'dbname', 'user', 'password', 'connect_timeout', 'options', 'sslmode', 'service') as $cfg){
77 if(isset($config[$cfg]))
78 $string .= "$cfg=$config[$cfg] ";
79 }
80 }
81
82
83 if(is_resource($config['resource']))
84 $connection = $config['resource'];
85 elseif($config['persistent'])
86 $connection = @pg_pconnect($string, PGSQL_CONNECT_FORCE_NEW);
87 else
88 $connection = @pg_connect($string, PGSQL_CONNECT_FORCE_NEW);
89
90 if(!is_resource($connection))
91 throw new NeevoException("Connection to database failed.");
92
93 $this->resource = $connection;
94
95
96 @pg_set_client_encoding($this->resource, $config['charset']);
97
98
99 if(isset($config['schema']))
100 $this->runQuery('SET search_path TO "' . $config['schema'] . '"');
101
102 $this->escapeMethod = version_compare(PHP_VERSION , '5.2.0', '>=');
103 }
104
105
106 107 108 109
110 public function closeConnection(){
111 @pg_close($this->resource);
112 }
113
114
115 116 117 118 119
120 public function freeResultSet($resultSet){
121 @pg_free_result($resultSet);
122 }
123
124
125 126 127 128 129 130
131 public function runQuery($queryString){
132 $this->affectedRows = false;
133
134 $result = @pg_query($this->resource, $queryString);
135 if($result === false)
136 throw new NeevoException("Query failed. " . pg_last_error($this->resource), null, $queryString);
137
138 $this->affectedRows = @pg_affected_rows($result);
139 return $result;
140 }
141
142
143 144 145 146 147
148 public function beginTransaction($savepoint = null){
149 $this->runQuery($savepoint ? "SAVEPOINT $savepoint" : 'START TRANSACTION');
150 }
151
152
153 154 155 156 157
158 public function commit($savepoint = null){
159 $this->runQuery($savepoint ? "RELEASE SAVEPOINT $savepoint" : 'COMMIT');
160 }
161
162
163 164 165 166 167
168 public function rollback($savepoint = null){
169 $this->runQuery($savepoint ? "ROLLBACK TO SAVEPOINT $savepoint" : 'ROLLBACK');
170 }
171
172
173 174 175 176 177
178 public function fetch($resultSet){
179 return @pg_fetch_assoc($resultSet);
180 }
181
182
183 184 185 186 187 188
189 public function seek($resultSet, $offset){
190 return @pg_result_seek($resultSet, $offset);
191 }
192
193
194 195 196 197
198 public function getInsertId(){
199 $result = $this->runQuery("SELECT LASTVAL()");
200 if(!$result)
201 return false;
202
203 $r = $this->fetch($result);
204 return is_array($r) ? reset($r) : false;
205 }
206
207
208 209 210 211 212
213 public function randomizeOrder(NeevoBaseStmt $statement){
214 $statement->order('RAND()');
215 }
216
217
218 219 220 221 222
223 public function getNumRows($resultSet){
224 return @pg_num_rows($resultSet);
225 }
226
227
228 229 230 231
232 public function getAffectedRows(){
233 return $this->affectedRows;
234 }
235
236
237 238 239 240 241 242 243
244 public function escape($value, $type){
245 switch($type){
246 case Neevo::BOOL:
247 return $value ? 'TRUE' : 'FALSE';
248
249 case Neevo::TEXT:
250 if($this->escapeMethod)
251 return "'" . pg_escape_string($this->resource, $value) . "'";
252 else
253 return "'" . pg_escape_string($value) . "'";
254
255 case Neevo::BINARY:
256 if($this->escapeMethod)
257 return "'" . pg_escape_bytea($this->resource, $value) . "'";
258 else
259 return "'" . pg_escape_bytea($value) . "'";
260
261 case Neevo::IDENTIFIER:
262 return '"' . str_replace('.', '"."', str_replace('"', '""', $value)) . '"';
263
264 case Neevo::DATETIME:
265 return ($value instanceof DateTime) ? $value->format("'Y-m-d H:i:s'") : date("'Y-m-d H:i:s'", $value);
266
267 default:
268 throw new InvalidArgumentException('Unsupported data type.');
269 break;
270 }
271 }
272
273
274 275 276 277 278 279 280
281 public function unescape($value, $type){
282 if($type === Neevo::BINARY)
283 return pg_unescape_bytea($value);
284 throw new InvalidArgumentException('Unsupported data type.');
285 }
286
287
288 289 290 291 292 293 294
295 public function getPrimaryKey($table){
296 $def = $this->fetch(
297 $this->runQuery("SELECT indexdef FROM pg_indexes WHERE indexname = '{$table}_pkey'")
298 );
299 $def = reset($def);
300 if(preg_match("~{$table}_pkey\s+ON\s+{$table}.*\((\w+).*\)~i", $def, $matches))
301 return $matches[1];
302 return false;
303 }
304
305
306 307 308 309 310 311
312 public function getColumnTypes($resultSet, $table){
313 if($table === null)
314 return array();
315 $cols = pg_meta_data($this->resource, $table);
316 foreach($cols as $key => $value){
317 $cols[$key] = preg_replace('~[^a-z]~i', '', $value['type']);
318 }
319 return $cols;
320 }
321
322
323 }
324