/caelum/classes/backend/MSSQLStorage.class.php

https://github.com/nemiah/projectMankind · PHP · 496 lines · 476 code · 2 blank · 18 comment · 1 complexity · 07173f72cb60107bbcc34231e2743262 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of phynx.
  4. * phynx is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. * phynx is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. *
  15. * 2007 - 2012, Rainer Furtmeier - Rainer@Furtmeier.de
  16. */
  17. function mssql_real_escape_string($s) {
  18. if(get_magic_quotes_gpc())
  19. $s = stripslashes($s);
  20. $s = str_replace("'","''",$s);
  21. return $s;
  22. }
  23. function mssql_insert_id() {
  24. $id = false;
  25. $res = mssql_query('SELECT @@identity AS id');
  26. if($row = mssql_fetch_row($res))
  27. $id = trim($row[0]);
  28. mssql_free_result($res);
  29. return $id;
  30. }
  31. function mssql_errno(){
  32. $errorCode = 0;
  33. $res = mssql_query('SELECT @@ERROR as ErrorCode');
  34. if ($row = mssql_fetch_row($res))
  35. $errorCode = trim($row[0]) * 1;
  36. mssql_free_result($res);
  37. return $errorCode;
  38. }
  39. class MSSQLStorage {
  40. protected $instance;
  41. protected $connection;
  42. private $parsers;
  43. protected $affectedRowsOnly = false;
  44. function __construct(){
  45. $this->renewConnection();
  46. }
  47. public function setGetAffectedRowsOnly($bool){
  48. $this->affectedRowsOnly = $bool;
  49. }
  50. public function renewConnection(){
  51. $this->connection = mssql_pconnect($_SESSION["DBData"]["host"],$_SESSION["DBData"]["user"],$_SESSION["DBData"]["password"]);
  52. if(!$this->connection) throw new NoDBUserDataException();
  53. if(!mssql_select_db($_SESSION["DBData"]["datab"], $this->connection))
  54. throw new DatabaseNotFoundException();
  55. }
  56. public function getConnection(){
  57. return $this->connection;
  58. }
  59. public function setParser($p){
  60. $this->parsers = $p;
  61. }
  62. static function checkForTable($name){
  63. $sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES";
  64. @$result = mssql_query($sql);
  65. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  66. if($result) while ($row = mssql_fetch_row($result))
  67. if(strtolower($row[2]) == strtolower($name)) return true;
  68. if($result) mssql_free_result($result);
  69. return false;
  70. }
  71. function checkMyTable($CIA){
  72. if(strpos($CIA->MSSQL, "INSERT INTO") !== false) return;
  73. $CIAAlt = clone $CIA;
  74. $view = false;
  75. if(strpos($CIA->MSSQL, "CREATE VIEW") !== false) $view = true;
  76. if(!$view) preg_match("/CREATE TABLE \[([a-zA-Z0-9]*)\]/",$CIA->MSSQL,$regs);
  77. else preg_match("/CREATE VIEW \[([a-zA-Z0-9]*)\]/",$CIA->MSSQL,$regs);
  78. $rand = "RANDOM".rand(10000,100000);
  79. while($this->checkForTable($regs[1].$rand))
  80. $rand = "RANDOM".rand(10000,100000);
  81. if(!$view) $CIA->MSSQL = str_replace("CREATE TABLE [$regs[1]]","CREATE TABLE [".$regs[1].$rand."]",$CIA->MSSQL);
  82. else $CIA->MSSQL = str_replace("CREATE VIEW [$regs[1]]","CREATE VIEW [".$regs[1].$rand."]",$CIA->MSSQL);
  83. $this->createTable($CIA);
  84. $newTable = PMReflector::getAttributesArrayAnyObject($this->getTableColumns($regs[1].$rand));
  85. if(!$view) $this->dropTable($regs[1].$rand);
  86. else $this->dropView($regs[1].$rand);
  87. $oldTable = PMReflector::getAttributesArrayAnyObject($this->getTableColumns($regs[1]));
  88. $unterschied2 = array_diff($newTable,$oldTable);
  89. if(count($unterschied2) == 0){
  90. $_SESSION["messages"]->addMessage("No differences found! (Only different field-names can be found!)");
  91. return -1;
  92. }
  93. if($view){
  94. $this->dropView($regs[1]);
  95. $this->createTable($CIAAlt);
  96. return count($unterschied2);
  97. }
  98. $_SESSION["messages"]->addMessage("Please be aware that this function only works on properly formatted SQL-code. The fieldname must be enclosed by ` and a newline \\n must follow the ,.");
  99. $changes = 0;
  100. foreach($unterschied2 as $key => $value){
  101. $newSQL = strstr($CIA->MSSQL,"[$value]");
  102. $ex = explode(",\n",$newSQL);
  103. $newSQL = $ex[0];
  104. mssql_query("ALTER TABLE [$regs[1]] ADD $newSQL");
  105. #echo mysql_error();
  106. $_SESSION["messages"]->addMessage("Added field $value in table $regs[1]");
  107. $changes++;
  108. }
  109. return $changes;
  110. }
  111. public function alterTable($CIA){
  112. if(strpos($CIA->MSSQL, "ALTER TABLE") != 0) return;
  113. $_SESSION["messages"]->addMessage("executing MSSQL: $CIA->MSSQL");
  114. mssql_query($CIA->MSSQL);
  115. }
  116. private function dropTable($name){
  117. $sql = "DROP TABLE [".$name."]";
  118. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  119. mssql_query($sql);
  120. }
  121. private function dropView($name){
  122. $sql = "DROP VIEW [".$name."]";
  123. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  124. mssql_query($sql);
  125. }
  126. function loadSingle($table, $keyName, $id, $fields) {
  127. throw new FunctionDeprecatedException("DBStorage", "loadSingle");
  128. }
  129. function loadSingle2($table, $id, $typsicher = false) {
  130. $sql = "SELECT * FROM [$table] WHERE ".$table."ID = '$id'";
  131. $q = mssql_query($sql);
  132. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  133. $t = mssql_fetch_object($q);
  134. if(mssql_get_last_message() AND mssql_errno() == 208) throw new TableDoesNotExistException();
  135. #if(mysql_error() AND (mysql_errno() == 1045 OR mysql_errno() == 2002)) throw new NoDBUserDataException();
  136. #if(mysql_error() AND mysql_errno() == 1054) {
  137. # preg_match("/[a-zA-Z0-9 ]*\'([a-zA-Z0-9\.]*)\'[a-zA-Z ]*\'([a-zA-Z ]*)\'.*/", mysql_error(), $regs);
  138. # throw new FieldDoesNotExistException($regs[1],$regs[2]);
  139. #}
  140. #if(mysql_error() AND mysql_errno() == 1046) throw new DatabaseNotSelectedException();
  141. #echo mysql_error();
  142. $fields = PMReflector::getAttributesArrayAnyObject($t);
  143. if($typsicher){
  144. $types = array();
  145. $qc = mssql_query("SHOW COLUMNS FROM $table");
  146. while($tc = mssql_fetch_object($qc))
  147. $types[$tc->Field] = $this->mssql2Object($tc->Type);
  148. }
  149. foreach($fields AS $key => $value){
  150. $t->$value = $this->fixUtf8(stripslashes($t->$value));
  151. if($typsicher){
  152. if(isset($types[$value])) $typObj = $types[$value];
  153. else throw new DataTypeNotDefinedException($value);
  154. $t->$value = new $typObj($t->$value);
  155. }
  156. }
  157. return $t;
  158. }
  159. function loadSingleT($table, $id) {
  160. return $this->loadSingle2($table, $id, true);
  161. }
  162. function createTable($CIA){
  163. $view = false;
  164. if(strpos($CIA->MSSQL, "CREATE VIEW") !== false) $view = true;
  165. if(!$view) preg_match("/CREATE TABLE \[([a-zA-Z0-9]*)\]/",$CIA->MSSQL,$regs);
  166. else preg_match("/CREATE VIEW \[([a-zA-Z0-9]*)\]/",$CIA->MSSQL,$regs);
  167. if(strpos($CIA->MSSQL, "INSERT INTO ") !== false){
  168. preg_match("/INSERT INTO \[([a-zA-Z0-9]*)\]/",$CIA->MSSQL,$regs);
  169. mssql_query("SET IDENTITY_INSERT [$regs[1]] ON;");
  170. }
  171. $_SESSION["messages"]->addMessage("executing MSSQL: $CIA->MSSQL");
  172. mssql_query($CIA->MSSQL);
  173. if(strpos($CIA->MSSQL, "INSERT INTO ") !== false){
  174. mssql_query("SET IDENTITY_INSERT [$regs[1]] OFF;");
  175. }
  176. #if(mysql_error() AND mysql_errno() == 1046) throw new DatabaseNotSelectedException();
  177. #if(strpos($CIA->MSSQL, "INSERT INTO") === false){
  178. #$sql = "ALTER TABLE `$regs[1]` COMMENT = '".$_SESSION["applications"]->getActiveApplication()."_".$_SESSION["applications"]->getRunningVersion().";'";
  179. #$_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  180. #mssql_query($sql);
  181. #}
  182. #if(mysql_error()) echo mysql_error()."<br /><pre style=\"font-size:8px;\">".($CIA->MSSQL != "" ? $CIA->MSSQL : "leeres MySQL-Statement!")."</pre>";
  183. $data = new stdClass();
  184. $data->error = mssql_get_last_message();
  185. $data->affected_rows = mssql_rows_affected($this->connection);
  186. return $data;
  187. }
  188. function saveSingle($table,$keyName,$id,$fields,Attributes $A) {
  189. throw new FunctionDeprecatedException("DBStorage", "saveSingle");
  190. }
  191. function saveSingle2($table, $id, $A) {
  192. $fields = PMReflector::getAttributesArray($A);
  193. $sql = "UPDATE [$table] SET";
  194. for($i = 0;$i < count($fields);$i++)
  195. $sql .= ($i > 0 ? "," : "")." [".$fields[$i]."]='".addslashes($A->$fields[$i])."'";
  196. $sql .= " WHERE [".$table."ID] = '$id'";
  197. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  198. mssql_query($sql);
  199. if(mysql_error() AND mysql_errno() == 1062) throw new DuplicateEntryException(mysql_error());
  200. echo mysql_error();
  201. }
  202. function getTableColumns($forWhat){
  203. $result = mssql_query("SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '$forWhat'");
  204. $a = new stdClass();
  205. while ($row = mssql_fetch_assoc($result))
  206. $a->$row["COLUMN_NAME"] = "";
  207. return $a;
  208. }
  209. private function fixUtf8($value){
  210. return $value;
  211. $value = str_replace("Ä", "Ä", $value);
  212. $value = str_replace("Ö", "Ö", $value);
  213. $value = str_replace("Ãœ", "Ü", $value);
  214. $value = str_replace("ä", "ä", $value);
  215. $value = str_replace("ö", "ö", $value);
  216. $value = str_replace("ü", "ü", $value);
  217. $value = str_replace("ß", "ß", $value);
  218. return $value;
  219. }
  220. function loadMultipleV4(SelectStatement $statement, $typsicher = false){
  221. #echo array_search("t1.".$statement->table[0], $statement->fields);
  222. unset($statement->fields[array_search("t1.".$statement->table[0]."ID", $statement->fields)]);
  223. if(array_search("t1.".$statement->table[0]."ID AS currentObjectID", $statement->fields) === false)
  224. $statement->fields[] = "t1.".$statement->table[0]."ID AS currentObjectID";
  225. #print_r($statement->fields);
  226. #return ;
  227. if(count($statement->order) == 0){
  228. $statement->order[] = "currentObjectID";
  229. $statement->orderAscDesc[] = "ASC";
  230. }
  231. $where = "(";
  232. $lastKey = "";
  233. $closeBrackets = "";
  234. foreach($statement->whereFields as $key => $value){
  235. $addOpenBracket = false;
  236. if($where != "(" AND $statement->whereBracketGroup[$lastKey] != $statement->whereBracketGroup[$key]){
  237. $addOpenBracket = true;
  238. $where .= ")";
  239. }
  240. $currentWhereValue = $statement->whereValues[$key];
  241. if($currentWhereValue != "NULL"
  242. AND $currentWhereValue != "NOT NULL")
  243. $currentWhereValue = "'".mssql_real_escape_string($currentWhereValue)."'";
  244. $where .= ($where != "(" ? " ".$statement->whereLogOp[$key]." ".($addOpenBracket ? "(" : "") : "")./*(in_array($statement->whereFields[$key], $nJAs) ? "t1." : "").*/"[".$statement->whereFields[$key]."] ".$statement->whereOperators[$key]." ".$currentWhereValue."";
  245. $lastKey = $key;
  246. }
  247. $where .= ")";
  248. $order = "";
  249. foreach($statement->order as $key => $value)
  250. $order .= ($order != "" ? ", ": "")."[".$statement->order[$key]."] ".$statement->orderAscDesc[$key];
  251. $tables = array();
  252. for($i=0;$i<count($statement->joinTables);$i++){
  253. if(!isset($tables[$statement->joinTables[$i]])) $tables[$statement->joinTables[$i]] = array();
  254. $tables[$statement->joinTables[$i]][] = array($statement->joinConditions[$i][0],$statement->joinConditionOperators[$i],$statement->joinConditions[$i][1]);
  255. }
  256. $t = 2;
  257. $joinAdd = "";
  258. foreach($tables as $table => $conditions){
  259. $ons = "";
  260. for($i=0;$i<count($conditions);$i++){
  261. if($i == 0) $ons .= ((!strpos($conditions[$i][0],".") AND $conditions[$i][0]{0} != " ") ? "t1." : "")."".$conditions[$i][0]." ".$conditions[$i][1]." t$t.".$conditions[$i][2];
  262. else {
  263. if($conditions[$i][2] != "NOT NULL" AND $conditions[$i][2] != "NULL") $conditions[$i][2] = "'".$conditions[$i][2]."'";
  264. $ons .= " AND t$t.".$conditions[$i][0]." ".$conditions[$i][1]." ".$conditions[$i][2]."";
  265. }
  266. }
  267. $joinAdd .= "\n LEFT JOIN [".$table."] t$t ON($ons)";
  268. $t++;
  269. }
  270. $sql = "WITH MSOrdered AS (\nSELECT\n (ROW_NUMBER() OVER(ORDER BY $order)) - 1 AS MSZeilennummer, ".implode(",\n ",$statement->fields)."\n FROM [".$statement->table[0]."] t1$joinAdd ".($where != "()" ? "\n WHERE $where" : "").(count($statement->group) > 0 ? "\n GROUP BY ".implode(", ",$statement->group) : "")."\n)\n";
  271. #.(count($statement->limit) > 0 ? "\n LIMIT ".implode(", ",$statement->limit) : "")
  272. $sql .= "SELECT * FROM MSOrdered";
  273. $limit = array();
  274. if(isset($statement->limit[0]))
  275. $limit = explode(",", $statement->limit[0]);
  276. if(count($limit) == 1)
  277. $sql .= " WHERE MSZeilennummer < ".$limit[0];
  278. if(count($limit) == 2)
  279. $sql .= " WHERE MSZeilennummer BETWEEN ".$limit[0]." AND ".$limit[1];
  280. $sql .= ($order != "" ? "\n ORDER BY $order" : "");
  281. $collector = array();
  282. #if($statement->table[0] != "Userdata")
  283. $_SESSION["messages"]->startMessage("executing MSSQL: $sql");
  284. #echo nl2br($sql)."<br /><br />";
  285. $q = mssql_query($sql);
  286. #echo mssql_get_last_message().": ".(mssql_errno() == 208)."<br />";
  287. #if(mysql_error() AND (mysql_errno() == 1045 OR mysql_errno() == 2002)) throw new NoDBUserDataException();
  288. if(mssql_get_last_message() AND mssql_errno() == 208) throw new TableDoesNotExistException();
  289. #if(mysql_error() AND mysql_errno() == 1046) throw new DatabaseNotSelectedException();
  290. #if(mysql_error() AND mysql_errno() == 1054) {
  291. # preg_match("/[a-zA-Z0-9 ]*\'([a-zA-Z0-9\.]*)\'[a-zA-Z ]*\'([a-zA-Z ]*)\'.*/", mysql_error(), $regs);
  292. # throw new FieldDoesNotExistException($regs[1],$regs[2]);
  293. #}
  294. #if(mysql_error()) echo "MySQL-Fehler: ".mysql_error()."<br />Fehlernummer: ".mysql_errno();
  295. if($statement->table[0] != "Userdata") $_SESSION["messages"]->endMessage(": ".mssql_rows_affected($this->connection)." ".$statement->table[0]." geladen");
  296. if($this->affectedRowsOnly) {
  297. $this->affectedRowsOnly = false;
  298. return mssql_rows_affected($this->connection);
  299. }
  300. if($typsicher){
  301. $types = array();
  302. $qc = mssql_query("SHOW COLUMNS FROM ".$statement->table[0]);
  303. while($tc = mssql_fetch_object($qc))
  304. $types[$tc->Field] = $this->mysql2Object($tc->Type);
  305. foreach($statement->joinTables AS $kc => $vc){
  306. $qc = mssql_query("SHOW COLUMNS FROM ".$vc);
  307. while($tc = mssql_fetch_object($qc))
  308. $types[$tc->Field] = $this->mysql2Object($tc->Type);
  309. }
  310. foreach($statement->dataTypes AS $kc => $vc)
  311. $types = array_merge($types, $vc);
  312. }
  313. $fields = null;
  314. while(@$t = mssql_fetch_object($q)){
  315. $A = new Attributes();
  316. if($fields == null) $fields = PMReflector::getAttributesArrayAnyObject($t);
  317. foreach($fields AS $key => $value){
  318. $A->$value = $this->fixUtf8(stripslashes($t->$value));
  319. if($typsicher){
  320. if(isset($types[$value])) $typObj = $types[$value];
  321. else throw new DataTypeNotDefinedException($value);
  322. $A->$value = new $typObj($A->$value);
  323. #echo "<pre>";
  324. #print_r($A);
  325. #echo "</pre>";
  326. }
  327. }
  328. if(count($this->parsers) > 0) foreach($this->parsers as $key => $value)
  329. if(isset($A->$key)) eval("\$A->\$key = ".$value."(\"".$A->$key."\",\"load\");");
  330. $oID = "currentObjectID";
  331. $cName = $statement->table[0];
  332. $newCOfClass = new $cName($t->$oID);
  333. $newCOfClass->setA($A);
  334. $collector[] = $newCOfClass;
  335. }
  336. return $collector;
  337. }
  338. function loadMultipleT(SelectStatement $statement){
  339. return $this->loadMultipleV4($statement, true);
  340. }
  341. function makeNewLine2($table, $A) {
  342. $fields = PMReflector::getAttributesArray($A);
  343. $values = "";#"''";
  344. $sets = "";#"[".$table."ID]";
  345. for($i = 0;$i < count($fields);$i++){
  346. if($fields[$i] == $table."ID") continue;
  347. $values .= ($values != "" ? ", " : "")." '".mssql_real_escape_string($A->$fields[$i])."'\n";
  348. $sets .= ($sets != "" ? ", " : "")."\n[".$fields[$i]."]";
  349. }
  350. $sql = "INSERT INTO\n [$table]\n ($sets) VALUES ($values)";
  351. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  352. mssql_query($sql);
  353. if(mysql_error() AND mysql_errno() == 1054) {
  354. preg_match("/[a-zA-Z0-9 ]*\'([a-zA-Z0-9\.]*)\'[a-zA-Z ]*\'([a-zA-Z ]*)\'.*/", $this->c->error, $regs);
  355. throw new FieldDoesNotExistException($regs[1],$regs[2]);
  356. }
  357. if(mysql_error() AND mysql_errno() == 1062) throw new DuplicateEntryException($this->c->error);
  358. if(mysql_error()) throw new StorageException();
  359. return mssql_insert_id();
  360. }
  361. function deleteSingle($table,$keyName,$id){
  362. $sql = "DELETE FROM [$table] WHERE [$keyName] = '$id'";
  363. mssql_query($sql);
  364. $_SESSION["messages"]->addMessage("executing MSSQL: $sql");
  365. }
  366. private function mssql2Object($type){
  367. $k = strpos($type, "(");
  368. if($k !== false) $type = substr($type, 0, $k);
  369. $values = array();
  370. $values["int"] = "I";
  371. $values["varchar"] = "S";
  372. $values["text"] = "S";
  373. $values["decimal"] = "D";
  374. $values["tinyint"] = "B";
  375. return isset($values[$type]) ? $values[$type] : "S";
  376. }
  377. }
  378. ?>