mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-02-02 02:40:42 +01:00
Added/Updated tests\bugs\gh_8176_test.py: Checked on 6.0.0.392-3fa8e6b, 5.0.1.1434-2593b3b. WARNING: SEE NOTES INSIDE.
This commit is contained in:
parent
19514b3aea
commit
55556e1595
194
tests/bugs/gh_8176_test.py
Normal file
194
tests/bugs/gh_8176_test.py
Normal file
@ -0,0 +1,194 @@
|
||||
#coding:utf-8
|
||||
|
||||
"""
|
||||
ID: issue-8176
|
||||
ISSUE: https://github.com/FirebirdSQL/firebird/issues/8176
|
||||
TITLE: Firebird hangs after starting remote profiling session
|
||||
DESCRIPTION:
|
||||
We create two users: tmp_worker_usr and tmp_profiler_usr.
|
||||
First of them will perform some 'useful work', second will PROFILE attachment of tmp_worker_usr.
|
||||
Also, we create role 'tmp_profiler_role' and grant it to 'tmp_profiler_usr'.
|
||||
Ability to profile ather attachment (by tmp_profiler_usr) is achieved via granting to role
|
||||
tmp_profiler_role system privilege PROFILE_ANY_ATTACHMENT.
|
||||
Then we create three connections to test DB belonging to tmp_worker_usr, tmp_profiler_usr and SYSDBA.
|
||||
We pass attachment_id of tmp_worker_usr to the call 'select rdb$profiler.start_session(...)' performed
|
||||
by tmp_profiler_usr. Executing of this causes creation of PLG$PROFILE* tables and views in the test DB
|
||||
(they are created by special internal connection - this can be seen in the trace).
|
||||
Unfortunately, usedr who calls rdb$profiler.start_session() will *NOT* have any access rights to created
|
||||
PLG* objects. This must be donw explicitly to SYSDBA (and this is the reason why we create 3rd connection).
|
||||
Finally, we do somewhat similar to example described doc/sql.extensions/README.profiler.md: run two dummy
|
||||
procedures by tmp_worker_usr, and after that - call proc rdb$profiler.finish_session by tmp_profiler_usr.
|
||||
At the last step, we query data from plg$prof_sessions (it must have number of records equal to the number
|
||||
of profiling sessions that we have created).
|
||||
NOTES:
|
||||
[10.07.2024] pzotov
|
||||
::: WARNING :::
|
||||
1. On CLASSIC problem still exists: firebird hangs, although new connections to test DB are allowed (found both on 5.x and 6.x).
|
||||
One may even to run 'delete from mon$attachments' (using new ISQL session) but there is no effect: server does not perform that.
|
||||
Because of this, test currently can be run only on Super.
|
||||
2. It looks weird that user (NON-sysdba) who has necessary rights to start profiling, must be explicitly granted to access PLG* tables/views.
|
||||
|
||||
Confirmed bug on 6.0.0.389-cc71c6f (SS), 5.0.1.1432-9d5a60a (SS) - server hanged and did not allow to make new connections to test DB.
|
||||
Checked on 6.0.0.392-3fa8e6b, 5.0.1.1434-2593b3b.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from firebird.qa import *
|
||||
from firebird.driver import tpb, Isolation # , TraLockResolution, TraAccessMode, DatabaseError
|
||||
import time
|
||||
|
||||
N_COUNT = 1000
|
||||
init_script = f"""
|
||||
create or alter procedure sp_ins as begin end;
|
||||
create or alter procedure sp_del as begin end;
|
||||
|
||||
recreate table test (
|
||||
id integer primary key,
|
||||
val integer not null
|
||||
);
|
||||
|
||||
set term ^;
|
||||
|
||||
create or alter function fn_mult(p1 integer, p2 integer) returns integer
|
||||
as
|
||||
begin
|
||||
return p1 * p2;
|
||||
end^
|
||||
|
||||
create or alter procedure sp_ins sql security definer
|
||||
as
|
||||
declare i integer = 1;
|
||||
begin
|
||||
while (i <= {N_COUNT})
|
||||
do
|
||||
begin
|
||||
if (mod(i, 2) = 1) then
|
||||
insert into test values (:i, fn_mult(:i, 2));
|
||||
i = i + 1;
|
||||
end
|
||||
end
|
||||
^
|
||||
|
||||
create or alter procedure sp_del sql security definer
|
||||
as
|
||||
declare i integer = 1;
|
||||
begin
|
||||
while (i <= {N_COUNT} / 2)
|
||||
do
|
||||
begin
|
||||
if (mod(i, 2) = 1) then
|
||||
delete from test where id = fn_mult(:i, 2);
|
||||
i = i + 1;
|
||||
end
|
||||
end
|
||||
^
|
||||
set term ;^
|
||||
commit;
|
||||
|
||||
grant execute on procedure sp_ins to public;
|
||||
grant execute on procedure sp_del to public;
|
||||
commit;
|
||||
"""
|
||||
|
||||
tmp_worker_usr = user_factory('db', name='tmp_worker_8176', password='123')
|
||||
tmp_profiler_usr = user_factory('db', name='tmp_profiler_8176', password='456')
|
||||
tmp_profiler_role = role_factory('db', name='tmp_profiler_role')
|
||||
|
||||
db = db_factory(init=init_script)
|
||||
act = python_act('db')
|
||||
|
||||
@pytest.mark.disabled_in_forks
|
||||
@pytest.mark.version('>=5.0.1')
|
||||
def test_1(act: Action, tmp_worker_usr: User, tmp_profiler_usr: User, tmp_profiler_role: Role, capsys):
|
||||
|
||||
if act.vars['server-arch'] != 'SuperServer':
|
||||
pytest.skip("SEE NOTES: currently Super only.")
|
||||
|
||||
addi_script = f"""
|
||||
set wng off;
|
||||
set bail on;
|
||||
alter user {tmp_profiler_usr.name} revoke admin role;
|
||||
revoke all on all from {tmp_profiler_usr.name};
|
||||
commit;
|
||||
-- doc/sql.extensions/README.profiler.md:
|
||||
-- If the remote attachment is from a different user, the calling user must have the system privilege `PROFILE_ANY_ATTACHMENT`.
|
||||
alter role {tmp_profiler_role.name}
|
||||
set system privileges to PROFILE_ANY_ATTACHMENT;
|
||||
commit;
|
||||
grant default {tmp_profiler_role.name} to user {tmp_profiler_usr.name};
|
||||
commit;
|
||||
"""
|
||||
act.isql(switches=['-q'], input=addi_script)
|
||||
|
||||
custom_tpb = tpb(isolation = Isolation.READ_COMMITTED_READ_CONSISTENCY, lock_timeout = 0)
|
||||
|
||||
with act.db.connect() as con_admin, \
|
||||
act.db.connect(user = tmp_worker_usr.name, password = tmp_worker_usr.password) as con_worker, \
|
||||
act.db.connect(user = tmp_profiler_usr.name, password = tmp_profiler_usr.password, role = tmp_profiler_role.name) as con_profiler:
|
||||
|
||||
cur_worker = con_worker.cursor()
|
||||
cur_worker.execute('select current_connection from rdb$database')
|
||||
worker_attach_id = cur_worker.fetchone()[0]
|
||||
|
||||
tx_profiler = con_profiler.transaction_manager(custom_tpb)
|
||||
cur_profiler = tx_profiler.cursor()
|
||||
|
||||
#..............................................................................
|
||||
|
||||
tx_profiler.begin()
|
||||
cur_profiler.execute(f"select rdb$profiler.start_session('remote_profiling_of_inserts', null, {worker_attach_id}) from rdb$database;")
|
||||
cur_profiler.fetchall()
|
||||
|
||||
cur_worker.callproc('sp_ins')
|
||||
|
||||
cur_profiler.callproc(f'rdb$profiler.finish_session(true, {worker_attach_id})')
|
||||
tx_profiler.commit()
|
||||
|
||||
#..............................................................................
|
||||
|
||||
tx_profiler.begin()
|
||||
cur_profiler.execute(f"select rdb$profiler.start_session('remote_profiling_of_deletions', null, {worker_attach_id}) from rdb$database;")
|
||||
cur_profiler.fetchall()
|
||||
|
||||
cur_worker.callproc('sp_del')
|
||||
|
||||
cur_profiler.callproc(f'rdb$profiler.finish_session(true, {worker_attach_id})')
|
||||
tx_profiler.commit()
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# firebird.driver.types.DatabaseError: no permission for SELECT access to TABLE PLG$PROF_SESSIONS
|
||||
# -Effective user is TMP_USER_PROFILER_ANY_ATT
|
||||
#################################
|
||||
# ::: NB ::: Why this is needed ?
|
||||
#################################
|
||||
con_admin.execute_immediate(f'grant select on plg$prof_sessions to role {tmp_profiler_role.name}')
|
||||
con_admin.execute_immediate(f'grant select on plg$prof_psql_stats_view to role {tmp_profiler_role.name}')
|
||||
con_admin.commit()
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
tx_profiler.begin()
|
||||
cur_profiler.execute('select description as profiler_session_descr, attachment_id as profiled_attachment, trim(user_name) as who_was_profiled from plg$prof_sessions order by profile_id')
|
||||
cur_cols = cur_profiler.description
|
||||
for r in cur_profiler:
|
||||
for i in range(0,len(cur_cols)):
|
||||
print( cur_cols[i][0], ':', r[i] )
|
||||
|
||||
#cur_profiler.execute('select * from plg$prof_psql_stats_view')
|
||||
#cur_cols = cur_profiler.description
|
||||
#for r in cur_profiler:
|
||||
# for i in range(0,len(cur_cols)):
|
||||
# print( cur_cols[i][0], ':', r[i] )
|
||||
|
||||
tx_profiler.commit()
|
||||
|
||||
act.expected_stdout = f"""
|
||||
PROFILER_SESSION_DESCR : remote_profiling_of_inserts
|
||||
PROFILED_ATTACHMENT : {worker_attach_id}
|
||||
WHO_WAS_PROFILED : {tmp_worker_usr.name.upper()}
|
||||
|
||||
PROFILER_SESSION_DESCR : remote_profiling_of_deletions
|
||||
PROFILED_ATTACHMENT : {worker_attach_id}
|
||||
WHO_WAS_PROFILED : {tmp_worker_usr.name.upper()}
|
||||
"""
|
||||
act.stdout = capsys.readouterr().out
|
||||
assert act.clean_stdout == act.clean_expected_stdout
|
Loading…
Reference in New Issue
Block a user