Back to index

awl  0.53
AwlDBDialect.php
Go to the documentation of this file.
00001 <?php
00018 if ( !defined('E_USER_ERROR') ) define('E_USER_ERROR',256);
00019 
00033 class AwlDBDialect {
00041   protected $dialect;
00042 
00046   protected $db;
00047 
00051   private $version;
00052 
00068   function __construct( $connection_string, $dbuser=null, $dbpass=null, $options=null ) {
00069     if ( preg_match( '/^(pgsql):/', $connection_string, $matches ) ) {
00070       $this->dialect = $matches[1];
00071     }
00072     else {
00073       error_log("Unable to connect to database: ". $e->getMessage() );
00074       trigger_error("Unsupported database connection '".$connection_string."'",E_USER_ERROR);
00075     }
00076     try {
00077       $this->db = new PDO( $connection_string, $dbuser, $dbpass, $options );
00078     } catch (PDOException $e) {
00079       error_log("Unable to connect to database: ". $e->getMessage() );
00080       if ( function_exists('trigger_error') )
00081         trigger_error("PDO connection error '".$connection_string."': ".$e->getMessage(),E_USER_ERROR);
00082       throw $e;
00083     }
00084   }
00085 
00086 
00087 
00091   function SetSearchPath( $search_path = null ) {
00092     if ( !isset($this->dialect) ) {
00093       trigger_error("Unsupported database dialect",E_USER_ERROR);
00094     }
00095 
00096     switch ( $this->dialect ) {
00097       case 'pgsql':
00098         if ( $search_path == null ) $search_path = 'public';
00099         $sql = "SET search_path TO " . $this->Quote( $search_path, 'identifier' );
00100         return $sql;
00101     }
00102   }
00103 
00104 
00109   function GetVersion( ) {
00110     if ( isset($this->version) ) return $this->version;
00111     if ( !isset($this->dialect) ) {
00112       trigger_error("Unsupported database dialect", E_USER_ERROR);
00113     }
00114 
00115     $version = $this->dialect.':';
00116 
00117     switch ( $this->dialect ) {
00118       case 'pgsql':
00119         $sql = "SELECT version()";
00120         if ( $sth = $this->db->query($sql) ) {
00121           $row = $sth->fetch(PDO::FETCH_NUM);
00122           $version .= preg_replace( '/^PostgreSQL (\d+\.\d+)\..*$/i', '$1', $row[0]);
00123         }
00124         break;
00125       default:
00126         return null;
00127     }
00128     $this->version = $version;
00129     return $version;
00130   }
00131 
00132 
00138   function GetFields( $tablename_string ) {
00139     if ( !isset($this->dialect) ) {
00140       trigger_error("Unsupported database dialect", E_USER_ERROR);
00141     }
00142 
00143     switch ( $this->dialect ) {
00144       case 'pgsql':
00145         $tablename_string = $this->Quote($tablename_string,PDO::PARAM_STR);
00146         $sql = 'SELECT f.attname AS fieldname, t.typname AS typename, f.atttypmod AS precision FROM pg_attribute f';
00147         $sql .= ' JOIN pg_class c ON ( f.attrelid = c.oid )';
00148         $sql .= ' JOIN pg_type t ON ( f.atttypid = t.oid )';
00149         $sql .= ' WHERE relname = '.$tablename_string.' AND attnum >= 0 order by f.attnum';
00150         return $sql;
00151     }
00152   }
00153 
00154 
00168   function TranslateSQL( $sql_string ) {
00169     // Noop for the time being...
00170     return $sql_string;
00171   }
00172 
00173 
00174 
00182   function Quote( $value, $value_type = null ) {
00183     if ( isset($value_type) && $value_type == 'identifier' ) {
00184       if ( $this->dialect == 'mysql' ) {
00186         $rv = '`' . str_replace('`', '\\`', $value ) . '`';
00187       }
00188       else {
00189         $rv = '"' . str_replace('"', '\\"', $value ) . '"';
00190       }
00191       return $rv;
00192     }
00193 
00194     if ( !isset($value_type) ) {
00195       if ( !isset($value) )       $value_type = PDO::PARAM_NULL;
00196       elseif ( is_bool($value) )  $value_type = PDO::PARAM_BOOL;
00197       elseif ( is_float($value) ) $value_type = PDO::PARAM_INT;
00198       elseif ( is_numeric($value)) {
00199         if ( preg_match('{^(19|20)\d\d(0[1-9]|1[012])([012]\d|30|31)$}', $value) )
00200           $value_type = PDO::PARAM_STR; // YYYYMMDD
00201         elseif ( preg_match('{^0x}i', $value) )
00202           $value_type = PDO::PARAM_STR; // Any hex numbers will need to be explicitly cast in SQL
00203         elseif ( preg_match('{^[0-9+-]+e[0-9+-]+$}i', $value) )
00204           $value_type = PDO::PARAM_STR; // 72e57650 could easily be a string and will need an explicit cast also
00205         elseif ( preg_match('/^[01]{6,}$/i', $value) )
00206           $value_type = PDO::PARAM_STR; // Binary numbers will need to be explicitly cast in SQL
00207         else
00208           $value_type = PDO::PARAM_INT;
00209       }
00210       else
00211         $value_type = PDO::PARAM_STR;
00212     }
00213 
00214     if ( is_string($value_type) ) {
00215       switch( $value_type ) {
00216         case 'null':
00217           $value_type = PDO::PARAM_NULL;
00218           break;
00219         case 'integer':
00220         case 'double' :
00221           $value_type = PDO::PARAM_INT;
00222           break;
00223         case 'boolean':
00224           $value_type = PDO::PARAM_BOOL;
00225           break;
00226         case 'string':
00227           $value_type = PDO::PARAM_STR;
00228           break;
00229       }
00230     }
00231 
00232     switch ( $value_type ) {
00233       case PDO::PARAM_NULL:
00234         $rv = 'NULL';
00235         break;
00236       case PDO::PARAM_INT:
00237         $rv = $value;
00238         break;
00239       case PDO::PARAM_BOOL:
00240         $rv = ($value ? 'TRUE' : 'FALSE');
00241         break;
00242       case PDO::PARAM_STR:
00243       default:
00250         $rv = "'".str_replace("'", "''", str_replace(':', '\\x3a', str_replace('\\', '\\x5c', $value)))."'";
00251 
00252         if ( $this->dialect == 'pgsql' && strpos( $rv, '\\' ) !== false ) {
00257           $rv = 'E'.str_replace('?', '\\x3f', $rv);
00258         }
00259 
00260     }
00261 
00262     return $rv;
00263 
00264   }
00265 
00266 
00284   function ReplaceParameters() {
00285     $argc = func_num_args();
00286     $args = func_get_args();
00287 
00288     if ( is_array($args[0]) ) {
00292       $args = $args[0];
00293       $argc = count($args);
00294     }
00295     $qry = array_shift($args);
00296 
00297     if ( is_array($args[0]) ) {
00298       $args = $args[0];
00299       $argc = count($args);
00300     }
00301 
00302     if ( ! isset($args[0]) ) return $this->ReplaceNamedParameters($qry,$args);
00303 
00308     $parts = explode( '?', $qry, $argc + 1 );
00309     $querystring = $parts[0];
00310     $z = count($parts);
00311 
00312     for( $i = 0; $i < $argc; $i++ ) {
00313       $arg = $args[$i];
00314       $querystring .= $this->Quote($arg);  //parameter
00315       $z = $i+1;
00316       if ( isset($parts[$z]) ) $querystring .= $parts[$z];
00317     }
00318 
00319     return $querystring;
00320   }
00321 
00340   function ReplaceNamedParameters() {
00341     $argc = func_num_args();
00342     $args = func_get_args();
00343 
00344     if ( is_array($args[0]) ) {
00348       $args = $args[0];
00349       $argc = count($args);
00350     }
00351     $querystring = array_shift($args);
00352 
00353     if ( is_array($args[0]) ) {
00354       $args = $args[0];
00355       $argc = count($args);
00356     }
00357 
00358     foreach( $args AS $name => $value ) {
00359       if ( substr($name, 0, 1) != ':' ) {
00360         dbg_error_log( "ERROR", "AwlDBDialect: Named parameter '%s' does not begin with a colon.", $name);
00361       }
00362       $replacement = str_replace('$', '\\$', $this->Quote($value));  // No positional replacement in $replacement!
00363       $querystring = preg_replace( '{\Q'.$name.'\E\b}s', $replacement, $querystring );
00364     }
00365 
00366     return $querystring;
00367   }
00368 
00369 }