Passed
Push — develop ( bc851f...2fcb4c )
by Felipe
04:47
created

SqlController::execute_query()   C

Complexity

Conditions 9
Paths 7

Size

Total Lines 58
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 58
rs 6.9928
c 0
b 0
f 0
cc 9
eloc 36
nc 7
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.48
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
/**
10
 * Base controller class.
11
 *
12
 * @package PHPPgAdmin
13
 */
14
class SqlController extends BaseController
15
{
16
    public $query   = '';
17
    public $subject = '';
18
    public $start_time;
19
    public $duration;
20
    public $controller_title = 'strqueryresults';
21
22
    /**
23
     * Default method to render the controller according to the action parameter.
24
     */
25
    public function render()
26
    {
27
        $data = $this->misc->getDatabaseAccessor();
28
29
        set_time_limit(0);
30
31
        // We need to store the query in a session for editing purposes
32
        // We avoid GPC vars to avoid truncating long queries
33
        if (isset($_REQUEST['subject']) && 'history' == $_REQUEST['subject']) {
34
            // Or maybe we came from the history popup
35
            $_SESSION['sqlquery'] = $_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']][$_GET['queryid']]['query'];
36
            $this->query          = $_SESSION['sqlquery'];
37
        } elseif (isset($_POST['query'])) {
38
            // Or maybe we came from an sql form
39
            $_SESSION['sqlquery'] = $_POST['query'];
40
            $this->query          = $_SESSION['sqlquery'];
41
        } else {
42
            echo 'could not find the query!!';
43
        }
44
45
        // Pagination maybe set by a get link that has it as FALSE,
46
        // if that's the case, unset the variable.
47
        if (isset($_REQUEST['paginate']) && 'f' == $_REQUEST['paginate']) {
48
            unset($_REQUEST['paginate'], $_POST['paginate'], $_GET['paginate']);
49
        }
50
51
        if (isset($_REQUEST['subject'])) {
52
            $this->subject = $_REQUEST['subject'];
53
        }
54
55
        // Check to see if pagination has been specified. In that case, send to display
56
        // script for pagination
57
        // if a file is given or the request is an explain, do not paginate
58
        if (isset($_REQUEST['paginate']) &&
59
            !(isset($_FILES['script']) && $_FILES['script']['size'] > 0) &&
60
            (0 == preg_match('/^\s*explain/i', $this->query))) {
61
            //if (!(isset($_FILES['script']) && $_FILES['script']['size'] > 0)) {
62
63
            $display_controller = new DisplayController($this->getContainer());
64
65
            return $display_controller->render();
66
        }
67
68
        $this->printHeader($this->headerTitle(), null, true, 'header_sqledit.twig');
69
        $this->printBody();
70
        $this->printTrail('database');
71
        $this->printTitle($this->lang['strqueryresults']);
72
73
        // Set the schema search path
74
        if (isset($_REQUEST['search_path'])) {
75
            if (0 != $data->setSearchPath(array_map('trim', explode(',', $_REQUEST['search_path'])))) {
76
                return $this->printFooter();
77
            }
78
        }
79
80
        // May as well try to time the query
81
        if (function_exists('microtime')) {
82
            list($usec, $sec) = explode(' ', microtime());
83
            $this->start_time = ((float) $usec + (float) $sec);
84
        }
85
86
        $rs = $this->doDefault();
87
88
        $this->doFooter(true, 'footer_sqledit.twig', $rs);
89
    }
90
91
    public function doDefault()
92
    {
93
        $_connection = $this->misc->getConnection();
94
95
        try {
96
            // Execute the query.  If it's a script upload, special handling is necessary
97
            if (isset($_FILES['script']) && $_FILES['script']['size'] > 0) {
98
                return $this->execute_script();
99
            }
100
101
            return $this->execute_query();
102
        } catch (\PHPPgAdmin\ADOdbException $e) {
103
            $message   = $e->getMessage();
104
            $trace     = $e->getTraceAsString();
105
            $lastError = $_connection->getLastError();
106
            $this->prtrace(['message' => $message, 'trace' => $trace, 'lastError' => $lastError]);
107
108
            return null;
109
        }
110
    }
111
112
    private function execute_script()
113
    {
114
        $misc        = $this->misc;
115
        $data        = $this->misc->getDatabaseAccessor();
116
        $_connection = $this->misc->getConnection();
117
        $lang        = $this->lang;
118
        /**
119
         * This is a callback function to display the result of each separate query.
120
         *
121
         * @param ADORecordSet $rs The recordset returned by the script execetor
122
         */
123
        $sqlCallback = function ($query, $rs, $lineno) use ($data, $misc, $lang, $_connection) {
124
            // Check if $rs is false, if so then there was a fatal error
125
            if (false === $rs) {
126
                echo htmlspecialchars($_FILES['script']['name']), ':', $lineno, ': ', nl2br(htmlspecialchars($_connection->getLastError())), "<br/>\n";
127
            } else {
128
                // Print query results
129
                switch (pg_result_status($rs)) {
130
                    case \PGSQL_TUPLES_OK:
131
                        // If rows returned, then display the results
132
                        $num_fields = pg_numfields($rs);
133
                        echo "<p><table>\n<tr>";
134
                        for ($k = 0; $k < $num_fields; ++$k) {
135
                            echo '<th class="data">', $misc->printVal(pg_fieldname($rs, $k)), '</th>';
136
                        }
137
138
                        $i   = 0;
139
                        $row = pg_fetch_row($rs);
140
                        while (false !== $row) {
141
                            $id = (0 == ($i % 2) ? '1' : '2');
142
                            echo "<tr class=\"data{$id}\">\n";
143
                            foreach ($row as $k => $v) {
144
                                echo '<td style="white-space:nowrap;">', $misc->printVal($v, pg_fieldtype($rs, $k), ['null' => true]), '</td>';
145
                            }
146
                            echo "</tr>\n";
147
                            $row = pg_fetch_row($rs);
148
                            ++$i;
149
                        }
150
151
                        echo "</table><br/>\n";
152
                        echo $i, " {$lang['strrows']}</p>\n";
153
154
                        break;
155
                    case \PGSQL_COMMAND_OK:
156
                        // If we have the command completion tag
157
                        if (version_compare(PHP_VERSION, '4.3', '>=')) {
158
                            echo htmlspecialchars(pg_result_status($rs, PGSQL_STATUS_STRING)), "<br/>\n";
159
                        } elseif ($data->conn->Affected_Rows() > 0) {
160
                            // Otherwise if any rows have been affected
161
                            echo $data->conn->Affected_Rows(), " {$lang['strrowsaff']}<br/>\n";
162
                        }
163
                        // Otherwise output nothing...
164
                        break;
165
                    case \PGSQL_EMPTY_QUERY:
166
                        break;
167
                    default:
168
                        break;
169
                }
170
            }
171
        };
172
173
        return $data->executeScript('script', $sqlCallback);
174
    }
175
176
    private function execute_query()
177
    {
178
        $data = $this->misc->getDatabaseAccessor();
179
180
        // Set fetch mode to NUM so that duplicate field names are properly returned
181
        $data->conn->setFetchMode(\ADODB_FETCH_NUM);
182
        set_time_limit(25000);
183
184
        $rs = $data->conn->Execute($this->query);
185
186
        echo '<form method="post" id="sqlform" action="'.$_SERVER['REQUEST_URI'].'">';
187
        echo '<textarea width="90%" name="query"  id="query" rows="5" cols="100" resizable="true">';
188
189
        echo htmlspecialchars($this->query);
190
        echo '</textarea><br>';
191
        echo $this->misc->setForm();
192
        echo '<input type="submit"/></form>';
193
194
        // $rs will only be an object if there is no error
195
        if (is_object($rs)) {
196
            // Request was run, saving it in history
197
            if (!isset($_REQUEST['nohistory'])) {
198
                $this->misc->saveScriptHistory($this->query);
199
            }
200
201
            // Now, depending on what happened do various things
202
203
            // First, if rows returned, then display the results
204
            if ($rs->recordCount() > 0) {
205
                echo "<table>\n<tr>";
206
                foreach ($rs->fields as $k => $v) {
207
                    $finfo = $rs->fetchField($k);
208
                    echo '<th class="data">', $this->misc->printVal($finfo->name), '</th>';
209
                }
210
                echo "</tr>\n";
211
                $i = 0;
212
                while (!$rs->EOF) {
213
                    $id = (0 == ($i % 2) ? '1' : '2');
214
                    echo "<tr class=\"data{$id}\">\n";
215
                    foreach ($rs->fields as $k => $v) {
216
                        $finfo = $rs->fetchField($k);
217
                        echo '<td style="white-space:nowrap;">', $this->misc->printVal($v, $finfo->type, ['null' => true]), '</td>';
218
                    }
219
                    echo "</tr>\n";
220
                    $rs->moveNext();
221
                    ++$i;
222
                }
223
                echo "</table>\n";
224
                echo '<p>', $rs->recordCount(), " {$this->lang['strrows']}</p>\n";
225
            } elseif ($data->conn->Affected_Rows() > 0) {
226
                // Otherwise if any rows have been affected
227
                echo '<p>', $data->conn->Affected_Rows(), " {$this->lang['strrowsaff']}</p>\n";
228
            } else {
229
                // Otherwise nodata to print
230
                echo '<p>', $this->lang['strnodata'], "</p>\n";
231
            }
232
233
            return $rs;
234
        }
235
    }
236
237
    private function doFooter($doBody = true, $template = 'footer.twig', $rs = null)
238
    {
239
        $data = $this->misc->getDatabaseAccessor();
240
241
        // May as well try to time the query
242
        if (null !== $this->start_time) {
243
            list($usec, $sec) = explode(' ', microtime());
244
            $end_time         = ((float) $usec + (float) $sec);
245
            // Get duration in milliseconds, round to 3dp's
246
            $this->duration = number_format(($end_time - $this->start_time) * 1000, 3);
247
        }
248
249
        // Reload the browser as we may have made schema changes
250
        $this->misc->setReloadBrowser(true);
251
252
        // Display duration if we know it
253
        if (null !== $this->duration) {
254
            echo '<p>', sprintf($this->lang['strruntime'], $this->duration), "</p>\n";
255
        }
256
257
        echo "<p>{$this->lang['strsqlexecuted']}</p>\n";
258
259
        $navlinks = [];
260
        $fields   = [
261
            'server'   => $_REQUEST['server'],
262
            'database' => $_REQUEST['database'],
263
        ];
264
265
        if (isset($_REQUEST['schema'])) {
266
            $fields['schema'] = $_REQUEST['schema'];
267
        }
268
269
        // Return
270
        if (isset($_REQUEST['return'])) {
271
            $urlvars          = $this->misc->getSubjectParams($_REQUEST['return']);
272
            $navlinks['back'] = [
273
                'attr'    => [
274
                    'href' => [
275
                        'url'     => $urlvars['url'],
276
                        'urlvars' => $urlvars['params'],
277
                    ],
278
                ],
279
                'content' => $this->lang['strback'],
280
            ];
281
        }
282
283
        // Edit
284
        $navlinks['alter'] = [
285
            'attr'    => [
286
                'href' => [
287
                    'url'     => 'database',
288
                    'urlvars' => array_merge($fields, [
289
                        'action' => 'sql',
290
                    ]),
291
                ],
292
            ],
293
            'content' => $this->lang['streditsql'],
294
        ];
295
296
        // Create view and download
297
        if ('' !== $this->query && isset($rs) && is_object($rs) && $rs->recordCount() > 0) {
298
            // Report views don't set a schema, so we need to disable create view in that case
299
            if (isset($_REQUEST['schema'])) {
300
                $navlinks['createview'] = [
301
                    'attr'    => [
302
                        'href' => [
303
                            'url'     => 'views',
304
                            'urlvars' => array_merge($fields, [
305
                                'action' => 'create',
306
                            ]),
307
                        ],
308
                    ],
309
                    'content' => $this->lang['strcreateview'],
310
                ];
311
            }
312
313
            if (isset($_REQUEST['search_path'])) {
314
                $fields['search_path'] = $_REQUEST['search_path'];
315
            }
316
317
            $navlinks['download'] = [
318
                'attr'    => [
319
                    'href' => [
320
                        'url'     => 'dataexport',
321
                        'urlvars' => $fields,
322
                    ],
323
                ],
324
                'content' => $this->lang['strdownload'],
325
            ];
326
        }
327
328
        $this->printNavLinks($navlinks, 'sql-form', get_defined_vars());
329
330
        return $this->printFooter($doBody, $template);
331
    }
332
}
333