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

Added/Updated tests\functional\arno\optimizer\test_opt_sort_by_index_18.py: re-implemented after #26e64e9c: Cost-based decision between ORDER and SORT plans (#8316). Checked on 6.0.0.532; 5.0.2.1567; 4.0.6.3168; 3.0.13.33794.

This commit is contained in:
pavel-zotov 2024-11-17 12:55:43 +03:00
parent 42fa9a402c
commit aabe3479b7

View File

@ -7,86 +7,122 @@ DESCRIPTION:
WHERE X = 1 ORDER BY Y
Index for both X and Y should be used when available.
FBTEST: functional.arno.optimizer.opt_sort_by_index_18
NOTES:
[17.11.2024] pzotov
Re-implemented after https://github.com/FirebirdSQL/firebird/commit/26e64e9c08f635d55ac7a111469498b3f0c7fe81
( Cost-based decision between ORDER and SORT plans (#8316) ).
Execution plan was replaced with explained. Plans are splitted for versions up to 5.x and 6.x+.
Discussed with dimitr, letters 16.11.2024.
Checked on 6.0.0.532; 5.0.2.1567; 4.0.6.3168; 3.0.13.33794.
"""
import pytest
from firebird.qa import *
init_script = """CREATE TABLE Table_53 (
ID1 INTEGER,
ID2 INTEGER
);
init_sql = """
recreate table table_53 (
id1 integer,
id2 integer
);
SET TERM ^^ ;
CREATE PROCEDURE PR_FillTable_53
AS
DECLARE VARIABLE FillID INTEGER;
DECLARE VARIABLE FillID1 INTEGER;
BEGIN
FillID = 1;
WHILE (FillID <= 50) DO
BEGIN
FillID1 = (FillID / 10) * 10;
INSERT INTO Table_53
(ID1, ID2)
VALUES
(:FillID1, :FillID - :FillID1);
FillID = FillID + 1;
END
INSERT INTO Table_53 (ID1, ID2) VALUES (0, NULL);
INSERT INTO Table_53 (ID1, ID2) VALUES (NULL, 0);
INSERT INTO Table_53 (ID1, ID2) VALUES (NULL, NULL);
END
^^
SET TERM ; ^^
set term ^ ;
create procedure pr_filltable_53
as
declare k integer;
declare i integer;
begin
k = 1;
while (k <= 50) do
begin
i = (k / 10) * 10;
insert into table_53 (id1, id2) values (:i, :k - :i);
k = k + 1;
end
insert into table_53 (id1, id2) values (0, null);
insert into table_53 (id1, id2) values (null, 0);
insert into table_53 (id1, id2) values (null, null);
end
^
set term ;^
commit;
COMMIT;
execute procedure pr_filltable_53;
commit;
EXECUTE PROCEDURE PR_FillTable_53;
COMMIT;
CREATE ASC INDEX I_Table_53_ID1_ASC ON Table_53 (ID1);
CREATE DESC INDEX I_Table_53_ID1_DESC ON Table_53 (ID1);
CREATE ASC INDEX I_Table_53_ID2_ASC ON Table_53 (ID2);
CREATE DESC INDEX I_Table_53_ID2_DESC ON Table_53 (ID2);
COMMIT;
create asc index i_table_53_id1_asc on table_53 (id1);
create desc index i_table_53_id1_desc on table_53 (id1);
create asc index i_table_53_id2_asc on table_53 (id2);
create desc index i_table_53_id2_desc on table_53 (id2);
commit;
"""
db = db_factory(init=init_script)
db = db_factory(init = init_sql)
test_script = """SET PLAN ON;
SELECT
t53.ID2,
t53.ID1
FROM
Table_53 t53
WHERE
t53.ID1 = 30
ORDER BY
t53.ID2 ASC;"""
act = python_act('db', substitutions = [(r'record length: \d+, key length: \d+', 'record length: NN, key length: MM')])
act = isql_act('db', test_script)
#-----------------------------------------------------------
expected_stdout = """PLAN (T53 ORDER I_TABLE_53_ID2_ASC INDEX (I_TABLE_53_ID1_ASC))
def replace_leading(source, char="."):
stripped = source.lstrip()
return char * (len(source) - len(stripped)) + stripped
ID2 ID1
============ ============
0 30
1 30
2 30
3 30
4 30
5 30
6 30
7 30
8 30
9 30"""
#-----------------------------------------------------------
@pytest.mark.version('>=3')
def test_1(act: Action):
act.expected_stdout = expected_stdout
act.execute()
def test_1(act: Action, capsys):
# opt_clause = '' if act.is_version('<5') else 'optimize for first rows' if act.is_version('<6') else ''
opt_clause = ''
test_sql = f"""
select
t53.id2,
t53.id1
from table_53 t53
where
t53.id1 = 30
order by
t53.id2 asc
{opt_clause}
"""
with act.db.connect() as con:
cur = con.cursor()
ps = None
try:
ps = cur.prepare(test_sql)
# Print explained plan with padding eash line by dots in order to see indentations:
# print(test_sql)
print( '\n'.join([replace_leading(s) for s in ps.detailed_plan.split('\n')]) )
print('')
except DatabaseError as e:
print(e.__str__())
print(e.gds_codes)
finally:
if ps:
ps.free()
expected_stdout_5x = """
Select Expression
....-> Filter
........-> Table "TABLE_53" as "T53" Access By ID
............-> Index "I_TABLE_53_ID2_ASC" Full Scan
................-> Bitmap
....................-> Index "I_TABLE_53_ID1_ASC" Range Scan (full match)
"""
expected_stdout_6x = """
Select Expression
....-> Sort (record length: NN, key length: MM)
........-> Filter
............-> Table "TABLE_53" as "T53" Access By ID
................-> Bitmap
....................-> Index "I_TABLE_53_ID1_ASC" Range Scan (full match)
"""
act.expected_stdout = expected_stdout_5x if act.is_version('<6') else expected_stdout_6x
act.stdout = capsys.readouterr().out
assert act.clean_stdout == act.clean_expected_stdout