diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py index 80f59a958..9f2191d1b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py @@ -17,7 +17,7 @@ from flask import render_template, make_response, request, jsonify from flask_babel import gettext from pgadmin.browser.collection import CollectionNodeModule from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \ - parse_priv_to_db + parse_priv_to_db, validate_options, tokenize_options from pgadmin.browser.utils import PGChildNodeView from pgadmin.utils.ajax import make_json_response, internal_server_error, \ make_response as ajax_response @@ -119,9 +119,6 @@ class ForeignDataWrapperView(PGChildNodeView): * properties(gid, sid, did, fid) - This function will show the properties of the selected foreign data wrapper node - * tokenizeOptions(option_value) - - This function will tokenize the string stored in database - * create(gid, sid, did) - This function will create the new foreign data wrapper node @@ -208,11 +205,15 @@ class ForeignDataWrapperView(PGChildNodeView): def wrap(*args, **kwargs): # Here args[0] will hold self & kwargs will hold gid,sid,did self = args[0] - self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid']) + self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager( + kwargs['sid'] + ) self.conn = self.manager.connection(did=kwargs['did']) # Set the template path for the SQL scripts - self.template_path = 'foreign_data_wrappers/sql/#{0}#'.format(self.manager.version) + self.template_path = 'foreign_data_wrappers/sql/#{0}#'.format( + self.manager.version + ) return f(*args, **kwargs) @@ -221,14 +222,16 @@ class ForeignDataWrapperView(PGChildNodeView): @check_precondition def list(self, gid, sid, did): """ - This function is used to list all the foreign data wrapper nodes within that collection. + This function is used to list all the foreign data wrapper + nodes within that collection. Args: gid: Server Group ID sid: Server ID did: Database ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: @@ -236,7 +239,9 @@ class ForeignDataWrapperView(PGChildNodeView): for row in res['rows']: if row['fdwoptions'] is not None: - row['fdwoptions'] = self.tokenize_options(row['fdwoptions']) + row['fdwoptions'] = tokenize_options( + row['fdwoptions'], 'fdwoption', 'fdwvalue' + ) return ajax_response( response=res['rows'], @@ -255,7 +260,9 @@ class ForeignDataWrapperView(PGChildNodeView): did: Database ID """ res = [] - sql = render_template("/".join([self.template_path, 'properties.sql']), conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + conn=self.conn + ) status, r_set = self.conn.execute_2darray(sql) if not status: return internal_server_error(errormsg=r_set) @@ -304,24 +311,6 @@ class ForeignDataWrapperView(PGChildNodeView): return gone(gettext("Could not find the specified foreign data wrapper.")) - def tokenize_options(self, option_value): - """ - This function will tokenize the string stored in database - e.g. database store the value as below - key1=value1, key2=value2, key3=value3, .... - This function will extract key and value from above string - - Args: - option_value: key value option/value pair read from database - """ - if option_value is not None: - option_str = option_value.split(',') - fdw_options = [] - for fdw_option in option_str: - k, v = fdw_option.split('=', 1) - fdw_options.append({'fdwoption': k, 'fdwvalue': v}) - return fdw_options - @check_precondition def properties(self, gid, sid, did, fid): """ @@ -333,7 +322,9 @@ class ForeignDataWrapperView(PGChildNodeView): did: Database ID fid: foreign data wrapper ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), fid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fid=fid, conn=self.conn + ) status, res = self.conn.execute_dict(sql) if not status: @@ -345,7 +336,10 @@ class ForeignDataWrapperView(PGChildNodeView): ) if res['rows'][0]['fdwoptions'] is not None: - res['rows'][0]['fdwoptions'] = self.tokenize_options(res['rows'][0]['fdwoptions']) + res['rows'][0]['fdwoptions'] = tokenize_options( + res['rows'][0]['fdwoptions'], + 'fdwoption', 'fdwvalue' + ) sql = render_template("/".join([self.template_path, 'acl.sql']), fid=fid) status, fdw_acl_res = self.conn.execute_dict(sql) @@ -392,32 +386,26 @@ class ForeignDataWrapperView(PGChildNodeView): ) try: - if 'fdwacl' in data: data['fdwacl'] = parse_priv_to_db(data['fdwacl'], ['U']) - new_list = [] - - # Allow user to set the blank value in fdwvalue field in option model + is_valid_options = False if 'fdwoptions' in data: - for item in data['fdwoptions']: - new_dict = {} - if item['fdwoption']: - if 'fdwvalue' in item and item['fdwvalue'] and item['fdwvalue'] != '': - new_dict.update(item); - else: - new_dict.update({'fdwoption': item['fdwoption'], 'fdwvalue': ''}) + is_valid_options, data['fdwoptions'] = validate_options( + data['fdwoptions'], 'fdwoption', 'fdwvalue' + ) - new_list.append(new_dict) - - data['fdwoptions'] = new_list - - sql = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn) + sql = render_template("/".join([self.template_path, 'create.sql']), + data=data, conn=self.conn, + is_valid_options=is_valid_options + ) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) - sql = render_template("/".join([self.template_path, 'properties.sql']), fname=data['name'], conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fname=data['name'], conn=self.conn + ) status, r_set = self.conn.execute_dict(sql) if not status: @@ -488,7 +476,9 @@ class ForeignDataWrapperView(PGChildNodeView): try: # Get name of foreign data wrapper from fid - sql = render_template("/".join([self.template_path, 'delete.sql']), fid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'delete.sql']), + fid=fid, conn=self.conn + ) status, name = self.conn.execute_scalar(sql) if not status: return internal_server_error(errormsg=name) @@ -505,7 +495,8 @@ class ForeignDataWrapperView(PGChildNodeView): ) ) # drop foreign data wrapper node - sql = render_template("/".join([self.template_path, 'delete.sql']), name=name, cascade=cascade, + sql = render_template("/".join([self.template_path, 'delete.sql']), + name=name, cascade=cascade, conn=self.conn) status, res = self.conn.execute_scalar(sql) if not status: @@ -549,7 +540,7 @@ class ForeignDataWrapperView(PGChildNodeView): sql = "--modified SQL" return make_json_response( - data=sql, + data=sql.strip('\n'), status=200 ) except Exception as e: @@ -571,7 +562,9 @@ class ForeignDataWrapperView(PGChildNodeView): ] if fid is not None: - sql = render_template("/".join([self.template_path, 'properties.sql']), fid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fid=fid, conn=self.conn + ) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) @@ -582,7 +575,10 @@ class ForeignDataWrapperView(PGChildNodeView): ) if res['rows'][0]['fdwoptions'] is not None: - res['rows'][0]['fdwoptions'] = self.tokenize_options(res['rows'][0]['fdwoptions']) + res['rows'][0]['fdwoptions'] = tokenize_options( + res['rows'][0]['fdwoptions'], + 'fdwoption', 'fdwvalue' + ) for key in ['fdwacl']: if key in data and data[key] is not None: @@ -598,63 +594,41 @@ class ForeignDataWrapperView(PGChildNodeView): if arg not in data: data[arg] = old_data[arg] - new_list_add = [] - new_list_change = [] - # Allow user to set the blank value in fdwvalue field in option model + is_valid_added_options = is_valid_changed_options = False if 'fdwoptions' in data and 'added' in data['fdwoptions']: - for item in data['fdwoptions']['added']: - new_dict_add = {} - if item['fdwoption']: - if 'fdwvalue' in item and item['fdwvalue'] and item['fdwvalue'] != '': - new_dict_add.update(item); - else: - new_dict_add.update({'fdwoption': item['fdwoption'], 'fdwvalue': ''}) - - new_list_add.append(new_dict_add) - - data['fdwoptions']['added'] = new_list_add - - # Allow user to set the blank value in fdwvalue field in option model + is_valid_added_options, data['fdwoptions']['added'] = validate_options( + data['fdwoptions']['added'], 'fdwoption', 'fdwvalue' + ) if 'fdwoptions' in data and 'changed' in data['fdwoptions']: - for item in data['fdwoptions']['changed']: - new_dict_change = {} - if item['fdwoption']: - if 'fdwvalue' in item and item['fdwvalue'] and item['fdwvalue'] != '': - new_dict_change.update(item); - else: - new_dict_change.update({'fdwoption': item['fdwoption'], 'fdwvalue': ''}) + is_valid_changed_options, data['fdwoptions']['changed'] = validate_options( + data['fdwoptions']['changed'], 'fdwoption', 'fdwvalue' + ) - new_list_change.append(new_dict_change) - - data['fdwoptions']['changed'] = new_list_change - - sql = render_template("/".join([self.template_path, 'update.sql']), data=data, o_data=old_data, - conn=self.conn) + sql = render_template("/".join([self.template_path, 'update.sql']), + data=data, o_data=old_data, + is_valid_added_options=is_valid_added_options, + is_valid_changed_options=is_valid_changed_options, + conn=self.conn + ) return sql, data['name'] if 'name' in data else old_data['name'] else: for key in ['fdwacl']: if key in data and data[key] is not None: data[key] = parse_priv_to_db(data[key], ['U']) - new_list = [] - # Allow user to set the blank value in fdwvalue field in option model + is_valid_options = False if 'fdwoptions' in data: - for item in data['fdwoptions']: - new_dict = {} - if item['fdwoption']: - if 'fdwvalue' in item and item['fdwvalue'] and item['fdwvalue'] != '': - new_dict.update(item); - else: - new_dict.update({'fdwoption': item['fdwoption'], 'fdwvalue': ''}) + is_valid_options, data['fdwoptions'] = validate_options( + data['fdwoptions'], 'fdwoption', 'fdwvalue' + ) - new_list.append(new_dict) + sql = render_template("/".join([self.template_path, 'create.sql']), + data=data, conn=self.conn, + is_valid_options=is_valid_options + ) - data['fdwoptions'] = new_list - - sql = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn) - sql += "\n" return sql, data['name'] @@ -669,13 +643,21 @@ class ForeignDataWrapperView(PGChildNodeView): did: Database ID fid: Foreign data wrapper ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), fid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fid=fid, conn=self.conn + ) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) + is_valid_options = False if res['rows'][0]['fdwoptions'] is not None: - res['rows'][0]['fdwoptions'] = self.tokenize_options(res['rows'][0]['fdwoptions']) + res['rows'][0]['fdwoptions'] = tokenize_options( + res['rows'][0]['fdwoptions'], 'fdwoption', 'fdwvalue' + ) + + if len(res['rows'][0]['fdwoptions']) > 0: + is_valid_options = True sql = render_template("/".join([self.template_path, 'acl.sql']), fid=fid) status, fdw_acl_res = self.conn.execute_dict(sql) @@ -694,7 +676,10 @@ class ForeignDataWrapperView(PGChildNodeView): res['rows'][0]['fdwacl'] = parse_priv_to_db(res['rows'][0]['fdwacl'], ['U']) sql = '' - sql = render_template("/".join([self.template_path, 'create.sql']), data=res['rows'][0], conn=self.conn) + sql = render_template("/".join([self.template_path, 'create.sql']), + data=res['rows'][0], conn=self.conn, + is_valid_options=is_valid_options + ) sql += "\n" sql_header = """-- Foreign Data Wrapper: {0} @@ -708,7 +693,7 @@ class ForeignDataWrapperView(PGChildNodeView): sql = sql_header + sql - return ajax_response(response=sql) + return ajax_response(response=sql.strip('\n')) @check_precondition def get_validators(self, gid, sid, did): @@ -722,14 +707,16 @@ class ForeignDataWrapperView(PGChildNodeView): """ res = [{'label': '', 'value': ''}] try: - sql = render_template("/".join([self.template_path, 'validators.sql']), conn=self.conn) + sql = render_template("/".join([self.template_path, 'validators.sql']), + conn=self.conn) status, r_set = self.conn.execute_2darray(sql) if not status: return internal_server_error(errormsg=r_set) for row in r_set['rows']: - res.append({'label': row['schema_prefix_fdw_val'], 'value': row['schema_prefix_fdw_val']}) + res.append({'label': row['schema_prefix_fdw_val'], + 'value': row['schema_prefix_fdw_val']}) return make_json_response(data=res, status=200) @@ -748,14 +735,16 @@ class ForeignDataWrapperView(PGChildNodeView): """ res = [{'label': '', 'value': ''}] try: - sql = render_template("/".join([self.template_path, 'handlers.sql']), conn=self.conn) + sql = render_template("/".join([self.template_path, 'handlers.sql']), + conn=self.conn) status, r_set = self.conn.execute_2darray(sql) if not status: return internal_server_error(errormsg=r_set) for row in r_set['rows']: - res.append({'label': row['schema_prefix_fdw_hand'], 'value': row['schema_prefix_fdw_hand']}) + res.append({'label': row['schema_prefix_fdw_hand'], + 'value': row['schema_prefix_fdw_hand']}) return make_json_response( data=res, diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py index 1f2836c60..e73cf29a8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/__init__.py @@ -17,7 +17,7 @@ from flask import render_template, make_response, request, jsonify from flask_babel import gettext from pgadmin.browser.collection import CollectionNodeModule from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \ - parse_priv_to_db + parse_priv_to_db, validate_options, tokenize_options from pgadmin.browser.utils import PGChildNodeView from pgadmin.utils.ajax import make_json_response, internal_server_error, \ make_response as ajax_response @@ -120,9 +120,6 @@ class ForeignServerView(PGChildNodeView): * properties(gid, sid, did, fid, fsid) - This function will show the properties of the selected foreign server node - * tokenizeOptions(option_value) - - This function will tokenize the string stored in database - * update(gid, sid, did, fid, fsid) - This function will update the data for the selected foreign server node @@ -202,10 +199,15 @@ class ForeignServerView(PGChildNodeView): def wrap(*args, **kwargs): # Here args[0] will hold self & kwargs will hold gid,sid,did self = args[0] - self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid']) + self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager( + kwargs['sid'] + ) self.conn = self.manager.connection(did=kwargs['did']) # Set the template path for the SQL scripts - self.template_path = "foreign_servers/sql/#{0}#".format(self.manager.version) + self.template_path = "foreign_servers/sql/#{0}#".format( + self.manager.version + ) + self.is_valid_options = False return f(*args, **kwargs) @@ -223,7 +225,8 @@ class ForeignServerView(PGChildNodeView): fid: Foreign data wrapper ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), fid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fid=fid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: @@ -248,7 +251,8 @@ class ForeignServerView(PGChildNodeView): """ res = [] - sql = render_template("/".join([self.template_path, 'properties.sql']), fid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fid=fid, conn=self.conn) status, r_set = self.conn.execute_2darray(sql) if not status: @@ -303,25 +307,6 @@ class ForeignServerView(PGChildNodeView): return gone(gettext("Could not find the specified foreign server.")) - def tokenizeOptions(self, option_value): - """ - This function will tokenize the string stored in database - e.g. database store the value as below - key1=value1, key2=value2, key3=value3, .... - This function will extract key and value from above string - - Args: - option_value: key value option/value pair read from database - """ - - if option_value is not None: - option_str = option_value.split(',') - fs_rv_options = [] - for fs_rv_option in option_str: - k, v = fs_rv_option.split('=', 1) - fs_rv_options.append({'fsrvoption': k, 'fsrvvalue': v}) - return fs_rv_options - @check_precondition def properties(self, gid, sid, did, fid, fsid): """ @@ -335,7 +320,8 @@ class ForeignServerView(PGChildNodeView): fsid: foreign server ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fsid=fsid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: @@ -347,7 +333,9 @@ class ForeignServerView(PGChildNodeView): ) if res['rows'][0]['fsrvoptions'] is not None: - res['rows'][0]['fsrvoptions'] = self.tokenizeOptions(res['rows'][0]['fsrvoptions']) + res['rows'][0]['fsrvoptions'] = tokenize_options( + res['rows'][0]['fsrvoptions'], 'fsrvoption', 'fsrvvalue' + ) sql = render_template("/".join([self.template_path, 'acl.sql']), fsid=fsid) status, fs_rv_acl_res = self.conn.execute_dict(sql) @@ -399,35 +387,30 @@ class ForeignServerView(PGChildNodeView): if 'fsrvacl' in data: data['fsrvacl'] = parse_priv_to_db(data['fsrvacl'], ['U']) - sql = render_template("/".join([self.template_path, 'properties.sql']), fdwid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fdwid=fid, conn=self.conn) status, res1 = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res1) fdw_data = res1['rows'][0] - new_list = [] - + is_valid_options = False if 'fsrvoptions' in data: - for item in data['fsrvoptions']: - new_dict = {} - if item['fsrvoption']: - if 'fsrvvalue' in item and item['fsrvvalue'] and item['fsrvvalue'] != '': - new_dict.update(item); - else: - new_dict.update({'fsrvoption': item['fsrvoption'], 'fsrvvalue': ''}) + is_valid_options, data['fsrvoptions'] = validate_options( + data['fsrvoptions'], 'fsrvoption', 'fsrvvalue' + ) - new_list.append(new_dict) - - data['fsrvoptions'] = new_list - - sql = render_template("/".join([self.template_path, 'create.sql']), data=data, fdwdata=fdw_data, + sql = render_template("/".join([self.template_path, 'create.sql']), + data=data, fdwdata=fdw_data, + is_valid_options=is_valid_options, conn=self.conn) status, res = self.conn.execute_scalar(sql) if not status: return internal_server_error(errormsg=res) - sql = render_template("/".join([self.template_path, 'properties.sql']), data=data, fdwdata=fdw_data, + sql = render_template("/".join([self.template_path, 'properties.sql']), + data=data, fdwdata=fdw_data, conn=self.conn) status, r_set = self.conn.execute_dict(sql) if not status: @@ -501,7 +484,8 @@ class ForeignServerView(PGChildNodeView): try: # Get name of foreign data wrapper from fid - sql = render_template("/".join([self.template_path, 'delete.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'delete.sql']), + fsid=fsid, conn=self.conn) status, name = self.conn.execute_scalar(sql) if not status: return internal_server_error(errormsg=name) @@ -519,7 +503,8 @@ class ForeignServerView(PGChildNodeView): ) # drop foreign server - sql = render_template("/".join([self.template_path, 'delete.sql']), name=name, cascade=cascade, + sql = render_template("/".join([self.template_path, 'delete.sql']), + name=name, cascade=cascade, conn=self.conn) status, res = self.conn.execute_scalar(sql) if not status: @@ -565,7 +550,7 @@ class ForeignServerView(PGChildNodeView): sql = "--modified SQL" return make_json_response( - data=sql, + data=sql.strip('\n'), status=200 ) @@ -590,13 +575,16 @@ class ForeignServerView(PGChildNodeView): ] if fsid is not None: - sql = render_template("/".join([self.template_path, 'properties.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fsid=fsid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) if res['rows'][0]['fsrvoptions'] is not None: - res['rows'][0]['fsrvoptions'] = self.tokenizeOptions(res['rows'][0]['fsrvoptions']) + res['rows'][0]['fsrvoptions'] = tokenize_options( + res['rows'][0]['fsrvoptions'], 'fsrvoption', 'fsrvvalue' + ) for key in ['fsrvacl']: if key in data and data[key] is not None: @@ -612,42 +600,25 @@ class ForeignServerView(PGChildNodeView): if arg not in data: data[arg] = old_data[arg] - new_list_add = [] - new_list_change = [] - - # Allow user to set the blank value in fsrvvalue field in option model + is_valid_added_options = is_valid_changed_options = False if 'fsrvoptions' in data and 'added' in data['fsrvoptions']: - for item in data['fsrvoptions']['added']: - new_dict_add = {} - if item['fsrvoption']: - if 'fsrvvalue' in item and item['fsrvvalue'] and item['fsrvvalue'] != '': - new_dict_add.update(item); - else: - new_dict_add.update({'fsrvoption': item['fsrvoption'], 'fsrvvalue': ''}) - - new_list_add.append(new_dict_add) - - data['fsrvoptions']['added'] = new_list_add - - # Allow user to set the blank value in fsrvvalue field in option model + is_valid_added_options, data['fsrvoptions']['added'] = validate_options( + data['fsrvoptions']['added'], 'fsrvoption', 'fsrvvalue' + ) if 'fsrvoptions' in data and 'changed' in data['fsrvoptions']: - for item in data['fsrvoptions']['changed']: - new_dict_change = {} - if item['fsrvoption']: - if 'fsrvvalue' in item and item['fsrvvalue'] and item['fsrvvalue'] != '': - new_dict_change.update(item); - else: - new_dict_change.update({'fsrvoption': item['fsrvoption'], 'fsrvvalue': ''}) + is_valid_changed_options, data['fsrvoptions']['changed'] = validate_options( + data['fsrvoptions']['changed'], 'fsrvoption', 'fsrvvalue' + ) - new_list_change.append(new_dict_change) - - data['fsrvoptions']['changed'] = new_list_change - - sql = render_template("/".join([self.template_path, 'update.sql']), data=data, o_data=old_data, + sql = render_template("/".join([self.template_path, 'update.sql']), + data=data, o_data=old_data, + is_valid_added_options=is_valid_added_options, + is_valid_changed_options=is_valid_changed_options, conn=self.conn) return sql, data['name'] if 'name' in data else old_data['name'] else: - sql = render_template("/".join([self.template_path, 'properties.sql']), fdwid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fdwid=fid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) @@ -658,22 +629,16 @@ class ForeignServerView(PGChildNodeView): if key in data and data[key] is not None: data[key] = parse_priv_to_db(data[key], ['U']) - new_list = [] + is_valid_options = False if 'fsrvoptions' in data: - for item in data['fsrvoptions']: - new_dict = {} - if item['fsrvoption']: - if 'fsrvvalue' in item and item['fsrvvalue'] and item['fsrvvalue'] != '': - new_dict.update(item); - else: - new_dict.update({'fsrvoption': item['fsrvoption'], 'fsrvvalue': ''}) + is_valid_options, data['fsrvoptions'] = validate_options( + data['fsrvoptions'], 'fsrvoption', 'fsrvvalue' + ) - new_list.append(new_dict) - - data['fsrvoptions'] = new_list - - sql = render_template("/".join([self.template_path, 'create.sql']), data=data, fdwdata=fdw_data, + sql = render_template("/".join([self.template_path, 'create.sql']), + data=data, fdwdata=fdw_data, + is_valid_options=is_valid_options, conn=self.conn) sql += "\n" return sql, data['name'] @@ -692,13 +657,20 @@ class ForeignServerView(PGChildNodeView): fsid: Foreign server ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fsid=fsid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) + is_valid_options = False if res['rows'][0]['fsrvoptions'] is not None: - res['rows'][0]['fsrvoptions'] = self.tokenizeOptions(res['rows'][0]['fsrvoptions']) + res['rows'][0]['fsrvoptions'] = tokenize_options( + res['rows'][0]['fsrvoptions'], 'fsrvoption', 'fsrvvalue' + ) + + if len(res['rows'][0]['fsrvoptions']) > 0: + is_valid_options = True sql = render_template("/".join([self.template_path, 'acl.sql']), fsid=fsid) status, fs_rv_acl_res = self.conn.execute_dict(sql) @@ -716,7 +688,8 @@ class ForeignServerView(PGChildNodeView): if 'fsrvacl' in res['rows'][0]: res['rows'][0]['fsrvacl'] = parse_priv_to_db(res['rows'][0]['fsrvacl'], ['U']) - sql = render_template("/".join([self.template_path, 'properties.sql']), fdwid=fid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fdwid=fid, conn=self.conn) status, res1 = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res1) @@ -724,7 +697,9 @@ class ForeignServerView(PGChildNodeView): fdw_data = res1['rows'][0] sql = '' - sql = render_template("/".join([self.template_path, 'create.sql']), data=res['rows'][0], fdwdata=fdw_data, + sql = render_template("/".join([self.template_path, 'create.sql']), + data=res['rows'][0], fdwdata=fdw_data, + is_valid_options=is_valid_options, conn=self.conn) sql += "\n" @@ -738,7 +713,7 @@ class ForeignServerView(PGChildNodeView): sql = sql_header + sql - return ajax_response(response=sql) + return ajax_response(response=sql.strip('\n')) @check_precondition def dependents(self, gid, sid, did, fid, fsid): @@ -756,14 +731,16 @@ class ForeignServerView(PGChildNodeView): dependents_result = self.get_dependents(self.conn, fsid) # Fetching dependents of foreign servers - query = render_template("/".join([self.template_path, 'dependents.sql']), fsid=fsid) + query = render_template("/".join([self.template_path, 'dependents.sql']), + fsid=fsid) status, result = self.conn.execute_dict(query) if not status: internal_server_error(errormsg=result) for row in result['rows']: dependents_result.append( - {'type': 'user_mapping', 'name': row['name'], 'field': 'normal' if (row['deptype'] == 'n') else ''}) + {'type': 'user_mapping', 'name': row['name'], + 'field': 'normal' if (row['deptype'] == 'n') else ''}) return ajax_response( response=dependents_result, diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/js/foreign_servers.js b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/js/foreign_servers.js index b641363eb..1d1bf1a86 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/js/foreign_servers.js +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/js/foreign_servers.js @@ -5,6 +5,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { // Extend the browser's node model class to create a Options model var OptionsModel = pgAdmin.Browser.Node.Model.extend({ + idAttribute: 'fsrvoption', defaults: { fsrvoption: undefined, fsrvvalue: undefined diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/9.3_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/9.3_plus/create.sql index ce508b580..46efe92ed 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/9.3_plus/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/9.3_plus/create.sql @@ -9,15 +9,9 @@ CREATE SERVER {{ conn|qtIdent(data.name) }}{% if data.fsrvtype %} FOREIGN DATA WRAPPER {{ conn|qtIdent(fdwdata.name) }}{% endif %}{% if data.fsrvoptions %} -{% set addAlter = "False" %} -{% for variable in data.fsrvoptions %} -{% if variable.fsrvoption and variable.fsrvoption != '' %} -{% if addAlter == "False" %} - OPTIONS ({% set addAlter = "True" %}{% endif %} -{{ conn|qtIdent(variable.fsrvoption) }} {{variable.fsrvvalue|qtLiteral}}{% if not loop.last %},{% else %}){% endif %} -{% endif %} -{% endfor %} -{% endif %}{% if data %};{% endif %} +{% if is_valid_options %} + OPTIONS ({% for variable in data.fsrvoptions %}{% if loop.index != 1 %}, {% endif %} +{{ conn|qtIdent(variable.fsrvoption) }} {{ variable.fsrvvalue|qtLiteral }}{% endfor %}){% endif %}{% endif %}; {# ============= Set the owner for foreign server ============= #} {% if data.fsrvowner %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/create.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/create.sql index da2630cd7..c9533f83a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/create.sql @@ -9,15 +9,9 @@ CREATE SERVER {{ conn|qtIdent(data.name) }}{% if data.fsrvtype %} FOREIGN DATA WRAPPER {{ conn|qtIdent(fdwdata.name) }}{% endif %}{% if data.fsrvoptions %} -{% set addAlter = "False" %} -{% for variable in data.fsrvoptions %} -{% if variable.fsrvoption and variable.fsrvoption != '' %} -{% if addAlter == "False" %} - OPTIONS ({% set addAlter = "True" %}{% endif %} -{{ conn|qtIdent(variable.fsrvoption) }} {{variable.fsrvvalue|qtLiteral}}{% if not loop.last %},{% else %}){% endif %} -{% endif %} -{% endfor %} -{% endif %}{% if data %};{% endif %} +{% if is_valid_options %} + OPTIONS ({% for variable in data.fsrvoptions %}{% if loop.index != 1 %}, {% endif %} +{{ conn|qtIdent(variable.fsrvoption) }} {{ variable.fsrvvalue|qtLiteral }}{% endfor %}){% endif %}{% endif %}; {# ============= Set the owner for foreign server ============= #} {% if data.fsrvowner %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/update.sql index 4c7590664..49e84b136 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/templates/foreign_servers/sql/default/update.sql @@ -25,44 +25,30 @@ COMMENT ON SERVER {{ conn|qtIdent(data.name) }} {% endif %} {# ============= Update foreign server options and values ============= #} -{% if data.fsrvoptions and data.fsrvoptions.deleted %} -{% set addAlter = "False" %} -{% for variable in data.fsrvoptions.deleted %} -{% if variable.fsrvoption and variable.fsrvoption != '' %} -{% if addAlter == "False" %} +{% if data.fsrvoptions and data.fsrvoptions.deleted and data.fsrvoptions.deleted|length > 0 %} ALTER SERVER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -DROP {{conn|qtIdent(variable.fsrvoption)}}{% if not loop.last %},{% else %});{% endif %} -{% endif %} -{% endfor %} - + OPTIONS ({% for variable in data.fsrvoptions.deleted %}{% if loop.index != 1 %}, {% endif %} +DROP {{ conn|qtIdent(variable.fsrvoption) }}{% endfor %} +); {% endif %} {% if data.fsrvoptions and data.fsrvoptions.added %} -{% set addAlter = "False" %} -{% for variable in data.fsrvoptions.added %} -{% if variable.fsrvoption and variable.fsrvoption != '' %} -{% if addAlter == "False" %} +{% if is_valid_added_options %} ALTER SERVER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -ADD {{ conn|qtIdent(variable.fsrvoption) }} {{variable.fsrvvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} + OPTIONS ({% for variable in data.fsrvoptions.added %}{% if loop.index != 1 %}, {% endif %} +ADD {{ conn|qtIdent(variable.fsrvoption) }} {{ variable.fsrvvalue|qtLiteral }}{% endfor %} +); + {% endif %} -{% endfor %} - - {% endif %} {% if data.fsrvoptions and data.fsrvoptions.changed %} -{% set addAlter = "False" %} -{% for variable in data.fsrvoptions.changed %} -{% if variable.fsrvoption and variable.fsrvoption != '' %} -{% if addAlter == "False" %} +{% if is_valid_changed_options %} ALTER SERVER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -SET {{conn|qtIdent(variable.fsrvoption)}} {{variable.fsrvvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} + OPTIONS ({% for variable in data.fsrvoptions.changed %}{% if loop.index != 1 %}, {% endif %} +SET {{ conn|qtIdent(variable.fsrvoption) }} {{ variable.fsrvvalue|qtLiteral }}{% endfor %} +); + {% endif %} -{% endfor %} - - {% endif %} {# Change the privileges #} {% if data.fsrvacl %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/__init__.py index 97c7d9d27..638887fd9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/__init__.py @@ -13,6 +13,8 @@ import simplejson as json from functools import wraps import pgadmin.browser.server_groups.servers as servers +from pgadmin.browser.server_groups.servers.utils import \ + validate_options, tokenize_options from flask import render_template, make_response, request, jsonify from flask_babel import gettext from pgadmin.browser.collection import CollectionNodeModule @@ -133,9 +135,6 @@ class UserMappingView(PGChildNodeView): * properties(gid, sid, did, fid, fsid, umid) - This function will show the properties of the selected user mapping node - * tokenizeOptions(option_value) - - This function will tokenize the string stored in database - * update(gid, sid, did, fid, fsid, umid) - This function will update the data for the selected user mapping node @@ -216,11 +215,15 @@ class UserMappingView(PGChildNodeView): def wrap(*args, **kwargs): # Here args[0] will hold self & kwargs will hold gid,sid,did self = args[0] - self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid']) + self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager( + kwargs['sid'] + ) self.conn = self.manager.connection(did=kwargs['did']) # Set the template path for the SQL scripts - self.template_path = 'user_mappings/sql/#{0}#'.format(self.manager.version) + self.template_path = 'user_mappings/sql/#{0}#'.format( + self.manager.version + ) return f(*args, **kwargs) @@ -239,7 +242,8 @@ class UserMappingView(PGChildNodeView): fsid: Foreign server ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fsid=fsid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: @@ -265,7 +269,8 @@ class UserMappingView(PGChildNodeView): """ res = [] - sql = render_template("/".join([self.template_path, 'properties.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fsid=fsid, conn=self.conn) status, r_set = self.conn.execute_2darray(sql) if not status: @@ -318,25 +323,6 @@ class UserMappingView(PGChildNodeView): return gone(gettext("Could not find the specified user mapping.")) - def tokenizeOptions(self, option_value): - """ - This function will tokenize the string stored in database - e.g. database store the value as below - key1=value1, key2=value2, key3=value3, .... - This function will extract key and value from above string - - Args: - option_value: key value option/value pair read from database - """ - - if option_value is not None: - option_str = option_value.split(',') - um_options = [] - for um_option in option_str: - k, v = um_option.split('=', 1) - um_options.append({'umoption': k, 'umvalue': v}) - return um_options - @check_precondition def properties(self, gid, sid, did, fid, fsid, umid): """ @@ -351,7 +337,8 @@ class UserMappingView(PGChildNodeView): umid: User mapping ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), umid=umid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + umid=umid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: @@ -363,8 +350,10 @@ class UserMappingView(PGChildNodeView): ) if res['rows'][0]['umoptions'] is not None: - res['rows'][0]['umoptions'] = self.tokenizeOptions(res['rows'][0]['umoptions']) - + res['rows'][0]['umoptions'] = tokenize_options( + res['rows'][0]['umoptions'], + 'umoption', 'umvalue' + ) return ajax_response( response=res['rows'][0], status=200 @@ -401,7 +390,8 @@ class UserMappingView(PGChildNodeView): ) try: - sql = render_template("/".join([self.template_path, 'properties.sql']), fserid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fserid=fsid, conn=self.conn) status, res1 = self.conn.execute_dict(sql) if not status: @@ -409,28 +399,22 @@ class UserMappingView(PGChildNodeView): fdw_data = res1['rows'][0] - new_list = [] - + is_valid_options = False if 'umoptions' in data: - for item in data['umoptions']: - new_dict = {} - if item['umoption']: - if 'umvalue' in item and item['umvalue'] and item['umvalue'] != '': - new_dict.update(item); - else: - new_dict.update({'umoption': item['umoption'], 'umvalue': ''}) + is_valid_options, data['umoptions'] = validate_options( + data['umoptions'], 'umoption', 'umvalue' + ) - new_list.append(new_dict) - - data['umoptions'] = new_list - - sql = render_template("/".join([self.template_path, 'create.sql']), data=data, fdwdata=fdw_data, + sql = render_template("/".join([self.template_path, 'create.sql']), + data=data, fdwdata=fdw_data, + is_valid_options=is_valid_options, conn=self.conn) status, res = self.conn.execute_scalar(sql) if not status: return internal_server_error(errormsg=res) - sql = render_template("/".join([self.template_path, 'properties.sql']), fsid=fsid, data=data, + sql = render_template("/".join([self.template_path, 'properties.sql']), + fsid=fsid, data=data, conn=self.conn) status, r_set = self.conn.execute_dict(sql) if not status: @@ -507,7 +491,8 @@ class UserMappingView(PGChildNodeView): try: # Get name of foreign server from fsid - sql = render_template("/".join([self.template_path, 'delete.sql']), fsid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'delete.sql']), + fsid=fsid, conn=self.conn) status, name = self.conn.execute_scalar(sql) if not status: return internal_server_error(errormsg=name) @@ -524,7 +509,8 @@ class UserMappingView(PGChildNodeView): ) ) - sql = render_template("/".join([self.template_path, 'properties.sql']), umid=umid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + umid=umid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) @@ -541,7 +527,8 @@ class UserMappingView(PGChildNodeView): data = res['rows'][0] # drop user mapping - sql = render_template("/".join([self.template_path, 'delete.sql']), data=data, name=name, cascade=cascade, + sql = render_template("/".join([self.template_path, 'delete.sql']), + data=data, name=name, cascade=cascade, conn=self.conn) status, res = self.conn.execute_scalar(sql) if not status: @@ -614,90 +601,68 @@ class UserMappingView(PGChildNodeView): ] if umid is not None: - sql = render_template("/".join([self.template_path, 'properties.sql']), umid=umid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + umid=umid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) if res['rows'][0]['umoptions'] is not None: - res['rows'][0]['umoptions'] = self.tokenizeOptions(res['rows'][0]['umoptions']) - + res['rows'][0]['umoptions'] = tokenize_options( + res['rows'][0]['umoptions'], + 'umoption', 'umvalue' + ) old_data = res['rows'][0] - sql = render_template("/".join([self.template_path, 'properties.sql']), fserid=fsid, conn=self.conn) - status, res1 = self.conn.execute_dict(sql) - if not status: - return internal_server_error(errormsg=res1) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fserid=fsid, conn=self.conn) + status, res1 = self.conn.execute_dict(sql) + if not status: + return internal_server_error(errormsg=res1) - fdw_data = res1['rows'][0] + fdw_data = res1['rows'][0] - for arg in required_args: - if arg not in data: - data[arg] = old_data[arg] + for arg in required_args: + if arg not in data: + data[arg] = old_data[arg] - new_list_add = [] - new_list_change = [] + # Allow user to set the blank value in fdwvalue field in option model + is_valid_added_options = is_valid_changed_options = False + if 'umoptions' in data and 'added' in data['umoptions']: + is_valid_added_options, data['umoptions']['added'] = validate_options( + data['umoptions']['added'], 'umoption', 'umvalue' + ) + if 'umoptions' in data and 'changed' in data['umoptions']: + is_valid_changed_options, data['umoptions']['changed'] = validate_options( + data['umoptions']['changed'], 'umoption', 'umvalue' + ) - # Allow user to set the blank value in fdwvalue field in option model - if 'umoptions' in data and 'added' in data['umoptions']: - for item in data['umoptions']['added']: - new_dict_add = {} - if item['umoption']: - if 'umvalue' in item and item['umvalue'] and item['umvalue'] != '': - new_dict_add.update(item); - else: - new_dict_add.update({'umoption': item['umoption'], 'umvalue': ''}) + sql = render_template("/".join([self.template_path, 'update.sql']), + data=data, o_data=old_data, + is_valid_added_options=is_valid_added_options, + is_valid_changed_options=is_valid_changed_options, + fdwdata=fdw_data, conn=self.conn) + return sql, data['name'] if 'name' in data else old_data['name'] + else: + sql = render_template("/".join([self.template_path, 'properties.sql']), + fserid=fsid, conn=self.conn) + status, res = self.conn.execute_dict(sql) + if not status: + return internal_server_error(errormsg=res) + fdw_data = res['rows'][0] - new_list_add.append(new_dict_add) + is_valid_options = False + if 'umoptions' in data: + is_valid_options, data['umoptions'] = validate_options( + data['umoptions'], 'umoption', 'umvalue' + ) - data['umoptions']['added'] = new_list_add - - # Allow user to set the blank value in fdwvalue field in option model - if 'umoptions' in data and 'changed' in data['umoptions']: - for item in data['umoptions']['changed']: - new_dict_change = {} - if item['umoption']: - if 'umvalue' in item and item['umvalue'] and item['umvalue'] != '': - new_dict_change.update(item); - else: - new_dict_change.update({'umoption': item['umoption'], 'umvalue': ''}) - - new_list_change.append(new_dict_change) - - data['umoptions']['changed'] = new_list_change - - sql = render_template("/".join([self.template_path, 'update.sql']), data=data, o_data=old_data, - fdwdata=fdw_data, conn=self.conn) - return sql, data['name'] if 'name' in data else old_data['name'] - else: - sql = render_template("/".join([self.template_path, 'properties.sql']), fserid=fsid, conn=self.conn) - status, res = self.conn.execute_dict(sql) - if not status: - return internal_server_error(errormsg=res) - fdw_data = res['rows'][0] - - new_list = [] - - if 'umoptions' in data: - for item in data['umoptions']: - new_dict = {} - if item['umoption']: - if 'umvalue' in item and item['umvalue'] \ - and item['umvalue'] != '': - new_dict.update(item); - else: - new_dict.update( - {'umoption': item['umoption'], - 'umvalue': ''} - ) - new_list.append(new_dict) - - data['umoptions'] = new_list - - sql = render_template("/".join([self.template_path, 'create.sql']), data=data, fdwdata=fdw_data, - conn=self.conn) - sql += "\n" - return sql, data['name'] + sql = render_template("/".join([self.template_path, 'create.sql']), + data=data, fdwdata=fdw_data, + is_valid_options=is_valid_options, + conn=self.conn) + sql += "\n" + return sql, data['name'] @check_precondition def sql(self, gid, sid, did, fid, fsid, umid): @@ -713,15 +678,24 @@ class UserMappingView(PGChildNodeView): umid: User mapping ID """ - sql = render_template("/".join([self.template_path, 'properties.sql']), umid=umid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + umid=umid, conn=self.conn) status, res = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res) + is_valid_options = False if res['rows'][0]['umoptions'] is not None: - res['rows'][0]['umoptions'] = self.tokenizeOptions(res['rows'][0]['umoptions']) + res['rows'][0]['umoptions'] = tokenize_options( + res['rows'][0]['umoptions'], + 'umoption', 'umvalue' + ) + if len(res['rows'][0]['umoptions']) > 0: + is_valid_options = True - sql = render_template("/".join([self.template_path, 'properties.sql']), fserid=fsid, conn=self.conn) + sql = render_template("/".join([self.template_path, 'properties.sql']), + fserid=fsid, conn=self.conn + ) status, res1 = self.conn.execute_dict(sql) if not status: return internal_server_error(errormsg=res1) @@ -729,7 +703,9 @@ class UserMappingView(PGChildNodeView): fdw_data = res1['rows'][0] sql = '' - sql = render_template("/".join([self.template_path, 'create.sql']), data=res['rows'][0], fdwdata=fdw_data, + sql = render_template("/".join([self.template_path, 'create.sql']), + data=res['rows'][0], fdwdata=fdw_data, + is_valid_options=is_valid_options, conn=self.conn) sql += "\n" @@ -743,7 +719,7 @@ class UserMappingView(PGChildNodeView): sql = sql_header + sql - return ajax_response(response=sql) + return ajax_response(response=sql.strip('\n')) @check_precondition def dependents(self, gid, sid, did, fid, fsid, umid): diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/js/user_mappings.js b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/js/user_mappings.js index cfa8b2a8b..43f2fb88d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/js/user_mappings.js +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/js/user_mappings.js @@ -4,6 +4,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { // Extend the browser's node model class to create a Options model var OptionsModel = pgAdmin.Browser.Node.Model.extend({ + idAttribute: 'umoption', defaults: { umoption: undefined, umvalue: undefined diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/create.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/create.sql index f467ae480..1737aecec 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/create.sql @@ -1,13 +1,6 @@ {# ============= Create of user mapping for server ============= #} {% if data and fdwdata %} -CREATE USER MAPPING FOR {% if data.name == "CURRENT_USER" or data.name == "PUBLIC" %}{{ data.name }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} SERVER {{ conn|qtIdent(fdwdata.name) }}{%endif%}{% if data.umoptions %} +CREATE USER MAPPING FOR {% if data.name == "CURRENT_USER" or data.name == "PUBLIC" %}{{ data.name }}{% else %}{{ conn|qtIdent(data.name) }}{% endif %} SERVER {{ conn|qtIdent(fdwdata.name) }}{%endif%}{% if data.umoptions %}{% if is_valid_options %} -{% set addAlter = "False" %} -{% for variable in data.umoptions %} -{% if variable.umoption and variable.umoption != '' %} -{% if addAlter == "False" %} - OPTIONS ({% set addAlter = "True" %}{% endif %} -{{ conn|qtIdent(variable.umoption) }} {{variable.umvalue|qtLiteral}}{% if not loop.last %},{%else%}){% endif %} -{% endif %} -{% endfor %} -{% endif %}{% if data %};{% endif %} \ No newline at end of file + OPTIONS ({% for variable in data.umoptions %}{% if loop.index != 1 %}, {% endif %} +{{ conn|qtIdent(variable.umoption) }} {{ variable.umvalue|qtLiteral }}{% endfor %}){% endif %}{% endif %}; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/update.sql index 021ba2460..416c29d96 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mapping/templates/user_mappings/sql/default/update.sql @@ -1,37 +1,26 @@ {# ============= Update user mapping options and values ============= #} -{% if data.umoptions and data.umoptions.deleted and fdwdata %} -{% set addAlter = "False" %} -{% for variable in data.umoptions.deleted %} -{% if variable.umoption and variable.umoption != '' %} -{% if addAlter == "False" %} +{% if data.umoptions and data.umoptions.deleted and data.umoptions.deleted|length > 0 and fdwdata %} ALTER USER MAPPING FOR {{ conn|qtIdent(o_data.name) }} SERVER {{ conn|qtIdent(fdwdata.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -DROP {{conn|qtIdent(variable.umoption)}}{% if not loop.last %},{% else %});{% endif %} -{% endif %} -{% endfor %} + OPTIONS ({% for variable in data.umoptions.deleted %}{% if loop.index != 1 %}, {% endif %} +DROP {{ conn|qtIdent(variable.umoption) }}{% endfor %} +); {% endif %} -{% if o_data.name and data.umoptions and data.umoptions.added and fdwdata %} -{% set addAlter = "False" %} -{% for variable in data.umoptions.added %} -{% if variable.umoption and variable.umoption != '' %} -{% if addAlter == "False" %} +{% if data.umoptions and data.umoptions.added %} +{% if is_valid_added_options %} ALTER USER MAPPING FOR {{ conn|qtIdent(o_data.name) }} SERVER {{ conn|qtIdent(fdwdata.name) }} - OPTIONS ({% set addAlter = "True" %}{% endif %} -ADD {{ conn|qtIdent(variable.umoption) }} {{variable.umvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} -{% endif %} -{% endfor %} + OPTIONS ({% for variable in data.umoptions.added %}{% if loop.index != 1 %}, {% endif %} +ADD {{ conn|qtIdent(variable.umoption) }} {{ variable.umvalue|qtLiteral }}{% endfor %} +); {% endif %} -{% if data.umoptions and data.umoptions.changed and fdwdata %} -{% set addAlter = "False" %} -{% for variable in data.umoptions.changed %} -{% if variable.umoption and variable.umoption != '' %} -{% if addAlter == "False" %} +{% endif %} +{% if data.umoptions and data.umoptions.changed %} +{% if is_valid_changed_options %} ALTER USER MAPPING FOR {{ conn|qtIdent(o_data.name) }} SERVER {{ conn|qtIdent(fdwdata.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -SET {{conn|qtIdent(variable.umoption)}} {{variable.umvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} -{%endif%} -{% endfor %} + OPTIONS ({% for variable in data.umoptions.changed %}{% if loop.index != 1 %}, {% endif %} +SET {{ conn|qtIdent(variable.umoption) }} {{ variable.umvalue|qtLiteral }}{% endfor %} +); {% endif %} +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/js/foreign_data_wrappers.js b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/js/foreign_data_wrappers.js index b5af7f03c..e3639fb61 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/js/foreign_data_wrappers.js +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/js/foreign_data_wrappers.js @@ -6,6 +6,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { // Extend the browser's node model class to create a Options model var OptionsModel = pgBrowser.Node.Model.extend({ + idAttribute: 'fdwoption', defaults: { fdwoption: undefined, fdwvalue: undefined diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/create.sql index 3d33a8ef8..a29fd75b1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/create.sql @@ -7,18 +7,12 @@ CREATE FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}{% if data.fdwvalue %} HANDLER {{ data.fdwhan }}{% endif %}{% if data.fdwoptions %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} - OPTIONS ({% set addAlter = "True" %}{% endif %} -{{ conn|qtIdent(variable.fdwoption) }} {{variable.fdwvalue|qtLiteral}}{% if not loop.last %},{% else %}){% endif %} -{% endif %} -{% endfor %}{% endif %}{%if data %};{%endif%} +{% if is_valid_options %} + OPTIONS ({% for variable in data.fdwoptions %}{% if loop.index != 1 %}, {% endif %} +{{ conn|qtIdent(variable.fdwoption) }} {{ variable.fdwvalue|qtLiteral }}{% endfor %}){% endif %}{% endif %}; {# ============= Set the owner for foreign data wrapper ============= #} {% if data.fdwowner %} - ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.fdwowner) }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/update.sql index 41860cdfe..86307cc0d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/9.3_plus/update.sql @@ -41,44 +41,30 @@ COMMENT ON FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} {% endif %} {# ============= Update foreign data wrapper options and values ============= #} -{% if data.fdwoptions and data.fdwoptions.deleted %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions.deleted %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} +{% if data.fdwoptions and data.fdwoptions.deleted and data.fdwoptions.deleted|length > 0 %} ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -DROP {{ conn|qtIdent(variable.fdwoption) }}{% if not loop.last %},{% else %});{% endif %} -{% endif %} -{% endfor %} - + OPTIONS ({% for variable in data.fdwoptions.deleted %}{% if loop.index != 1 %}, {% endif %} +DROP {{ conn|qtIdent(variable.fdwoption) }}{% endfor %} +); {% endif %} {% if data.fdwoptions and data.fdwoptions.added %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions.added %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} +{% if is_valid_added_options %} ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{% endif %} -ADD {{ conn|qtIdent(variable.fdwoption) }} {{variable.fdwvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} + OPTIONS ({% for variable in data.fdwoptions.added %}{% if loop.index != 1 %}, {% endif %} +ADD {{ conn|qtIdent(variable.fdwoption) }} {{ variable.fdwvalue|qtLiteral }}{% endfor %} +); + {% endif %} -{%endfor%} - - {% endif %} {% if data.fdwoptions and data.fdwoptions.changed %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions.changed %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} +{% if is_valid_changed_options %} ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{% endif %} -SET {{ conn|qtIdent(variable.fdwoption) }} {{variable.fdwvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} + OPTIONS ({% for variable in data.fdwoptions.changed %}{% if loop.index != 1 %}, {% endif %} +SET {{ conn|qtIdent(variable.fdwoption) }} {{ variable.fdwvalue|qtLiteral }}{% endfor %} +); + {% endif %} -{%endfor%} - - {% endif %} {# Change the privileges #} {% if data.fdwacl %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/create.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/create.sql index 17241df8e..5805807a6 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/create.sql @@ -7,14 +7,9 @@ CREATE FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }}{% if data.fdwvalue %} HANDLER {{ data.fdwhan }}{% endif %}{% if data.fdwoptions %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} - OPTIONS ({% set addAlter = "True" %}{% endif %} -{{ conn|qtIdent(variable.fdwoption) }} {{variable.fdwvalue|qtLiteral}}{% if not loop.last %},{% else %}){% endif %} -{% endif %} -{% endfor %}{% endif %}{%if data %};{%endif%} +{% if is_valid_options %} + OPTIONS ({% for variable in data.fdwoptions %}{% if loop.index != 1 %}, {% endif %} +{{ conn|qtIdent(variable.fdwoption) }} {{ variable.fdwvalue|qtLiteral }}{% endfor %}){% endif %}{% endif %}; {# ============= Set the owner for foreign data wrapper ============= #} {% if data.fdwowner %} @@ -24,7 +19,6 @@ ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} {% endif %} {# ============= Comment on of foreign data wrapper object ============= #} {% if data.description %} - COMMENT ON FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} IS {{ data.description|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/update.sql b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/update.sql index 451ea74b1..678585fd4 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/update.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/templates/foreign_data_wrappers/sql/default/update.sql @@ -41,44 +41,30 @@ COMMENT ON FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} {% endif %} {# ============= Update foreign data wrapper options and values ============= #} -{% if data.fdwoptions and data.fdwoptions.deleted %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions.deleted %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} +{% if data.fdwoptions and data.fdwoptions.deleted and data.fdwoptions.deleted|length > 0 %} ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{%endif%} -DROP {{ conn|qtIdent(variable.fdwoption) }}{% if not loop.last %},{% else %});{% endif %} -{% endif %} -{% endfor %} - + OPTIONS ({% for variable in data.fdwoptions.deleted %}{% if loop.index != 1 %}, {% endif %} +DROP {{ conn|qtIdent(variable.fdwoption) }}{% endfor %} +); {% endif %} {% if data.fdwoptions and data.fdwoptions.added %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions.added %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} +{% if is_valid_added_options %} ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{% endif %} -ADD {{ conn|qtIdent(variable.fdwoption) }} {{variable.fdwvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} + OPTIONS ({% for variable in data.fdwoptions.added %}{% if loop.index != 1 %}, {% endif %} +ADD {{ conn|qtIdent(variable.fdwoption) }} {{ variable.fdwvalue|qtLiteral }}{% endfor %} +); + {% endif %} -{%endfor%} - - {% endif %} {% if data.fdwoptions and data.fdwoptions.changed %} -{% set addAlter = "False" %} -{% for variable in data.fdwoptions.changed %} -{% if variable.fdwoption and variable.fdwoption != '' %} -{% if addAlter == "False" %} +{% if is_valid_changed_options %} ALTER FOREIGN DATA WRAPPER {{ conn|qtIdent(data.name) }} - OPTIONS ({% set addAlter = "True" %}{% endif %} -SET {{ conn|qtIdent(variable.fdwoption) }} {{variable.fdwvalue|qtLiteral}}{% if not loop.last %},{% else %});{% endif %} + OPTIONS ({% for variable in data.fdwoptions.changed %}{% if loop.index != 1 %}, {% endif %} +SET {{ conn|qtIdent(variable.fdwoption) }} {{ variable.fdwvalue|qtLiteral }}{% endfor %} +); + {% endif %} -{%endfor%} - - {% endif %} {# Change the privileges #} {% if data.fdwacl %} diff --git a/web/pgadmin/browser/server_groups/servers/utils.py b/web/pgadmin/browser/server_groups/servers/utils.py index 41e62a119..52ff6c381 100644 --- a/web/pgadmin/browser/server_groups/servers/utils.py +++ b/web/pgadmin/browser/server_groups/servers/utils.py @@ -111,3 +111,68 @@ def parse_priv_to_db(str_privileges, allowed_acls=[]): }) return privileges + + +def tokenize_options(options_from_db, option_name, option_value): + """ + This function will tokenize the string stored in database + e.g. database store the value as below + key1=value1, key2=value2, key3=value3, .... + This function will extract key and value from above string + + Args: + options_from_db: Options from database + option_name: Option Name + option_value: Option Value + + Returns: + Tokenized options + """ + options = [] + if options_from_db is not None: + option_str = options_from_db.split(',') + for fdw_option in option_str: + k, v = fdw_option.split('=', 1) + options.append({option_name: k, option_value: v}) + return options + + +def validate_options(options, option_name, option_value): + """ + This function will filter validated options + and sets flag to use in sql template if there are any + valid options + + Args: + options: List of options + option_name: Option Name + option_value: Option Value + + Returns: + Flag, Filtered options + """ + valid_options = [] + is_valid_options = False + + for option in options: + # If option name is valid + if option_name in option and \ + option[option_name] is not None and \ + option[option_name] != '' and \ + len(option[option_name].strip()) > 0: + # If option value is valid + if option_value in option and \ + option[option_value] is not None and \ + option[option_value] != '' and \ + len(option[option_value].strip()) > 0: + # Do nothing here + pass + else: + # Set empty string if no value provided + option[option_value] = '' + valid_options.append(option) + + if len(valid_options) > 0: + is_valid_options = True + + return is_valid_options, valid_options