Subversion Repositories oidplus

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. if (!defined('IN_OIDPLUS')) die();
  21.  
  22. class OIDplusDataBaseODBC extends OIDplusDataBase {
  23.         private $odbc;
  24.         private $last_query;
  25.         private $prepare_cache = array();
  26.  
  27.         public static function name() {
  28.                 return "ODBC";
  29.         }
  30.  
  31.         public function query($sql, $prepared_args=null) {
  32.                 $this->last_query = $sql;
  33.                 if (is_null($prepared_args)) {
  34.                         return @odbc_exec($this->odbc, $sql);
  35.                 } else {
  36.  
  37.  
  38.                         // TEST: Emulate the prepared statement
  39.  
  40. /*
  41.                         foreach ($prepared_args as $arg) {
  42.                                 $needle = '?';
  43.                                 $replace = "'$arg'"; // TODO: types
  44.                                 $pos = strpos($sql, $needle);
  45.                                 if ($pos !== false) {
  46.                                         $sql = substr_replace($sql, $replace, $pos, strlen($needle));
  47.                                 }
  48.                         }
  49.                         return @odbc_exec($this->odbc, $sql);
  50. */
  51.  
  52.  
  53.                         if (!is_array($prepared_args)) {
  54.                                 throw new Exception("'prepared_args' must be either NULL or an ARRAY.");
  55.                         }
  56.                         if (isset($this->prepare_cache[$sql])) {
  57.                                 $ps = $this->prepare_cache[$sql];
  58.                         } else {
  59.                                 $ps = odbc_prepare($this->odbc, $sql);
  60.                                 if (!$ps) {
  61.                                         throw new Exception("Cannot prepare statement '$sql'");
  62.                                 }
  63.                                 $this->prepare_cache[$sql] = $ps;
  64.                         }
  65.                         if (!@odbc_execute($ps, $prepared_args)) {
  66.                                 // Note: Our plugins prepare the configs by trying to insert stuff, which raises a Primary Key exception. So we cannot throw an Exception.
  67.                                 return false;
  68.                         }
  69.                         return $ps;
  70.  
  71.                 }
  72.         }
  73.         public function num_rows($res) {
  74.                 if (!is_resource($res)) {
  75.                         throw new Exception("num_rows called on non object. Last query: ".$this->last_query);
  76.                 } else {
  77.                         return odbc_num_rows($res);
  78.                 }
  79.         }
  80.         public function fetch_array($res) {
  81.                 if (!is_resource($res)) {
  82.                         throw new Exception("fetch_array called on non object. Last query: ".$this->last_query);
  83.                 } else {
  84.                         return odbc_fetch_array($res);
  85.                 }
  86.         }
  87.         public function fetch_object($res) {
  88.                 if (!is_resource($res)) {
  89.                         throw new Exception("fetch_object called on non object. Last query: ".$this->last_query);
  90.                 } else {
  91.                         return odbc_fetch_object($res);
  92.                 }
  93.         }
  94.         public function insert_id() {
  95.                 $res = $this->query("SELECT LAST_INSERT_ID AS ID"); // MySQL
  96.                 if (!$res) $res = $this->query("SELECT @@IDENTITY AS ID"); // MS SQL
  97.                 if (!$res) return false;
  98.                 $row = $this->fetch_array($res);
  99.                 return $row['ID'];
  100.         }
  101.         public function error() {
  102.                 return odbc_errormsg($this->odbc);
  103.         }
  104.         public function connect() {
  105.                 $html = OIDPLUS_HTML_OUTPUT;
  106.  
  107.                 // Try connecting to the database
  108.                 $this->odbc = @odbc_connect(OIDPLUS_ODBC_DSN, OIDPLUS_ODBC_USERNAME, base64_decode(OIDPLUS_ODBC_PASSWORD));
  109.  
  110.                 if (!$this->odbc) {
  111.                         if ($html) {
  112.                                 echo "<h1>Error</h1><p>Database connection failed! (".odbc_errormsg().")</p>";
  113.                                 if (is_dir(__DIR__.'/../../../setup')) {
  114.                                         echo '<p>If you believe that the login credentials are wrong, please run <a href="setup/">setup</a> again.</p>';
  115.                                 }
  116.                         } else {
  117.                                 echo "Error: Database connection failed! (".odbc_errormsg().")";
  118.                                 if (is_dir(__DIR__.'/../../../setup')) {
  119.                                         echo ' If you believe that the login credentials are wrong, please run setup again.';
  120.                                 }
  121.                         }
  122.                         die();
  123.                 }
  124.  
  125.                 $this->query("SET NAMES 'utf8'"); // Does most likely NOT work with ODBC. Try adding ";CHARSET=UTF8" (or similar) to the DSN
  126.                 $this->afterConnect($html);
  127.                 $this->connected = true;
  128.         }
  129.  
  130.         private $intransaction = false;
  131.  
  132.         public function transaction_begin() {
  133.                 if ($this->intransaction) throw new Exception("Nested transactions are not supported by this database plugin.");
  134.                 odbc_autocommit($this->odbc, true);
  135.                 $this->intransaction = true;
  136.         }
  137.  
  138.         public function transaction_commit() {
  139.                 odbc_commit($this->odbc);
  140.                 odbc_autocommit($this->odbc, false);
  141.                 $this->intransaction = false;
  142.         }
  143.  
  144.         public function transaction_rollback() {
  145.                 odbc_rollback($this->odbc);
  146.                 odbc_autocommit($this->odbc, false);
  147.                 $this->intransaction = false;
  148.         }
  149. }
  150.  
  151. OIDplus::registerDatabasePlugin(new OIDplusDataBaseODBC());
  152.