Add support for setting prepare threshold in server connection. #6285
parent
82fade7645
commit
10adb6a11b
Binary file not shown.
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 74 KiB |
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.')
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue