2015-10-20 02:03:18 -05:00
|
|
|
##########################################################################
|
|
|
|
#
|
|
|
|
# pgAdmin 4 - PostgreSQL Tools
|
|
|
|
#
|
2018-01-05 04:42:49 -06:00
|
|
|
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
2015-10-20 02:03:18 -05:00
|
|
|
# This software is released under the PostgreSQL Licence
|
|
|
|
#
|
|
|
|
##########################################################################
|
2016-01-18 08:48:14 -06:00
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
"""Implement the Base class for Driver and Connection"""
|
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
from abc import ABCMeta, abstractmethod, abstractproperty
|
2016-06-21 08:12:14 -05:00
|
|
|
|
2015-11-06 04:23:19 -06:00
|
|
|
import six
|
2015-10-20 02:03:18 -05:00
|
|
|
|
2016-06-21 08:12:14 -05:00
|
|
|
from .registry import DriverRegistry
|
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
|
2015-11-06 04:23:19 -06:00
|
|
|
@six.add_metaclass(DriverRegistry)
|
2015-10-20 02:03:18 -05:00
|
|
|
class BaseDriver(object):
|
|
|
|
"""
|
|
|
|
class BaseDriver(object):
|
|
|
|
|
|
|
|
This is a base class for different server types.
|
|
|
|
Inherit this class to implement different type of database driver
|
|
|
|
implementation.
|
|
|
|
|
2017-03-21 05:12:26 -05:00
|
|
|
(For PostgreSQL/EDB Postgres Advanced Server, we will be using psycopg2)
|
2015-10-20 02:03:18 -05:00
|
|
|
|
|
|
|
Abstract Properties:
|
|
|
|
-------- ----------
|
|
|
|
* Version (string):
|
|
|
|
Current version string for the database server
|
|
|
|
|
2017-10-10 03:31:27 -05:00
|
|
|
* libpq_version (string):
|
|
|
|
Current version string for the used libpq library
|
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
Abstract Methods:
|
|
|
|
-------- -------
|
|
|
|
* get_connection(*args, **kwargs)
|
|
|
|
- It should return a Connection class object, which may/may not be
|
|
|
|
connected to the database server.
|
|
|
|
|
|
|
|
* release_connection(*args, **kwargs)
|
|
|
|
- Implement the connection release logic
|
|
|
|
|
|
|
|
* gc()
|
|
|
|
- Implement this function to release the connections assigned in the
|
|
|
|
session, which has not been pinged from more than the idle timeout
|
|
|
|
configuration.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractproperty
|
|
|
|
def Version(cls):
|
|
|
|
pass
|
|
|
|
|
2017-10-10 03:31:27 -05:00
|
|
|
@abstractproperty
|
|
|
|
def libpq_version(cls):
|
|
|
|
pass
|
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
@abstractmethod
|
|
|
|
def get_connection(self, *args, **kwargs):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def release_connection(self, *args, **kwargs):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def gc(self):
|
|
|
|
pass
|
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
|
2015-11-06 04:23:19 -06:00
|
|
|
@six.add_metaclass(ABCMeta)
|
2015-10-20 02:03:18 -05:00
|
|
|
class BaseConnection(object):
|
|
|
|
"""
|
|
|
|
class BaseConnection(object)
|
|
|
|
|
|
|
|
It is a base class for database connection. A different connection
|
|
|
|
drive must implement this to expose abstract methods for this server.
|
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
General idea is to create a wrapper around the actual driver
|
2015-10-20 02:03:18 -05:00
|
|
|
implementation. It will be instantiated by the driver factory
|
|
|
|
basically. And, they should not be instantiated directly.
|
|
|
|
|
|
|
|
|
|
|
|
Abstract Methods:
|
|
|
|
-------- -------
|
|
|
|
* connect(**kwargs)
|
|
|
|
- Define this method to connect the server using that particular driver
|
|
|
|
implementation.
|
|
|
|
|
2016-04-04 01:58:52 -05:00
|
|
|
* execute_scalar(query, params, formatted_exception_msg)
|
2015-10-20 02:03:18 -05:00
|
|
|
- Implement this method to execute the given query and returns single
|
|
|
|
datum result.
|
|
|
|
|
2016-04-04 01:58:52 -05:00
|
|
|
* execute_async(query, params, formatted_exception_msg)
|
2018-01-31 07:58:55 -06:00
|
|
|
- Implement this method to execute the given query asynchronously and
|
|
|
|
returns result.
|
2016-03-02 07:29:15 -06:00
|
|
|
|
2016-04-04 01:58:52 -05:00
|
|
|
* execute_void(query, params, formatted_exception_msg)
|
2016-03-02 07:29:15 -06:00
|
|
|
- Implement this method to execute the given query with no result.
|
|
|
|
|
2016-04-04 01:58:52 -05:00
|
|
|
* execute_2darray(query, params, formatted_exception_msg)
|
2015-10-20 02:03:18 -05:00
|
|
|
- Implement this method to execute the given query and returns the result
|
2016-03-02 07:29:15 -06:00
|
|
|
as a 2 dimensional array.
|
2015-10-20 02:03:18 -05:00
|
|
|
|
2016-04-04 01:58:52 -05:00
|
|
|
* execute_dict(query, params, formatted_exception_msg)
|
2015-10-20 02:03:18 -05:00
|
|
|
- Implement this method to execute the given query and returns the result
|
|
|
|
as an array of dict (column name -> value) format.
|
|
|
|
|
2017-06-27 08:03:04 -05:00
|
|
|
* def async_fetchmany_2darray(records=-1, formatted_exception_msg=False):
|
|
|
|
- Implement this method to retrieve result of asynchronous connection and
|
|
|
|
polling with no_result flag set to True.
|
|
|
|
This returns the result as a 2 dimensional array.
|
|
|
|
If records is -1 then fetchmany will behave as fetchall.
|
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
* connected()
|
|
|
|
- Implement this method to get the status of the connection. It should
|
|
|
|
return True for connected, otherwise False
|
|
|
|
|
|
|
|
* reset()
|
|
|
|
- Implement this method to reconnect the database server (if possible)
|
|
|
|
|
|
|
|
* transaction_status()
|
|
|
|
- Implement this method to get the transaction status for this
|
|
|
|
connection. Range of return values different for each driver type.
|
|
|
|
|
|
|
|
* ping()
|
|
|
|
- Implement this method to ping the server. There are times, a connection
|
|
|
|
has been lost, but - the connection driver does not know about it. This
|
|
|
|
can be helpful to figure out the actual reason for query failure.
|
|
|
|
|
|
|
|
* _release()
|
|
|
|
- Implement this method to release the connection object. This should not
|
|
|
|
be directly called using the connection object itself.
|
|
|
|
|
|
|
|
NOTE: Please use BaseDriver.release_connection(...) for releasing the
|
|
|
|
connection object for better memory management, and connection pool
|
|
|
|
management.
|
2016-03-02 07:29:15 -06:00
|
|
|
|
|
|
|
* _wait(conn)
|
2016-03-04 04:35:50 -06:00
|
|
|
- Implement this method to wait for asynchronous connection to finish the
|
|
|
|
execution, hence - it must be a blocking call.
|
2016-03-02 07:29:15 -06:00
|
|
|
|
|
|
|
* _wait_timeout(conn, time)
|
2016-03-04 04:35:50 -06:00
|
|
|
- Implement this method to wait for asynchronous connection with timeout.
|
|
|
|
This must be a non blocking call.
|
2016-03-02 07:29:15 -06:00
|
|
|
|
2017-06-27 08:03:04 -05:00
|
|
|
* poll(formatted_exception_msg, no_result)
|
2016-03-04 04:35:50 -06:00
|
|
|
- Implement this method to poll the data of query running on asynchronous
|
|
|
|
connection.
|
2016-03-02 07:29:15 -06:00
|
|
|
|
|
|
|
* cancel_transaction(conn_id, did=None)
|
|
|
|
- Implement this method to cancel the running transaction.
|
2016-03-04 04:35:50 -06:00
|
|
|
|
|
|
|
* messages()
|
|
|
|
- Implement this method to return the list of the messages/notices from
|
|
|
|
the database server.
|
2016-04-12 11:02:54 -05:00
|
|
|
|
|
|
|
* rows_affected()
|
|
|
|
- Implement this method to get the rows affected by the last command
|
|
|
|
executed on the server.
|
2015-10-20 02:03:18 -05:00
|
|
|
"""
|
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
ASYNC_OK = 1
|
|
|
|
ASYNC_READ_TIMEOUT = 2
|
|
|
|
ASYNC_WRITE_TIMEOUT = 3
|
|
|
|
ASYNC_NOT_CONNECTED = 4
|
2016-04-04 01:58:52 -05:00
|
|
|
ASYNC_EXECUTION_ABORTED = 5
|
2018-03-07 07:38:27 -06:00
|
|
|
ASYNC_TIMEOUT = 0.2
|
|
|
|
ASYNC_NOTICE_MAXLENGTH = 100000
|
2016-03-02 07:29:15 -06:00
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
@abstractmethod
|
|
|
|
def connect(self, **kwargs):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-01-31 07:58:55 -06:00
|
|
|
def execute_scalar(self, query, params=None,
|
|
|
|
formatted_exception_msg=False):
|
2015-10-20 02:03:18 -05:00
|
|
|
pass
|
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
@abstractmethod
|
2018-01-31 07:58:55 -06:00
|
|
|
def execute_async(self, query, params=None,
|
|
|
|
formatted_exception_msg=True):
|
2016-03-02 07:29:15 -06:00
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-01-31 07:58:55 -06:00
|
|
|
def execute_void(self, query, params=None,
|
|
|
|
formatted_exception_msg=False):
|
2016-03-02 07:29:15 -06:00
|
|
|
pass
|
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
@abstractmethod
|
2018-01-31 07:58:55 -06:00
|
|
|
def execute_2darray(self, query, params=None,
|
|
|
|
formatted_exception_msg=False):
|
2015-10-20 02:03:18 -05:00
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
2018-01-31 07:58:55 -06:00
|
|
|
def execute_dict(self, query, params=None,
|
|
|
|
formatted_exception_msg=False):
|
2015-10-20 02:03:18 -05:00
|
|
|
pass
|
|
|
|
|
2017-06-27 08:03:04 -05:00
|
|
|
@abstractmethod
|
2018-01-31 07:58:55 -06:00
|
|
|
def async_fetchmany_2darray(self, records=-1,
|
|
|
|
formatted_exception_msg=False):
|
2017-06-27 08:03:04 -05:00
|
|
|
pass
|
|
|
|
|
2015-10-20 02:03:18 -05:00
|
|
|
@abstractmethod
|
|
|
|
def connected(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def reset(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def transaction_status(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def ping(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def _release(self):
|
|
|
|
pass
|
2016-03-02 07:29:15 -06:00
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def _wait(self, conn):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def _wait_timeout(self, conn, time):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@abstractmethod
|
2017-06-27 08:03:04 -05:00
|
|
|
def poll(self, formatted_exception_msg=True, no_result=False):
|
2016-03-02 07:29:15 -06:00
|
|
|
pass
|
|
|
|
|
2016-04-05 02:59:13 -05:00
|
|
|
@abstractmethod
|
|
|
|
def status_message(self):
|
|
|
|
pass
|
|
|
|
|
2016-04-12 11:02:54 -05:00
|
|
|
@abstractmethod
|
|
|
|
def rows_affected(self):
|
|
|
|
pass
|
|
|
|
|
2016-03-02 07:29:15 -06:00
|
|
|
@abstractmethod
|
|
|
|
def cancel_transaction(self, conn_id, did=None):
|
|
|
|
pass
|