6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-01-22 13:33:07 +01:00

Added/Updated tests\bugs\core_2650_test.py: Separated expected_out for FB 6.x after #b2d03 (More correct plan output for subqueries generated during NOT IN transformation). See notes.

This commit is contained in:
pavel-zotov 2025-01-13 13:12:28 +03:00
parent 4634414e66
commit 3bbf0047ba

View File

@ -17,7 +17,7 @@ DESCRIPTION:
JIRA: CORE-2650 JIRA: CORE-2650
FBTEST: bugs.core_2650 FBTEST: bugs.core_2650
NOTES: NOTES:
[02.09.2024] [02.09.2024] pzotov
1. Test was fully re-implemented in order to have ability to see both query and its comment in case of mismatch. 1. Test was fully re-implemented in order to have ability to see both query and its comment in case of mismatch.
The 'f'-notation is used in expected output with substitution query text and comments to it, e.g.: The 'f'-notation is used in expected output with substitution query text and comments to it, e.g.:
{query_map[1000][0]} // output will be compared with: "select txt_short from test a01 order by id" {query_map[1000][0]} // output will be compared with: "select txt_short from test a01 order by id"
@ -37,6 +37,13 @@ NOTES:
https://github.com/FirebirdSQL/firebird/commit/901b4ced9a3615929e0027d42ebb2392e943b205 https://github.com/FirebirdSQL/firebird/commit/901b4ced9a3615929e0027d42ebb2392e943b205
Checked on 6.0.0.447-901b4ce, 5.0.2.1487, 4.0.6.3142 Checked on 6.0.0.447-901b4ce, 5.0.2.1487, 4.0.6.3142
[13.01.2025] pzotov
6. Separated expected_out for FB 6.x after b2d03 2025.01.10 ("More correct plan output for subqueries generated during NOT IN transformation")
7. Parameter OptimizeForFirstRows must have default value fcor this test (i.e. false). To prevent test fail in case of occasional changing of
this parameter, session-level command is used for FB 5.x+: 'set optimize for all rows'.
Checked 6.0.0.573-c20f37a
""" """
import pytest import pytest
@ -212,11 +219,6 @@ query_map = {
} }
test_script = """
set plan on;
set explain on;
"""
############################################################################### ###############################################################################
fb4x_expected_out = f""" fb4x_expected_out = f"""
@ -859,6 +861,316 @@ fb5x_expected_out = f"""
........-> Table "TEST_NS_06" Full Scan ........-> Table "TEST_NS_06" Full Scan
""" """
###############################################################################
fb6x_expected_out = f"""
1000
select txt_short from test a01 order by id
Must NOT use refetch because length of non-key column is less than threshold
Select Expression
....-> Sort (record length: 1036, key length: 8)
........-> Table "TEST" as "A01" Full Scan
1010
select txt_broad from test a02 order by id
MUST use refetch because length of non-key column is greater than threshold
Select Expression
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Table "TEST" as "A02" Full Scan
1020
select txt_short from test a03 order by id rows 1
MUST use refetch regardless on length of column because ROWS <N> presents
Select Expression
....-> First N Records
........-> Refetch
............-> Sort (record length: 28, key length: 8)
................-> Table "TEST" as "A03" Full Scan
2000
select id, computed_ts_dup from test order by id
Must NOT use refetch because computed column is based on txt_short with length < threshold
Select Expression
....-> Sort (record length: 1036, key length: 8)
........-> Table "TEST" Full Scan
2010
select id, computed_tb_dup from test order by id
MUST use refetch because computed column is based on txt_broad which has length >= threshold
Select Expression
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Table "TEST" Full Scan
3000
select id from test a04 where '' in (select txt_short from test x04 where txt_short = '' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Filter
........-> Sort (record length: 1036, key length: 8)
............-> Filter
................-> Table "TEST" as "X04" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A04" Full Scan
3010
select id from test a05 where '' in (select txt_broad from test x05 where txt_broad = '' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Filter
........-> Refetch
............-> Sort (record length: 28, key length: 8)
................-> Filter
....................-> Table "TEST" as "X05" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A05" Full Scan
3020
select id from test a06 where '' not in (select txt_short from test x06 where txt_short>'' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Sort (record length: 1036, key length: 8)
........-> Filter
............-> Table "TEST" as "X06" Full Scan
Sub-query (invariant)
....-> Sort (record length: 1036, key length: 8)
........-> Filter
............-> Table "TEST" as "X06" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A06" Full Scan
3030
select id from test a07 where '' not in (select txt_broad from test x07 where txt_broad>'' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Filter
................-> Table "TEST" as "X07" Full Scan
Sub-query (invariant)
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Filter
................-> Table "TEST" as "X07" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A07" Full Scan
3040
select id from test a08 where '' > all (select id from test x08 where txt_short>'' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Filter
........-> Sort (record length: 1036, key length: 8)
............-> Filter
................-> Table "TEST" as "X08" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A08" Full Scan
3050
select id from test a09 where '' > all (select id from test x09 where txt_broad>'' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Filter
........-> Refetch
............-> Sort (record length: 28, key length: 8)
................-> Filter
....................-> Table "TEST" as "X09" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A09" Full Scan
3060
select id from test a10 where '' <> any (select id from test x10 where txt_short>'' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Filter
........-> Sort (record length: 1036, key length: 8)
............-> Filter
................-> Table "TEST" as "X10" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A10" Full Scan
3070
select id from test a11 where '' <> any (select id from test x11 where txt_broad>'' order by id)
*** not [yet] commented ***
Sub-query (invariant)
....-> Filter
........-> Refetch
............-> Sort (record length: 28, key length: 8)
................-> Filter
....................-> Table "TEST" as "X11" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A11" Full Scan
4000
select id,txt_short from test a12 where exists(select 1 from test x12 where txt_short>'' order by id)
MUST use refetch: column x12.txt_short not present in order by
Sub-query (invariant)
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Filter
................-> Table "TEST" as "X12" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A12" Full Scan
4010
select id,txt_short from test a13 where exists(select 1 from test x13 where computed_id_dup > 0 order by id)
Must NOT use refetch: ORDER BY list contains the single element: ID, and it is base for x13.computed_id_dup column
Sub-query (invariant)
....-> Sort (record length: 28, key length: 8)
........-> Filter
............-> Table "TEST" as "X13" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A13" Full Scan
4020
select id,txt_short from test a14 where exists(select 1 from test x14 where computed_id_dup > 0 order by computed_id_dup)
MUST use refetch! See letter from dimitr 28.12.2020 14:49
Sort procedure will get:
a KEY = result of evaluating 'computed_id_dup';
a VAL = value of the field 'ID' which is base for computing 'computed_id_dup'
Thus sorter will have a field which not equals to a key, which leads to refetch.
Sub-query (invariant)
....-> Refetch
........-> Sort (record length: 36, key length: 12)
............-> Filter
................-> Table "TEST" as "X14" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A14" Full Scan
4030
select id,txt_short from test a15 where exists(select 1 from test x15 where f02>0 and f01>0 order by f01, f02)
Must NOT use refetch: all persistent columns from WHERE expression (f01, f02) belong to ORDER BY list
Sub-query (invariant)
....-> Sort (record length: 36, key length: 16)
........-> Filter
............-> Table "TEST" as "X15" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A15" Full Scan
4040
select id,txt_short from test a16 where exists(select 1 from test x16 where id>0 and f01>0 order by f01, f02)
Must use refetch: one of columns from WHERE expr (id) does not belong to ORDER BY list
Sub-query (invariant)
....-> Refetch
........-> Sort (record length: 36, key length: 16)
............-> Filter
................-> Table "TEST" as "X16" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A16" Full Scan
4050
select id,txt_short from test a17 where exists(select 1 from test x17 where computed_id_dup > 0 order by f01)
Must use refetch: computed column in WHERE expr does not belong to ORDER BY list
Sub-query (invariant)
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Filter
................-> Table "TEST" as "X17" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A17" Full Scan
4060
select id,txt_short from test a18 where exists(select 1 from test x18 where computed_guid > '' order by f01)
Must NOT use refetch: computed column x18.computed_guid does is evaluated via GUID and does not refer to any columns
Sub-query (invariant)
....-> Sort (record length: 28, key length: 8)
........-> Filter
............-> Table "TEST" as "X18" Full Scan
Select Expression
....-> Filter (preliminary)
........-> Table "TEST" as "A18" Full Scan
4070
with recursive
r as (
select a19.id, a19.txt_short
from test a19
where not exists(select * from test x where x.txt_short < a19.txt_short order by id)
UNION ALL
select i.id, i.txt_short
from test i
join r on i.id > r.id
and not exists( select * from test x where x.txt_short between r.txt_short and i.txt_short order by id )
)
select * from r
MUST use refetch both in anchor and recursive parts
Sub-query
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Filter
................-> Table "TEST" as "R X" Full Scan
Sub-query
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Filter
................-> Table "TEST" as "R X" Full Scan
Select Expression
....-> Recursion
........-> Filter
............-> Table "TEST" as "R A19" Full Scan
........-> Filter
............-> Table "TEST" as "R I" Full Scan
5000
select txt_broad from v_unioned v01 order by id
Must NOT use refetch because view DDL includes UNION
Select Expression
....-> Sort (record length: 4044, key length: 8)
........-> First N Records
............-> Union
................-> Table "TEST" as "V01 TEST" Full Scan
................-> Table "RDB$DATABASE" as "V01 RDB$DATABASE" Full Scan
6000
select left(txt_broad, 50) as txt from test a21 order by id
MUST use refetch because expression is based on column which has length >= threshold
(even if final length of expression result is much less than threshold)
Select Expression
....-> Refetch
........-> Sort (record length: 28, key length: 8)
............-> Table "TEST" as "A21" Full Scan
6010
select left( txt_short || txt_short, 2000) as txt from test a22 order by id
Must NOT use refetch because expression is based on column which has length < threshold
(even if final length of expression result is much bigger than threshold)
Select Expression
....-> Sort (record length: 1036, key length: 8)
........-> Table "TEST" as "A22" Full Scan
7000
select * from test_ns_01 a23 order by id
MUST use refetch
Select Expression
....-> Refetch
........-> Sort (record length: 44, key length: 24)
............-> Table "TEST_NS_01" as "A23" Full Scan
7010
select * from test_ns_02 a24 order by id
Must NOT refetch
Select Expression
....-> Sort (record length: 1052, key length: 24)
........-> Table "TEST_NS_02" as "A24" Full Scan
7020
select * from test_ns_03 order by id
MUST use refetch
Select Expression
....-> Refetch
........-> Sort (record length: 36, key length: 12)
............-> Table "TEST_NS_03" Full Scan
7030
select * from test_ns_04 order by id
Must NOT use refetch
Select Expression
....-> Sort (record length: 1036, key length: 12)
........-> Table "TEST_NS_04" Full Scan
7040
select * from test_ns_05 order by id
MUST use refetch
Select Expression
....-> Refetch
........-> Sort (record length: 36, key length: 12)
............-> Table "TEST_NS_05" Full Scan
7050
select * from test_ns_06 order by id
Must NOT use refetch
Select Expression
....-> Sort (record length: 1036, key length: 12)
........-> Table "TEST_NS_06" Full Scan
"""
act = python_act('db') act = python_act('db')
#----------------------------------------------------------- #-----------------------------------------------------------
@ -872,6 +1184,14 @@ def replace_leading(source, char="."):
@pytest.mark.version('>=4.0') @pytest.mark.version('>=4.0')
def test_1(act: Action, capsys): def test_1(act: Action, capsys):
with act.db.connect() as con: with act.db.connect() as con:
# 13.01.2025: test will FAIL if config parameter OptimizeForFirstRows differs from default value (i.e. is set to true).
# To prevent this, we have to explicitly change appropriate session-level value:
if act.is_version('<5'):
pass
else:
con.execute_immediate('set optimize for all rows')
cur = con.cursor() cur = con.cursor()
for q_idx, q_tuple in query_map.items(): for q_idx, q_tuple in query_map.items():
test_sql, qry_comment = q_tuple[:2] test_sql, qry_comment = q_tuple[:2]
@ -882,6 +1202,6 @@ def test_1(act: Action, capsys):
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) ) print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
ps.free() ps.free()
act.expected_stdout = fb4x_expected_out if act.is_version('<5') else fb5x_expected_out act.expected_stdout = fb4x_expected_out if act.is_version('<5') else fb5x_expected_out if act.is_version('<6') else fb6x_expected_out
act.stdout = capsys.readouterr().out act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout assert act.clean_stdout == act.clean_expected_stdout