mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 13:33:07 +01:00
Added/Updated tests\bugs\gh_8290_test.py: Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds).
This commit is contained in:
parent
d0a66d4f63
commit
debd6ed3fd
154
tests/bugs/gh_8290_test.py
Normal file
154
tests/bugs/gh_8290_test.py
Normal file
@ -0,0 +1,154 @@
|
||||
#coding:utf-8
|
||||
|
||||
"""
|
||||
ID: issue-8290
|
||||
ISSUE: https://github.com/FirebirdSQL/firebird/issues/8290
|
||||
TITLE: "Unique scan" is incorrectly reported in the explained plan for unique index and IS NULL predicate
|
||||
DESCRIPTION:
|
||||
Test creates a table and checks several cases related to issue: asc/desc, computed-by and partial indices.
|
||||
For each case we ask engine to show explained plan. Every case must have 'Range Scan (full match)'.
|
||||
NOTES:
|
||||
[25.10.2024] pzotov
|
||||
Confirmed problem on 6.0.0.485, 5.0.2.1519.
|
||||
Checked on 6.0.0.502-d2f4cf6, 5.0.2.1542-ab50e20 (intermediate builds).
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from firebird.qa import *
|
||||
|
||||
init_sql = """
|
||||
recreate table test(id int generated by default as identity, x int, y int, z int);
|
||||
insert into test(x, y, z) select null, null, null from rdb$types, rdb$types rows 1000;
|
||||
commit;
|
||||
create unique index test_x_asc on test(x);
|
||||
create unique descending index test_y_desc on test(y);
|
||||
create unique index test_x_plus_y on test computed by (x+y);
|
||||
|
||||
create unique index test_z_partial on test(z) where mod(id,2) = 0;
|
||||
create unique index test_x_minus_y_partial on test computed by (x-y) where mod(id,3) <= 1;
|
||||
commit;
|
||||
"""
|
||||
db = db_factory(init = init_sql)
|
||||
|
||||
act = python_act('db')
|
||||
|
||||
#-----------------------------------------------------------
|
||||
|
||||
def replace_leading(source, char="."):
|
||||
stripped = source.lstrip()
|
||||
return char * (len(source) - len(stripped)) + stripped
|
||||
|
||||
#-----------------------------------------------------------
|
||||
|
||||
@pytest.mark.version('>=5.0.2')
|
||||
def test_1(act: Action, capsys):
|
||||
|
||||
qry_map = {
|
||||
0 : 'select count(*) from test where x is null'
|
||||
,1 : 'select count(*) from test where y is null'
|
||||
,2 : 'select count(*) from test where x+y is null'
|
||||
,3 : 'select count(*) from test where z is null and mod(id,2) = 0'
|
||||
,4 : 'select count(*) from test where x-y is null and mod(id,3) <= 1'
|
||||
,5 : 'select count(*) from test where x is not distinct from null'
|
||||
,6 : 'select count(*) from test where y is not distinct from null'
|
||||
,7 : 'select count(*) from test where x+y is not distinct from null'
|
||||
,8 : 'select count(*) from test where z is not distinct from null and mod(id,2) = 0'
|
||||
,9 : 'select count(*) from test where x-y is not distinct from null and mod(id,3) <= 1'
|
||||
}
|
||||
|
||||
with act.db.connect() as con:
|
||||
cur = con.cursor()
|
||||
for k,v in qry_map.items():
|
||||
ps = cur.prepare(v)
|
||||
# Print explained plan with padding eash line by dots in order to see indentations:
|
||||
print(v)
|
||||
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
|
||||
print('')
|
||||
|
||||
|
||||
expected_out = f"""
|
||||
{qry_map[0]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_X_ASC" Range Scan (full match)
|
||||
|
||||
{qry_map[1]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_Y_DESC" Range Scan (full match)
|
||||
|
||||
{qry_map[2]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_X_PLUS_Y" Range Scan (full match)
|
||||
|
||||
{qry_map[3]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_Z_PARTIAL" Range Scan (full match)
|
||||
|
||||
{qry_map[4]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_X_MINUS_Y_PARTIAL" Range Scan (full match)
|
||||
|
||||
{qry_map[5]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_X_ASC" Range Scan (full match)
|
||||
|
||||
{qry_map[6]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_Y_DESC" Range Scan (full match)
|
||||
|
||||
{qry_map[7]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_X_PLUS_Y" Range Scan (full match)
|
||||
|
||||
{qry_map[8]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_Z_PARTIAL" Range Scan (full match)
|
||||
|
||||
{qry_map[9]}
|
||||
Select Expression
|
||||
....-> Aggregate
|
||||
........-> Filter
|
||||
............-> Table "TEST" Access By ID
|
||||
................-> Bitmap
|
||||
....................-> Index "TEST_X_MINUS_Y_PARTIAL" Range Scan (full match)
|
||||
"""
|
||||
|
||||
act.expected_stdout = expected_out
|
||||
|
||||
act.stdout = capsys.readouterr().out
|
||||
assert act.clean_stdout == act.clean_expected_stdout
|
Loading…
Reference in New Issue
Block a user