Back to index

awl  0.53
Public Member Functions | Protected Attributes | Private Attributes
AwlDBDialect Class Reference
Inheritance diagram for AwlDBDialect:
Inheritance graph
[legend]

List of all members.

Public Member Functions

 __construct ($connection_string, $dbuser=null, $dbpass=null, $options=null)
 

@-


 SetSearchPath ($search_path=null)
 Sets the current search path for the database.
 GetVersion ()
 Sets the current search path for the database.
 GetFields ($tablename_string)
 Returns the SQL for the current database dialect which will return a two-column resultset containing a list of fields and their associated data types.
 TranslateSQL ($sql_string)
 Translates the given SQL string into a form that will hopefully work for this database dialect.
 Quote ($value, $value_type=null)
 Returns $value escaped in an appropriate way for this database dialect.
 ReplaceParameters ()
 Replaces query parameters with appropriately escaped substitutions.
 ReplaceNamedParameters ()
 Replaces named query parameters of the form :name with appropriately escaped substitutions.

Protected Attributes

 $dialect
 

@+

private
 $db
 Holds the PDO database connection.

Private Attributes

 $version
 Holds the version.

Detailed Description

Definition at line 33 of file AwlDBDialect.php.


Constructor & Destructor Documentation

AwlDBDialect::__construct ( connection_string,
dbuser = null,
dbpass = null,
options = null 
)

@-

Parses the connection string to ascertain the database dialect. Returns true if the dialect is supported and fails if the dialect is not supported. All code to support any given database should be within in an external include.

The database will be opened.

Parameters:
string$connection_stringThe PDO connection string, in all it's glory
string$dbuserThe database username to connect as
string$dbpassThe database password to connect with
array$optionsAn array of driver options

Definition at line 68 of file AwlDBDialect.php.

                                                                                        {
    if ( preg_match( '/^(pgsql):/', $connection_string, $matches ) ) {
      $this->dialect = $matches[1];
    }
    else {
      error_log("Unable to connect to database: ". $e->getMessage() );
      trigger_error("Unsupported database connection '".$connection_string."'",E_USER_ERROR);
    }
    try {
      $this->db = new PDO( $connection_string, $dbuser, $dbpass, $options );
    } catch (PDOException $e) {
      error_log("Unable to connect to database: ". $e->getMessage() );
      if ( function_exists('trigger_error') )
        trigger_error("PDO connection error '".$connection_string."': ".$e->getMessage(),E_USER_ERROR);
      throw $e;
    }
  }

Member Function Documentation

AwlDBDialect::GetFields ( tablename_string)

Returns the SQL for the current database dialect which will return a two-column resultset containing a list of fields and their associated data types.

Parameters:
string$tablename_stringThe name of the table we want fields from

Definition at line 138 of file AwlDBDialect.php.

                                          {
    if ( !isset($this->dialect) ) {
      trigger_error("Unsupported database dialect", E_USER_ERROR);
    }

    switch ( $this->dialect ) {
      case 'pgsql':
        $tablename_string = $this->Quote($tablename_string,PDO::PARAM_STR);
        $sql = 'SELECT f.attname AS fieldname, t.typname AS typename, f.atttypmod AS precision FROM pg_attribute f';
        $sql .= ' JOIN pg_class c ON ( f.attrelid = c.oid )';
        $sql .= ' JOIN pg_type t ON ( f.atttypid = t.oid )';
        $sql .= ' WHERE relname = '.$tablename_string.' AND attnum >= 0 order by f.attnum';
        return $sql;
    }
  }

Here is the call graph for this function:

Sets the current search path for the database.

Parameters:
handle$pdoA handle to an opened database

Definition at line 109 of file AwlDBDialect.php.

                         {
    if ( isset($this->version) ) return $this->version;
    if ( !isset($this->dialect) ) {
      trigger_error("Unsupported database dialect", E_USER_ERROR);
    }

    $version = $this->dialect.':';

    switch ( $this->dialect ) {
      case 'pgsql':
        $sql = "SELECT version()";
        if ( $sth = $this->db->query($sql) ) {
          $row = $sth->fetch(PDO::FETCH_NUM);
          $version .= preg_replace( '/^PostgreSQL (\d+\.\d+)\..*$/i', '$1', $row[0]);
        }
        break;
      default:
        return null;
    }
    $this->version = $version;
    return $version;
  }
AwlDBDialect::Quote ( value,
value_type = null 
)

Returns $value escaped in an appropriate way for this database dialect.

Parameters:
mixed$valueThe value to be escaped
string$value_typeThe type of escaping desired. If blank this will be worked out from the type of the $value. The special type of 'identifier' can also be used for escaping of SQL identifiers.

: Someone should confirm this is correct for MySql

PDO handling of \ seems unreliable. We can't use $$string$$ syntax because it also doesn't work. We need to replace ':' so no other named parameters accidentally rewrite the content inside this string(!), and since we're using ' to delimit the string we need SQL92-compliant '' to replace it.

PostgreSQL wants to know when a string might contain escapes, and if this happens old versions of PHP::PDO need the ? escaped as well...

Definition at line 182 of file AwlDBDialect.php.

                                               {
    if ( isset($value_type) && $value_type == 'identifier' ) {
      if ( $this->dialect == 'mysql' ) {
        $rv = '`' . str_replace('`', '\\`', $value ) . '`';
      }
      else {
        $rv = '"' . str_replace('"', '\\"', $value ) . '"';
      }
      return $rv;
    }

    if ( !isset($value_type) ) {
      if ( !isset($value) )       $value_type = PDO::PARAM_NULL;
      elseif ( is_bool($value) )  $value_type = PDO::PARAM_BOOL;
      elseif ( is_float($value) ) $value_type = PDO::PARAM_INT;
      elseif ( is_numeric($value)) {
        if ( preg_match('{^(19|20)\d\d(0[1-9]|1[012])([012]\d|30|31)$}', $value) )
          $value_type = PDO::PARAM_STR; // YYYYMMDD
        elseif ( preg_match('{^0x}i', $value) )
          $value_type = PDO::PARAM_STR; // Any hex numbers will need to be explicitly cast in SQL
        elseif ( preg_match('{^[0-9+-]+e[0-9+-]+$}i', $value) )
          $value_type = PDO::PARAM_STR; // 72e57650 could easily be a string and will need an explicit cast also
        elseif ( preg_match('/^[01]{6,}$/i', $value) )
          $value_type = PDO::PARAM_STR; // Binary numbers will need to be explicitly cast in SQL
        else
          $value_type = PDO::PARAM_INT;
      }
      else
        $value_type = PDO::PARAM_STR;
    }

    if ( is_string($value_type) ) {
      switch( $value_type ) {
        case 'null':
          $value_type = PDO::PARAM_NULL;
          break;
        case 'integer':
        case 'double' :
          $value_type = PDO::PARAM_INT;
          break;
        case 'boolean':
          $value_type = PDO::PARAM_BOOL;
          break;
        case 'string':
          $value_type = PDO::PARAM_STR;
          break;
      }
    }

    switch ( $value_type ) {
      case PDO::PARAM_NULL:
        $rv = 'NULL';
        break;
      case PDO::PARAM_INT:
        $rv = $value;
        break;
      case PDO::PARAM_BOOL:
        $rv = ($value ? 'TRUE' : 'FALSE');
        break;
      case PDO::PARAM_STR:
      default:
        $rv = "'".str_replace("'", "''", str_replace(':', '\\x3a', str_replace('\\', '\\x5c', $value)))."'";

        if ( $this->dialect == 'pgsql' && strpos( $rv, '\\' ) !== false ) {
          $rv = 'E'.str_replace('?', '\\x3f', $rv);
        }

    }

    return $rv;

  }

Here is the caller graph for this function:

Replaces named query parameters of the form :name with appropriately escaped substitutions.

The function takes a variable number of arguments, the first is the SQL string, with replaceable ':name' characters (a la DBI). The subsequent parameters being the values to replace into the SQL string.

The values passed to the routine are analyzed for type, and quoted if they appear to need quoting. This can go wrong for (e.g.) NULL or other special SQL values which are not straightforwardly identifiable as needing quoting (or not).

Parameters:
stringThe query string with replacable ':name' identifiers
mixedA ':name' => 'value' hash of values to replace into the SQL string.
Returns:
The built query string

If the first argument is an array we treat that as our arguments instead

Definition at line 340 of file AwlDBDialect.php.

                                    {
    $argc = func_num_args();
    $args = func_get_args();

    if ( is_array($args[0]) ) {
      $args = $args[0];
      $argc = count($args);
    }
    $querystring = array_shift($args);

    if ( is_array($args[0]) ) {
      $args = $args[0];
      $argc = count($args);
    }

    foreach( $args AS $name => $value ) {
      if ( substr($name, 0, 1) != ':' ) {
        dbg_error_log( "ERROR", "AwlDBDialect: Named parameter '%s' does not begin with a colon.", $name);
      }
      $replacement = str_replace('$', '\\$', $this->Quote($value));  // No positional replacement in $replacement!
      $querystring = preg_replace( '{\Q'.$name.'\E\b}s', $replacement, $querystring );
    }

    return $querystring;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Replaces query parameters with appropriately escaped substitutions.

The function takes a variable number of arguments, the first is the SQL string, with replaceable '?' characters (a la DBI). The subsequent parameters being the values to replace into the SQL string.

The values passed to the routine are analyzed for type, and quoted if they appear to need quoting. This can go wrong for (e.g.) NULL or other special SQL values which are not straightforwardly identifiable as needing quoting (or not). In such cases the parameter can be forced to be inserted unquoted by passing it as "array( 'plain' => $param )".

Parameters:
stringThe query string with replacable '?' characters.
mixedThe values to replace into the SQL string.
Returns:
The built query string

If the first argument is an array we treat that as our arguments instead

We only split into a maximum of $argc chunks. Any leftover ? will remain in the string and may be replaced at Exec rather than Prepare. Scary!

Definition at line 284 of file AwlDBDialect.php.

                               {
    $argc = func_num_args();
    $args = func_get_args();

    if ( is_array($args[0]) ) {
      $args = $args[0];
      $argc = count($args);
    }
    $qry = array_shift($args);

    if ( is_array($args[0]) ) {
      $args = $args[0];
      $argc = count($args);
    }

    if ( ! isset($args[0]) ) return $this->ReplaceNamedParameters($qry,$args);

    $parts = explode( '?', $qry, $argc + 1 );
    $querystring = $parts[0];
    $z = count($parts);

    for( $i = 0; $i < $argc; $i++ ) {
      $arg = $args[$i];
      $querystring .= $this->Quote($arg);  //parameter
      $z = $i+1;
      if ( isset($parts[$z]) ) $querystring .= $parts[$z];
    }

    return $querystring;
  }

Here is the call graph for this function:

AwlDBDialect::SetSearchPath ( search_path = null)

Sets the current search path for the database.

Definition at line 91 of file AwlDBDialect.php.

                                                {
    if ( !isset($this->dialect) ) {
      trigger_error("Unsupported database dialect",E_USER_ERROR);
    }

    switch ( $this->dialect ) {
      case 'pgsql':
        if ( $search_path == null ) $search_path = 'public';
        $sql = "SET search_path TO " . $this->Quote( $search_path, 'identifier' );
        return $sql;
    }
  }

Here is the call graph for this function:

AwlDBDialect::TranslateSQL ( sql_string)

Translates the given SQL string into a form that will hopefully work for this database dialect.

This hook is intended to be used by developers to provide support for differences in database operation by translating the query string in an arbitrary way, such as through a file or database lookup.

The actual translation to other SQL dialects will be application-specific, so that any routines called by this will be external to this library, or will use resources loaded from some source external to this library.

The application developer is expected to use this functionality to solve harder translation problems, but is less likely to call this directly, hopefully switching ->Prepare to ->PrepareTranslated in those cases, and then adding that statement to whatever SQL translation infrastructure is in place.

Definition at line 168 of file AwlDBDialect.php.

                                       {
    // Noop for the time being...
    return $sql_string;
  }

Here is the caller graph for this function:


Member Data Documentation

AwlDBDialect::$db [protected]

Holds the PDO database connection.

Definition at line 46 of file AwlDBDialect.php.

@+

private

Holds the name of the database dialect

Definition at line 41 of file AwlDBDialect.php.

Holds the version.

Definition at line 51 of file AwlDBDialect.php.


The documentation for this class was generated from the following file: