Passed
Push — 1.0.0-dev ( 4efac2...b68981 )
by nguereza
02:49
created

DatabaseQueryRunner::setQueryResult()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 1
eloc 2
c 1
b 1
f 1
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
    defined('ROOT_PATH') || exit('Access denied');
3
  /**
4
   * TNH Framework
5
   *
6
   * A simple PHP framework using HMVC architecture
7
   *
8
   * This content is released under the GNU GPL License (GPL)
9
   *
10
   * Copyright (C) 2017 Tony NGUEREZA
11
   *
12
   * This program is free software; you can redistribute it and/or
13
   * modify it under the terms of the GNU General Public License
14
   * as published by the Free Software Foundation; either version 3
15
   * of the License, or (at your option) any later version.
16
   *
17
   * This program is distributed in the hope that it will be useful,
18
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
   * GNU General Public License for more details.
21
   *
22
   * You should have received a copy of the GNU General Public License
23
   * along with this program; if not, write to the Free Software
24
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25
  */
26
  class DatabaseQueryRunner{
27
      
28
    /**
29
	* The logger instance
30
	* @var object
31
	*/
32
    private $logger            = null;
33
    
34
  	/**
35
  	 * The last query result
36
  	 * @var object
37
  	*/
38
  	private $queryResult       = null;
39
  	
40
  	/**
41
    * The benchmark instance
42
    * @var object
43
    */
44
    private $benchmarkInstance = null;
45
    
46
    /**
47
	 * The SQL query statment to execute
48
	 * @var string
49
	*/
50
    private $query             = null;
51
    
52
    /**
53
	 * Indicate if we need return result as list (boolean) 
54
     * or the data used to replace the placeholder (array)
55
	 * @var array|boolean
56
	 */
57
     private $all               = true;
0 ignored issues
show
introduced by
The private property $all is not used, and could be removed.
Loading history...
58
     
59
     
60
     /**
61
	   * Indicate if we need return result as array or not
62
     * @var boolean
63
	   */
64
     private $returnAsArray     = true;
65
     
66
     /**
67
     * The last PDOStatment instance
68
     * @var object
69
     */
70
     private $pdoStatment       = null;
71
     
72
     /**
73
  	 * The error returned for the last query
74
  	 * @var string
75
  	 */
76
     private $error             = null;
77
	
78
    /**
79
     * The PDO instance
80
     * @var object
81
    */
82
    private $pdo                = null;
83
  
84
    /**
85
     * The database driver name used
86
     * @var string
87
    */
88
    private $driver             = null;
89
90
91
	
92
    /**
93
     * Construct new DatabaseQueryRunner
94
     * @param object $pdo the PDO object
95
     * @param string $query the SQL query to be executed
96
     * @param boolean $returnAsList if need return as list or just one row
97
     * @param boolean $returnAsArray whether to return the result as array or not
98
     */
99
    public function __construct(PDO $pdo = null, $query = null, $returnAsList = true, $returnAsArray = false){
100
        if (is_object($pdo)){
101
          $this->pdo = $pdo;
102
        }
103
        $this->query = $query;
104
        $this->returnAsList = $returnAsList;
0 ignored issues
show
Bug Best Practice introduced by
The property returnAsList does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
105
        $this->returnAsArray = $returnAsArray;
106
        $this->setLoggerFromParamOrCreateNewInstance(null);
107
    }
108
    
109
    /**
110
     * Run the database SQL query and return the DatabaseQueryResult object
111
     * @see Database::query
112
     * 
113
     * @return object|void
114
     */
115
    public function execute(){
116
        //reset instance
117
        $this->reset();
118
       
119
       //for database query execution time
120
        $benchmarkMarkerKey = $this->getBenchmarkKey();
121
        if (! is_object($this->benchmarkInstance)){
122
          $this->benchmarkInstance = & class_loader('Benchmark');
123
        }
124
        
125
        $this->logger->info(
126
                          'Execute SQL query [' . $this->query . '], return type: ' 
127
                          . ($this->returnAsArray ? 'ARRAY' : 'OBJECT') .', return as list: ' 
128
                          . ($this->returnAsList ? 'YES':'NO')
129
                        );
130
131
        $this->benchmarkInstance->mark('DATABASE_QUERY_START(' . $benchmarkMarkerKey . ')');                
132
        //Now execute the query
133
        $this->pdoStatment = $this->pdo->query($this->query);
134
        
135
        //get response time for this query
136
        $responseTime = $this->benchmarkInstance->elapsedTime(
137
                                                                'DATABASE_QUERY_START(' . $benchmarkMarkerKey . ')', 
138
                                                                'DATABASE_QUERY_END(' . $benchmarkMarkerKey . ')'
139
                                                              );
140
		    //TODO use the configuration value for the high response time currently is 1 second
141
        if ($responseTime >= 1 ){
142
            $this->logger->warning(
143
                                    'High response time while processing database query [' . $this->query . ']. 
144
                                     The response time is [' .$responseTime. '] sec.'
145
                                  );
146
        }
147
		
148
        if ($this->pdoStatment !== false){
149
          $isSqlSELECTQuery = stristr($this->query, 'SELECT') !== false;
150
          if($isSqlSELECTQuery){
151
              $this->setResultForSelect();              
152
          }
153
          else{
154
              $this->setResultForNonSelect();
155
          }
156
          return $this->queryResult;
157
        }
158
        $this->setQueryRunnerError();
159
    }
160
	
161
   /**
162
   * Return the result for SELECT query
163
   * @see DatabaseQueryRunner::execute
164
   */
165
    protected function setResultForSelect(){
166
      //if need return all result like list of record
167
      $result = null;
168
      $numRows = 0;
169
      $fetchMode = PDO::FETCH_OBJ;
170
      if($this->returnAsArray){
171
        $fetchMode = PDO::FETCH_ASSOC;
172
      }
173
      if ($this->returnAsList){
174
          $result = $this->pdoStatment->fetchAll($fetchMode);
175
      }
176
      else{
177
          $result = $this->pdoStatment->fetch($fetchMode);
178
      }
179
      //Sqlite and pgsql always return 0 when using rowCount()
180
      if (in_array($this->driver, array('sqlite', 'pgsql'))){
181
        $numRows = count($result);  
182
      }
183
      else{
184
        $numRows = $this->pdoStatment->rowCount(); 
185
      }
186
      if(! is_object($this->queryResult)){
187
          $this->queryResult = & class_loader('DatabaseQueryResult', 'classes/database');
188
      }
189
      $this->queryResult->setResult($result);
190
      $this->queryResult->setNumRows($numRows);
191
    }
192
193
    /**
194
   * Return the result for non SELECT query
195
   * @see DatabaseQueryRunner::execute
196
   */
197
    protected function setResultForNonSelect(){
198
      //Sqlite and pgsql always return 0 when using rowCount()
199
      $result = false;
200
      $numRows = 0;
201
      if (in_array($this->driver, array('sqlite', 'pgsql'))){
202
        $result = true; //to test the result for the query like UPDATE, INSERT, DELETE
203
        $numRows = 1; //TODO use the correct method to get the exact affected row
204
      }
205
      else{
206
          //to test the result for the query like UPDATE, INSERT, DELETE
207
          $result  = $this->pdoStatment->rowCount() >= 0; 
208
          $numRows = $this->pdoStatment->rowCount(); 
209
      }
210
      if(! is_object($this->queryResult)){
211
          $this->queryResult = & class_loader('DatabaseQueryResult', 'classes/database');
212
      }
213
      $this->queryResult->setResult($result);
214
      $this->queryResult->setNumRows($numRows);
215
    }
216
217
218
	/**
219
     * Return the benchmark instance
220
     * @return Benchmark
221
     */
222
    public function getBenchmark(){
223
      return $this->benchmarkInstance;
224
    }
225
226
    /**
227
     * Set the benchmark instance
228
     * @param Benchmark $benchmark the benchmark object
229
	 * @return object DatabaseQueryRunner
230
     */
231
    public function setBenchmark($benchmark){
232
      $this->benchmarkInstance = $benchmark;
233
      return $this;
234
    }
235
    
236
    /**
237
     * Return the database query result
238
     *
239
     * @return object DatabaseQueryResult
240
     */
241
    public function getQueryResult(){
242
      return $this->queryResult;
243
    }
244
245
    /**
246
     * Set the database query result instance
247
     * @param object $queryResult the query result
248
     *
249
	 * @return object DatabaseQueryRunner
250
     */
251
    public function setQueryResult(DatabaseQueryResult $queryResult){
252
      $this->queryResult = $queryResult;
253
      return $this;
254
    }
255
    
256
    /**
257
     * Return the Log instance
258
     * @return Log
259
     */
260
    public function getLogger(){
261
      return $this->logger;
262
    }
263
264
    /**
265
     * Set the log instance
266
     * @param Log $logger the log object
267
	 * @return object DatabaseQueryRunner
268
     */
269
    public function setLogger($logger){
270
      $this->logger = $logger;
271
      return $this;
272
    }
273
    
274
    /**
275
     * Return the current query SQL string
276
     * @return string
277
     */
278
    public function getQuery(){
279
      return $this->query;
280
    }
281
    
282
    /**
283
     * Set the query SQL string
284
     * @param string $query the SQL query to set
285
     * @return object DatabaseQueryRunner
286
     */
287
    public function setQuery($query){
288
       $this->query = $query;
289
       return $this;
290
    }
291
    
292
    /**
293
     * Set the query return type as list or not
294
     * @param boolean $returnType
295
     * @return object DatabaseQueryRunner
296
     */
297
    public function setReturnType($returnType){
298
       $this->returnAsList = $returnType;
0 ignored issues
show
Bug Best Practice introduced by
The property returnAsList does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
299
       return $this;
300
    }
301
    
302
    /**
303
     * Set the return as array or not
304
     * @param boolean $status the status if true will return as array
305
     * @return object DatabaseQueryRunner
306
     */
307
    public function setReturnAsArray($status = true){
308
       $this->returnAsArray = $status;
309
       return $this;
310
    }
311
    
312
    /**
313
     * Return the error for last query execution
314
     * @return string
315
     */
316
    public function getQueryError(){
317
      return $this->error;
318
    }
319
320
    /**
321
     * Return the PDO instance
322
     * @return object
323
     */
324
    public function getPdo(){
325
      return $this->pdo;
326
    }
327
328
    /**
329
     * Set the PDO instance
330
     * @param PDO $pdo the pdo object
331
     * @return object DatabaseQueryRunner
332
     */
333
    public function setPdo(PDO $pdo = null){
334
      $this->pdo = $pdo;
335
      return $this;
336
    }
337
  
338
     /**
339
     * Return the database driver
340
     * @return string
341
     */
342
    public function getDriver(){
343
      return $this->driver;
344
    }
345
346
    /**
347
     * Set the database driver
348
     * @param string $driver the new driver
349
     * @return object DatabaseQueryRunner
350
     */
351
    public function setDriver($driver){
352
      $this->driver = $driver;
353
      return $this;
354
    }
355
    
356
    /**
357
     * Return the benchmark key for the current query
358
     * 
359
     *  @return string
360
     */
361
    protected function getBenchmarkKey(){
362
      return md5($this->query . $this->returnAsList . $this->returnAsArray);
363
    }
364
    
365
    /**
366
     * Set error for database query execution
367
     */
368
    protected function setQueryRunnerError(){
369
      $error = $this->pdo->errorInfo();
370
      $this->error = isset($error[2]) ? $error[2] : '';
371
      $this->logger->error('The database query execution got an error: ' . stringfy_vars($error));
372
	  //show error message
373
      show_error('Query: "' . $this->query . '" Error: ' . $this->error, 'Database Error');
374
    }
375
    
376
    /**
377
     * Set the Log instance using argument or create new instance
378
     * @param object $logger the Log instance if not null
379
     */
380
    protected function setLoggerFromParamOrCreateNewInstance(Log $logger = null){
381
      if ($logger !== null){
382
        $this->logger = $logger;
383
      }
384
      else{
385
          $this->logger =& class_loader('Log', 'classes');
386
          $this->logger->setLogger('Library::DatabaseQueryRunner');
387
      }
388
    }
389
    
390
    
391
    /**
392
    * Reset the instance before run each query
393
    */
394
    private function reset(){
395
        $this->error = null;
396
        $this->pdoStatment = null;
397
    }
398
399
}
400