/src/application/code/core/Wootook/Core/Database/Sql/Select.php

https://github.com/deathsta/xnova-legacies · PHP · 332 lines · 291 code · 41 blank · 0 comment · 47 complexity · c770f53ef7ed018002df9248151c88de MD5 · raw file

  1. <?php
  2. class Wootook_Core_Database_Sql_Select
  3. extends Wootook_Core_Database_Sql_DmlFilterableQuery
  4. {
  5. const COLUMNS = 'COLUMNS';
  6. const FROM = 'FROM';
  7. const JOIN = 'JOIN';
  8. const ORDER = 'ORDER';
  9. const UNION = 'UNION';
  10. const GROUP = 'GROUP';
  11. const HAVING = 'HAVING';
  12. const JOIN_INNER = 'INNER';
  13. const JOIN_OUTER = 'OUTER';
  14. const JOIN_LEFT = 'LEFT';
  15. const JOIN_RIGHT = 'RIGHT';
  16. protected function _init($tableName = null)
  17. {
  18. parent::_init($tableName);
  19. if ($tableName !== null) {
  20. $this->from($tableName);
  21. }
  22. return $this;
  23. }
  24. public function reset($part = null)
  25. {
  26. if ($part === null) {
  27. $this->_parts = array(
  28. self::COLUMNS => array(),
  29. self::FROM => array(),
  30. self::JOIN => array(),
  31. self::WHERE => array(),
  32. self::UNION => array(),
  33. self::LIMIT => null,
  34. self::OFFSET => null,
  35. self::GROUP => array(),
  36. self::HAVING => array(),
  37. self::ORDER => array(),
  38. );
  39. } else if (isset($this->_parts[$part])) {
  40. $this->_parts[$part] = array();
  41. }
  42. return $this;
  43. }
  44. public function column($column = '*', $table = null)
  45. {
  46. if (is_array($column)) {
  47. foreach ($column as $alias => $field) {
  48. if (is_int($alias)) {
  49. $this->_parts[self::COLUMNS][] = array(
  50. 'table' => $table,
  51. 'alias' => null,
  52. 'field' => $field
  53. );
  54. } else {
  55. $this->_parts[self::COLUMNS][] = array(
  56. 'table' => $table,
  57. 'alias' => $alias,
  58. 'field' => $field
  59. );
  60. }
  61. }
  62. } else {
  63. if ($column instanceof Wootook_Core_Database_Sql_Placeholder_Placeholder) {
  64. $this->_placeholders[] = $column;
  65. }
  66. $this->_parts[self::COLUMNS][] = array(
  67. 'table' => $table,
  68. 'alias' => null,
  69. 'field' => $column
  70. );
  71. }
  72. return $this;
  73. }
  74. public function from($table, $schema = null)
  75. {
  76. if (is_array($table)) {
  77. $alias = key($table);
  78. $table = current($table);
  79. } else {
  80. $alias = null;
  81. }
  82. $this->_parts[self::FROM][] = array(
  83. 'table' => $table,
  84. 'alias' => $alias,
  85. 'schema' => $schema
  86. );
  87. return $this;
  88. }
  89. public function join($table, $condition, $fields = array('*'), $mode = self::JOIN_INNER, $schema = null)
  90. {
  91. $this->column($fields);
  92. if (is_array($table)) {
  93. $alias = key($table);
  94. $table = $this->_connection->getTable(current($table));
  95. if ($schema !== null) {
  96. $this->_parts[self::JOIN][] = "\n{$mode} JOIN {$this->_connection->quoteIdentifier($schema)}{$this->_connection->quoteIdentifier($table)} AS {$this->_connection->quoteIdentifier($alias)}"
  97. . "\n ON {$condition}";
  98. } else {
  99. $this->_parts[self::JOIN][] = "\n{$mode} JOIN {$this->_connection->quoteIdentifier($table)} AS {$this->_connection->quoteIdentifier($alias)}"
  100. . "\n ON {$condition}";
  101. }
  102. } else {
  103. $this->_parts[self::JOIN][] = "\n{$mode} JOIN {$this->_connection->quoteIdentifier($table)}"
  104. . "\n ON {$condition}";
  105. }
  106. return $this;
  107. }
  108. public function joinLeft($table, $condition, $fields = array('*'))
  109. {
  110. return $this->join($table, $condition, $fields, self::JOIN_LEFT);
  111. }
  112. public function joinRight($table, $condition, $fields = array('*'))
  113. {
  114. return $this->join($table, $condition, $fields, self::JOIN_RIGHT);
  115. }
  116. public function joinInner($table, $condition, $fields = array('*'))
  117. {
  118. return $this->join($table, $condition, $fields, self::JOIN_INNER);
  119. }
  120. public function joinOuter($table, $condition, $fields = array('*'))
  121. {
  122. return $this->join($table, $condition, $fields, self::JOIN_OUTER);
  123. }
  124. public function order($field, $direction = 'ASC')
  125. {
  126. $this->_parts[self::ORDER][] = "{$field} {$direction}";
  127. return $this;
  128. }
  129. public function union($collection)
  130. {
  131. $this->_parts[self::UNION][] = $collection;
  132. return $this;
  133. }
  134. public function group($groupField)
  135. {
  136. $this->_parts[self::GROUP][] = $groupField;
  137. return $this;
  138. }
  139. public function __toString()
  140. {
  141. return $this->render();
  142. }
  143. public function toString($part = null)
  144. {
  145. if ($part === null) {
  146. return $this->render();
  147. }
  148. switch ($part) {
  149. case self::COLUMNS:
  150. return $this->renderColumns();
  151. break;
  152. case self::FROM:
  153. return $this->renderFrom();
  154. break;
  155. case self::WHERE:
  156. return $this->renderWhere();
  157. break;
  158. case self::JOIN:
  159. return $this->renderJoin();
  160. break;
  161. case self::ORDER:
  162. return $this->renderOrder();
  163. break;
  164. case self::UNION:
  165. return $this->renderUnion();
  166. break;
  167. case self::LIMIT:
  168. return $this->renderLimit();
  169. break;
  170. case self::GROUP:
  171. return $this->renderGroup();
  172. break;
  173. case self::HAVING:
  174. return $this->renderHaving();
  175. break;
  176. }
  177. return null;
  178. }
  179. public function renderColumns()
  180. {
  181. $fields = array();
  182. foreach ($this->_parts[self::COLUMNS] as $field) {
  183. if ($field['field'] instanceof Wootook_Core_Database_Sql_Dml) {
  184. if ($field['alias'] !== null) {
  185. $fields[] = "({$field['field']}) AS {$field['alias']}";
  186. } else {
  187. $fields[] = "({$field['field']})";
  188. }
  189. } else if ($field['field'] instanceof Wootook_Core_Database_Sql_Placeholder_Placeholder) {
  190. if ($field['alias'] !== null) {
  191. $fields[] = "({$field['field']}) AS {$field['alias']}";
  192. } else {
  193. $fields[] = "({$field['field']})";
  194. }
  195. } else if ($field['alias'] !== null) {
  196. if ($field['table'] !== null) {
  197. $fields[] = "{$field['table']}.{$field['field']} AS {$field['alias']}";
  198. } else {
  199. $fields[] = "{$field['field']} AS {$field['alias']}";
  200. }
  201. } else if ($field['table'] !== null) {
  202. $fields[] = "{$field['table']}.{$field['field']}";
  203. } else {
  204. $fields[] = "{$field['field']}";
  205. }
  206. }
  207. if (!empty($fields)) {
  208. return 'SELECT ' . implode(", ", $fields);
  209. }
  210. return 'SELECT *';
  211. }
  212. public function renderFrom()
  213. {
  214. $tables = array();
  215. foreach ($this->_parts[self::FROM] as $table) {
  216. if ($table['table'] instanceof Wootook_Core_Database_Sql_Dml) {
  217. if ($table['alias'] !== null) {
  218. $tables[] = "({$table['table']}) AS {$this->_connection->quoteIdentifier($table['alias'])}";
  219. } else {
  220. $tables[] = "({$table['table']})";
  221. }
  222. } else if ($table['alias'] !== null) {
  223. if ($table['schema'] !== null) {
  224. $tables[] = "{$this->_connection->quoteIdentifier($table['schema'])}.{$this->_connection->quoteIdentifier($table['table'])} AS {$this->_connection->quoteIdentifier($table['alias'])}";
  225. } else {
  226. $tables[] = "{$this->_connection->quoteIdentifier($table['table'])} AS {$this->_connection->quoteIdentifier($table['alias'])}";
  227. }
  228. } else if ($table['schema'] !== null) {
  229. $tables[] = "{$this->_connection->quoteIdentifier($table['schema'])}.{$this->_connection->quoteIdentifier($table['table'])}";
  230. } else {
  231. $tables[] = "({$this->_connection->quoteIdentifier($table['table'])})";
  232. }
  233. }
  234. return " FROM " . implode(', ', $tables);
  235. }
  236. public function renderJoin()
  237. {
  238. return implode('', $this->_parts[self::JOIN]);
  239. }
  240. public function renderOrder()
  241. {
  242. if (count($this->_parts[self::ORDER]) <= 0) {
  243. return null;
  244. }
  245. return " ORDER BY " . implode(', ', $this->_parts[self::ORDER]);
  246. }
  247. public function renderUnion()
  248. {
  249. $statements = array();
  250. foreach ($this->_parts[self::UNION] as $statement) {
  251. $statements[] = $statement->render();
  252. }
  253. return " (\n" . implode(" )\n UNION\n (\n", $statements) . "\n )";
  254. }
  255. public function renderGroup()
  256. {
  257. if (count($this->_parts[self::GROUP]) <= 0) {
  258. return null;
  259. }
  260. return " GROUP BY " . implode(', ', $this->_parts[self::GROUP]);
  261. }
  262. public function renderHaving()
  263. {
  264. if (count($this->_parts[self::HAVING]) <= 0) {
  265. return null;
  266. }
  267. return " HAVING " . implode(', ', $this->_parts[self::HAVING]);
  268. }
  269. public function render()
  270. {
  271. if (empty($this->_parts[self::UNION])) {
  272. return implode("\n", array(
  273. $this->renderColumns(),
  274. $this->renderFrom(),
  275. $this->renderJoin(),
  276. $this->renderWhere(),
  277. $this->renderGroup(),
  278. $this->renderHaving(),
  279. $this->renderOrder(),
  280. $this->renderLimit()
  281. ));
  282. } else {
  283. return implode("\n", array(
  284. $this->renderUnion(),
  285. $this->renderWhere(),
  286. $this->renderOrder(),
  287. $this->renderLimit()
  288. ));
  289. }
  290. }
  291. }