Modified some logic for the EPAS server as the user can change the view definition without dropping it. Fixes #5053

This commit is contained in:
Khushboo Vashi
2020-04-13 16:00:01 +05:30
committed by Akshay Joshi
parent 41be5479af
commit 030741bba5
7 changed files with 88 additions and 30 deletions

View File

@@ -496,7 +496,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
"Could not find the required parameter (%s).") % arg
)
try:
SQL, nameOrError = self.getSQL(gid, sid, did, scid, data)
SQL, nameOrError = self.getSQL(gid, sid, did, data)
if SQL is None:
return nameOrError
SQL = SQL.strip('\n').strip(' ')
@@ -541,7 +541,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
request.data, encoding='utf-8'
)
try:
SQL, name = self.getSQL(gid, sid, did, scid, data, vid)
SQL, name = self.getSQL(gid, sid, did, data, vid)
if SQL is None:
return name
SQL = SQL.strip('\n').strip(' ')
@@ -678,7 +678,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
except ValueError:
data[k] = v
sql, nameOrError = self.getSQL(gid, sid, did, scid, data, vid)
sql, nameOrError = self.getSQL(gid, sid, did, data, vid)
if sql is None:
return nameOrError
@@ -692,7 +692,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
status=200
)
def getSQL(self, gid, sid, did, scid, data, vid=None):
def getSQL(self, gid, sid, did, data, vid=None):
"""
This function will generate sql from model data
"""
@@ -716,22 +716,6 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
if 'schema' not in data:
data['schema'] = res['rows'][0]['schema']
DEL_SQL = None
if 'definition' in data:
new_def = re.sub(r"\W", "", data['definition']).split('FROM')
old_def = re.sub(r"\W", "", res['rows'][0]['definition']
).split('FROM')
if 'definition' in data and (
len(old_def) > 1 or len(new_def) > 1
) and(
old_def[0] != new_def[0] and
old_def[0] not in new_def[0]
):
DEL_SQL = self.delete(gid=gid, sid=sid, did=did,
scid=scid,
vid=vid, only_sql=True
)
try:
acls = render_template(
"/".join([self.template_path, 'sql/allowed_privs.json'])
@@ -750,14 +734,53 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
data[aclcol][key] = parse_priv_to_db(
data[aclcol][key], allowedacl['acl']
)
data['del_sql'] = False
old_data['acl_sql'] = ''
if 'definition' in data and self.manager.server_type == 'pg':
new_def = re.sub(r"\W", "", data['definition']).split('FROM')
old_def = re.sub(r"\W", "", res['rows'][0]['definition']
).split('FROM')
if 'definition' in data and (
len(old_def) > 1 or len(new_def) > 1
) and(
old_def[0] != new_def[0] and
old_def[0] not in new_def[0]
):
data['del_sql'] = True
# If we drop and recreate the view, the
# privileges must be restored
# Fetch all privileges for view
sql_acl = render_template("/".join(
[self.template_path, 'sql/acl.sql']), vid=vid)
status, dataclres = self.conn.execute_dict(sql_acl)
if not status:
return internal_server_error(errormsg=res)
for row in dataclres['rows']:
priv = parse_priv_from_db(row)
res['rows'][0].setdefault(row['deftype'], []
).append(priv)
old_data.update(res['rows'][0])
# Privileges
for aclcol in acls:
if aclcol in old_data:
allowedacl = acls[aclcol]
old_data[aclcol] = parse_priv_to_db(
old_data[aclcol], allowedacl['acl'])
old_data['acl_sql'] = render_template("/".join(
[self.template_path, 'sql/grant.sql']), data=old_data)
try:
SQL = render_template("/".join(
[self.template_path, 'sql/update.sql']), data=data,
o_data=old_data, conn=self.conn)
if DEL_SQL:
SQL = DEL_SQL + SQL
except Exception as e:
current_app.logger.exception(e)
return None, internal_server_error(errormsg=str(e))
@@ -1457,7 +1480,7 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
if data:
if diff_schema:
data['schema'] = diff_schema
sql, nameOrError = self.getSQL(gid, sid, did, scid, data, oid)
sql, nameOrError = self.getSQL(gid, sid, did, data, oid)
if sql.find('DROP VIEW') != -1:
sql = gettext("""
-- Changing the columns in a view requires dropping and re-creating the view.
@@ -1539,7 +1562,7 @@ class MViewNode(ViewNode, VacuumSettings):
'9.3_plus'
)
def getSQL(self, gid, sid, did, scid, data, vid=None):
def getSQL(self, gid, sid, did, data, vid=None):
"""
This function will generate sql from model data
"""

View File

@@ -158,7 +158,7 @@ define('pgadmin.node.view', [
control: Backform.SqlCodeControl.extend({
onChange: function() {
Backform.SqlCodeControl.prototype.onChange.apply(this, arguments);
if(this.model && this.model.changed) {
if(this.model && this.model.changed && this.model.node_info.server.server_type == 'pg') {
if(this.model.origSessAttrs && (this.model.changed.definition != this.model.origSessAttrs.definition)) {
let old_def = this.model.origSessAttrs.definition.replace(/\s/gi, '').split('FROM'),
new_def = [];

View File

@@ -9,5 +9,5 @@ LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
WHERE
c.relfilenode = {{ vid }};
{% elif (name and nspname) %}
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
DROP VIEW {{ conn|qtIdent(nspname, name) }}{% if cascade %} CASCADE {% endif %};
{% endif %}

View File

@@ -13,11 +13,10 @@ ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
SET SCHEMA {{ conn|qtIdent(data.schema) }};
{% endif %}
{% if data.owner and data.owner != o_data.owner %}
ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(data.owner) }};
{% endif %}
{% if def and def != o_data.definition.rstrip(';') %}
{% if data.del_sql %}
DROP VIEW {{ conn|qtIdent(view_schema, view_name) }};
{% endif %}
CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %}
WITH ({% if (data.check_option or o_data.check_option) %}check_option={{ data.check_option if data.check_option else o_data.check_option }}{{', ' }}{% endif %}security_barrier={{ data.security_barrier|lower if data.security_barrier is defined else o_data.security_barrier|default('false', 'true')|lower }})
@@ -36,13 +35,23 @@ ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET (check_option);
{% endif %}
{% endif %}
{% if data.owner and data.owner != o_data.owner %}
ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(data.owner) }};
{% endif %}
{% set old_comment = o_data.comment|default('', true) %}
{% if (data.comment is defined and (data.comment != old_comment)) %}
COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
IS {{ data.comment|qtLiteral }};
{% elif data.del_sql == True %}
COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
IS {{ old_comment|qtLiteral }};
{% endif %}
{# The SQL generated below will change privileges #}
{% if o_data.acl_sql and o_data.acl_sql != '' %}
{{o_data['acl_sql']}}
{% endif %}
{% if data.datacl %}
{% if 'deleted' in data.datacl %}
{% for priv in data.datacl.deleted %}

View File

@@ -1 +1,5 @@
ALTER VIEW public."testview_$%{}[]()&*^!@""'`\/#"
SET (security_barrier=true);
ALTER VIEW public."testview_$%{}[]()&*^!@""'`\/#"
SET (check_option=cascaded);
GRANT SELECT ON TABLE public."testview_$%{}[]()&*^!@""'`\/#" TO PUBLIC;

View File

@@ -1,3 +1,7 @@
DROP VIEW public."testview_$%{}[]()&*^!@""'`\/#";
CREATE OR REPLACE VIEW public."testview_$%{}[]()&*^!@""'`\/#"
AS
SELECT * FROM test_view_table;
COMMENT ON VIEW public."testview_$%{}[]()&*^!@""'`\/#"
IS 'Testcomment-updated';
GRANT ALL ON TABLE public."testview_$%{}[]()&*^!@""'`\/#" TO postgres;

View File

@@ -57,6 +57,18 @@
"expected_sql_file": "alter_view.sql",
"expected_msql_file": "alter_view_msql.sql"
},
{
"type": "alter",
"name": "Alter View (changing code)",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"definition": "SELECT * FROM test_view_table;"
},
"expected_sql_file": "alter_view_definition.sql",
"expected_msql_file": "alter_view_definition_msql.sql"
},
{
"type": "alter",
"name": "Alter View (adding privileges)",
@@ -64,6 +76,12 @@
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":{
"added":[
{