You are here

public function FrxOracle::call in Forena Reports 8

Parameters

string $sql : script containing function

array $data : parameter array.

array $types : array containing types

Return value

object oci statement resource Call a pl/sql block of code. The code snippet is expected to contain a begin/end data block as well as any variable binding that is necessary. Note that bind variables should appear only once in the calling code.

1 call to FrxOracle::call()
FrxOracle::sqlData in src/FrxPlugin/Driver/FrxOracle.php
Get data based on file data block in the repository.

File

src/FrxPlugin/Driver/FrxOracle.php, line 244
Oracle specific driver that takes advantage of oracles native XML support

Class

FrxOracle
Class FrxOracle

Namespace

Drupal\forena\FrxPlugin\Driver

Code

public function call($sql, &$data, $types = array()) {
  $db = $this->db;
  $begin_end_block = stripos($sql, 'begin') === FALSE ? FALSE : TRUE;
  $match = array();
  $collections = array();
  $return = array();
  if ($db) {
    $stmt = oci_parse($db, $sql);
  }
  if ($stmt) {
    if (preg_match_all(FRX_SQL_TOKEN, $sql, $match)) {

      //list($params) = $match[1];
      $i = 0;
      foreach ($match[0] as $match_num => $token) {
        $name = trim($token, ':');
        $value = @$data[$name];
        @(list($type, $subtype) = explode(' of ', $types[$name], 2));

        // Default varchar
        if (!$type) {
          $type = 'varchar';
        }
        switch (strtolower($type)) {

          // Handle arrays based on subtype.
          case 'array':
            $value = (array) $value;
            $bind_type = $this
              ->oci_bind_type($subtype);
            $entries = count($value);
            if (!count($value)) {
              $entries = 255;
            }
            oci_bind_array_by_name($stmt, $token, $value, $entries, -1, $bind_type);
            break;
          case 'clob':
            $c = oci_new_descriptor($db, OCI_D_LOB);
            $lobs[$name] = $c;
            oci_bind_by_name($stmt, $token, $lobs[$name], -1, OCI_B_CLOB);
            if (is_object($c)) {
              $c
                ->writeTemporary($value);
            }
            break;
          case 'number':
          case 'numeric':
          case 'varchar':
            oci_bind_by_name($stmt, $token, $data[$name], 32767);
            break;
          default:
            $o = oci_new_collection($db, strtoupper($type), $this->schema);
            $value = (array) $value;
            $collections[$name] = $o;
            if ($value && $o) {
              foreach ($value as $element) {
                $o
                  ->append($element);
              }
            }
            oci_bind_by_name($stmt, $token, $o, -1, OCI_B_NTY);
            break;
        }
      }
    }

    // putting the @ operator before the oci_execute call will suppress php warnings.
    try {
      $r = @oci_execute($stmt, OCI_DEFAULT);

      // Report errors
      if (!$r) {
        $e = oci_error($stmt);

        // For oci_execute errors pass the statement handle

        //drupal_set_message(e_display_array($e));
        if ($e['code'] != '1403') {
          if (!$this->block_name) {
            $short = t('%e at offset %o', array(
              '%e' => $e['message'],
              '%o' => $e['offset'],
            ));
          }
          else {
            $short = t('%e in %b.sql line %o', array(
              '%e' => $e['message'],
              '%b' => $this->block_name,
              '%o' => $e['offset'],
            ));
          }
          $msg = htmlentities($e['message']);
          $msg .= "\n<pre>\n";
          $msg .= htmlentities($e['sqltext']);
          $msg .= "\n</pre>\n";
          $this
            ->app()
            ->error($short, $msg);
        }
      }
    } catch (\Exception $e) {
      if (!$this->block_name) {
        $short = t('%e at offset %o', array(
          '%e' => $e['message'],
          '%o' => $e['offset'],
        ));
      }
      else {
        $short = t('%e in %b.sql line %o', array(
          '%e' => $e['message'],
          '%b' => $this->block_name,
          '%o' => $e['offset'],
        ));
      }
      $msg .= htmlentities($e['message']);
      $msg .= "\n<pre>\n";
      $msg .= htmlentities($e['sqltext']);

      //printf("\n%".($e['offset']+1)."s", "^");
      $msg .= "\n</pre>\n";
      $this
        ->app()
        ->error($short, $msg);
    }

    // Retrieve any clob data.
    if ($lobs) {
      foreach ($lobs as $name => $lob) {
        if (is_object($lob)) {
          $data[$name] = $lob
            ->load();
          $lob
            ->free();
        }
      }
    }

    // Free any collections
    if ($collections) {
      foreach ($collections as $col) {
        if ($col) {
          $col
            ->free();
        }
      }
    }
    if (!$begin_end_block) {
      $rows = array();
      $rows = oci_fetch_all($stmt, $return, NULL, NULL, OCI_FETCHSTATEMENT_BY_ROW);
    }
    oci_free_statement($stmt);
  }
  return $return;
}