summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Treat2019-09-24 21:05:24 +0000
committerRobert Treat2019-09-24 21:05:24 +0000
commit2355dc514354ebb78d14a9e27d2dcc20da96e428 (patch)
treee416cbcfaded199a477d0525396b9f7ad1bf605b
parentfd9c78875b2683dea27989943345f91ce2f31450 (diff)
Overhaul sequence properties page to better handle different permissions.
Whilst fixing the sequence group viewing bug, noticed that sequence properties in general would throw an error if you did not have appropriate permissions. While this is similar to permission denied errors when looking directly at a sequence, there is other information to be exposed which is accesible through pg_sequence and pg_sequences. The change implements a method for determining if a user can access the sequence directly (ie. select * from seq) and if so, include that information in the output. If not, we null those columns. This also fixes cases where last_value information is not visible due to a sequence not haveing been "read" yet. ie. after sequence creation, or anytime a sequence is altered, and nextval/setval hasn't been called. This problem seems to go back to at least postgres 9, so I've mainlined the fix. It might break on older unsupported versions of postgres; if someone wants to fix that well... patches welcome.
-rw-r--r--classes/database/Postgres.php45
1 files changed, 45 insertions, 0 deletions
diff --git a/classes/database/Postgres.php b/classes/database/Postgres.php
index 12103b77..17eef2bd 100644
--- a/classes/database/Postgres.php
+++ b/classes/database/Postgres.php
@@ -2628,6 +2628,24 @@ class Postgres extends ADODB_base {
// Sequence functions
/**
+ * Determines whether or not the current user can directly access sequence information
+ * @param $sequence Sequence Name
+ * @return t/f based on user permissions
+ */
+ function hasSequencePrivilege($sequence) {
+ /* This double-cleaning is deliberate */
+ $f_schema = $this->_schema;
+ $this->fieldClean($f_schema);
+ $this->clean($f_schema);
+ $this->fieldClean($sequence);
+ $this->clean($sequence);
+
+ $sql = "SELECT pg_catalog.has_sequence_privilege('{$f_schema}.{$sequence}','SELECT,USAGE')";
+
+ return $this->execute($sql);
+ }
+
+ /**
* Returns properties of a single sequence
* @param $sequence Sequence name
* @return A recordset
@@ -2639,6 +2657,13 @@ class Postgres extends ADODB_base {
$this->fieldClean($sequence);
$this->clean($c_sequence);
+ $join = '';
+ if ($this->hasSequencePrivilege($sequence) == 't') {
+ $join = "CROSS JOIN \"{$c_schema}\".\"{$c_sequence}\" AS s";
+ } else {
+ $join = 'CROSS JOIN ( values (null, null, null) ) AS s (last_value, log_cnt, is_called) ';
+ };
+
$sql = "
SELECT
c.relname AS seqname, s.*,
@@ -2654,6 +2679,26 @@ class Postgres extends ADODB_base {
AND c.oid = m.seqrelid AND c.relname = '{$c_sequence}' AND c.relkind = 'S' AND n.nspname='{$c_schema}'
AND n.oid = c.relnamespace";
+ $sql = "
+ SELECT
+ c.relname AS seqname,
+ s.last_value, s.log_cnt, s.is_called,
+ m.seqstart AS start_value, m.seqincrement AS increment_by, m.seqmax AS max_value, m.seqmin AS min_value,
+ m.seqcache AS cache_value, m.seqcycle AS is_cycled,
+ pg_catalog.obj_description(c.oid, 'pg_class') as seqcomment,
+ pg_catalog.pg_get_userbyid(c.relowner) as seqowner,
+ n.nspname
+ FROM
+ pg_catalog.pg_class c
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
+ JOIN pg_catalog.pg_sequence m ON m.seqrelid = c.oid
+ {$join}
+ WHERE
+ c.relkind IN ('S')
+ AND c.relname = '{$c_sequence}'
+ AND n.nspname = '{$c_schema}'
+ ";
+
return $this->selectSet( $sql );
}