6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-23 14:03:06 +01:00
firebird-qa/tests/bugs/core_6278_test.py

114 lines
4.1 KiB
Python
Raw Normal View History

2021-04-26 20:07:00 +02:00
#coding:utf-8
2022-01-27 20:08:36 +01:00
"""
ID: issue-6520
ISSUE: 6520
TITLE: Efficient table scans for DBKEY-based range conditions
DESCRIPTION:
We create table with very wide column and add there about 300 rows from rdb$types, with random data
(in order to prevent RLE-compression which eventually can reduce number of data pages).
Then we extract all values of rdb$db_key from this table and take into processing two of them.
First value has 'distance' from starting db_key = 1/3 of total numbers of rows, second has similar
distance from final db_key.
Finally we launch trace and start query with SCOPED expression for RDB$DB_KEY:
select count(*) from tmp_test_6278 where rdb$db_key between ? and ?
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
Trace must contain after this explained plan with "lower bound, upper bound" phrase and table statistics
which shows number of reads = count of rows plus 1.
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
Before fix trace table statistics did not reflect scoped WHERE-expression on RDB$DB_KEY column.
JIRA: CORE-6278
FBTEST: bugs.core_6278
2022-01-27 20:08:36 +01:00
"""
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
import pytest
import re
from firebird.qa import *
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
db = db_factory()
2021-12-14 20:56:34 +01:00
2022-01-27 20:08:36 +01:00
act = python_act('db')
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
expected_stdout = """
2021-04-26 20:07:00 +02:00
-> Table "TMP_TEST_6278" Full Scan (lower bound, upper bound)
Reads difference: EXPECTED.
2021-12-14 20:56:34 +01:00
"""
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
test_script = """
2021-12-14 20:56:34 +01:00
recreate table tmp_test_6278 (s varchar(32700)) ;
insert into tmp_test_6278 select lpad('', 32700, uuid_to_char(gen_uuid())) from rdb$types ;
commit ;
set heading off ;
set term ^ ;
execute block returns(
count_intermediate_rows int
) as
declare dbkey_1 char(8) character set octets ;
declare dbkey_2 char(8) character set octets ;
declare sttm varchar(255) ;
begin
select max(iif( ri=1, dbkey, null)), max(iif( ri=2, dbkey, null))
from (
select dbkey, row_number()over(order by dbkey) ri
from (
select
dbkey
,row_number()over(order by dbkey) ra
,row_number()over(order by dbkey desc) rd
from (select rdb$db_key as dbkey from tmp_test_6278)
)
where
ra = (ra+rd)/3
or rd = (ra+rd)/3
) x
into dbkey_1, dbkey_2 ;
sttm = q'{select count(*) from tmp_test_6278 where rdb$db_key between ? and ?}' ;
execute statement (sttm) (dbkey_1, dbkey_2) into count_intermediate_rows ;
suspend ;
end ^
set term ; ^
commit ;
"""
2021-04-26 20:07:00 +02:00
2022-01-27 20:08:36 +01:00
trace = ['log_statement_finish = true',
'print_plan = true',
'print_perf = true',
'explain_plan = true',
'time_threshold = 0',
'log_initfini = false',
'exclude_filter = "%(execute block)%"',
'include_filter = "%(select count)%"',
]
2021-12-14 20:56:34 +01:00
@pytest.mark.version('>=4.0')
2022-01-27 20:08:36 +01:00
def test_1(act: Action, capsys):
2021-12-14 20:56:34 +01:00
allowed_patterns = [re.compile(' Table "TMP_TEST_6278"', re.IGNORECASE),
re.compile('TMP_TEST_6278\\s+\\d+', re.IGNORECASE)
]
2021-12-19 22:25:36 +01:00
# For yet unknown reason, trace must be read as in 'cp1252' (neither ascii or utf8 works)
2022-01-27 20:08:36 +01:00
with act.trace(db_events=trace, encoding='cp1252'):
act.isql(switches=['-q'], input=test_script)
2022-02-09 20:47:40 +01:00
# Process isql output
for line in act.clean_stdout.splitlines():
if elements := line.rstrip().split():
count_intermediate_rows = int(elements[0])
break
# Process trace
2022-01-27 20:08:36 +01:00
for line in act.trace_log:
2021-12-14 20:56:34 +01:00
for p in allowed_patterns:
if p.search(line):
if line.startswith('TMP_TEST_6278'):
trace_reads_statistics = int(line.rstrip().split()[1])
result = ('EXPECTED.' if (trace_reads_statistics - count_intermediate_rows) <= 1
else f'UNEXPECTED: {trace_reads_statistics - count_intermediate_rows}')
print(f'Reads difference: {result}')
else:
print(line)
# Check
2022-02-09 20:47:40 +01:00
act.reset() # necessary to reset 'clean_stdout' !!
2022-01-27 20:08:36 +01:00
act.expected_stdout = expected_stdout
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout