Passed
Push — 1.0.0-dev ( 46666d...4e6922 )
by nguereza
02:47
created

DatabaseQueryRunner::getDriver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 1
eloc 1
c 1
b 1
f 1
nc 1
nop 0
dl 0
loc 2
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 extends BaseClass {
27
        /**
28
         * The last query result
29
         * @var object
30
         */
31
        protected $queryResult = null;
32
  	
33
        /**
34
         * The benchmark instance
35
         * @var object
36
         */
37
        protected $benchmarkInstance = null;
38
        
39
        /**
40
         * The SQL query statment to execute
41
         * @var string
42
         */
43
        private $query = null;
44
    
45
        /**
46
         * Indicate if we need return result as list
47
         * @var boolean
48
         */
49
        private $returnAsList = true;
50
     
51
     
52
        /**
53
         * Indicate if we need return result as array or not
54
         * @var boolean
55
         */
56
        private $returnAsArray = true;
57
     
58
        /**
59
         * The last PDOStatment instance
60
         * @var object
61
         */
62
        private $pdoStatment = null;
63
     
64
        /**
65
         * The error returned for the last query
66
         * @var string
67
         */
68
        private $error = null;
69
	
70
        /**
71
         * The PDO instance
72
         * @var object
73
         */
74
        private $pdo = null;
75
      
76
        /**
77
         * The database driver name used
78
         * @var string
79
         */
80
        private $driver = null;
81
82
83
	
84
        /**
85
         * Construct new DatabaseQueryRunner
86
         * @param object $pdo the PDO object
87
         * @param string $query the SQL query to be executed
88
         * @param boolean $returnAsList if need return as list or just one row
89
         * @param boolean $returnAsArray whether to return the result as array or not
90
         */
91
        public function __construct(PDO $pdo = null, $query = null, $returnAsList = true, $returnAsArray = false) {
92
            parent::__construct();
93
            if (is_object($pdo)) {
94
                $this->pdo = $pdo;
95
            }
96
97
            //Set DatabaseQueryResult instance to use
98
            $this->setDependencyInstanceFromParamOrCreate('queryResult', null, 'DatabaseQueryResult', 'classes/database');
99
             
100
            //Set Benchmark instance to use
101
            $this->setDependencyInstanceFromParamOrCreate('benchmarkInstance', null, 'Benchmark', 'libraries');
102
       
103
104
            $this->query         = $query;
105
            $this->returnAsList  = $returnAsList;
106
            $this->returnAsArray = $returnAsArray;
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
            
122
            $this->benchmarkInstance->mark('DATABASE_QUERY_START(' . $benchmarkMarkerKey . ')');                
123
            //Now execute the query
124
            $this->pdoStatment = $this->pdo->query($this->query);
125
            
126
            //get response time for this query
127
            $responseTime = $this->benchmarkInstance->elapsedTime(
128
                                                                    'DATABASE_QUERY_START(' . $benchmarkMarkerKey . ')', 
129
                                                                    'DATABASE_QUERY_END(' . $benchmarkMarkerKey . ')'
130
                                                                    );
131
                //TODO use the configuration value for the high response time currently is 1 second
132
            if ($responseTime >= 1) {
133
                $this->logger->warning(
134
                                        'High response time while processing database query [' . $this->query . ']. 
135
                                         The response time is [' .$responseTime . '] sec.'
136
                                        );
137
            }
138
    		
139
            if ($this->pdoStatment !== false) {
140
                $isSqlSELECTQuery = stristr($this->query, 'SELECT') !== false;
141
                if ($isSqlSELECTQuery) {
142
                    $this->setResultForSelect();              
143
                } else {
144
                    $this->setResultForNonSelect();
145
                }
146
                return $this->queryResult;
147
            }
148
            $this->setQueryRunnerError();
149
        }
150
    	
151
        /**
152
         * Return the result for SELECT query
153
         * @see DatabaseQueryRunner::execute
154
         */
155
        protected function setResultForSelect() {
156
            //if need return all result like list of record
157
            $result = null;
158
            $numRows = 0;
159
            $fetchMode = PDO::FETCH_OBJ;
160
            if ($this->returnAsArray) {
161
                $fetchMode = PDO::FETCH_ASSOC;
162
            }
163
            if ($this->returnAsList) {
164
                $result = $this->pdoStatment->fetchAll($fetchMode);
165
            } else {
166
                $result = $this->pdoStatment->fetch($fetchMode);
167
            }
168
            //Sqlite and pgsql always return 0 when using rowCount()
169
            if (in_array($this->driver, array('sqlite', 'pgsql'))) {
170
                //by default count() return 1 if the parameter is not an array
171
                //object or object implements Countable.
172
                if (is_array($result) || is_object($result) || $result instanceof Countable) {
173
                     $numRows = count($result);  
174
                }
175
            } else {
176
                $numRows = $this->pdoStatment->rowCount(); 
177
            }
178
            $this->queryResult->setResult($result);
179
            $this->queryResult->setNumRows($numRows);
180
        }
181
182
        /**
183
         * Return the result for non SELECT query
184
         * @see DatabaseQueryRunner::execute
185
         */
186
        protected function setResultForNonSelect() {
187
            //Sqlite and pgsql always return 0 when using rowCount()
188
            $result = false;
189
            $numRows = 0;
190
            if (in_array($this->driver, array('sqlite', 'pgsql'))) {
191
            $result = true; //to test the result for the query like UPDATE, INSERT, DELETE
192
            $numRows = 1; //TODO use the correct method to get the exact affected row
193
            } else {
194
                //to test the result for the query like UPDATE, INSERT, DELETE
195
                $result  = $this->pdoStatment->rowCount() >= 0; 
196
                $numRows = $this->pdoStatment->rowCount(); 
197
            }
198
            $this->queryResult->setResult($result);
199
            $this->queryResult->setNumRows($numRows);
200
        }
201
202
203
        /**
204
         * Return the benchmark instance
205
         * @return Benchmark
206
         */
207
        public function getBenchmark() {
208
            return $this->benchmarkInstance;
209
        }
210
211
        /**
212
         * Set the benchmark instance
213
         * @param Benchmark $benchmark the benchmark object
214
         * @return object DatabaseQueryRunner
215
         */
216
        public function setBenchmark($benchmark) {
217
            $this->benchmarkInstance = $benchmark;
218
            return $this;
219
        }
220
        
221
        /**
222
         * Return the database query result
223
         *
224
         * @return object DatabaseQueryResult
225
         */
226
        public function getQueryResult() {
227
            return $this->queryResult;
228
        }
229
230
        /**
231
         * Set the database query result instance
232
         * @param object $queryResult the query result
233
         *
234
         * @return object DatabaseQueryRunner
235
         */
236
        public function setQueryResult(DatabaseQueryResult $queryResult) {
237
            $this->queryResult = $queryResult;
238
            return $this;
239
        }
240
        
241
        /**
242
         * Return the current query SQL string
243
         * @return string
244
         */
245
        public function getQuery() {
246
            return $this->query;
247
        }
248
        
249
        /**
250
         * Set the query SQL string
251
         * @param string $query the SQL query to set
252
         * @return object DatabaseQueryRunner
253
         */
254
        public function setQuery($query) {
255
            $this->query = $query;
256
            return $this;
257
        }
258
        
259
        /**
260
         * Set the query return type as list or not
261
         * @param boolean $returnType
262
         * @return object DatabaseQueryRunner
263
         */
264
        public function setReturnType($returnType) {
265
            $this->returnAsList = $returnType;
266
            return $this;
267
        }
268
        
269
        /**
270
         * Set the return as array or not
271
         * @param boolean $status the status if true will return as array
272
         * @return object DatabaseQueryRunner
273
         */
274
        public function setReturnAsArray($status = true) {
275
            $this->returnAsArray = $status;
276
            return $this;
277
        }
278
        
279
        /**
280
         * Return the error for last query execution
281
         * @return string
282
         */
283
        public function getQueryError() {
284
            return $this->error;
285
        }
286
287
        /**
288
         * Return the PDO instance
289
         * @return object
290
         */
291
        public function getPdo() {
292
            return $this->pdo;
293
        }
294
295
        /**
296
         * Set the PDO instance
297
         * @param PDO $pdo the pdo object
298
         * @return object DatabaseQueryRunner
299
         */
300
        public function setPdo(PDO $pdo = null) {
301
            $this->pdo = $pdo;
302
            return $this;
303
        }
304
      
305
            /**
306
             * Return the database driver
307
             * @return string
308
             */
309
        public function getDriver() {
310
            return $this->driver;
311
        }
312
313
        /**
314
         * Set the database driver
315
         * @param string $driver the new driver
316
         * @return object DatabaseQueryRunner
317
         */
318
        public function setDriver($driver) {
319
            $this->driver = $driver;
320
            return $this;
321
        }
322
        
323
        /**
324
         * Return the benchmark key for the current query
325
         * 
326
         *  @return string
327
         */
328
        protected function getBenchmarkKey() {
329
            return md5($this->query . $this->returnAsList . $this->returnAsArray);
330
        }
331
        
332
        /**
333
         * Set error for database query execution
334
         */
335
        protected function setQueryRunnerError() {
336
            $error = $this->pdo->errorInfo();
337
            $this->error = isset($error[2]) ? $error[2] : '';
338
            $this->logger->error('The database query execution got an error: ' . stringfy_vars($error));
339
            //show error message
340
            show_error('Query: "' . $this->query . '" Error: ' . $this->error, 'Database Error');
341
        }
342
        
343
        
344
        /**
345
         * Reset the instance before run each query
346
         */
347
        private function reset() {
348
            $this->error = null;
349
            $this->pdoStatment = null;
350
        }
351
352
    }
353