Location: PHPKode > projects > VuFind > vufind-1.0.1/web/Drivers/USQOracle.php
<?php

class oracle_connection {
  // Database Handle
  private $db_handle;

  // Error information
  private $last_error;
  private $last_error_type;
  private $last_error_fields;
  private $last_sql;

  /**
   * *************************
   *   Connection
   */
  public function __construct($username, $password, $tns) {
    $this->clear_error();
    $tmp = error_reporting(1);
    if ($this->db_handle = @oci_connect($username, $password, $tns)) {
      error_reporting($tmp);
      $this->audit_id = 0;
      $this->detail_id = 0;
    } else {
      error_reporting($tmp);
      $this->handle_error('connect', oci_error());
      return false;
    }
  }
  public function get_handle() {return $this->db_handle;}
  public function __destruct() {oci_close($this->db_handle);}

  /**
   * *************************
   *   Basic SQL functions
   */
  public function prepare($sql) {
    if ($parsed = @oci_parse($this->db_handle, $sql)) {
      return $parsed;
    } else {
      $this->handle_error('parsing', oci_error($this->db_handle), $sql);
      return false;
    }
  }
  public function prep_row_id() {
    if ($new_id = @oci_new_descriptor($this->db_handle, OCI_D_ROWID)) {
      return $new_id;
    } else {
      $this->handle_error('new_descriptor', oci_error($this->db_handle));
      return false;
    }
  }
  public function bind_param($parsed, $place_holder, $data, $data_type = 'string', $length = -1) {
    switch ($data_type) {
      case 'string':  $oracle_data_type = SQLT_CHR;  break;
      case 'integer': $oracle_data_type = SQLT_INT;  break;
      case 'float':   $oracle_data_type = SQLT_FLT;  break;
      case 'long':    $oracle_data_type = SQLT_LNG;  break;
      // Date is redundant since default is varchar,
      //  but it's here for clarity.
      case 'date':    $oracle_data_type = SQLT_CHR;  break;
      case 'row_id':  $oracle_data_type = SQLT_RDD;  break;
      case 'clob':    $oracle_data_type = SQLT_CLOB; break;
      case 'blob':    $oracle_data_type = SQLT_BLOB; break;
      default:        $oracle_data_type = SQLT_CHR;  break;
    }

    if (@oci_bind_by_name($parsed, $place_holder, $data, $length, $oracle_data_type)) {
      return true;
    } else {
      $this->handle_error('binding', oci_error());
      return false;
    }
  }
  // Same as above, but variable is parsed by reference to allow for correct functioning
  //  of the 'RETURNING' sql statement. Annoying, but putting it in two seperate functions
  //  allows the user to pass string literals into bind_param without a fatal error.
  public function return_param($parsed, $place_holder, &$data, $data_type = 'string', $length = -1) {
    switch ($data_type) {
      case 'string':  $oracle_data_type = SQLT_CHR;  break;
      case 'integer': $oracle_data_type = SQLT_INT;  break;
      case 'float':   $oracle_data_type = SQLT_FLT;  break;
      case 'long':    $oracle_data_type = SQLT_LNG;  break;
      // Date is redundant since default is varchar,
      //  but it's here for clarity.
      case 'date':    $oracle_data_type = SQLT_CHR;  break;
      case 'row_id':  $oracle_data_type = SQLT_RDD;  break;
      case 'clob':    $oracle_data_type = SQLT_CLOB; break;
      case 'blob':    $oracle_data_type = SQLT_BLOB; break;
      default:        $oracle_data_type = SQLT_CHR;  break;
    }

    if (@oci_bind_by_name($parsed, $place_holder, $data, $length, $oracle_data_type)) {
      return true;
    } else {
      $this->handle_error('binding', oci_error());
      return false;
    }
  }
  public function exec($parsed) {
    // OCI_DEFAULT == DO NOT COMMIT!!!
    if (@oci_execute($parsed, OCI_DEFAULT)) {
      return true;
    } else {
      $this->handle_error('executing', oci_error($parsed));
      return false;
    }
  }
  public function commit() {
    if (@oci_commit($this->db_handle)) {
      return true;
    } else {
      $this->handle_error('commit', oci_error($this->db_handle));
      return false;
    }
  }
  public function rollback() {
    if (@oci_rollback($this->db_handle)) {
      return true;
    } else {
      $this->handle_error('rollback', oci_error($this->db_handle));
      return false;
    }
  }
  public function free($parsed) {
    if (@oci_free_statement($parsed)) {
      return true;
    } else {
      $this->handle_error('free', oci_error($this->db_handle));
      return false;
    }
  }

  /**
   * *************************
   *   Template function
   *   - common functions we require
   */
  public function simple_select($sql, $fields = array()) {
    $stmt = $this->prepare($sql);
    foreach ($fields as $field => $datum) {
      list($column, $type) = split(":", $field);
      $this->bind_param($stmt, ":".$column, $datum, $type);
    }

    if ($this->exec($stmt)) {
      oci_fetch_all($stmt, $return_array, 0, -1, OCI_FETCHSTATEMENT_BY_ROW);
      $this->free($stmt);
      return $return_array;
    } else {
      $this->last_error_fields = $fields;
      $this->free($stmt);
      return false;
    }
  }
  public function simple_delete($table, $fields = array()) {
    $types   = array();
    $data    = array();
    $clauses = array();

    // Split all the fields up into arrays
    foreach ($fields as $field => $datum) {
      list($column, $type) = split(":", $field);
      $types[$column] = $type;
      $data[$column]  = $datum;
      $clauses[]      = "$column = :$column";
    }

    // Prepare the SQL for child table - turn the columns in placeholders for the bind
    $sql  = "DELETE FROM $table WHERE ".join(" AND ", $clauses);
    $delete = $this->prepare($sql);

    // Bind Variables
    foreach (array_keys($data) as $column) {
      $this->bind_param($delete, ":".$column, $data[$column], $types[$column]);
    }

    // Execute
    if ($this->exec($delete)) {
      $this->commit();
      $this->free($delete);
      return true;
    } else {
      $this->last_error_fields = $fields;
      $this->free($delete);
      return false;
    }
  }
  public function simple_insert($table, $fields = array()) {
    $types   = array();
    $data    = array();
    $columns = array();
    $values  = array();

    // Split all the fields up into arrays
    foreach ($fields as $field => $datum) {
      $tmp = split(":", $field);
      $column = array_shift($tmp);

      // For binding
      $types[$column] = array_shift($tmp);
      $data[$column]  = $datum;

      // For building the sql
      $columns[]      = $column;
      // Dates are special
      if (count($tmp) > 0 && !is_null($datum)) {
        $values[] = "TO_DATE(:$column, '".join(":", $tmp)."')";
      } else {
        $values[] = ":$column";
      }
    }

    $sql  = "INSERT INTO $table (".join(", ", $columns).") VALUES (".join(", ", $values).")";
    $insert = $this->prepare($sql);

    // Bind Variables
    foreach (array_keys($data) as $column) {
      $this->bind_param($insert, ":".$column, $data[$column], $types[$column]);
    }

    // Execute
    if ($this->exec($insert)) {
      $this->commit();
      $this->free($insert);
      return true;
    } else {
      $this->last_error_fields = $fields;
      $this->free($insert);
      return false;
    }
  }
  public function simple_sql($sql, $fields = array()) {
    $stmt = $this->prepare($sql);
    foreach ($fields as $field => $datum) {
      list($column, $type) = split(":", $field);
      $this->bind_param($stmt, ":".$column, $datum, $type);
    }
    if ($this->exec($stmt)) {
      $this->commit();
      $this->free($stmt);
      return true;
    } else {
      $this->last_error_fields = $fields;
      $this->free($stmt);
      return false;
    }
  }

  /**
   * *************************
   *   Error Handling
   */
  private function clear_error() {
    $this->last_error        = null;
    $this->last_error_type   = null;
    $this->last_error_fields = null;
    $this->last_sql          = null;
  }
  private function handle_error($type, $error, $sql = '') {
    // All we are doing at the moment is storing it
    $this->last_error        = $error;
    $this->last_error_type   = $type;
    $this->last_sql          = $sql;
  }

  /**
   * *************************
   *   Error Retrieval
   */
  // User can retrieve the raw error data
  public function get_last_error()      {return $this->last_error;}
  public function get_last_error_type() {return $this->last_error_type;}
  public function get_last_sql()        {return $this->last_sql;}

  // Or request it formatted as html output
  public function get_html_error() {
    if ($this->last_error == null) return "No error found!";

    // Generic stuff
    $output  = "<b>ORACLE ERROR</b><br/>\n";
    $output .= "Oracle '".$this->last_error_type."' Error<br />\n";
    $output .= "=============<br />\n";
    foreach($this->last_error as $key => $value) {$output .= "($key) => $value<br />\n";}

    // Anything special for this error type?
    switch ($this->last_error_type) {
      case 'parsing':
        $output .= "=============<br />\n";
        $output .= "Offset into SQL:<br />\n";
        $output .= substr($this->last_error['sqltext'], $this->last_error['offset'])."\n";
        break;
      case 'executing':
        $output .= "=============<br />\n";
        $output .= "Offset into SQL:<br />\n";
        $output .= substr($this->last_error['sqltext'], $this->last_error['offset'])."<br />\n";
        if (count($this->last_error_fields) > 0) {
          $output .= "=============<br />\n";
          $output .= "Bind Variables:<br />\n";
          foreach ($this->last_error_fields as $k => $l) {
            if (is_array($l)) {
              $output .= "$k => (".join(", ", $l).")<br />\n";
            } else {
              $output .= "$k => $l<br />\n";
            }
          }
        }
        break;
    }

    $this->clear_error();
    return $output;
  }
}
?>
Return current item: VuFind