Add support for setting prepare threshold in server connection. #6285

This commit is contained in:
Aditya Toshniwal 2023-10-12 16:54:06 +05:30 committed by GitHub
parent 82fade7645
commit 10adb6a11b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 10 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -206,6 +206,12 @@ Use the fields in the *Advanced* tab to configure a connection:
the password will not expire until your pgAdmin session does.
Zero means the command will be executed for each new connection or reconnection that is made.
If the generated password is not valid indefinitely, set this value to slightly before it will expire.
* Use the *Prepare threshold* field to specify the number of times a query is
executed before it is prepared. If it is set to 0, every query is prepared
the first time it is executed. If it is set to blank, prepared statements are disabled
on the connection. This is particularly useful with external connection poolers,
such as PgBouncer, which is not compatible with prepared statements. Set this to
blank in such cases.
.. note:: The password file option is only supported when pgAdmin is using libpq
v10.0 or later to connect to the server.

View File

@ -0,0 +1,54 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Add support for prepare_threshold param
https://www.psycopg.org/psycopg3/docs/advanced/prepare.html#prepared-statements
Revision ID: 44b9ce549393
Revises: 9426ad06a63b
Create Date: 2023-10-12 12:15:01.757931
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '44b9ce549393'
down_revision = '9426ad06a63b'
branch_labels = None
depends_on = None
def upgrade():
with op.batch_alter_table(
"server", table_kwargs={'sqlite_autoincrement': True}) as batch_op:
batch_op.add_column(sa.Column('prepare_threshold', sa.Integer(),
nullable=True))
with op.batch_alter_table("sharedserver") as batch_op:
batch_op.add_column(sa.Column('prepare_threshold', sa.Integer(),
nullable=True))
# get metadata from current connection
meta = sa.MetaData()
# define table representation
meta.reflect(op.get_bind(), only=('server', 'sharedserver'))
table = sa.Table('server', meta)
op.execute(
table.update().values(prepare_threshold=5)
)
table = sa.Table('sharedserver', meta)
op.execute(
table.update().values(prepare_threshold=5)
)
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass

View File

@ -35,7 +35,6 @@ def upgrade():
batch_op.add_column(sa.Column('shared_username', sa.String(64), nullable=True))
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass

View File

@ -176,6 +176,7 @@ class ServerModule(sg.ServerGroupPluginModule):
server.username = sharedserver.username
server.server_owner = sharedserver.server_owner
server.password = sharedserver.password
server.prepare_threshold = sharedserver.prepare_threshold
return server
@ -390,7 +391,8 @@ class ServerModule(sg.ServerGroupPluginModule):
tunnel_authentication=0,
tunnel_identity_file=None,
shared=True,
connection_params=data.connection_params
connection_params=data.connection_params,
prepare_threshold=data.prepare_threshold
)
db.session.add(shared_server)
db.session.commit()
@ -816,7 +818,8 @@ class ServerNode(PGChildNodeView):
'shared': 'shared',
'shared_username': 'shared_username',
'kerberos_conn': 'kerberos_conn',
'connection_params': 'connection_params'
'connection_params': 'connection_params',
'prepare_threshold': 'prepare_threshold'
}
disp_lbl = {
@ -1109,7 +1112,8 @@ class ServerNode(PGChildNodeView):
'gss_encrypted': manager.gss_encrypted,
'cloud_status': server.cloud_status,
'connection_params': connection_params,
'connection_string': manager.display_connection_string
'connection_string': manager.display_connection_string,
'prepare_threshold': server.prepare_threshold
}
return ajax_response(response)
@ -1202,7 +1206,8 @@ class ServerNode(PGChildNodeView):
passexec_cmd=data.get('passexec_cmd', None),
passexec_expiration=data.get('passexec_expiration', None),
kerberos_conn=1 if data.get('kerberos_conn', False) else 0,
connection_params=connection_params
connection_params=connection_params,
prepare_threshold=data.get('prepare_threshold', None)
)
db.session.add(server)
db.session.commit()

View File

@ -344,9 +344,16 @@ export default class ServerSchema extends BaseUISchema {
id: 'passexec_expiration', label: gettext('Password exec expiration (seconds)'), type: 'int',
group: gettext('Advanced'),
mode: ['properties', 'edit', 'create'],
visible: function(state) {
return !_.isEmpty(state.passexec_cmd);
disabled: function(state) {
return isEmptyString(state.passexec_cmd);
},
},
{
id: 'prepare_threshold', label: gettext('Prepare threshold'), type: 'int',
group: gettext('Advanced'),
mode: ['properties', 'edit', 'create'],
helpMessageMode: ['edit', 'create'],
helpMessage: gettext('If it is set to 0, every query is prepared the first time it is executed. If it is set to blank, prepared statements are disabled on the connection.')
}
];
}

View File

@ -33,7 +33,7 @@ import config
#
##########################################################################
SCHEMA_VERSION = 36
SCHEMA_VERSION = 37
##########################################################################
#
@ -206,6 +206,7 @@ class Server(db.Model):
kerberos_conn = db.Column(db.Boolean(), nullable=False, default=0)
cloud_status = db.Column(db.Integer(), nullable=False, default=0)
connection_params = db.Column(MutableDict.as_mutable(types.JSON))
prepare_threshold = db.Column(db.Integer(), nullable=True)
class ModulePreference(db.Model):
@ -414,6 +415,7 @@ class SharedServer(db.Model):
tunnel_password = db.Column(PgAdminDbBinaryString())
shared = db.Column(db.Boolean(), nullable=False)
connection_params = db.Column(MutableDict.as_mutable(types.JSON))
prepare_threshold = db.Column(db.Integer(), nullable=True)
class Macros(db.Model):

View File

@ -360,12 +360,15 @@ class Connection(BaseConnection):
return await psycopg.AsyncConnection.connect(
connection_string,
cursor_factory=AsyncDictCursor,
autocommit=autocommit)
autocommit=autocommit,
prepare_threshold=manager.prepare_threshold
)
pg_conn = asyncio.run(connectdbserver())
else:
pg_conn = psycopg.Connection.connect(
connection_string,
cursor_factory=DictCursor)
cursor_factory=DictCursor,
prepare_threshold=manager.prepare_threshold)
except psycopg.Error as e:
manager.stop_ssh_tunnel()

View File

@ -112,6 +112,7 @@ class ServerManager(object):
self.gss_encrypted = False
self.connection_params = server.connection_params
self.create_connection_string(self.db, self.user)
self.prepare_threshold = server.prepare_threshold
for con in self.connections:
self.connections[con]._release()