1: <?php
2:
3: namespace zsql;
4:
5: /**
6: * Select query generator
7: */
8: class Select extends ExtendedQuery
9: {
10: /**
11: * Columns clause
12: *
13: * @var mixed
14: */
15: protected $columns;
16:
17: /**
18: * Distinct clause
19: *
20: * @var boolean
21: */
22: protected $distinct;
23:
24: /**
25: * Index hint clause (column)
26: *
27: * @var string
28: */
29: protected $hint;
30:
31: /**
32: * Index hint clause (mode)
33: *
34: * @var string
35: */
36: protected $hintMode;
37:
38: /**
39: * The result class
40: *
41: * @var string
42: */
43: protected $resultClass;
44:
45: /**
46: * Set the columns
47: *
48: * @param mixed $columns
49: * @return \zsql\Select
50: * @throws \zsql\Exception
51: */
52: public function columns($columns)
53: {
54: if( is_array($columns) ||
55: is_string($columns) ||
56: $columns instanceof Expression ) {
57: $this->columns = $columns;
58: } else {
59: throw new \zsql\Exception('Invalid columns parameter');
60: }
61: return $this;
62: }
63:
64: /**
65: * Set distinct clause
66: *
67: * @param type $distinct
68: * @return \zsql\Select
69: */
70: public function distinct($distinct = true)
71: {
72: $this->distinct = (bool) $distinct;
73: return $this;
74: }
75:
76: /**
77: * Alias for {@link Query::table()} and {@link Select::columns()}
78: *
79: * @param mixed $table
80: * @param mixed $columns
81: * @return \zsql\Select
82: */
83: public function from($table, $columns = null)
84: {
85: $this->table($table);
86: if( !empty($columns) ) {
87: $this->columns($columns);
88: }
89: return $this;
90: }
91:
92: /**
93: * Hint at index to use
94: *
95: * @param mixed $columns
96: * @param string $mode
97: * @return \zsql\Select
98: */
99: public function hint($columns, $mode = null)
100: {
101: $this->hint = $columns;
102: $this->hintMode = $mode;
103: return $this;
104: }
105:
106: /**
107: * Alias for {@link Select::columns()}
108: *
109: * @param mixed $columns
110: * @return \zsql\Select
111: */
112: public function select($columns)
113: {
114: $this->columns($columns);
115: return $this;
116: }
117:
118: /**
119: * Get the result class
120: *
121: * @return string
122: */
123: public function getResultClass()
124: {
125: return $this->resultClass;
126: }
127:
128: /**
129: * Set result class
130: *
131: * @param string $class
132: * @return \zsql\Select
133: */
134: public function setResultClass($class)
135: {
136: $this->resultClass = $class;
137: return $this;
138: }
139:
140: /**
141: * Execute a query
142: *
143: * @return \zsql\Result
144: */
145: public function query()
146: {
147: $result = parent::query();
148: if( $this->resultClass ) {
149: $result->setResultClass($this->getResultClass());
150: }
151: return $result;
152: }
153:
154: /**
155: * Assemble parts
156: *
157: * @return void
158: */
159: protected function assemble()
160: {
161: $this->push('SELECT')
162: ->pushDistinct()
163: ->pushColumns()
164: ->push('FROM')
165: ->pushTable()
166: ->pushHint()
167: ->pushWhere()
168: ->pushGroup()
169: ->pushOrder()
170: ->pushLimit();
171: }
172:
173: /**
174: * Push columns onto parts
175: *
176: * @return \zsql\Select
177: */
178: protected function pushColumns()
179: {
180: if( !$this->columns || $this->columns == '*' ) {
181: $this->parts[] = '*';
182: } else if( is_array($this->columns) ) {
183: $cols = array();
184: foreach( $this->columns as $col ) {
185: $cols[] = $this->quoteIdentifierIfNotExpression($col);
186: }
187: $this->parts[] = join(', ', $cols);
188: } else if( is_string($this->columns) ) {
189: $this->parts[] = $this->quoteIdentifierIfNotExpression($this->columns);
190: } else if( $this->columns instanceof Expression ) {
191: $this->parts[] = (string) $this->columns;
192: }
193: return $this;
194: }
195:
196: /**
197: * Push distinct onto parts
198: *
199: * @return \zsql\Select
200: */
201: protected function pushDistinct()
202: {
203: if( $this->distinct ) {
204: $this->parts[] = 'DISTINCT';
205: }
206: return $this;
207: }
208:
209: /**
210: * Push hint onto parts
211: *
212: * @return \zsql\Select
213: */
214: protected function pushHint()
215: {
216: if( $this->hint ) {
217: $this->parts[] = $this->hintMode ?: 'USE';
218: $this->parts[] = 'INDEX';
219: if( is_array($this->hint) ) {
220: $this->parts[] = '(' . join(', ', array_map(array($this, 'quoteIdentifierIfNotExpression'), $this->hint)) . ')';
221: } else {
222: $this->parts[] = '(' . $this->quoteIdentifierIfNotExpression($this->hint) . ')';
223: }
224: }
225: return $this;
226: }
227: }
228: