PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/dbal/src/query/lmbSelectRawQuery.class.php

https://github.com/syfisher/limb
PHP | 396 lines | 312 code | 64 blank | 20 comment | 38 complexity | f0550cd6777e81ca74997182008f2e9f MD5 | raw file
  1. <?php
  2. /*
  3. * Limb PHP Framework
  4. *
  5. * @link http://limb-project.com
  6. * @copyright Copyright &copy; 2004-2009 BIT(http://bit-creative.com)
  7. * @license LGPL http://www.gnu.org/copyleft/lesser.html
  8. */
  9. lmb_require('limb/dbal/src/query/lmbCriteriaQuery.class.php');
  10. //TODO: use primitive lexer for parsing sql templates someday...
  11. /**
  12. * class lmbSelectRawQuery.
  13. *
  14. * @package dbal
  15. * @version $Id: lmbSelectRawQuery.class.php 6005 2007-06-19 21:14:49Z pachanga $
  16. */
  17. class lmbSelectRawQuery extends lmbCriteriaQuery
  18. {
  19. const DEFAULT_SQL_TEMPLATE = "SELECT %fields% FROM %tables% %left_join% %where% %group% %having% %order%";
  20. protected $_fields = array();
  21. protected $_raw_fields = array();
  22. protected $_tables = array();
  23. protected $_left_join_constraints = array();
  24. protected $_order = array();
  25. protected $_having = array();
  26. protected $_group_by = array();
  27. function __construct($sql_or_conn = null, $conn = null)
  28. {
  29. if(is_object($sql_or_conn))
  30. parent :: __construct(self :: DEFAULT_SQL_TEMPLATE, $sql_or_conn);
  31. else
  32. parent :: __construct($sql_or_conn, $conn);
  33. }
  34. function addField($field, $alias = null)
  35. {
  36. $this->_fields[$field] = $alias;
  37. $this->_registerHint('fields');
  38. return $this;
  39. }
  40. function field($field, $alias = null)
  41. {
  42. return $this->addField($field, $alias);
  43. }
  44. function getFields()
  45. {
  46. return array_keys($this->_fields);
  47. }
  48. function setFields($fields)
  49. {
  50. $this->_fields = array();
  51. foreach($fields as $alias => $field)
  52. $this->_fields[$field] = $alias;
  53. return $this;
  54. }
  55. function addRawField($field, $alias = null)
  56. {
  57. $this->_raw_fields[$field] = $alias;
  58. $this->_registerHint('fields');
  59. return $this;
  60. }
  61. function addTable($table, $alias = null)
  62. {
  63. $this->_tables[] = array($table, $alias);
  64. $this->_registerHint('tables');
  65. return $this;
  66. }
  67. function from($table, $alias = null)
  68. {
  69. return $this->addTable($table, $alias);
  70. }
  71. function getTables()
  72. {
  73. $tables = array();
  74. foreach($this->_tables as $item)
  75. $tables[] = $item[0];
  76. return $tables;
  77. }
  78. function addOrder($field, $type='ASC')
  79. {
  80. if(is_array($field))
  81. {
  82. foreach($field as $field_name => $type)
  83. $this->_order[] = $this->_conn->quoteIdentifier($field_name) . " $type";
  84. }
  85. else
  86. $this->_order[] = $this->_conn->quoteIdentifier($field) . " $type";
  87. $this->_registerHint('order');
  88. return $this;
  89. }
  90. function addRawOrder($field)
  91. {
  92. $this->_order[] = $field;
  93. $this->_registerHint('order');
  94. return $this;
  95. }
  96. function order($field, $type='ASC')
  97. {
  98. return $this->addOrder($field, $type);
  99. }
  100. function getOrder()
  101. {
  102. return $this->_order;
  103. }
  104. function addGroupBy($group)
  105. {
  106. $this->_group_by[] = $group;
  107. $this->_registerHint('group');
  108. return $this;
  109. }
  110. function group($group)
  111. {
  112. return $this->addGroupBy($group);
  113. }
  114. function getGroupBy()
  115. {
  116. return $this->_group_by;
  117. }
  118. function addHaving($criteria)
  119. {
  120. $this->_having[] = lmbSQLCriteria :: objectify($criteria);
  121. $this->_registerHint('having');
  122. return $this;
  123. }
  124. function having($criteria)
  125. {
  126. return $this->addHaving($criteria);
  127. }
  128. function getHaving()
  129. {
  130. return $this->_having;
  131. }
  132. function addLeftJoin($table, $field, $connect_table, $connect_field, $table_alias = '')
  133. {
  134. if(!$table_alias)
  135. $connect_by = array($table . '.' . $field => $connect_table . '.' . $connect_field);
  136. else
  137. $connect_by = array($table_alias . '.' . $field => $connect_table . '.' . $connect_field);
  138. $this->_left_join_constraints[] = array('table' => $table,
  139. 'connect_by' => $connect_by,
  140. 'alias' => $table_alias);
  141. $this->_registerHint('left_join');
  142. return $this;
  143. }
  144. function join($table, $field, $connect_table, $connect_field)
  145. {
  146. return $this->addLeftJoin($table, $field, $connect_table, $connect_field);
  147. }
  148. function getJoins()
  149. {
  150. return $this->_left_join_constraints;
  151. }
  152. function toString()
  153. {
  154. if(!count($this->_fields) && !count($this->_raw_fields) && !$this->_selectFieldsExists() && $this->_fromClauseExists())
  155. $this->addRawField('*');
  156. return parent :: toString();
  157. }
  158. function getRecordSet()
  159. {
  160. $stmt = $this->getStatement();
  161. return $stmt->getRecordSet();
  162. }
  163. function fetch()
  164. {
  165. return $this->getRecordSet();
  166. }
  167. protected function _getFieldsHint()
  168. {
  169. $fields = '';
  170. foreach($this->_fields as $field => $alias)
  171. {
  172. if(strpos($field, '*') !== false)
  173. {
  174. $fields .= $field . ',';
  175. continue;
  176. }
  177. $fields .= $this->_conn->quoteIdentifier($field) .
  178. ($alias ? ' as ' . $this->_conn->quoteIdentifier($alias) : '') . ',';
  179. }
  180. if(count($this->_raw_fields) == 0)
  181. $fields = rtrim($fields, ',');
  182. foreach($this->_raw_fields as $field => $alias)
  183. {
  184. if(strpos($field, '*') !== false)
  185. {
  186. $fields .= $field . ',';
  187. continue;
  188. }
  189. $fields .= $field . ($alias ? ' as ' . $alias : '') . ',';
  190. }
  191. $fields = rtrim($fields, ',');
  192. if($this->_selectFieldsExists())
  193. {
  194. if(count($this->_fields) || count($this->_raw_fields))
  195. return ',' . $fields;
  196. else
  197. return '';
  198. }
  199. elseif(count($this->_fields) == 0 && count($this->_raw_fields) == 0)
  200. return '*';
  201. else
  202. return $fields;
  203. }
  204. protected function _getTablesHint()
  205. {
  206. if(count($this->_tables) == 0)
  207. return '';
  208. $tables = '';
  209. foreach($this->_tables as $item)
  210. {
  211. $tables .= $this->_conn->quoteIdentifier($item[0]) .
  212. ($item[1] ? ' ' . $this->_conn->quoteIdentifier($item[1]) : '') . ',';
  213. }
  214. $tables = rtrim($tables, ',');
  215. if($this->_selectTablesExists())
  216. $tables = ',' . $tables;
  217. return $tables;
  218. }
  219. protected function _getLeftJoinHint()
  220. {
  221. $join = array();
  222. foreach($this->_left_join_constraints as $info)
  223. {
  224. $table = $info['table'];
  225. $connect_by = $info['connect_by'];
  226. $alias = $info['alias'] ? ' AS ' . $this->_conn->quoteIdentifier($info['alias']) : '';
  227. $foreign_key = $this->_conn->quoteIdentifier(key($connect_by));
  228. $alias_key = $this->_conn->quoteIdentifier(reset($connect_by));
  229. $join[] = "LEFT JOIN " . $this->_conn->quoteIdentifier($table) . "$alias ON $foreign_key=$alias_key";
  230. }
  231. return implode(' ', $join);
  232. }
  233. protected function _getGroupHint()
  234. {
  235. if (count($this->_group_by) == 0)
  236. return '';
  237. $group = implode(',', array_map(array($this->_conn, 'quoteIdentifier'), $this->_group_by));
  238. if($this->_groupByClauseExists($group_by_args))
  239. {
  240. //primitive check if comma is required
  241. if($group_by_args)
  242. return ',' . $group;
  243. else
  244. return $group;
  245. }
  246. else
  247. return 'GROUP BY ' . $group;
  248. }
  249. protected function _getHavingHint()
  250. {
  251. if (count($this->_having) == 0)
  252. return '';
  253. if(!count($this->_group_by) && !$this->_groupByClauseExists())
  254. throw new lmbException('can not generate HAVING condition GROUP BY missing');
  255. $implode = array();
  256. foreach($this->_having as $criteria)
  257. {
  258. $implode[] = $criteria->toStatementString($this->_stmt_values);
  259. }
  260. $having = implode(' AND ', $implode);
  261. if($this->_havingClauseExists($having_args))
  262. {
  263. if($having_args)
  264. return 'AND ' . $having;
  265. else
  266. return $having;
  267. }
  268. else
  269. return 'HAVING ' . $having;
  270. }
  271. protected function _getOrderHint()
  272. {
  273. if (count($this->_order) == 0)
  274. return '';
  275. $order = implode(',', $this->_order);
  276. if($this->_orderByClauseExists($order_by_args))
  277. {
  278. //primitive check if comma is required
  279. if($order_by_args)
  280. return ',' . $order;
  281. else
  282. return $order;
  283. }
  284. else
  285. return 'ORDER BY ' . $order;
  286. }
  287. protected function _orderByClauseExists(&$args = '')
  288. {
  289. //!!!make it better later
  290. if(preg_match('~(?<=from).+order\s+by\s(.*)$~si', $this->_getNoHintsSQL(), $matches))
  291. {
  292. $args = trim($matches[1]);
  293. return true;
  294. }
  295. return false;
  296. }
  297. protected function _groupByClauseExists(&$args = '')
  298. {
  299. //!!!make it better later
  300. if(preg_match('~(?<=\Wfrom).+group\s+by\s(.*)$~si', $this->_getNoHintsSQL(), $matches))
  301. {
  302. $args = trim($matches[1]);
  303. return true;
  304. }
  305. return false;
  306. }
  307. protected function _havingClauseExists(&$args = '')
  308. {
  309. //!!!make it better later
  310. if(preg_match('~(?<=\Wgroup)\s+by\s+.+?having\s(.*)(order)?$~si', $this->_getNoHintsSQL(), $matches))
  311. {
  312. $args = trim($matches[1]);
  313. return true;
  314. }
  315. return false;
  316. }
  317. protected function _selectFieldsExists()
  318. {
  319. //!!!make it better later
  320. return preg_match('~^select\s+\S+.+?from~si', $this->_getNoHintsSQL());
  321. }
  322. protected function _selectTablesExists()
  323. {
  324. if(!preg_match('~(?<=\Wfrom)((.*?)(?=(where|order|group|limit))|.*)~si', $this->_getNoHintsSQL(), $matches))
  325. return false;
  326. return (boolean)strlen(trim($matches[1]));
  327. }
  328. protected function _fromClauseExists()
  329. {
  330. return preg_match('~from\s+~si', $this->_getNoHintsSQL());
  331. }
  332. }