<?php
/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */



class DBOperationOracle extends DBOperationODBC
{
  public function __construct($connectionInfo, $pDBnr)
  {
    parent::__construct($connectionInfo, $pDBnr);
  }

  public function connect_db($dbserver, $dbname, $dbuser, $dbpass)
  {
    parent::connect_db($dbserver, $dbname, $dbuser, $dbpass);

    odbc_exec($this->connection, 'ALTER SESSION SET NLS_LANGUAGE = \'GERMAN\' NLS_TERRITORY = \'GERMANY\'') or $this->throwCriticalError('Das SQL-Statement enthält Fehler!<br />', $sql);
  }

  
  public function _hasSeqGenTable($tablename)
  {
    
    
    
    $tablename = StringOperations::strtoupper($tablename);

    
    static $cache = array('WEB_PROTOCOL' => false);

    
    if (isset($cache[$tablename])) {
      return $cache[$tablename];
    }

    $this->clear();
    
    $this->query("SELECT 1 FROM all_sequences WHERE sequence_name = 'SEQ_GEN_$tablename'");
    $hasGen = $this->rowcount() > 0;

    
    $cache[$tablename] = $hasGen;

    return $hasGen;
  }

  public function execute($sql)
  {
    if ($this->connectionInfo->db_isEncodingUtf8) {
      $sql = mb_convert_encoding($sql, CP1252, \CodingOperations::getInternalEncoding()); 
    }

    return parent::execute($sql);
  }

  public function query($sql)
  {
    if ($this->connectionInfo->db_isEncodingUtf8) {
      $sql = mb_convert_encoding($sql, CP1252, \CodingOperations::getInternalEncoding()); 
    }

    parent::query($sql);
  }

  
  public function _getSequenceName($tablename)
  {
    
    

    if ($this->_hasSeqGenTable($tablename)) {
      return 'SEQ_GEN_' . StringOperations::strtoupper($tablename);
    } else {
      return 'SEQ_AUTO_' . StringOperations::strtoupper($tablename);
    }
  }

  
  public function getLastID($tablename)
  {
    $genTablename = $this->_getSequenceName($tablename);

    $this->clear();
    
    $this->query("SELECT $genTablename.currval LID FROM dual");
    $this->selectrow(0);

    return abs($this->fieldbyName('LID'));
  }

  
  public function getNextIDGen($tablename, $columnname)
  {
    $genTablename = $this->_getSequenceName($tablename);

    $this->clear();
    $this->query("SELECT $genTablename.nextval LID FROM dual");
    $this->selectrow(0);

    return $this->fieldbyName('LID');
  }

  
  public function getDBName()
  {
    return 'ORACLE';
  }

  
  public function checkTableExists($pTableName, $pRefreshCache = false)
  {
    if (self::$_tableExistsCache == null) {
      self::$_tableExistsCache = array();
    }

    if (!$pRefreshCache && isset(self::$_tableExistsCache[$pTableName])) {
      return self::$_tableExistsCache[$pTableName];
    }

    $sql = "SELECT table_name FROM USER_TABLES WHERE TABLE_NAME = '" . StringOperations::strtoupper($pTableName) . "'";
    $this->clear();
    $this->query($sql);
    self::$_tableExistsCache[$pTableName] = ($this->rowcount() == 1);

    return self::$_tableExistsCache[$pTableName];
  }

  public function getColumnsOfTable(string $table): array
  {
    $result = array();
    $table = \StringOperations::strtolower($table);

    $this->clear();
    $this->query("SELECT column_name FROM all_tab_columns WHERE lower(table_name) = '$table';");

    for ($i = 0; $i < $this->rowcount(); ++$i) {
      $this->selectrow($i);
      $result[] = $this->fieldbyname('column_name');
    }

    return $result;
  }

  public function getColumnsOfTables(array $tables): array
  {
    $result = array();
    $tables = array_map(\StringOperations::class . '::strtolower', $tables);

    $inList = \StringOperations::convertArray2InList($tables);
    $this->clear();
    $this->query("SELECT table_name, column_name FROM all_tab_columns WHERE lower(table_name) IN ($inList);");

    while ($this->selectNextRow()) {
      $table = \StringOperations::strtolower($this->fieldbyname('table_name'));
      $column = \StringOperations::strtolower($this->fieldbyname('column_name'));
      if (!array_key_exists($table, $result)) {
        $result[$table] = array();
      }
      $result[$table][] = $column;
    }

    return $result;
  }

  public function caseInsensitiveCompOperation(string $pOperation, string $pPraefix, string $pFieldname, string $pMatch): string
  {
    return 'LOWER(' . $pPraefix . $pFieldname . ') ' . $pOperation
      . ' LOWER(' . $this->getEnclosedString4Sql($pMatch) . ')';
  }

  public function caseInsensitiveBetween(string $pPraefix, string $pFieldname, string $pLowerBound, string $pUpperBound): string
  {
    return 'LOWER(' . $pPraefix . $pFieldname . ') BETWEEN '
      . 'LOWER(' . $this->getEnclosedString4Sql($pLowerBound) . ') AND '
      . 'LOWER(' . $this->getEnclosedString4Sql($pUpperBound) . ')';
  }
}