KXStudio Website https://kx.studio/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
8.6KB

  1. <?php
  2. /**
  3. * Class: Query
  4. * Handles a query based on the <SQL.method>.
  5. */
  6. class Query {
  7. # Variable: $query
  8. # Holds the current query.
  9. public $query;
  10. /**
  11. * Function: __construct
  12. * Creates a query based on the <SQL.interface>.
  13. *
  14. * Parameters:
  15. * $sql - <SQL> instance.
  16. * $query - Query to execute.
  17. * $params - An associative array of parameters used in the query.
  18. * $throw_exceptions - Throw exceptions on error?
  19. */
  20. public function __construct($sql, $query, $params = array(), $throw_exceptions = false) {
  21. if (DEBUG)
  22. global $time_start;
  23. $this->sql = $sql;
  24. # Don't count config setting queries.
  25. $count = !preg_match("/^SET /", strtoupper($query));
  26. if ($count)
  27. ++$this->sql->queries;
  28. $this->db =& $this->sql->db;
  29. $this->params = $params;
  30. $this->throw_exceptions = $throw_exceptions;
  31. $this->queryString = $query;
  32. if ($count and defined('DEBUG') and DEBUG) {
  33. $trace = debug_backtrace();
  34. $target = $trace[$index = 0];
  35. # Getting a traceback from these files doesn't help much.
  36. while (match(array("/SQL\.php/", "/Model\.php/", "/\/model\//"), $target["file"]))
  37. if (isset($trace[$index + 1]["file"]))
  38. $target = $trace[$index++];
  39. else
  40. break;
  41. $logQuery = $query;
  42. foreach ($params as $name => $val)
  43. $logQuery = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/", str_replace("\\", "\\\\", $this->sql->escape($val))."\\1", $logQuery);
  44. $this->sql->debug[] = array("number" => $this->sql->queries,
  45. "file" => str_replace(MAIN_DIR."/", "", $target["file"]),
  46. "line" => $target["line"],
  47. "query" => $logQuery,
  48. "time" => timer_stop());
  49. }
  50. switch($this->sql->method) {
  51. case "pdo":
  52. try {
  53. $this->query = $this->db->prepare($query);
  54. $result = $this->query->execute($params);
  55. $this->query->setFetchMode(PDO::FETCH_ASSOC);
  56. $this->queryString = $query;
  57. foreach ($params as $name => $val)
  58. $this->queryString = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/",
  59. str_replace(array("\\", "\$"),
  60. array("\\\\", "\\\$"),
  61. $this->sql->escape($val))."\\1",
  62. $this->queryString);
  63. if (!$result)
  64. throw new PDOException;
  65. } catch (PDOException $error) {
  66. if (!empty($error->errorInfo[1]) and $error->errorInfo[1] == 17)
  67. return new self($sql, $query, $params, $throw_exceptions);
  68. return $this->handle($error);
  69. }
  70. break;
  71. case "mysqli":
  72. foreach ($params as $name => $val)
  73. $query = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/",
  74. str_replace(array("\\", "\$"),
  75. array("\\\\", "\\\$"),
  76. $this->sql->escape($val))."\\1",
  77. $query);
  78. $this->queryString = $query;
  79. try {
  80. if (!$this->query = $this->db->query($query))
  81. throw new Exception($this->db->error);
  82. } catch (Exception $error) {
  83. return $this->handle($error);
  84. }
  85. break;
  86. case "mysql":
  87. foreach ($params as $name => $val)
  88. $query = preg_replace("/{$name}([^a-zA-Z0-9_]|$)/",
  89. str_replace(array("\\", "\$"),
  90. array("\\\\", "\\\$"),
  91. $this->sql->escape($val))."\\1",
  92. $query);
  93. $this->queryString = $query;
  94. try {
  95. if (!$this->query = @mysql_query($query))
  96. throw new Exception(mysql_error());
  97. } catch (Exception $error) {
  98. return $this->handle($error);
  99. }
  100. break;
  101. }
  102. }
  103. /**
  104. * Function: fetchColumn
  105. * Fetches a column of the current row.
  106. *
  107. * Parameters:
  108. * $column - The offset of the column to grab. Default 0.
  109. */
  110. public function fetchColumn($column = 0) {
  111. switch($this->sql->method) {
  112. case "pdo":
  113. return $this->query->fetchColumn($column);
  114. case "mysqli":
  115. $result = $this->query->fetch_array();
  116. return $result[$column];
  117. case "mysql":
  118. $result = mysql_fetch_array($this->query);
  119. return $result[$column];
  120. }
  121. }
  122. /**
  123. * Function: fetch
  124. * Returns the current row as an array.
  125. */
  126. public function fetch() {
  127. switch($this->sql->method) {
  128. case "pdo":
  129. return $this->query->fetch();
  130. case "mysqli":
  131. return $this->query->fetch_array();
  132. case "mysql":
  133. return mysql_fetch_array($this->query);
  134. }
  135. }
  136. /**
  137. * Function: fetchObject
  138. * Returns the current row as an object.
  139. */
  140. public function fetchObject() {
  141. switch($this->sql->method) {
  142. case "pdo":
  143. return $this->query->fetchObject();
  144. case "mysqli":
  145. return $this->query->fetch_object();
  146. case "mysql":
  147. return mysql_fetch_object($this->query);
  148. }
  149. }
  150. /**
  151. * Function: fetchAll
  152. * Returns an array of every result.
  153. */
  154. public function fetchAll($style = null) {
  155. switch($this->sql->method) {
  156. case "pdo":
  157. return $this->query->fetchAll($style);
  158. case "mysqli":
  159. $results = array();
  160. while ($row = $this->query->fetch_assoc())
  161. $results[] = $row;
  162. return $results;
  163. case "mysql":
  164. $results = array();
  165. while ($row = mysql_fetch_assoc($this->query))
  166. $results[] = $row;
  167. return $results;
  168. }
  169. }
  170. /**
  171. * Function: grab
  172. * Grabs all of the given column out of the full result of a query.
  173. *
  174. * Parameters:
  175. * $column - Name of the column to grab.
  176. *
  177. * Returns:
  178. * An array of all of the values of that column in the result.
  179. */
  180. public function grab($column) {
  181. $all = $this->fetchAll();
  182. $result = array();
  183. foreach ($all as $row)
  184. $result[] = $row[$column];
  185. return $result;
  186. }
  187. /**
  188. * Function: handle
  189. * Handles exceptions thrown by failed queries.
  190. */
  191. public function handle($error) {
  192. $this->sql->error = $error;
  193. if (UPGRADING or $this->sql->silence_errors) return false;
  194. $message = $error->getMessage();
  195. $message.= "\n\n<pre>".print_r($this->queryString, true)."\n\n<pre>".print_r($this->params, true)."</pre>\n\n<pre>".$error->getTraceAsString()."</pre>";
  196. if (XML_RPC or $this->throw_exceptions)
  197. throw new Exception($message);
  198. error(__("Database Error"), $message);
  199. }
  200. }