diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/controllers/DataexportController.php | 89 | ||||
-rw-r--r-- | src/controllers/DataimportController.php | 216 | ||||
-rw-r--r-- | src/controllers/MaterializedviewpropertiesController.php | 2 | ||||
-rw-r--r-- | src/controllers/TablesController.php | 3 | ||||
-rw-r--r-- | src/controllers/TblpropertiesController.php | 65 | ||||
-rw-r--r-- | src/controllers/TypesController.php | 4 | ||||
-rw-r--r-- | src/controllers/ViewpropertiesController.php | 2 | ||||
-rw-r--r-- | src/database/Connection.php | 2 | ||||
-rw-r--r-- | src/database/Postgres.php | 1 | ||||
-rw-r--r-- | src/database/Postgres11.php | 3 | ||||
-rw-r--r-- | src/database/databasetraits/ColumnTrait.php | 12 | ||||
-rw-r--r-- | src/database/databasetraits/DatabaseTrait.php | 4 | ||||
-rw-r--r-- | src/database/databasetraits/TableTrait.php | 155 | ||||
-rw-r--r-- | src/traits/AdminTrait.php | 32 |
14 files changed, 316 insertions, 274 deletions
diff --git a/src/controllers/DataexportController.php b/src/controllers/DataexportController.php index 559e94ed..f303efd4 100644 --- a/src/controllers/DataexportController.php +++ b/src/controllers/DataexportController.php @@ -36,7 +36,7 @@ class DataexportController extends BaseController $format = 'N/A'; // force behavior to assume there is no pg_dump in the system - $forcemimic = false; + $forcemimic = isset($_REQUEST['forcemimic']) ? $_REQUEST['forcemimic'] : false; // If format is set, then perform the export if (!isset($_REQUEST['what'])) { @@ -89,11 +89,12 @@ class DataexportController extends BaseController break; } + $cleanprefix = $clean ? '' : '-- '; - return $this->mimicDumpFeature($format, $clean, $oids); + return $this->mimicDumpFeature($format, $cleanprefix, $oids); } - protected function mimicDumpFeature($format, $clean, $oids) + protected function mimicDumpFeature($format, $cleanprefix, $oids) { $data = $this->misc->getDatabaseAccessor(); @@ -111,34 +112,8 @@ class DataexportController extends BaseController // Include application functions $this->setNoOutput(true); - $clean = false; - $response = $this - ->container - ->responseobj; - // Make it do a download, if necessary - if ('download' == $_REQUEST['output']) { - // Set headers. MSIE is totally broken for SSL downloading, so - // we need to have it download in-place as plain text - if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) { - $response = $response - ->withHeader('Content-type', 'text/plain'); - } else { - $response = $response - ->withHeader('Content-type', 'application/download'); - - if (isset($this->extensions[$format])) { - $ext = $this->extensions[$format]; - } else { - $ext = 'txt'; - } - $response = $response - ->withHeader('Content-Disposition', 'attachment; filename=dump.'.$ext); - } - } else { - $response = $response - ->withHeader('Content-type', 'text/plain'); - } + $response = $this->_getResponse($format); $this->coalesceArr($_REQUEST, 'query', ''); @@ -164,7 +139,7 @@ class DataexportController extends BaseController // If the dump is not dataonly then dump the structure prefix if ('dataonly' != $_REQUEST['what']) { - $tabledefprefix = $data->getTableDefPrefix($object, $clean); + $tabledefprefix = $data->getTableDefPrefix($object, $cleanprefix); $this->prtrace('tabledefprefix', $tabledefprefix); echo $tabledefprefix; } @@ -178,12 +153,7 @@ class DataexportController extends BaseController $data->conn->setFetchMode(\ADODB_FETCH_NUM); // Execute the query, if set, otherwise grab all rows from the table - if ($object) { - $rs = $data->dumpRelation($object, $oids); - } else { - $rs = $data->conn->Execute($_REQUEST['query']); - $this->prtrace('$_REQUEST[query]', $_REQUEST['query']); - } + $rs = $this->_getRS($data, $object, $oids); $response = $this->pickFormat($data, $object, $oids, $rs, $format, $response); } @@ -200,7 +170,47 @@ class DataexportController extends BaseController return $response; } - public function pickFormat($data, $object, $oids, $rs, $format, $response) + private function _getRS($data, $object, $oids) + { + if ($object) { + return $data->dumpRelation($object, $oids); + } + + $this->prtrace('$_REQUEST[query]', $_REQUEST['query']); + + return $data->conn->Execute($_REQUEST['query']); + } + + private function _getResponse($format) + { + $response = $this + ->container + ->responseobj; + + // Make it do a download, if necessary + if ('download' !== $_REQUEST['output']) { + return $response + ->withHeader('Content-type', 'text/plain'); + } + // Set headers. MSIE is totally broken for SSL downloading, so + // we need to have it download in-place as plain text + if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) { + return $response + ->withHeader('Content-type', 'text/plain'); + } + $response = $response + ->withHeader('Content-type', 'application/download'); + + $ext = 'txt'; + if (isset($this->extensions[$format])) { + $ext = $this->extensions[$format]; + } + + return $response + ->withHeader('Content-Disposition', 'attachment; filename=dump.'.$ext); + } + + private function pickFormat($data, $object, $oids, $rs, $format, $response) { if ('copy' == $format) { $this->_mimicCopy($data, $object, $oids, $rs); @@ -214,9 +224,8 @@ class DataexportController extends BaseController $this->_mimicXml($data, $object, $oids, $rs); } elseif ('sql' == $format) { $this->_mimicSQL($data, $object, $oids, $rs); - } else { - $this->_csvOrTab($data, $object, $oids, $rs, $format); } + $this->_csvOrTab($data, $object, $oids, $rs, $format); return $response; } diff --git a/src/controllers/DataimportController.php b/src/controllers/DataimportController.php index 82f518b9..fdeb5f70 100644 --- a/src/controllers/DataimportController.php +++ b/src/controllers/DataimportController.php @@ -27,7 +27,7 @@ class DataimportController extends BaseController $this->printHeader(); $this->printTrail('table'); - $this->printTabs('table', 'import'); + $tabs = $this->printTabs('table', 'import'); // Default state for XML parser $state = 'XML'; @@ -179,127 +179,129 @@ class DataimportController extends BaseController }; // Check that file is specified and is an uploaded file - if (isset($_FILES['source']) && is_uploaded_file($_FILES['source']['tmp_name']) && is_readable($_FILES['source']['tmp_name'])) { - $fd = fopen($_FILES['source']['tmp_name'], 'rb'); - // Check that file was opened successfully - if (false !== $fd) { - $null_array = self::loadNULLArray(); - $status = $data->beginTransaction(); - if (0 != $status) { - $this->halt($this->lang['strimporterror']); - } + if (!isset($_FILES['source']) || !is_uploaded_file($_FILES['source']['tmp_name']) || !is_readable($_FILES['source']['tmp_name'])) { + // Upload went wrong + $this->printMsg($this->lang['strimporterror-uploadedfile']); - // If format is set to 'auto', then determine format automatically from file name - if ('auto' == $_REQUEST['format']) { - $extension = substr(strrchr($_FILES['source']['name'], '.'), 1); - switch ($extension) { - case 'csv': - $_REQUEST['format'] = 'csv'; - - break; - case 'txt': - $_REQUEST['format'] = 'tab'; - - break; - case 'xml': - $_REQUEST['format'] = 'xml'; - - break; - default: - $data->rollbackTransaction(); - $this->halt($this->lang['strimporterror-fileformat']); - } - } + return $this->printFooter(); + } + $fd = fopen($_FILES['source']['tmp_name'], 'rb'); + // Check that file was opened successfully + if (false === $fd) { + // File could not be opened + $this->printMsg($this->lang['strimporterror']); - // Do different import technique depending on file format - switch ($_REQUEST['format']) { - case 'csv': - case 'tab': - // XXX: Length of CSV lines limited to 100k - $csv_max_line = 100000; - // Set delimiter to tabs or commas - if ('csv' == $_REQUEST['format']) { - $csv_delimiter = ','; - } else { - $csv_delimiter = "\t"; - } + return $this->printFooter(); + } + $null_array = self::loadNULLArray(); + $status = $data->beginTransaction(); + if (0 != $status) { + $this->halt($this->lang['strimporterror']); + } - // Get first line of field names - $fields = fgetcsv($fd, $csv_max_line, $csv_delimiter); - $row = 2; //We start on the line AFTER the field names - while ($line = fgetcsv($fd, $csv_max_line, $csv_delimiter)) { - // Build value map - $t_fields = []; - $vars = []; - $nulls = []; - $format = []; - $types = []; - $i = 0; - foreach ($fields as $f) { - // Check that there is a column - if (!isset($line[$i])) { - $this->halt(sprintf($this->lang['strimporterrorline-badcolumnnum'], $row)); - } - $t_fields[$i] = $f; - - // Check for nulls - if (self::determineNull($line[$i], $null_array)) { - $nulls[$i] = 'on'; - } - // Add to value array - $vars[$i] = $line[$i]; - // Format is always VALUE - $format[$i] = 'VALUE'; - // Type is always text - $types[$i] = 'text'; - ++$i; - } - - $status = $data->insertRow($_REQUEST['table'], $t_fields, $vars, $nulls, $format, $types); - if (0 != $status) { - $data->rollbackTransaction(); - $this->halt(sprintf($this->lang['strimporterrorline'], $row)); - } - ++$row; - } + // If format is set to 'auto', then determine format automatically from file name + if ('auto' == $_REQUEST['format']) { + $extension = substr(strrchr($_FILES['source']['name'], '.'), 1); + switch ($extension) { + case 'csv': + $_REQUEST['format'] = 'csv'; - break; - case 'xml': - $parser = xml_parser_create(); - xml_set_element_handler($parser, $_startElement, $_endElement); - xml_set_character_data_handler($parser, $_charHandler); + break; + case 'txt': + $_REQUEST['format'] = 'tab'; + + break; + case 'xml': + $_REQUEST['format'] = 'xml'; + + break; + default: + $data->rollbackTransaction(); + $this->halt($this->lang['strimporterror-fileformat']); + } + } + + // Do different import technique depending on file format + switch ($_REQUEST['format']) { + case 'csv': + case 'tab': + // XXX: Length of CSV lines limited to 100k + $csv_max_line = 100000; + // Set delimiter to tabs or commas + if ('csv' == $_REQUEST['format']) { + $csv_delimiter = ','; + } else { + $csv_delimiter = "\t"; + } - while (!feof($fd)) { - $line = fgets($fd, 4096); - xml_parse($parser, $line); + // Get first line of field names + $fields = fgetcsv($fd, $csv_max_line, $csv_delimiter); + $row = 2; //We start on the line AFTER the field names + while ($line = fgetcsv($fd, $csv_max_line, $csv_delimiter)) { + // Build value map + $t_fields = []; + $vars = []; + $nulls = []; + $format = []; + $types = []; + $i = 0; + foreach ($fields as $f) { + // Check that there is a column + if (!isset($line[$i])) { + $this->halt(sprintf($this->lang['strimporterrorline-badcolumnnum'], $row)); } + $t_fields[$i] = $f; - xml_parser_free($parser); + // Check for nulls + if (self::determineNull($line[$i], $null_array)) { + $nulls[$i] = 'on'; + } + // Add to value array + $vars[$i] = $line[$i]; + // Format is always VALUE + $format[$i] = 'VALUE'; + // Type is always text + $types[$i] = 'text'; + ++$i; + } - break; - default: - // Unknown type + $status = $data->insertRow($_REQUEST['table'], $t_fields, $vars, $nulls, $format, $types); + if (0 != $status) { $data->rollbackTransaction(); - $this->halt($this->lang['strinvalidparam']); + $this->halt(sprintf($this->lang['strimporterrorline'], $row)); + } + ++$row; } - $status = $data->endTransaction(); - if (0 != $status) { - $this->halt($this->lang['strimporterror']); + break; + case 'xml': + $parser = xml_parser_create(); + xml_set_element_handler($parser, $_startElement, $_endElement); + xml_set_character_data_handler($parser, $_charHandler); + + while (!feof($fd)) { + $line = fgets($fd, 4096); + xml_parse($parser, $line); } - fclose($fd); - $this->printMsg($this->lang['strfileimported']); - } else { - // File could not be opened - $this->printMsg($this->lang['strimporterror']); - } - } else { - // Upload went wrong - $this->printMsg($this->lang['strimporterror-uploadedfile']); + xml_parser_free($parser); + + break; + default: + // Unknown type + $data->rollbackTransaction(); + $this->halt($this->lang['strinvalidparam']); } - $this->printFooter(); + $status = $data->endTransaction(); + if (0 != $status) { + $this->printMsg($this->lang['strimporterror']); + } + fclose($fd); + + $this->printMsg($this->lang['strfileimported']); + + return $this->printFooter(); } public static function loadNULLArray() diff --git a/src/controllers/MaterializedviewpropertiesController.php b/src/controllers/MaterializedviewpropertiesController.php index 55cf482f..91086e30 100644 --- a/src/controllers/MaterializedviewpropertiesController.php +++ b/src/controllers/MaterializedviewpropertiesController.php @@ -182,7 +182,6 @@ class MaterializedviewpropertiesController extends BaseController switch ($_REQUEST['stage']) { case 1: - $this->printTrail('column'); $this->printTitle($this->lang['stralter'], 'pg.column.alter'); $this->printMsg($msg); @@ -224,7 +223,6 @@ class MaterializedviewpropertiesController extends BaseController break; case 2: - // Check inputs if ('' == trim($_REQUEST['field'])) { $_REQUEST['stage'] = 1; diff --git a/src/controllers/TablesController.php b/src/controllers/TablesController.php index 07e04927..b47ad507 100644 --- a/src/controllers/TablesController.php +++ b/src/controllers/TablesController.php @@ -42,7 +42,6 @@ class TablesController extends BaseController switch ($this->action) { case 'create': - if (isset($_POST['cancel'])) { $this->doDefault(); } else { @@ -515,7 +514,6 @@ class TablesController extends BaseController break; case 2: - // Check inputs $fields = trim($_REQUEST['fields']); if ('' == trim($_REQUEST['name'])) { @@ -636,7 +634,6 @@ class TablesController extends BaseController break; case 3: - $this->coalesceArr($_REQUEST, 'notnull', []); $this->coalesceArr($_REQUEST, 'uniquekey', []); diff --git a/src/controllers/TblpropertiesController.php b/src/controllers/TblpropertiesController.php index 67752f00..ca13bfdc 100644 --- a/src/controllers/TblpropertiesController.php +++ b/src/controllers/TblpropertiesController.php @@ -594,37 +594,38 @@ class TblpropertiesController extends BaseController $this->printMsg($msg); // Check that file uploads are enabled - if (ini_get('file_uploads')) { - // Don't show upload option if max size of uploads is zero - $max_size = $misc->inisizeToBytes(ini_get('upload_max_filesize')); - if (is_double($max_size) && $max_size > 0) { - echo '<form action="'.\SUBFOLDER.'/src/views/dataimport" method="post" enctype="multipart/form-data">'.PHP_EOL; - echo '<table>'.PHP_EOL; - echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strformat']}</th>".PHP_EOL; - echo "\t\t<td><select name=\"format\">".PHP_EOL; - echo "\t\t\t<option value=\"auto\">{$this->lang['strauto']}</option>".PHP_EOL; - echo "\t\t\t<option value=\"csv\">CSV</option>".PHP_EOL; - echo "\t\t\t<option value=\"tab\">{$this->lang['strtabbed']}</option>".PHP_EOL; - if (function_exists('xml_parser_create')) { - echo "\t\t\t<option value=\"xml\">XML</option>".PHP_EOL; - } - echo "\t\t</select></td>\n\t</tr>".PHP_EOL; - echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strallowednulls']}</th>".PHP_EOL; - echo "\t\t<td><label><input type=\"checkbox\" name=\"allowednulls[0]\" value=\"\\N\" checked=\"checked\" />{$this->lang['strbackslashn']}</label><br />".PHP_EOL; - echo "\t\t<label><input type=\"checkbox\" name=\"allowednulls[1]\" value=\"NULL\" />NULL</label><br />".PHP_EOL; - echo "\t\t<label><input type=\"checkbox\" name=\"allowednulls[2]\" value=\"\" />{$this->lang['stremptystring']}</label></td>\n\t</tr>".PHP_EOL; - echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strfile']}</th>".PHP_EOL; - echo "\t\t<td><input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"{$max_size}\" />"; - echo "<input type=\"file\" name=\"source\" /></td>\n\t</tr>".PHP_EOL; - echo '</table>'.PHP_EOL; - echo '<p><input type="hidden" name="action" value="import" />'.PHP_EOL; - echo $misc->form; - echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), '" />'.PHP_EOL; - echo "<input type=\"submit\" value=\"{$this->lang['strimport']}\" /></p>".PHP_EOL; - echo '</form>'.PHP_EOL; - } - } else { + if (!ini_get('file_uploads')) { echo "<p>{$this->lang['strnouploads']}</p>".PHP_EOL; + + return; + } + // Don't show upload option if max size of uploads is zero + $max_size = $misc->inisizeToBytes(ini_get('upload_max_filesize')); + if (is_double($max_size) && $max_size > 0) { + echo '<form action="'.\SUBFOLDER.'/src/views/dataimport" method="post" enctype="multipart/form-data">'.PHP_EOL; + echo '<table>'.PHP_EOL; + echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strformat']}</th>".PHP_EOL; + echo "\t\t<td><select name=\"format\">".PHP_EOL; + echo "\t\t\t<option value=\"auto\">{$this->lang['strauto']}</option>".PHP_EOL; + echo "\t\t\t<option value=\"csv\">CSV</option>".PHP_EOL; + echo "\t\t\t<option value=\"tab\">{$this->lang['strtabbed']}</option>".PHP_EOL; + if (function_exists('xml_parser_create')) { + echo "\t\t\t<option value=\"xml\">XML</option>".PHP_EOL; + } + echo "\t\t</select></td>\n\t</tr>".PHP_EOL; + echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strallowednulls']}</th>".PHP_EOL; + echo "\t\t<td><label><input type=\"checkbox\" name=\"allowednulls[0]\" value=\"\\N\" checked=\"checked\" />{$this->lang['strbackslashn']}</label><br />".PHP_EOL; + echo "\t\t<label><input type=\"checkbox\" name=\"allowednulls[1]\" value=\"NULL\" />NULL</label><br />".PHP_EOL; + echo "\t\t<label><input type=\"checkbox\" name=\"allowednulls[2]\" value=\"\" />{$this->lang['stremptystring']}</label></td>\n\t</tr>".PHP_EOL; + echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strfile']}</th>".PHP_EOL; + echo "\t\t<td><input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"{$max_size}\" />"; + echo "<input type=\"file\" name=\"source\" /></td>\n\t</tr>".PHP_EOL; + echo '</table>'.PHP_EOL; + echo '<p><input type="hidden" name="action" value="import" />'.PHP_EOL; + echo $misc->form; + echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), '" />'.PHP_EOL; + echo "<input type=\"submit\" value=\"{$this->lang['strimport']}\" /></p>".PHP_EOL; + echo '</form>'.PHP_EOL; } } @@ -743,7 +744,7 @@ class TblpropertiesController extends BaseController } $this->coalesceArr($_POST, 'length', ''); - $status = $data->addColumn( + list($status, $sql) = $data->addColumn( $_POST['table'], $_POST['field'], $_POST['type'], @@ -755,7 +756,7 @@ class TblpropertiesController extends BaseController ); if (0 == $status) { $misc->setReloadBrowser(true); - $this->doDefault($this->lang['strcolumnadded']); + $this->doDefault(sprintf('%s %s %s', $sql, PHP_EOL, $this->lang['strcolumnadded'])); } else { $_REQUEST['stage'] = 1; $this->doAddColumn($this->lang['strcolumnaddedbad']); diff --git a/src/controllers/TypesController.php b/src/controllers/TypesController.php index bc0a2de2..a382349e 100644 --- a/src/controllers/TypesController.php +++ b/src/controllers/TypesController.php @@ -406,7 +406,6 @@ class TypesController extends BaseController break; case 2: - // Check inputs $fields = trim($_REQUEST['fields']); if ('' == trim($_REQUEST['name'])) { @@ -486,7 +485,6 @@ class TypesController extends BaseController break; case 3: - // Check inputs $fields = trim($_REQUEST['fields']); if ('' == trim($_REQUEST['name'])) { @@ -579,7 +577,6 @@ class TypesController extends BaseController break; case 2: - // Check inputs $values = trim($_REQUEST['values']); if ('' == trim($_REQUEST['name'])) { @@ -627,7 +624,6 @@ class TypesController extends BaseController break; case 3: - // Check inputs $values = trim($_REQUEST['values']); if ('' == trim($_REQUEST['name'])) { diff --git a/src/controllers/ViewpropertiesController.php b/src/controllers/ViewpropertiesController.php index e89b5817..acdb54df 100644 --- a/src/controllers/ViewpropertiesController.php +++ b/src/controllers/ViewpropertiesController.php @@ -162,7 +162,6 @@ class ViewpropertiesController extends BaseController switch ($_REQUEST['stage']) { case 1: - $this->printTrail('column'); $this->printTitle($this->lang['stralter'], 'pg.column.alter'); $this->printMsg($msg); @@ -204,7 +203,6 @@ class ViewpropertiesController extends BaseController break; case 2: - // Check inputs if ('' == trim($_REQUEST['field'])) { $_REQUEST['stage'] = 1; diff --git a/src/database/Connection.php b/src/database/Connection.php index c6156f79..34fa1a74 100644 --- a/src/database/Connection.php +++ b/src/database/Connection.php @@ -145,7 +145,7 @@ class Connection $version_parts = explode('.', $version); - if (in_array($version_parts[0], ['10','11'])) { + if (in_array($version_parts[0], ['10', '11'], true)) { $major_version = $version_parts[0]; } else { $major_version = implode('.', [$version_parts[0], $version_parts[1]]); diff --git a/src/database/Postgres.php b/src/database/Postgres.php index 0c386c0b..a176663a 100644 --- a/src/database/Postgres.php +++ b/src/database/Postgres.php @@ -17,7 +17,6 @@ namespace PHPPgAdmin\Database; class Postgres extends ADOdbBase { use \PHPPgAdmin\Traits\HelperTrait; - use \PHPPgAdmin\Database\Traits\AggregateTrait; use \PHPPgAdmin\Database\Traits\DatabaseTrait; use \PHPPgAdmin\Database\Traits\DomainTrait; diff --git a/src/database/Postgres11.php b/src/database/Postgres11.php index c6ab4cf6..1a47fc32 100644 --- a/src/database/Postgres11.php +++ b/src/database/Postgres11.php @@ -1,13 +1,14 @@ <?php + /** * PHPPgAdmin v6.0.0-beta.49 */ + namespace PHPPgAdmin\Database; /** * @file * PostgreSQL 11.x support - * */ /** * Class to add support for Postgres10. diff --git a/src/database/databasetraits/ColumnTrait.php b/src/database/databasetraits/ColumnTrait.php index 0f7a451f..15ce6abc 100644 --- a/src/database/databasetraits/ColumnTrait.php +++ b/src/database/databasetraits/ColumnTrait.php @@ -23,7 +23,7 @@ trait ColumnTrait * @param mixed $default The default for the column. '' for none. * @param string $comment comment for the column * - * @return bool|int 0 success + * @return array first element is 0 on success, second element is sql sentence */ public function addColumn($table, $column, $type, $array, $length, $notnull, $default, $comment) { @@ -77,24 +77,26 @@ trait ColumnTrait $status = $this->beginTransaction(); if ($status != 0) { - return -1; + return [-1, $sql]; } $status = $this->execute($sql); if ($status != 0) { $this->rollbackTransaction(); - return -1; + return [-1, $sql]; } $status = $this->setComment('COLUMN', $column, $table, $comment); if ($status != 0) { $this->rollbackTransaction(); - return -1; + return [-1, $sql]; } - return $this->endTransaction(); + $status = $this->endTransaction(); + + return [$status, $sql]; } /** diff --git a/src/database/databasetraits/DatabaseTrait.php b/src/database/databasetraits/DatabaseTrait.php index abdbb7aa..b7d0be75 100644 --- a/src/database/databasetraits/DatabaseTrait.php +++ b/src/database/databasetraits/DatabaseTrait.php @@ -520,7 +520,9 @@ trait DatabaseTrait $sql .= " \"{$f_schema}\".\"{$table}\""; } - return $this->execute($sql); + $status = $this->execute($sql); + + return [$status, $sql]; } /** diff --git a/src/database/databasetraits/TableTrait.php b/src/database/databasetraits/TableTrait.php index 69558944..fc02d305 100644 --- a/src/database/databasetraits/TableTrait.php +++ b/src/database/databasetraits/TableTrait.php @@ -129,12 +129,12 @@ trait TableTrait * Returns the SQL definition for the table. * MUST be run within a transaction. * - * @param string $table The table to define - * @param bool|true $clean True to issue drop command, false otherwise + * @param string $table The table to define + * @param string $cleanprefix set to '-- ' to avoid issuing DROP statement * * @return string A string containing the formatted SQL code */ - public function getTableDefPrefix($table, $clean = false) + public function getTableDefPrefix($table, $cleanprefix = '') { // Fetch table $t = $this->getTable($table); @@ -171,12 +171,7 @@ trait TableTrait // Begin CREATE TABLE definition $sql .= "-- Definition\n\n"; // DROP TABLE must be fully qualified in case a table with the same name exists - // in pg_catalog. - if (!$clean) { - $sql .= '-- '; - } - - $sql .= 'DROP TABLE '; + $sql .= $cleanprefix.'DROP TABLE '; $sql .= "\"{$t->fields['nspname']}\".\"{$t->fields['relname']}\";\n"; $sql .= "CREATE TABLE \"{$t->fields['nspname']}\".\"{$t->fields['relname']}\" (\n"; @@ -397,6 +392,7 @@ trait TableTrait break; case 'user': + case 'role': $this->fieldClean($v[1]); $sql .= "\"{$v[1]}\";\n"; @@ -439,6 +435,7 @@ trait TableTrait break; case 'user': + case 'role': $this->fieldClean($v[1]); $sql .= "\"{$v[1]}\""; @@ -480,15 +477,20 @@ trait TableTrait $this->clean($c_schema); $this->clean($table); - $sql = " + $sql = ' SELECT - c.relname, n.nspname, u.usename AS relowner, + c.relname, n.nspname, '; + + $sql .= ($this->hasRoles() ? ' coalesce(u.usename,r.rolname) ' : ' u.usename')." AS relowner, pg_catalog.obj_description(c.oid, 'pg_class') AS relcomment, - (SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace + pt.spcname AS tablespace FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_tablespace pt ON pt.oid=c.reltablespace LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner - LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE c.relkind = 'r' + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "; + + $sql .= ($this->hasRoles() ? ' LEFT JOIN pg_catalog.pg_roles r ON c.relowner = r.oid ' : ''). + " WHERE c.relkind = 'r' AND n.nspname = '{$c_schema}' AND n.oid = c.relnamespace AND c.relname = '{$table}'"; @@ -497,55 +499,68 @@ trait TableTrait } /** - * Retrieve the attribute definition of a table. + * Retrieve all attributes definition of a table. * - * @param string $table The name of the table - * @param string $field (optional) The name of a field to return + * @param string $table The name of the table + * @param string $c_schema The name of the schema * * @return \PHPPgAdmin\ADORecordSet All attributes in order */ - public function getTableAttributes($table, $field = '') + private function _getTableAttributesAll($table, $c_schema) { - $c_schema = $this->_schema; - $this->clean($c_schema); - $this->clean($table); - $this->clean($field); + $sql = " + SELECT + a.attname, + a.attnum, + pg_catalog.format_type(a.atttypid, a.atttypmod) AS TYPE, + a.atttypmod, + a.attnotnull, + a.atthasdef, + pg_catalog.pg_get_expr(adef.adbin, adef.adrelid, TRUE) AS adsrc, + a.attstattarget, + a.attstorage, + t.typstorage, + CASE + WHEN pc.oid IS NULL THEN FALSE + ELSE TRUE + END AS attisserial, + pg_catalog.col_description(a.attrelid, a.attnum) AS COMMENT + + FROM pg_catalog.pg_tables tbl + JOIN pg_catalog.pg_class tbl_class ON tbl.tablename=tbl_class.relname + JOIN pg_catalog.pg_attribute a ON tbl_class.oid = a.attrelid + JOIN pg_catalog.pg_namespace ON pg_namespace.oid = tbl_class.relnamespace + AND pg_namespace.nspname=tbl.schemaname + LEFT JOIN pg_catalog.pg_attrdef adef ON a.attrelid=adef.adrelid + AND a.attnum=adef.adnum + LEFT JOIN pg_catalog.pg_type t ON a.atttypid=t.oid + LEFT JOIN pg_catalog.pg_depend pd ON pd.refobjid=a.attrelid + AND pd.refobjsubid=a.attnum + AND pd.deptype='i' + LEFT JOIN pg_catalog.pg_class pc ON pd.objid=pc.oid + AND pd.classid=pc.tableoid + AND pd.refclassid=pc.tableoid + AND pc.relkind='S' + WHERE tbl.tablename='{$table}' + AND tbl.schemaname='{$c_schema}' + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum"; - if ($field == '') { - // This query is made much more complex by the addition of the 'attisserial' field. - // The subquery to get that field checks to see if there is an internally dependent - // sequence on the field. - $sql = " - SELECT - a.attname, a.attnum, - pg_catalog.format_type(a.atttypid, a.atttypmod) as type, - a.atttypmod, - a.attnotnull, a.atthasdef, pg_catalog.pg_get_expr(adef.adbin, adef.adrelid, true) as adsrc, - a.attstattarget, a.attstorage, t.typstorage, - ( - SELECT 1 FROM pg_catalog.pg_depend pd, pg_catalog.pg_class pc - WHERE pd.objid=pc.oid - AND pd.classid=pc.tableoid - AND pd.refclassid=pc.tableoid - AND pd.refobjid=a.attrelid - AND pd.refobjsubid=a.attnum - AND pd.deptype='i' - AND pc.relkind='S' - ) IS NOT NULL AS attisserial, - pg_catalog.col_description(a.attrelid, a.attnum) AS comment - FROM - pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_attrdef adef - ON a.attrelid=adef.adrelid - AND a.attnum=adef.adnum - LEFT JOIN pg_catalog.pg_type t ON a.atttypid=t.oid - WHERE - a.attrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='{$table}' - AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE - nspname = '{$c_schema}')) - AND a.attnum > 0 AND NOT a.attisdropped - ORDER BY a.attnum"; - } else { - $sql = " + return $this->selectSet($sql); + } + + /** + * Retrieve single attribute definition of a table. + * + * @param string $table The name of the table + * @param string $c_schema The schema of the table + * @param string $field (optional) The name of a field to return + * + * @return \PHPPgAdmin\ADORecordSet All attributes in order + */ + private function _getTableAttribute($table, $c_schema, $field) + { + $sql = " SELECT a.attname, a.attnum, pg_catalog.format_type(a.atttypid, a.atttypmod) as type, @@ -564,12 +579,36 @@ trait TableTrait AND relnamespace = (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = '{$c_schema}')) AND a.attname = '{$field}'"; - } return $this->selectSet($sql); } /** + * Retrieve the attribute definition of a table. + * + * @param string $table The name of the table + * @param string $field (optional) The name of a field to return + * + * @return \PHPPgAdmin\ADORecordSet All attributes in order + */ + public function getTableAttributes($table, $field = '') + { + $c_schema = $this->_schema; + $this->clean($c_schema); + $this->clean($table); + + if ($field == '') { + // This query is made much more complex by the addition of the 'attisserial' field. + // The subquery to get that field checks to see if there is an internally dependent + // sequence on the field. + return $this->_getTableAttributesAll($table, $c_schema); + } + $this->clean($field); + + return $this->_getTableAttribute($table, $c_schema, $field); + } + + /** * Returns a list of all constraints on a table. * * @param string $table The table to find rules for diff --git a/src/traits/AdminTrait.php b/src/traits/AdminTrait.php index cc400b9a..391786e7 100644 --- a/src/traits/AdminTrait.php +++ b/src/traits/AdminTrait.php @@ -514,28 +514,26 @@ trait AdminTrait if (is_array($_REQUEST['table'])) { $msg = ''; foreach ($_REQUEST['table'] as $t) { - $status = $data->vacuumDB($t, isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze'])); - if (0 == $status) { - $msg .= sprintf('%s: %s<br />', htmlentities($t, ENT_QUOTES, 'UTF-8'), $this->lang['strvacuumgood']); - } else { - $this->doDefault(sprintf('%s %s%s: %s<br />', $type, $msg, htmlentities($t, ENT_QUOTES, 'UTF-8'), $this->lang['strvacuumbad'])); - - return; + list($status, $sql) = $data->vacuumDB($t, isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze'])); + if (0 !== $status) { + return $this->doDefault(sprintf('%s %s%s: %s<br />', $type, $msg, htmlentities($t, ENT_QUOTES, 'UTF-8'), $this->lang['strvacuumbad'])); } + $msg .= sprintf('%s%s %s: %s<br />', $sql, PHP_EOL, htmlentities($t, ENT_QUOTES, 'UTF-8'), $this->lang['strvacuumgood']); } // Everything went fine, back to the Default page.... $this->misc->setReloadBrowser(true); - $this->doDefault($msg); - } else { - //we must pass table here. When empty, vacuum the whole db - $status = $data->vacuumDB($_REQUEST['table'], isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze'])); - if (0 == $status) { - $this->misc->setReloadBrowser(true); - $this->doAdmin($type, $this->lang['strvacuumgood']); - } else { - $this->doAdmin($type, $this->lang['strvacuumbad']); - } + + return $this->doDefault($msg); + } + //we must pass table here. When empty, vacuum the whole db + list($status, $sql) = $data->vacuumDB($_REQUEST['table'], isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze'])); + if (0 == $status) { + $this->misc->setReloadBrowser(true); + + return $this->doAdmin($type, sprintf('%s%s%s', $sql, PHP_EOL, $this->lang['strvacuumgood'])); } + + return $this->doAdmin($type, $this->lang['strvacuumbad']); } /** |