Source for file DibiDataSource.php

Documentation is available at DibiDataSource.php

  1. 1: <?php
  2. 2:  
  3. 3: /**
  4. 4:  * dibi - tiny'n'smart database abstraction layer
  5. 5:  * ----------------------------------------------
  6. 6:  *
  7. 7:  * @copyright  Copyright (c) 2005, 2010 David Grudl
  8. 8:  * @license    http://dibiphp.com/license  dibi license
  9. 9:  * @link       http://dibiphp.com
  10. 10:  * @package    dibi
  11. 11:  */
  12. 12:  
  13. 13:  
  14. 14:  
  15. 15: /**
  16. 16:  * Default implementation of IDataSource for dibi.
  17. 17:  *
  18. 18:  * @copyright  Copyright (c) 2005, 2010 David Grudl
  19. 19:  * @package    dibi
  20. 20:  *
  21. 21:  * @property-read DibiConnection $connection 
  22. 22:  * @property-read DibiResult $result 
  23. 23:  * @property-read DibiResultIterator $iterator 
  24. 24:  * @property-read int $totalCount 
  25. 25:  */
  26. 26: class DibiDataSource extends DibiObject implements IDataSource
  27. 27: {
  28. 28:     /** @var DibiConnection */
  29. 29:     private $connection;
  30. 30:  
  31. 31:     /** @var string */
  32. 32:     private $sql;
  33. 33:  
  34. 34:     /** @var DibiResult */
  35. 35:     private $result;
  36. 36:  
  37. 37:     /** @var int */
  38. 38:     private $count;
  39. 39:  
  40. 40:     /** @var int */
  41. 41:     private $totalCount;
  42. 42:  
  43. 43:     /** @var array */
  44. 44:     private $cols array();
  45. 45:  
  46. 46:     /** @var array */
  47. 47:     private $sorting array();
  48. 48:  
  49. 49:     /** @var array */
  50. 50:     private $conds array();
  51. 51:  
  52. 52:     /** @var int */
  53. 53:     private $offset;
  54. 54:  
  55. 55:     /** @var int */
  56. 56:     private $limit;
  57. 57:  
  58. 58:  
  59. 59:  
  60. 60:     /**
  61. 61:      * @param  string  SQL command or table or view name, as data source
  62. 62:      * @param  DibiConnection  connection
  63. 63:      */
  64. 64:     public function __construct($sqlDibiConnection $connection)
  65. 65:     {
  66. 66:         if (strpbrk($sql" \t\r\n"=== FALSE{
  67. 67:             $this->sql $connection->getDriver()->escape($sqldibi::IDENTIFIER)// table name
  68. 68:         else {
  69. 69:             $this->sql '(' $sql ') t'// SQL command
  70. 70:         }
  71. 71:         $this->connection $connection;
  72. 72:     }
  73. 73:  
  74. 74:  
  75. 75:  
  76. 76:     /**
  77. 77:      * Selects columns to query.
  78. 78:      * @param  string|array column name or array of column names
  79. 79:      * @param  string           column alias
  80. 80:      * @return DibiDataSource  provides a fluent interface
  81. 81:      */
  82. 82:     public function select($col$as NULL)
  83. 83:     {
  84. 84:         if (is_array($col)) {
  85. 85:             $this->cols $col;
  86. 86:         else {
  87. 87:             $this->cols[$col$as;
  88. 88:         }
  89. 89:         $this->result NULL;
  90. 90:         return $this;
  91. 91:     }
  92. 92:  
  93. 93:  
  94. 94:  
  95. 95:     /**
  96. 96:      * Adds conditions to query.
  97. 97:      * @param  mixed  conditions
  98. 98:      * @return DibiDataSource  provides a fluent interface
  99. 99:      */
  100. 100:     public function where($cond)
  101. 101:     {
  102. 102:         if (is_array($cond)) {
  103. 103:             // TODO: not consistent with select and orderBy
  104. 104:             $this->conds[$cond;
  105. 105:         else {
  106. 106:             $this->conds[func_get_args();
  107. 107:         }
  108. 108:         $this->result $this->count NULL;
  109. 109:         return $this;
  110. 110:     }
  111. 111:  
  112. 112:  
  113. 113:  
  114. 114:     /**
  115. 115:      * Selects columns to order by.
  116. 116:      * @param  string|array column name or array of column names
  117. 117:      * @param  string           sorting direction
  118. 118:      * @return DibiDataSource  provides a fluent interface
  119. 119:      */
  120. 120:     public function orderBy($row$sorting 'ASC')
  121. 121:     {
  122. 122:         if (is_array($row)) {
  123. 123:             $this->sorting $row;
  124. 124:         else {
  125. 125:             $this->sorting[$row$sorting;
  126. 126:         }
  127. 127:         $this->result NULL;
  128. 128:         return $this;
  129. 129:     }
  130. 130:  
  131. 131:  
  132. 132:  
  133. 133:     /**
  134. 134:      * Limits number of rows.
  135. 135:      * @param  int limit
  136. 136:      * @param  int offset
  137. 137:      * @return DibiDataSource  provides a fluent interface
  138. 138:      */
  139. 139:     public function applyLimit($limit$offset NULL)
  140. 140:     {
  141. 141:         $this->limit $limit;
  142. 142:         $this->offset $offset;
  143. 143:         $this->result $this->count NULL;
  144. 144:         return $this;
  145. 145:     }
  146. 146:  
  147. 147:  
  148. 148:  
  149. 149:     /**
  150. 150:      * Returns the dibi connection.
  151. 151:      * @return DibiConnection 
  152. 152:      */
  153. 153:     final public function getConnection()
  154. 154:     {
  155. 155:         return $this->connection;
  156. 156:     }
  157. 157:  
  158. 158:  
  159. 159:  
  160. 160:     /********************* executing ****************d*g**/
  161. 161:  
  162. 162:  
  163. 163:  
  164. 164:     /**
  165. 165:      * Returns (and queries) DibiResult.
  166. 166:      * @return DibiResult 
  167. 167:      */
  168. 168:     public function getResult()
  169. 169:     {
  170. 170:         if ($this->result === NULL{
  171. 171:             $this->result $this->connection->nativeQuery($this->__toString());
  172. 172:         }
  173. 173:         return $this->result;
  174. 174:     }
  175. 175:  
  176. 176:  
  177. 177:  
  178. 178:     /**
  179. 179:      * @return DibiResultIterator 
  180. 180:      */
  181. 181:     public function getIterator()
  182. 182:     {
  183. 183:         return $this->getResult()->getIterator();
  184. 184:     }
  185. 185:  
  186. 186:  
  187. 187:  
  188. 188:     /**
  189. 189:      * Generates, executes SQL query and fetches the single row.
  190. 190:      * @return DibiRow|FALSE array on success, FALSE if no next record
  191. 191:      */
  192. 192:     public function fetch()
  193. 193:     {
  194. 194:         return $this->getResult()->fetch();
  195. 195:     }
  196. 196:  
  197. 197:  
  198. 198:  
  199. 199:     /**
  200. 200:      * Like fetch(), but returns only first field.
  201. 201:      * @return mixed  value on success, FALSE if no next record
  202. 202:      */
  203. 203:     public function fetchSingle()
  204. 204:     {
  205. 205:         return $this->getResult()->fetchSingle();
  206. 206:     }
  207. 207:  
  208. 208:  
  209. 209:  
  210. 210:     /**
  211. 211:      * Fetches all records from table.
  212. 212:      * @return array 
  213. 213:      */
  214. 214:     public function fetchAll()
  215. 215:     {
  216. 216:         return $this->getResult()->fetchAll();
  217. 217:     }
  218. 218:  
  219. 219:  
  220. 220:  
  221. 221:     /**
  222. 222:      * Fetches all records from table and returns associative tree.
  223. 223:      * @param  string  associative descriptor
  224. 224:      * @return array 
  225. 225:      */
  226. 226:     public function fetchAssoc($assoc)
  227. 227:     {
  228. 228:         return $this->getResult()->fetchAssoc($assoc);
  229. 229:     }
  230. 230:  
  231. 231:  
  232. 232:  
  233. 233:     /**
  234. 234:      * Fetches all records from table like $key => $value pairs.
  235. 235:      * @param  string  associative key
  236. 236:      * @param  string  value
  237. 237:      * @return array 
  238. 238:      */
  239. 239:     public function fetchPairs($key NULL$value NULL)
  240. 240:     {
  241. 241:         return $this->getResult()->fetchPairs($key$value);
  242. 242:     }
  243. 243:  
  244. 244:  
  245. 245:  
  246. 246:     /**
  247. 247:      * Discards the internal cache.
  248. 248:      * @return void 
  249. 249:      */
  250. 250:     public function release()
  251. 251:     {
  252. 252:         $this->result $this->count $this->totalCount NULL;
  253. 253:     }
  254. 254:  
  255. 255:  
  256. 256:  
  257. 257:     /********************* exporting ****************d*g**/
  258. 258:  
  259. 259:  
  260. 260:  
  261. 261:     /**
  262. 262:      * Returns this data source wrapped in DibiFluent object.
  263. 263:      * @return DibiFluent 
  264. 264:      */
  265. 265:     public function toFluent()
  266. 266:     {
  267. 267:         return $this->connection->select('*')->from('(%SQL) AS t'$this->__toString());
  268. 268:     }
  269. 269:  
  270. 270:  
  271. 271:  
  272. 272:     /**
  273. 273:      * Returns this data source wrapped in DibiDataSource object.
  274. 274:      * @return DibiDataSource 
  275. 275:      */
  276. 276:     public function toDataSource()
  277. 277:     {
  278. 278:         return new self($this->__toString()$this->connection);
  279. 279:     }
  280. 280:  
  281. 281:  
  282. 282:  
  283. 283:     /**
  284. 284:      * Returns SQL query.
  285. 285:      * @return string 
  286. 286:      */
  287. 287:     public function __toString()
  288. 288:     {
  289. 289:         return $this->connection->translate('
  290. 290:             SELECT %n'(empty($this->cols'*' $this->cols)'
  291. 291:             FROM %SQL'$this->sql'
  292. 292:             %ex'$this->conds array('WHERE %and'$this->condsNULL'
  293. 293:             %ex'$this->sorting array('ORDER BY %by'$this->sortingNULL'
  294. 294:             %ofs %lmt'$this->offset$this->limit
  295. 295:         );
  296. 296:     }
  297. 297:  
  298. 298:  
  299. 299:  
  300. 300:     /********************* counting ****************d*g**/
  301. 301:  
  302. 302:  
  303. 303:  
  304. 304:     /**
  305. 305:      * Returns the number of rows in a given data source.
  306. 306:      * @return int 
  307. 307:      */
  308. 308:     public function count()
  309. 309:     {
  310. 310:         if ($this->count === NULL{
  311. 311:             $this->count $this->conds || $this->offset || $this->limit
  312. 312:                 ? (int) $this->connection->nativeQuery(
  313. 313:                     'SELECT COUNT(*) FROM (' $this->__toString(') AS t'
  314. 314:                 )->fetchSingle()
  315. 315:                 : $this->getTotalCount();
  316. 316:         }
  317. 317:         return $this->count;
  318. 318:     }
  319. 319:  
  320. 320:  
  321. 321:  
  322. 322:     /**
  323. 323:      * Returns the number of rows in a given data source.
  324. 324:      * @return int 
  325. 325:      */
  326. 326:     public function getTotalCount()
  327. 327:     {
  328. 328:         if ($this->totalCount === NULL{
  329. 329:             $this->totalCount = (int) $this->connection->nativeQuery(
  330. 330:                 'SELECT COUNT(*) FROM ' $this->sql
  331. 331:             )->fetchSingle();
  332. 332:         }
  333. 333:         return $this->totalCount;
  334. 334:     }
  335. 335: