PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/db_mysql.inc

http://ebpls.googlecode.com/
PHP | 420 lines | 282 code | 61 blank | 77 comment | 58 complexity | 396588469597e5a44e4ab5f2058bd945 MD5 | raw file
  1. <?php
  2. /*
  3. * Session Management for PHP3
  4. *
  5. * Copyright (c) 1998-2000 NetUSE AG
  6. * Boris Erdmann, Kristian Koehntopp
  7. *
  8. * $Id: db_mysql.inc,v 1.11 2002/08/07 19:33:57 layne_weathers Exp $
  9. *
  10. */
  11. class DB_Sql {
  12. /* public: connection parameters */
  13. var $Host = "";
  14. var $Database = "";
  15. var $User = "";
  16. var $Password = "";
  17. /* public: configuration parameters */
  18. var $Auto_Free = 0; ## Set to 1 for automatic mysql_free_result()
  19. var $Debug = 0; ## Set to 1 for debugging messages.
  20. var $Halt_On_Error = "yes"; ## "yes" (halt with message), "no" (ignore errors quietly), "report" (ignore errror, but spit a warning)
  21. var $PConnect = 0; ## Set to 1 to use persistent database connections
  22. var $Seq_Table = "db_sequence";
  23. /* public: result array and current row number */
  24. var $Record = array();
  25. var $Row;
  26. /* public: current error number and error text */
  27. var $Errno = 0;
  28. var $Error = "";
  29. /* public: this is an api revision, not a CVS revision. */
  30. var $type = "mysql";
  31. var $revision = "1.2";
  32. /* private: link and query handles */
  33. var $Link_ID = 0;
  34. var $Query_ID = 0;
  35. var $locked = false; ## set to true while we have a lock
  36. /* public: constructor */
  37. function DB_Sql($query = "") {
  38. $this->query($query);
  39. }
  40. /* public: some trivial reporting */
  41. function link_id() {
  42. return $this->Link_ID;
  43. }
  44. function query_id() {
  45. return $this->Query_ID;
  46. }
  47. /* public: connection management */
  48. function connect($Database = "", $Host = "", $User = "", $Password = "") {
  49. /* Handle defaults */
  50. if ("" == $Database)
  51. $Database = $this->Database;
  52. if ("" == $Host)
  53. $Host = $this->Host;
  54. if ("" == $User)
  55. $User = $this->User;
  56. if ("" == $Password)
  57. $Password = $this->Password;
  58. /* establish connection, select database */
  59. if ( 0 == $this->Link_ID ) {
  60. if(!$this->PConnect) {
  61. $this->Link_ID = mysql_connect($Host, $User, $Password);
  62. } else {
  63. $this->Link_ID = mysql_pconnect($Host, $User, $Password);
  64. }
  65. if (!$this->Link_ID) {
  66. $this->halt("connect($Host, $User, \$Password) failed.");
  67. return 0;
  68. }
  69. if (!@mysql_select_db($Database,$this->Link_ID)) {
  70. $this->halt("cannot use database ".$Database);
  71. return 0;
  72. }
  73. }
  74. return $this->Link_ID;
  75. }
  76. /* public: discard the query result */
  77. function free() {
  78. @mysql_free_result($this->Query_ID);
  79. $this->Query_ID = 0;
  80. }
  81. /* public: perform a query */
  82. function query($Query_String) {
  83. /* No empty queries, please, since PHP4 chokes on them. */
  84. if ($Query_String == "")
  85. /* The empty query string is passed on from the constructor,
  86. * when calling the class without a query, e.g. in situations
  87. * like these: '$db = new DB_Sql_Subclass;'
  88. */
  89. return 0;
  90. if (!$this->connect()) {
  91. return 0; /* we already complained in connect() about that. */
  92. };
  93. # New query, discard previous result.
  94. if ($this->Query_ID) {
  95. $this->free();
  96. }
  97. if ($this->Debug)
  98. printf("Debug: query = %s<br>\n", $Query_String);
  99. $this->Query_ID = @mysql_query($Query_String,$this->Link_ID);
  100. $this->Row = 0;
  101. $this->Errno = mysql_errno();
  102. $this->Error = mysql_error();
  103. if (!$this->Query_ID) {
  104. $this->halt("Invalid SQL: ".$Query_String);
  105. }
  106. # Will return nada if it fails. That's fine.
  107. return $this->Query_ID;
  108. }
  109. /* public: walk result set */
  110. function next_record() {
  111. if (!$this->Query_ID) {
  112. $this->halt("next_record called with no query pending.");
  113. return 0;
  114. }
  115. $this->Record = @mysql_fetch_array($this->Query_ID);
  116. $this->Row += 1;
  117. $this->Errno = mysql_errno();
  118. $this->Error = mysql_error();
  119. $stat = is_array($this->Record);
  120. if (!$stat && $this->Auto_Free) {
  121. $this->free();
  122. }
  123. return $stat;
  124. }
  125. /* public: position in result set */
  126. function seek($pos = 0) {
  127. $status = @mysql_data_seek($this->Query_ID, $pos);
  128. if ($status)
  129. $this->Row = $pos;
  130. else {
  131. $this->halt("seek($pos) failed: result has ".$this->num_rows()." rows.");
  132. /* half assed attempt to save the day,
  133. * but do not consider this documented or even
  134. * desireable behaviour.
  135. */
  136. @mysql_data_seek($this->Query_ID, $this->num_rows());
  137. $this->Row = $this->num_rows();
  138. return 0;
  139. }
  140. return 1;
  141. }
  142. /* public: table locking */
  143. function lock($table, $mode = "write") {
  144. $query = "lock tables ";
  145. if(is_array($table)) {
  146. while(list($key,$value) = each($table)) {
  147. // text keys are "read", "read local", "write", "low priority write"
  148. if(is_int($key)) $key = $mode;
  149. if(strpos($value, ",")) {
  150. $query .= str_replace(",", " $key, ", $value) . " $key, ";
  151. } else {
  152. $query .= "$value $key, ";
  153. }
  154. }
  155. $query = substr($query, 0, -2);
  156. } elseif(strpos($table, ",")) {
  157. $query .= str_replace(",", " $mode, ", $table) . " $mode";
  158. } else {
  159. $query .= "$table $mode";
  160. }
  161. if(!$this->query($query)) {
  162. $this->halt("lock() failed.");
  163. return false;
  164. }
  165. $this->locked = true;
  166. return true;
  167. }
  168. function unlock() {
  169. // set before unlock to avoid potential loop
  170. $this->locked = false;
  171. if(!$this->query("unlock tables")) {
  172. $this->halt("unlock() failed.");
  173. return false;
  174. }
  175. return true;
  176. }
  177. /* public: evaluate the result (size, width) */
  178. function affected_rows() {
  179. return @mysql_affected_rows($this->Link_ID);
  180. }
  181. function num_rows() {
  182. return @mysql_num_rows($this->Query_ID);
  183. }
  184. function num_fields() {
  185. return @mysql_num_fields($this->Query_ID);
  186. }
  187. /* public: shorthand notation */
  188. function nf() {
  189. return $this->num_rows();
  190. }
  191. function np() {
  192. print $this->num_rows();
  193. }
  194. function f($Name) {
  195. if (isset($this->Record[$Name])) {
  196. return $this->Record[$Name];
  197. }
  198. }
  199. function p($Name) {
  200. if (isset($this->Record[$Name])) {
  201. print $this->Record[$Name];
  202. }
  203. }
  204. /* public: sequence numbers */
  205. function nextid($seq_name) {
  206. /* if no current lock, lock sequence table */
  207. if(!$this->locked) {
  208. if($this->lock($this->Seq_Table)) {
  209. $locked = true;
  210. } else {
  211. $this->halt("cannot lock ".$this->Seq_Table." - has it been created?");
  212. return 0;
  213. }
  214. }
  215. /* get sequence number and increment */
  216. $q = sprintf("select nextid from %s where seq_name = '%s'",
  217. $this->Seq_Table,
  218. $seq_name);
  219. if(!$this->query($q)) {
  220. $this->halt('query failed in nextid: '.$q);
  221. return 0;
  222. }
  223. /* No current value, make one */
  224. if(!$this->next_record()) {
  225. $currentid = 0;
  226. $q = sprintf("insert into %s values('%s', %s)",
  227. $this->Seq_Table,
  228. $seq_name,
  229. $currentid);
  230. if(!$this->query($q)) {
  231. $this->halt('query failed in nextid: '.$q);
  232. return 0;
  233. }
  234. } else {
  235. $currentid = $this->f("nextid");
  236. }
  237. $nextid = $currentid + 1;
  238. $q = sprintf("update %s set nextid = '%s' where seq_name = '%s'",
  239. $this->Seq_Table,
  240. $nextid,
  241. $seq_name);
  242. if(!$this->query($q)) {
  243. $this->halt('query failed in nextid: '.$q);
  244. return 0;
  245. }
  246. /* if nextid() locked the sequence table, unlock it */
  247. if($locked) {
  248. $this->unlock();
  249. }
  250. return $nextid;
  251. }
  252. /* public: return table metadata */
  253. function metadata($table = "", $full = false) {
  254. $count = 0;
  255. $id = 0;
  256. $res = array();
  257. /*
  258. * Due to compatibility problems with Table we changed the behavior
  259. * of metadata();
  260. * depending on $full, metadata returns the following values:
  261. *
  262. * - full is false (default):
  263. * $result[]:
  264. * [0]["table"] table name
  265. * [0]["name"] field name
  266. * [0]["type"] field type
  267. * [0]["len"] field length
  268. * [0]["flags"] field flags
  269. *
  270. * - full is true
  271. * $result[]:
  272. * ["num_fields"] number of metadata records
  273. * [0]["table"] table name
  274. * [0]["name"] field name
  275. * [0]["type"] field type
  276. * [0]["len"] field length
  277. * [0]["flags"] field flags
  278. * ["meta"][field name] index of field named "field name"
  279. * This last one could be used if you have a field name, but no index.
  280. * Test: if (isset($result['meta']['myfield'])) { ...
  281. */
  282. // if no $table specified, assume that we are working with a query
  283. // result
  284. if ($table) {
  285. $this->connect();
  286. $id = @mysql_list_fields($this->Database, $table);
  287. if (!$id) {
  288. $this->halt("Metadata query failed.");
  289. return false;
  290. }
  291. } else {
  292. $id = $this->Query_ID;
  293. if (!$id) {
  294. $this->halt("No query specified.");
  295. return false;
  296. }
  297. }
  298. $count = @mysql_num_fields($id);
  299. // made this IF due to performance (one if is faster than $count if's)
  300. if (!$full) {
  301. for ($i=0; $i<$count; $i++) {
  302. $res[$i]["table"] = @mysql_field_table ($id, $i);
  303. $res[$i]["name"] = @mysql_field_name ($id, $i);
  304. $res[$i]["type"] = @mysql_field_type ($id, $i);
  305. $res[$i]["len"] = @mysql_field_len ($id, $i);
  306. $res[$i]["flags"] = @mysql_field_flags ($id, $i);
  307. }
  308. } else { // full
  309. $res["num_fields"]= $count;
  310. for ($i=0; $i<$count; $i++) {
  311. $res[$i]["table"] = @mysql_field_table ($id, $i);
  312. $res[$i]["name"] = @mysql_field_name ($id, $i);
  313. $res[$i]["type"] = @mysql_field_type ($id, $i);
  314. $res[$i]["len"] = @mysql_field_len ($id, $i);
  315. $res[$i]["flags"] = @mysql_field_flags ($id, $i);
  316. $res["meta"][$res[$i]["name"]] = $i;
  317. }
  318. }
  319. // free the result only if we were called on a table
  320. if ($table) {
  321. @mysql_free_result($id);
  322. }
  323. return $res;
  324. }
  325. /* public: find available table names */
  326. function table_names() {
  327. $this->connect();
  328. $h = @mysql_query("show tables", $this->Link_ID);
  329. $i = 0;
  330. while ($info = @mysql_fetch_row($h)) {
  331. $return[$i]["table_name"] = $info[0];
  332. $return[$i]["tablespace_name"] = $this->Database;
  333. $return[$i]["database"] = $this->Database;
  334. $i++;
  335. }
  336. @mysql_free_result($h);
  337. return $return;
  338. }
  339. /* private: error handling */
  340. function halt($msg) {
  341. $this->Error = @mysql_error($this->Link_ID);
  342. $this->Errno = @mysql_errno($this->Link_ID);
  343. if ($this->locked) {
  344. $this->unlock();
  345. }
  346. if ($this->Halt_On_Error == "no")
  347. return;
  348. $this->haltmsg($msg);
  349. if ($this->Halt_On_Error != "report")
  350. die("Session halted.");
  351. }
  352. function haltmsg($msg) {
  353. printf("</td></tr></table><b>Database error:</b> %s<br>\n", $msg);
  354. printf("<b>MySQL Error</b>: %s (%s)<br>\n",
  355. $this->Errno,
  356. $this->Error);
  357. }
  358. }
  359. ?>