Andrew's Web Libraries (AWL)
Loading...
Searching...
No Matches
AwlDBDialect.php
1<?php
17
18if ( !defined('E_USER_ERROR') ) define('E_USER_ERROR',256);
19
33class AwlDBDialect {
37
41 protected $dialect;
42
46 protected $db;
47
51 private $version;
52
54
59 const HttpDateFormat = "'Dy, DD Mon IYYY HH24:MI:SS \"GMT\"'";
60
64 const SqlDateFormat = "'YYYYMMDD\"T\"HH24MISS'";
65
70 const SqlUTCFormat = "'YYYYMMDD\"T\"HH24MISS\"Z\"'";
71
76 const SqlDurationFormat = "'\"PT\"HH24\"H\"MI\"M\"'";
77
90 function __construct( $connection_string, $dbuser=null, $dbpass=null, $options=null ) {
91 if ( preg_match( '/^(pgsql):/', $connection_string, $matches ) ) {
92 $this->dialect = $matches[1];
93 }
94 else {
95 error_log("Unable to connect to database: ". $e->getMessage() );
96 trigger_error("Unsupported database connection '".$connection_string."'",E_USER_ERROR);
97 }
98 try {
99 $this->db = new PDO( $connection_string, $dbuser, $dbpass, $options );
100 } catch (PDOException $e) {
101 error_log("Unable to connect to database: ". $e->getMessage() );
102 if ( function_exists('trigger_error') )
103 trigger_error("PDO connection error '".$connection_string."': ".$e->getMessage(),E_USER_ERROR);
104 throw $e;
105 }
106 }
107
108
109
113 function SetSearchPath( $search_path = null ) {
114 if ( !isset($this->dialect) ) {
115 trigger_error("Unsupported database dialect",E_USER_ERROR);
116 }
117
118 switch ( $this->dialect ) {
119 case 'pgsql':
120 if ( $search_path == null ) $search_path = 'public';
121 $sql = "SET search_path TO " . $search_path;
122 $sth = $this->db->query($sql);
123 return $sql;
124 }
125 }
126
127
132 function GetVersion( ) {
133 if ( isset($this->version) ) return $this->version;
134 if ( !isset($this->dialect) ) {
135 trigger_error("Unsupported database dialect", E_USER_ERROR);
136 }
137
138 $version = $this->dialect.':';
139
140 switch ( $this->dialect ) {
141 case 'pgsql':
142 $sql = "SELECT version()";
143 if ( $sth = $this->db->query($sql) ) {
144 $row = $sth->fetch(PDO::FETCH_NUM);
145 $version .= preg_replace( '/^PostgreSQL (\d+\.\d+)\..*$/i', '$1', $row[0]);
146 }
147 break;
148 default:
149 return null;
150 }
151 $this->version = $version;
152 return $version;
153 }
154
155
161 function GetFields( $tablename_string ) {
162 if ( !isset($this->dialect) ) {
163 trigger_error("Unsupported database dialect", E_USER_ERROR);
164 }
165
166 switch ( $this->dialect ) {
167 case 'pgsql':
168 $schema = null;
169 $table = null;
170 if ( strpos($tablename_string, '.') ) {
171 list( $schema, $table ) = explode('.', $tablename_string, 2);
172 } else {
173 $table = $tablename_string;
174 }
175
176 $sql = 'SELECT f.attname AS fieldname, t.typname AS typename, f.atttypmod AS precision FROM pg_attribute f';
177 $sql .= ' JOIN pg_class c ON ( f.attrelid = c.oid )';
178 $sql .= ' JOIN pg_type t ON ( f.atttypid = t.oid )';
179 $sql .= ' JOIN pg_namespace ns ON ( c.relnamespace = ns.oid )';
180 $sql .= ' WHERE relname = '.$this->Quote($table,PDO::PARAM_STR).' AND attnum >= 0 ';
181 if ( isset($schema) ) $sql .= ' AND ns.nspname = '.$this->Quote($schema,PDO::PARAM_STR);
182 $sql .= ' ORDER BY f.attnum';
183 dbg_error_log('AwlDBDialect', $sql);
184 return $sql;
185 }
186 }
187
188
202 function TranslateSQL( $sql_string ) {
203 // Noop for the time being...
204 return $sql_string;
205 }
206
207
208
216 function Quote( $value, $value_type = null ) {
217 if ( isset($value_type) && $value_type == 'identifier' ) {
218 if ( $this->dialect == 'mysql' ) {
220 $rv = '`' . str_replace('`', '\\`', $value ) . '`';
221 }
222 else {
223 $rv = '"' . str_replace('"', '\\"', $value ) . '"';
224 }
225 return $rv;
226 }
227
228 if ( !isset($value_type) ) {
229 if ( !isset($value) ) $value_type = PDO::PARAM_NULL;
230 elseif ( is_bool($value) ) $value_type = PDO::PARAM_BOOL;
231 elseif ( is_float($value) ) $value_type = PDO::PARAM_INT;
232 elseif ( is_numeric($value)) {
233 if ( preg_match('{^(19|20)\d\d(0[1-9]|1[012])([012]\d|30|31)$}', $value) )
234 $value_type = PDO::PARAM_STR; // YYYYMMDD
235 elseif ( preg_match('{^0x}i', $value) )
236 $value_type = PDO::PARAM_STR; // Any hex numbers will need to be explicitly cast in SQL
237 elseif ( preg_match('{^[0-9+-]+e[0-9+-]+$}i', $value) )
238 $value_type = PDO::PARAM_STR; // 72e57650 could easily be a string and will need an explicit cast also
239 elseif ( preg_match('/^[01]{6,}$/i', $value) )
240 $value_type = PDO::PARAM_STR; // Binary numbers will need to be explicitly cast in SQL
241 else
242 $value_type = PDO::PARAM_INT;
243 }
244 else
245 $value_type = PDO::PARAM_STR;
246 }
247
248 if ( is_string($value_type) ) {
249 switch( $value_type ) {
250 case 'null':
251 $value_type = PDO::PARAM_NULL;
252 break;
253 case 'integer':
254 case 'double' :
255 $value_type = PDO::PARAM_INT;
256 break;
257 case 'boolean':
258 $value_type = PDO::PARAM_BOOL;
259 break;
260 case 'string':
261 $value_type = PDO::PARAM_STR;
262 break;
263 }
264 }
265
266 switch ( $value_type ) {
267 case PDO::PARAM_NULL:
268 $rv = 'NULL';
269 break;
270 case PDO::PARAM_INT:
271 $rv = $value;
272 break;
273 case PDO::PARAM_BOOL:
274 $rv = ($value ? 'TRUE' : 'FALSE');
275 break;
276 case PDO::PARAM_STR:
277 default:
284 $rv = "'".str_replace("'", "''", str_replace(':', '\\x3a', str_replace('\\', '\\x5c', $value)))."'";
285
286 if ( $this->dialect == 'pgsql' && strpos( $rv, '\\' ) !== false ) {
291 $rv = 'E'.str_replace('?', '\\x3f', $rv);
292 }
293
294 }
295
296 return $rv;
297
298 }
299
300
318 function ReplaceParameters() {
319 $argc = func_num_args();
320 $args = func_get_args();
321
322 if ( is_array($args[0]) ) {
326 $args = $args[0];
327 $argc = count($args);
328 }
329 $qry = array_shift($args);
330
331 if ( is_array($args[0]) ) {
332 $args = $args[0];
333 $argc = count($args);
334 }
335
336 if ( ! isset($args[0]) ) return $this->ReplaceNamedParameters($qry,$args);
337
342 $parts = explode( '?', $qry, $argc + 1 );
343 $querystring = $parts[0];
344 $z = count($parts);
345
346 for( $i = 0; $i < $argc; $i++ ) {
347 $arg = $args[$i];
348 $querystring .= $this->Quote($arg); //parameter
349 $z = $i+1;
350 if ( isset($parts[$z]) ) $querystring .= $parts[$z];
351 }
352
353 return $querystring;
354 }
355
374 function ReplaceNamedParameters() {
375 $argc = func_num_args();
376 $args = func_get_args();
377
378 if ( is_array($args[0]) ) {
382 $args = $args[0];
383 $argc = count($args);
384 }
385 $querystring = array_shift($args);
386
387 if ( is_array($args[0]) ) {
388 $args = $args[0];
389 $argc = count($args);
390 }
391
392 foreach( $args AS $name => $value ) {
393 if ( substr($name, 0, 1) != ':' ) {
394 dbg_error_log( "ERROR", "AwlDBDialect: Named parameter '%s' does not begin with a colon.", $name);
395 }
396 $replacement = str_replace('$', '\\$', $this->Quote($value)); // No positional replacement in $replacement!
397 $querystring = preg_replace( '{\Q'.$name.'\E\b}s', $replacement, $querystring );
398 }
399
400 return $querystring;
401 }
402
403}