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



class DBOperationMySQL extends DBOperation
{
  protected static $_cache_lastid = array();

  public function __construct($connectionInfo, $pDBnr)
  {
    parent::__construct($connectionInfo, $pDBnr);
  }

  public function __destruct()
  {
    if (is_resource($this->resultset)) {
      mysql_free_result($this->resultset);
    }
    parent::__destruct();
  }

  
  public function connect_db($dbserver, $dbname, $dbuser, $dbpass)
  {
    $this->connection = @mysql_connect($dbserver, $dbuser, $dbpass) or $this->throwCriticalError("Die Verbindung zum MySQL-Datenbankserver '" . $dbserver . "' konnte nicht hergestellt werden!");
    @mysql_select_db($dbname, $this->connection) or $this->throwCriticalError("Die Verbindung zur Datenbank '" . $dbname . "' konnte nicht hergestellt werden!");
    
    
    
    
    
    $this->executeDontDie("SET SESSION sql_mode = '';");
    $this->setCharset();
  }

  protected function setCharset($pConnection = null)
  {
    $connection = $this->connection;
    if ($pConnection !== null) {
      $connection = $pConnection;
    }
    $sql = $this->getSqlForCharset();
    mysql_query($sql, $connection);
  }

  protected function getSqlForCharset()
  {
    if (System::isUnicode()) {
      return 'SET NAMES utf8;';
    } else {
      return 'SET NAMES latin1;';
    }
  }

  
  public function query($sql)
  {
    $this->openConnection();
    if (LOG_DB) {
      Logger::logg('query on db ' . $this->dbnr . ' : ' . StringOperations::getReadableString($sql), 9);
    }
    $this->resultset = @mysql_query($sql, $this->connection) or $this->throwCriticalError('Das SQL-Statement enthält Fehler! <br/>', $sql);
  }

  
  public function execute($sql)
  {
    $this->openConnection();

    
    if (mysql_query($sql, $this->connection) === false) {
      return false;
    } else {
      
      return true;
    }
  }

  
  public function callStoredProcedure($pSQL)
  {
    $result = false;
    $conn = @mysql_connect(
      $this->connectionInfo->db_server,
      $this->connectionInfo->db_user,
      $this->connectionInfo->db_password,
      true,
      131072
    )
                     
            or $this->throwCriticalError("Die Verbindung zum MySQL-Datenbankserver '" . $this->connectionInfo->db_server
                  . "' konnte nicht hergestellt werden!");
    @mysql_select_db($this->connectionInfo->db_name, $conn) or $this->throwCriticalError("Die Verbindung zur Datenbank '"
            . $this->connectionInfo->db_server . "' konnte nicht hergestellt werden!");
    mysql_query("SET SESSION sql_mode = '';", $conn);
    $this->setCharset($conn);
    if (mysql_query($pSQL, $conn) === false) {
      $result = false;
    } else {
      $result = true;
    }
    mysql_close($conn);

    return $result;
  }

  
  public function executeDontDie($sql)
  {
    $this->openConnection();

    return @mysql_query($sql, $this->connection);
  }

  
  public function rowcount()
  {
    if (isset($this->resultset)) {
      return mysql_num_rows($this->resultset);
    } else {
      return -1;
    }
  }

  
  public function selectrow($rownr)
  { 
    if ($rownr < $this->rowcount() && $rownr > -1) {
      if (mysql_data_seek($this->resultset, $rownr)) {
        $this->actualrow = $rownr;
        
        
        
        $this->currentRow = array_change_key_case(mysql_fetch_array($this->resultset), CASE_LOWER);
        mysql_data_seek($this->resultset, $rownr);

        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }

  
  public function debug()
  {
    while ($row = mysql_fetch_array($this->resultset, MYSQL_ASSOC)) {
      foreach ($row as $column => $value) {
        echo "$column: $value; ";
      }
      echo "\n";
    }
  }

  
  public function fieldbyname($name)
  {
    
    
    $normname = StringOperations::strtolower($name);
    if (isset($this->currentRow[$normname])) {
      return $this->currentRow[$normname];
    } else {
      return '';
    }
  }

  
  public function fieldExists($name)
  {
    $count = mysql_num_fields($this->resultset);
    for ($i = 0;$i < $count;$i++) {
      if (StringOperations::strtoupper($name) == StringOperations::strtoupper(mysql_field_name($this->resultset, $i))) {
        return true;
      }
    }

    return false;
  }

  
  public function getLastID($tablename)
  {
    
    
    
    $this->clear();
    $this->query('SELECT last_insert_id() LID');
    $this->selectrow(0);

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

  
  public function getNextIdGenWithoutCorrespondingTable($pTablename, $columnname)
  {
    return parent::getNextIDGen($pTablename, $columnname);
  }

  
  public function getNextIDGen($tablename, $columnname)
  {
    $autoIncId = parent::getNextIDGen($tablename, $columnname);

    
    

    
    $sql2 = "select $columnname from $tablename order by $columnname desc limit 1";

    $this->clear();
    $this->query($sql2);
    $this->selectrow(0);

    $highestIdInTable = $this->fieldbyname($columnname);

    $this->clear();

    
      
      $dbwReplikatSettings = new DBWorkWebReplikatSettings(1, true);
      $maxPk = $dbwReplikatSettings->getMaxPK($tablename);
    $highestIdInWebReplikatSettings = 0;
    if ($maxPk !== null && !$maxPk->isEmpty()) {
      $highestIdInWebReplikatSettings = $maxPk->value;
    }

    
    return max(array(intval($highestIdInTable) + 1, intval($highestIdInWebReplikatSettings) + 1, $autoIncId));
  }

  
  public function getError()
  {
    return 'Error #' . mysql_errno() . ': ' . mysql_error() . "<br />\n";
  }

  
  public function subselectPossible()
  {
    
    $version = mysql_get_server_info();

    
    $ary = explode('.', $version);
    $part1 = count($ary) > 0 ? $ary[0] : 0;
    $part2 = count($ary) > 1 ? $ary[1] : 0;

    
    if ($part1 > 4) {
      return true;
    }
    if ($part1 == 4 and $part2 > 0) {
      return true;
    }

    return false;
  }

  public function multiValueInsertPossible()
  {
    return true;
  }

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

  
  public function checkConnection($pCheckTables = true)
  {
    $connection = false;
    $conInfo = DBConnectionInfo::getInstance();
    if ($this->dbnr == 1) {
      $dbserver = $conInfo->db_server;
      $dbname = $conInfo->db_name;
      $dbuser = $conInfo->db_user;
      $dbpass = $conInfo->db_password;
    } else {
      $dbserver = $conInfo->db2_server;
      $dbname = $conInfo->db2_name;
      $dbuser = $conInfo->db2_user;
      $dbpass = $conInfo->db2_password;
    }

    if (Connections::IsConnected($this->dbnr)) {
      $connection = &Connections::GetConnection($this->dbnr);
    } else {
      if (!function_exists('mysql_connect')) {
        return false;
      }

      $connection = @mysql_connect($dbserver, $dbuser, $dbpass);
      
      @mysql_query("SET SESSION sql_mode = '';", $connection);
      $this->setCharset($connection);
      Connections::RegisterConnection($this->dbnr, $connection);
    }



    
    if (!$connection) {
      return false;
    }

    
    if (!@mysql_select_db($dbname, $connection)) {
      return false;
    }

    if ($pCheckTables) {
      $res = @mysql_query("show tables like 'aussenst'", $connection);
      if (mysql_num_rows($res) != 1) {
        return false;
      }

      $res = @mysql_query("show tables like 'kategorien'", $connection);
      if (mysql_num_rows($res) != 1) {
        return false;
      }
    }

    
    
    
    return true;
  }

  public function closeConnection()
  {
    @mysql_close($this->connection);
    $this->connection = false;
    Connections::CloseConnection($this->dbnr);
    if (LOG_DB) {
      Logger::logg('connection geschlossen!', 900);
    }
  }

  
  protected function weitereFehlerbehandlung($pErrorMsg, $sql = '')
  {
    
    
    
    

    if ($this->connection === false) {
      return;
    } 

    $errorsToReportToKufer = array(1194);
    $errno = mysql_errno($this->connection);
    $error = mysql_error($this->connection);

    Logger::logg('MySQL Error (' . $errno . '): ' . $error . ' SQL: ' . $sql, 500);

    

    if (in_array($errno, $errorsToReportToKufer)) {
      if (SessionOperations::getVarValueIntern('MySqlError-' . $errno . '-MailVersendet') == '') {
        SessionOperations::setVarValueIntern('MySqlError-' . $errno . '-MailVersendet', 'true');


        $settings = AllgSettingsAPI::getAllgSettings();
        $msg = "MySQL Fehler !\n";
        $msg .= 'Errno: ' . @$errno . "\n";
        $msg .= 'Error: ' . @$error . "\n";
        $msg .= 'SQL Statement bei dem der Fehler auftrat: ' . StringOperations::getReadableString(@$sql) . "\n";
        $msg .= 'dbnr: ' . @$this->dbnr . "\n";
        $msg .= 'vhsname: ' . @$settings->vhsname . "\n";
        $msg .= 'url: ' . DebugOperations::getVollstaendigeAufgerufeneURL() . "\n";
        $msg .= DebugOperations::getBackTrace();


        Logger::logg("E-mail:\n" . $msg, 500);
        smtpMail::sendStandardTextMail('info@kufer.de', 'MySQL Fehler bei ' . @$settings->vhsname, $msg);
        Logger::logg("E-mail für MySQL Fehler $errno versendet!", 500);
      }
    }
  }

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

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

    $sql = "SHOW TABLES LIKE '$pTableName'";
    $this->clear();
    $this->query($sql);
    self::$_tableExistsCache[$pTableName] = ($this->rowcount() == 1);

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

  public function getString4Sql($pString)
  {
    $this->openConnection();

    return mysql_real_escape_string($pString, $this->connection);
  }

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

    $this->clear();
    $this->query("SHOW COLUMNS FROM `$table`");
    for ($i = 0; $i < $this->rowcount(); ++$i) {
      $this->selectrow($i);
      $result[] = \StringOperations::strtolower($this->fieldbyname('field'));
    }

    return $result;
  }
}