mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Ensure the query tool will work with older versions of psycopg2 than we officially support, albeit without updateable resultsets. Fixes #4520
This commit is contained in:
committed by
Dave Page
parent
cbe40176c1
commit
7b65507533
@@ -134,6 +134,9 @@ A result set is updatable if:
|
|||||||
* All the primary keys or OIDs of the table are explicitly selected.
|
* All the primary keys or OIDs of the table are explicitly selected.
|
||||||
* No columns are duplicated.
|
* No columns are duplicated.
|
||||||
|
|
||||||
|
The psycopg2 driver version should be equal to or above 2.8 for updatable
|
||||||
|
query result sets to work.
|
||||||
|
|
||||||
An updatable result set can be modified just like in
|
An updatable result set can be modified just like in
|
||||||
:ref:`View/Edit Data <modifying-data-grid>` mode.
|
:ref:`View/Edit Data <modifying-data-grid>` mode.
|
||||||
|
|
||||||
|
|||||||
@@ -26,3 +26,4 @@ Bug fixes
|
|||||||
| `Issue #4496 <https://redmine.postgresql.org/issues/4496>`_ - Ensure columns can be created when they are IDENTITY fields with the CYCLE option enabled.
|
| `Issue #4496 <https://redmine.postgresql.org/issues/4496>`_ - Ensure columns can be created when they are IDENTITY fields with the CYCLE option enabled.
|
||||||
| `Issue #4497 <https://redmine.postgresql.org/issues/4497>`_ - Ensure purely numeric comments can be saved on new columns.
|
| `Issue #4497 <https://redmine.postgresql.org/issues/4497>`_ - Ensure purely numeric comments can be saved on new columns.
|
||||||
| `Issue #4508 <https://redmine.postgresql.org/issues/4508>`_ - Fix accessibility issue for Datetime cell in backgrid.
|
| `Issue #4508 <https://redmine.postgresql.org/issues/4508>`_ - Fix accessibility issue for Datetime cell in backgrid.
|
||||||
|
| `Issue #4520 <https://redmine.postgresql.org/issues/4520>`_ - Ensure the query tool will work with older versions of psycopg2 than we officially support, albeit without updatable resultsets.
|
||||||
@@ -50,6 +50,9 @@ class QueryToolJourneyTest(BaseFeatureTest):
|
|||||||
|
|
||||||
self.page.add_server(self.server)
|
self.page.add_server(self.server)
|
||||||
|
|
||||||
|
driver_version = test_utils.get_driver_version()
|
||||||
|
self.driver_version = float('.'.join(driver_version.split('.')[:2]))
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
self._navigate_to_query_tool()
|
self._navigate_to_query_tool()
|
||||||
self._execute_query(
|
self._execute_query(
|
||||||
@@ -190,6 +193,9 @@ class QueryToolJourneyTest(BaseFeatureTest):
|
|||||||
self._assert_clickable(query_we_need_to_scroll_to)
|
self._assert_clickable(query_we_need_to_scroll_to)
|
||||||
|
|
||||||
def _test_updatable_resultset(self):
|
def _test_updatable_resultset(self):
|
||||||
|
if self.driver_version < 2.8:
|
||||||
|
return
|
||||||
|
|
||||||
self.page.click_tab("Query Editor")
|
self.page.click_tab("Query Editor")
|
||||||
|
|
||||||
# Insert data into test table
|
# Insert data into test table
|
||||||
|
|||||||
@@ -424,16 +424,16 @@ def poll(trans_id):
|
|||||||
# If trans_obj is a QueryToolCommand then check for updatable
|
# If trans_obj is a QueryToolCommand then check for updatable
|
||||||
# resultsets and primary keys
|
# resultsets and primary keys
|
||||||
if isinstance(trans_obj, QueryToolCommand):
|
if isinstance(trans_obj, QueryToolCommand):
|
||||||
trans_obj.check_updatable_results_pkeys_oids()
|
if trans_obj.check_updatable_results_pkeys_oids():
|
||||||
pk_names, primary_keys = trans_obj.get_primary_keys()
|
pk_names, primary_keys = trans_obj.get_primary_keys()
|
||||||
session_obj['has_oids'] = trans_obj.has_oids()
|
session_obj['has_oids'] = trans_obj.has_oids()
|
||||||
# Update command_obj in session obj
|
# Update command_obj in session obj
|
||||||
session_obj['command_obj'] = pickle.dumps(
|
session_obj['command_obj'] = pickle.dumps(
|
||||||
trans_obj, -1)
|
trans_obj, -1)
|
||||||
# If primary_keys exist, add them to the session_obj to
|
# If primary_keys exist, add them to the session_obj to
|
||||||
# allow for saving any changes to the data
|
# allow for saving any changes to the data
|
||||||
if primary_keys is not None:
|
if primary_keys is not None:
|
||||||
session_obj['primary_keys'] = primary_keys
|
session_obj['primary_keys'] = primary_keys
|
||||||
|
|
||||||
if 'has_oids' in session_obj:
|
if 'has_oids' in session_obj:
|
||||||
has_oids = session_obj['has_oids']
|
has_oids = session_obj['has_oids']
|
||||||
|
|||||||
@@ -896,6 +896,13 @@ class QueryToolCommand(BaseCommand, FetchedRowTracker):
|
|||||||
manager = driver.connection_manager(self.sid)
|
manager = driver.connection_manager(self.sid)
|
||||||
conn = manager.connection(did=self.did, conn_id=self.conn_id)
|
conn = manager.connection(did=self.did, conn_id=self.conn_id)
|
||||||
|
|
||||||
|
# Get the driver version as a float
|
||||||
|
driver_version = float('.'.join(driver.Version().split('.')[:2]))
|
||||||
|
|
||||||
|
# Checking for updatable resultsets uses features in psycopg 2.8
|
||||||
|
if driver_version < 2.8:
|
||||||
|
return False
|
||||||
|
|
||||||
# Get the path to the sql templates
|
# Get the path to the sql templates
|
||||||
sql_path = 'sqleditor/sql/#{0}#'.format(manager.version)
|
sql_path = 'sqleditor/sql/#{0}#'.format(manager.version)
|
||||||
|
|
||||||
@@ -918,6 +925,7 @@ class QueryToolCommand(BaseCommand, FetchedRowTracker):
|
|||||||
self.__set_updatable_results_attrs(sql_path=sql_path,
|
self.__set_updatable_results_attrs(sql_path=sql_path,
|
||||||
table_oid=table_oid,
|
table_oid=table_oid,
|
||||||
conn=conn)
|
conn=conn)
|
||||||
|
return self.is_updatable_resultset
|
||||||
|
|
||||||
def save(self,
|
def save(self,
|
||||||
changed_data,
|
changed_data,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
|||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression import parent_node_dict
|
from regression import parent_node_dict
|
||||||
from regression.python_test_utils import test_utils as utils
|
from regression.python_test_utils import test_utils as utils
|
||||||
from .execute_query_utils import execute_query
|
from pgadmin.tools.sqleditor.tests.execute_query_utils import execute_query
|
||||||
|
|
||||||
|
|
||||||
class TestQueryUpdatableResultset(BaseTestGenerator):
|
class TestQueryUpdatableResultset(BaseTestGenerator):
|
||||||
@@ -120,6 +120,7 @@ class TestQueryUpdatableResultset(BaseTestGenerator):
|
|||||||
|
|
||||||
def _initialize_database_connection(self):
|
def _initialize_database_connection(self):
|
||||||
database_info = parent_node_dict["database"][-1]
|
database_info = parent_node_dict["database"][-1]
|
||||||
|
self.db_name = database_info["db_name"]
|
||||||
self.server_id = database_info["server_id"]
|
self.server_id = database_info["server_id"]
|
||||||
|
|
||||||
self.server_version = parent_node_dict["schema"][-1]["server_version"]
|
self.server_version = parent_node_dict["schema"][-1]["server_version"]
|
||||||
@@ -128,6 +129,12 @@ class TestQueryUpdatableResultset(BaseTestGenerator):
|
|||||||
self.skipTest('Tables with OIDs are not supported starting '
|
self.skipTest('Tables with OIDs are not supported starting '
|
||||||
'PostgreSQL 12')
|
'PostgreSQL 12')
|
||||||
|
|
||||||
|
driver_version = utils.get_driver_version()
|
||||||
|
driver_version = float('.'.join(driver_version.split('.')[:2]))
|
||||||
|
|
||||||
|
if driver_version < 2.8:
|
||||||
|
self.skipTest('Updatable resultsets require pyscopg 2.8 or later')
|
||||||
|
|
||||||
self.db_id = database_info["db_id"]
|
self.db_id = database_info["db_id"]
|
||||||
db_con = database_utils.connect_database(self,
|
db_con = database_utils.connect_database(self,
|
||||||
utils.SERVER_GROUP,
|
utils.SERVER_GROUP,
|
||||||
@@ -172,10 +179,5 @@ class TestQueryUpdatableResultset(BaseTestGenerator):
|
|||||||
else:
|
else:
|
||||||
create_sql += ';'
|
create_sql += ';'
|
||||||
|
|
||||||
is_success, _ = \
|
utils.create_table_with_query(self.server, self.db_name, create_sql)
|
||||||
execute_query(tester=self.tester,
|
|
||||||
query=create_sql,
|
|
||||||
start_query_tool_url=self.start_query_tool_url,
|
|
||||||
poll_url=self.poll_url)
|
|
||||||
self.assertEquals(is_success, True)
|
|
||||||
return test_table_name
|
return test_table_name
|
||||||
@@ -15,11 +15,11 @@ from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
|||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression import parent_node_dict
|
from regression import parent_node_dict
|
||||||
from regression.python_test_utils import test_utils as utils
|
from regression.python_test_utils import test_utils as utils
|
||||||
from .execute_query_utils import execute_query
|
from pgadmin.tools.sqleditor.tests.execute_query_utils import execute_query
|
||||||
|
|
||||||
|
|
||||||
class TestSaveChangedData(BaseTestGenerator):
|
class TestSaveChangedData(BaseTestGenerator):
|
||||||
""" This class tests saving data changes in the grid to the database """
|
""" This class tests saving data changes to updatable query resultsets """
|
||||||
scenarios = [
|
scenarios = [
|
||||||
('When inserting new valid row', dict(
|
('When inserting new valid row', dict(
|
||||||
save_payload={
|
save_payload={
|
||||||
@@ -304,6 +304,7 @@ class TestSaveChangedData(BaseTestGenerator):
|
|||||||
|
|
||||||
def _initialize_database_connection(self):
|
def _initialize_database_connection(self):
|
||||||
database_info = parent_node_dict["database"][-1]
|
database_info = parent_node_dict["database"][-1]
|
||||||
|
self.db_name = database_info["db_name"]
|
||||||
self.server_id = database_info["server_id"]
|
self.server_id = database_info["server_id"]
|
||||||
|
|
||||||
self.db_id = database_info["db_id"]
|
self.db_id = database_info["db_id"]
|
||||||
@@ -311,6 +312,13 @@ class TestSaveChangedData(BaseTestGenerator):
|
|||||||
utils.SERVER_GROUP,
|
utils.SERVER_GROUP,
|
||||||
self.server_id,
|
self.server_id,
|
||||||
self.db_id)
|
self.db_id)
|
||||||
|
|
||||||
|
driver_version = utils.get_driver_version()
|
||||||
|
driver_version = float('.'.join(driver_version.split('.')[:2]))
|
||||||
|
|
||||||
|
if driver_version < 2.8:
|
||||||
|
self.skipTest('Updatable resultsets require pyscopg 2.8 or later')
|
||||||
|
|
||||||
if not db_con["info"] == "Database connected.":
|
if not db_con["info"] == "Database connected.":
|
||||||
raise Exception("Could not connect to the database.")
|
raise Exception("Could not connect to the database.")
|
||||||
|
|
||||||
@@ -347,9 +355,5 @@ class TestSaveChangedData(BaseTestGenerator):
|
|||||||
self.test_table_name,
|
self.test_table_name,
|
||||||
self.test_table_name)
|
self.test_table_name)
|
||||||
self.select_sql = 'SELECT * FROM %s;' % self.test_table_name
|
self.select_sql = 'SELECT * FROM %s;' % self.test_table_name
|
||||||
is_success, _ = \
|
|
||||||
execute_query(tester=self.tester,
|
utils.create_table_with_query(self.server, self.db_name, create_sql)
|
||||||
query=create_sql,
|
|
||||||
start_query_tool_url=self.start_query_tool_url,
|
|
||||||
poll_url=self.poll_url)
|
|
||||||
self.assertEquals(is_success, True)
|
|
||||||
@@ -1080,3 +1080,8 @@ def get_watcher_dialogue_status(self):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
||||||
|
def get_driver_version():
|
||||||
|
version = getattr(psycopg2, '__version__', None)
|
||||||
|
return version
|
||||||
|
|||||||
Reference in New Issue
Block a user