Andrew's Web Libraries (AWL)
Loading...
Searching...
No Matches
AwlDBDialect.php
1<?php
18if ( !defined('E_USER_ERROR') ) define('E_USER_ERROR',256);
19
41 protected $dialect;
42
46 protected $db;
47
51 private $version;
52
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 list( $schema, $table ) = explode('.', $tablename_string, 2);
169 if ( empty($table) ) {
170 $table = $tablename_string;
171 $schema = null;
172 }
173
174 $sql = 'SELECT f.attname AS fieldname, t.typname AS typename, f.atttypmod AS precision FROM pg_attribute f';
175 $sql .= ' JOIN pg_class c ON ( f.attrelid = c.oid )';
176 $sql .= ' JOIN pg_type t ON ( f.atttypid = t.oid )';
177 $sql .= ' JOIN pg_namespace ns ON ( c.relnamespace = ns.oid )';
178 $sql .= ' WHERE relname = '.$this->Quote($table,PDO::PARAM_STR).' AND attnum >= 0 ';
179 if ( isset($schema) ) $sql .= ' AND ns.nspname = '.$this->Quote($schema,PDO::PARAM_STR);
180 $sql .= ' ORDER BY f.attnum';
181 dbg_error_log('AwlDBDialect', $sql);
182 return $sql;
183 }
184 }
185
186
200 function TranslateSQL( $sql_string ) {
201 // Noop for the time being...
202 return $sql_string;
203 }
204
205
206
214 function Quote( $value, $value_type = null ) {
215 if ( isset($value_type) && $value_type == 'identifier' ) {
216 if ( $this->dialect == 'mysql' ) {
218 $rv = '`' . str_replace('`', '\\`', $value ) . '`';
219 }
220 else {
221 $rv = '"' . str_replace('"', '\\"', $value ) . '"';
222 }
223 return $rv;
224 }
225
226 if ( !isset($value_type) ) {
227 if ( !isset($value) ) $value_type = PDO::PARAM_NULL;
228 elseif ( is_bool($value) ) $value_type = PDO::PARAM_BOOL;
229 elseif ( is_float($value) ) $value_type = PDO::PARAM_INT;
230 elseif ( is_numeric($value)) {
231 if ( preg_match('{^(19|20)\d\d(0[1-9]|1[012])([012]\d|30|31)$}', $value) )
232 $value_type = PDO::PARAM_STR; // YYYYMMDD
233 elseif ( preg_match('{^0x}i', $value) )
234 $value_type = PDO::PARAM_STR; // Any hex numbers will need to be explicitly cast in SQL
235 elseif ( preg_match('{^[0-9+-]+e[0-9+-]+$}i', $value) )
236 $value_type = PDO::PARAM_STR; // 72e57650 could easily be a string and will need an explicit cast also
237 elseif ( preg_match('/^[01]{6,}$/i', $value) )
238 $value_type = PDO::PARAM_STR; // Binary numbers will need to be explicitly cast in SQL
239 else
240 $value_type = PDO::PARAM_INT;
241 }
242 else
243 $value_type = PDO::PARAM_STR;
244 }
245
246 if ( is_string($value_type) ) {
247 switch( $value_type ) {
248 case 'null':
249 $value_type = PDO::PARAM_NULL;
250 break;
251 case 'integer':
252 case 'double' :
253 $value_type = PDO::PARAM_INT;
254 break;
255 case 'boolean':
256 $value_type = PDO::PARAM_BOOL;
257 break;
258 case 'string':
259 $value_type = PDO::PARAM_STR;
260 break;
261 }
262 }
263
264 switch ( $value_type ) {
265 case PDO::PARAM_NULL:
266 $rv = 'NULL';
267 break;
268 case PDO::PARAM_INT:
269 $rv = $value;
270 break;
271 case PDO::PARAM_BOOL:
272 $rv = ($value ? 'TRUE' : 'FALSE');
273 break;
274 case PDO::PARAM_STR:
275 default:
282 $rv = "'".str_replace("'", "''", str_replace(':', '\\x3a', str_replace('\\', '\\x5c', $value)))."'";
283
284 if ( $this->dialect == 'pgsql' && strpos( $rv, '\\' ) !== false ) {
289 $rv = 'E'.str_replace('?', '\\x3f', $rv);
290 }
291
292 }
293
294 return $rv;
295
296 }
297
298
316 function ReplaceParameters() {
317 $argc = func_num_args();
318 $args = func_get_args();
319
320 if ( is_array($args[0]) ) {
324 $args = $args[0];
325 $argc = count($args);
326 }
327 $qry = array_shift($args);
328
329 if ( is_array($args[0]) ) {
330 $args = $args[0];
331 $argc = count($args);
332 }
333
334 if ( ! isset($args[0]) ) return $this->ReplaceNamedParameters($qry,$args);
335
340 $parts = explode( '?', $qry, $argc + 1 );
341 $querystring = $parts[0];
342 $z = count($parts);
343
344 for( $i = 0; $i < $argc; $i++ ) {
345 $arg = $args[$i];
346 $querystring .= $this->Quote($arg); //parameter
347 $z = $i+1;
348 if ( isset($parts[$z]) ) $querystring .= $parts[$z];
349 }
350
351 return $querystring;
352 }
353
373 $argc = func_num_args();
374 $args = func_get_args();
375
376 if ( is_array($args[0]) ) {
380 $args = $args[0];
381 $argc = count($args);
382 }
383 $querystring = array_shift($args);
384
385 if ( is_array($args[0]) ) {
386 $args = $args[0];
387 $argc = count($args);
388 }
389
390 foreach( $args AS $name => $value ) {
391 if ( substr($name, 0, 1) != ':' ) {
392 dbg_error_log( "ERROR", "AwlDBDialect: Named parameter '%s' does not begin with a colon.", $name);
393 }
394 $replacement = str_replace('$', '\\$', $this->Quote($value)); // No positional replacement in $replacement!
395 $querystring = preg_replace( '{\Q'.$name.'\E\b}s', $replacement, $querystring );
396 }
397
398 return $querystring;
399 }
400
401}
__construct( $connection_string, $dbuser=null, $dbpass=null, $options=null)
SetSearchPath( $search_path=null)
const SqlDateFormat
Quote( $value, $value_type=null)
GetFields( $tablename_string)
TranslateSQL( $sql_string)
const HttpDateFormat
const SqlDurationFormat