6
0
mirror of https://github.com/FirebirdSQL/firebird-qa.git synced 2025-02-02 02:40:42 +01:00

Added/Updated tests\functional\tabloid\test_cc183f59.py: Checked on 6.0.0.467. See notes about MERGE JOIN selecting.

This commit is contained in:
pavel-zotov 2024-09-25 00:09:52 +03:00
parent 7f28961f1b
commit a60b8c72cb

View File

@ -0,0 +1,102 @@
#coding:utf-8
"""
ID: None
ISSUE: https://github.com/FirebirdSQL/firebird/commit/cc183f599ee09233d6da294893f651de0ab76136
TITLE: Add key info to the merge join plan output
DESCRIPTION:
NOTES:
MERGE JOIN will be chosen by optimizer when several conditions are met:
* data sources are joined by INNER join;
* data sources are ORDERED, BUT *NOT* via GROUP BY (because optimizer tends to think about grouped data
that its cardinality *much* less than cardinality of source and it causes to decide using hash join instead).
This was explained by dimitr privately, letter: 24-sep-2024 16:30.
* number of conflicts in the hash table must be above 1009 * 1000 = 1009000.
Experimental shows that minimal threshold for switching from HJ to MJ is 1009883 rows.
This value must NOT depend on machine but can have limited dependency on page_size
(see letter from dimitr, 24-sep-2024 19:09).
* No ticket has been created for this test.
Checked on 6.0.0.467.
"""
import re
import time
import pytest
from firebird.qa import *
init_sql = """
create table test1(id int not null);
create table test2(id int not null, pid int not null);
set stat on;
set echo on;
set term ^;
execute block as
declare n_cnt int = 1009883; -- OK, plan MERGE JOIN
-- declare n_cnt int = 1009882; -- plan HJ
declare i int = 0;
begin
while (i < n_cnt) do
begin
insert into test1(id) values(:i);
i = i + 1;
end
end
^
set term ;^
insert into test2(id, pid) select row_number()over(), id from test1;
commit;
"""
db = db_factory(init = init_sql, page_size = 8192)
substitutions = [ ('[ \t]+', ' ')
,('keys: \\d+, total key length: \\d+', 'keys, total key length')
,('record length: \\d+, key length: \\d+', 'record length, key length')
]
act = python_act('db', substitutions = substitutions)
#-----------------------------------------------------------
def replace_leading(source, char="."):
stripped = source.lstrip()
return char * (len(source) - len(stripped)) + stripped
#-----------------------------------------------------------
@pytest.mark.version('>=6.0')
def test_1(act: Action, capsys):
test_sql = """
select a.id, b.pid
from (
select id from test1 order by id
) a
join
(
select pid from test2 b order by pid
) b
on a.id = b.pid
"""
with act.db.connect() as con:
cur = con.cursor()
ps = cur.prepare(test_sql)
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
act.expected_stdout = """
Select Expression
....-> Filter
........-> Merge Join (inner) (keys: 1, total key length: 8)
............-> Sort (record length: 28, key length: 8)
................-> Sort (record length: 28, key length: 8)
....................-> Table "TEST1" as "A TEST1" Full Scan
............-> Sort (record length: 28, key length: 8)
................-> Sort (record length: 28, key length: 8)
....................-> Table "TEST2" as "B B" Full Scan
"""
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout